annotate ffmpeg/libavformat/c93.c @ 13:844d341cf643 tip

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