1/* 2 * Interplay C93 demuxer 3 * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> 4 * 5 * This file is part of Libav. 6 * 7 * Libav is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * Libav is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "avformat.h" 23#include "internal.h" 24#include "voc.h" 25#include "libavutil/intreadwrite.h" 26 27typedef struct { 28 uint16_t index; 29 uint8_t length; 30 uint8_t frames; 31} C93BlockRecord; 32 33typedef struct { 34 VocDecContext voc; 35 36 C93BlockRecord block_records[512]; 37 int current_block; 38 39 uint32_t frame_offsets[32]; 40 int current_frame; 41 int next_pkt_is_audio; 42 43 AVStream *audio; 44} C93DemuxContext; 45 46static int probe(AVProbeData *p) 47{ 48 int i; 49 int index = 1; 50 if (p->buf_size < 16) 51 return 0; 52 for (i = 0; i < 16; i += 4) { 53 if (AV_RL16(p->buf + i) != index || !p->buf[i + 2] || !p->buf[i + 3]) 54 return 0; 55 index += p->buf[i + 2]; 56 } 57 return AVPROBE_SCORE_MAX; 58} 59 60static int read_header(AVFormatContext *s, 61 AVFormatParameters *ap) 62{ 63 AVStream *video; 64 AVIOContext *pb = s->pb; 65 C93DemuxContext *c93 = s->priv_data; 66 int i; 67 int framecount = 0; 68 69 for (i = 0; i < 512; i++) { 70 c93->block_records[i].index = avio_rl16(pb); 71 c93->block_records[i].length = avio_r8(pb); 72 c93->block_records[i].frames = avio_r8(pb); 73 if (c93->block_records[i].frames > 32) { 74 av_log(s, AV_LOG_ERROR, "too many frames in block\n"); 75 return AVERROR_INVALIDDATA; 76 } 77 framecount += c93->block_records[i].frames; 78 } 79 80 /* Audio streams are added if audio packets are found */ 81 s->ctx_flags |= AVFMTCTX_NOHEADER; 82 83 video = avformat_new_stream(s, NULL); 84 if (!video) 85 return AVERROR(ENOMEM); 86 87 video->codec->codec_type = AVMEDIA_TYPE_VIDEO; 88 video->codec->codec_id = CODEC_ID_C93; 89 video->codec->width = 320; 90 video->codec->height = 192; 91 /* 4:3 320x200 with 8 empty lines */ 92 video->sample_aspect_ratio = (AVRational) { 5, 6 }; 93 avpriv_set_pts_info(video, 64, 2, 25); 94 video->nb_frames = framecount; 95 video->duration = framecount; 96 video->start_time = 0; 97 98 c93->current_block = 0; 99 c93->current_frame = 0; 100 c93->next_pkt_is_audio = 0; 101 return 0; 102} 103 104#define C93_HAS_PALETTE 0x01 105#define C93_FIRST_FRAME 0x02 106 107static int read_packet(AVFormatContext *s, AVPacket *pkt) 108{ 109 AVIOContext *pb = s->pb; 110 C93DemuxContext *c93 = s->priv_data; 111 C93BlockRecord *br = &c93->block_records[c93->current_block]; 112 int datasize; 113 int ret, i; 114 115 if (c93->next_pkt_is_audio) { 116 c93->current_frame++; 117 c93->next_pkt_is_audio = 0; 118 datasize = avio_rl16(pb); 119 if (datasize > 42) { 120 if (!c93->audio) { 121 c93->audio = avformat_new_stream(s, NULL); 122 if (!c93->audio) 123 return AVERROR(ENOMEM); 124 c93->audio->codec->codec_type = AVMEDIA_TYPE_AUDIO; 125 } 126 avio_skip(pb, 26); /* VOC header */ 127 ret = voc_get_packet(s, pkt, c93->audio, datasize - 26); 128 if (ret > 0) { 129 pkt->stream_index = 1; 130 pkt->flags |= AV_PKT_FLAG_KEY; 131 return ret; 132 } 133 } 134 } 135 if (c93->current_frame >= br->frames) { 136 if (c93->current_block >= 511 || !br[1].length) 137 return AVERROR(EIO); 138 br++; 139 c93->current_block++; 140 c93->current_frame = 0; 141 } 142 143 if (c93->current_frame == 0) { 144 avio_seek(pb, br->index * 2048, SEEK_SET); 145 for (i = 0; i < 32; i++) { 146 c93->frame_offsets[i] = avio_rl32(pb); 147 } 148 } 149 150 avio_seek(pb,br->index * 2048 + 151 c93->frame_offsets[c93->current_frame], SEEK_SET); 152 datasize = avio_rl16(pb); /* video frame size */ 153 154 ret = av_new_packet(pkt, datasize + 768 + 1); 155 if (ret < 0) 156 return ret; 157 pkt->data[0] = 0; 158 pkt->size = datasize + 1; 159 160 ret = avio_read(pb, pkt->data + 1, datasize); 161 if (ret < datasize) { 162 ret = AVERROR(EIO); 163 goto fail; 164 } 165 166 datasize = avio_rl16(pb); /* palette size */ 167 if (datasize) { 168 if (datasize != 768) { 169 av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize); 170 ret = AVERROR_INVALIDDATA; 171 goto fail; 172 } 173 pkt->data[0] |= C93_HAS_PALETTE; 174 ret = avio_read(pb, pkt->data + pkt->size, datasize); 175 if (ret < datasize) { 176 ret = AVERROR(EIO); 177 goto fail; 178 } 179 pkt->size += 768; 180 } 181 pkt->stream_index = 0; 182 c93->next_pkt_is_audio = 1; 183 184 /* only the first frame is guaranteed to not reference previous frames */ 185 if (c93->current_block == 0 && c93->current_frame == 0) { 186 pkt->flags |= AV_PKT_FLAG_KEY; 187 pkt->data[0] |= C93_FIRST_FRAME; 188 } 189 return 0; 190 191 fail: 192 av_free_packet(pkt); 193 return ret; 194} 195 196AVInputFormat ff_c93_demuxer = { 197 .name = "c93", 198 .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), 199 .priv_data_size = sizeof(C93DemuxContext), 200 .read_probe = probe, 201 .read_header = read_header, 202 .read_packet = read_packet, 203}; 204