annotate ffmpeg/libavformat/flic.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 * FLI/FLC Animation File Demuxer
yading@11 3 * Copyright (c) 2003 The ffmpeg Project
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 /**
yading@11 23 * @file
yading@11 24 * FLI/FLC file demuxer
yading@11 25 * by Mike Melanson (melanson@pcisys.net)
yading@11 26 * for more information on the .fli/.flc file format and all of its many
yading@11 27 * variations, visit:
yading@11 28 * http://www.compuphase.com/flic.htm
yading@11 29 *
yading@11 30 * This demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also handles
yading@11 31 * special FLIs from the PC games "Magic Carpet" and "X-COM: Terror from the Deep".
yading@11 32 */
yading@11 33
yading@11 34 #include "libavutil/channel_layout.h"
yading@11 35 #include "libavutil/intreadwrite.h"
yading@11 36 #include "avformat.h"
yading@11 37 #include "internal.h"
yading@11 38
yading@11 39 #define FLIC_FILE_MAGIC_1 0xAF11
yading@11 40 #define FLIC_FILE_MAGIC_2 0xAF12
yading@11 41 #define FLIC_FILE_MAGIC_3 0xAF44 /* Flic Type for Extended FLX Format which
yading@11 42 originated in Dave's Targa Animator (DTA) */
yading@11 43 #define FLIC_CHUNK_MAGIC_1 0xF1FA
yading@11 44 #define FLIC_CHUNK_MAGIC_2 0xF5FA
yading@11 45 #define FLIC_MC_SPEED 5 /* speed for Magic Carpet game FLIs */
yading@11 46 #define FLIC_DEFAULT_SPEED 5 /* for FLIs that have 0 speed */
yading@11 47 #define FLIC_TFTD_CHUNK_AUDIO 0xAAAA /* Audio chunk. Used in Terror from the Deep.
yading@11 48 Has 10 B extra header not accounted for in the chunk header */
yading@11 49 #define FLIC_TFTD_SAMPLE_RATE 22050
yading@11 50
yading@11 51 #define FLIC_HEADER_SIZE 128
yading@11 52 #define FLIC_PREAMBLE_SIZE 6
yading@11 53
yading@11 54 typedef struct FlicDemuxContext {
yading@11 55 int video_stream_index;
yading@11 56 int audio_stream_index;
yading@11 57 int frame_number;
yading@11 58 } FlicDemuxContext;
yading@11 59
yading@11 60 static int flic_probe(AVProbeData *p)
yading@11 61 {
yading@11 62 int magic_number;
yading@11 63
yading@11 64 if(p->buf_size < FLIC_HEADER_SIZE)
yading@11 65 return 0;
yading@11 66
yading@11 67 magic_number = AV_RL16(&p->buf[4]);
yading@11 68 if ((magic_number != FLIC_FILE_MAGIC_1) &&
yading@11 69 (magic_number != FLIC_FILE_MAGIC_2) &&
yading@11 70 (magic_number != FLIC_FILE_MAGIC_3))
yading@11 71 return 0;
yading@11 72
yading@11 73 if(AV_RL16(&p->buf[0x10]) != FLIC_CHUNK_MAGIC_1){
yading@11 74 if(AV_RL32(&p->buf[0x10]) > 2000)
yading@11 75 return 0;
yading@11 76 }
yading@11 77
yading@11 78 if( AV_RL16(&p->buf[0x08]) > 4096
yading@11 79 || AV_RL16(&p->buf[0x0A]) > 4096)
yading@11 80 return 0;
yading@11 81
yading@11 82
yading@11 83 return AVPROBE_SCORE_MAX;
yading@11 84 }
yading@11 85
yading@11 86 static int flic_read_header(AVFormatContext *s)
yading@11 87 {
yading@11 88 FlicDemuxContext *flic = s->priv_data;
yading@11 89 AVIOContext *pb = s->pb;
yading@11 90 unsigned char header[FLIC_HEADER_SIZE];
yading@11 91 AVStream *st, *ast;
yading@11 92 int speed;
yading@11 93 int magic_number;
yading@11 94 unsigned char preamble[FLIC_PREAMBLE_SIZE];
yading@11 95
yading@11 96 flic->frame_number = 0;
yading@11 97
yading@11 98 /* load the whole header and pull out the width and height */
yading@11 99 if (avio_read(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE)
yading@11 100 return AVERROR(EIO);
yading@11 101
yading@11 102 magic_number = AV_RL16(&header[4]);
yading@11 103 speed = AV_RL32(&header[0x10]);
yading@11 104 if (speed == 0)
yading@11 105 speed = FLIC_DEFAULT_SPEED;
yading@11 106
yading@11 107 /* initialize the decoder streams */
yading@11 108 st = avformat_new_stream(s, NULL);
yading@11 109 if (!st)
yading@11 110 return AVERROR(ENOMEM);
yading@11 111 flic->video_stream_index = st->index;
yading@11 112 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 113 st->codec->codec_id = AV_CODEC_ID_FLIC;
yading@11 114 st->codec->codec_tag = 0; /* no fourcc */
yading@11 115 st->codec->width = AV_RL16(&header[0x08]);
yading@11 116 st->codec->height = AV_RL16(&header[0x0A]);
yading@11 117
yading@11 118 if (!st->codec->width || !st->codec->height) {
yading@11 119 /* Ugly hack needed for the following sample: */
yading@11 120 /* http://samples.mplayerhq.hu/fli-flc/fli-bugs/specular.flc */
yading@11 121 av_log(s, AV_LOG_WARNING,
yading@11 122 "File with no specified width/height. Trying 640x480.\n");
yading@11 123 st->codec->width = 640;
yading@11 124 st->codec->height = 480;
yading@11 125 }
yading@11 126
yading@11 127 /* send over the whole 128-byte FLIC header */
yading@11 128 st->codec->extradata_size = FLIC_HEADER_SIZE;
yading@11 129 st->codec->extradata = av_malloc(FLIC_HEADER_SIZE);
yading@11 130 memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE);
yading@11 131
yading@11 132 /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */
yading@11 133 if (avio_read(pb, preamble, FLIC_PREAMBLE_SIZE) != FLIC_PREAMBLE_SIZE) {
yading@11 134 av_log(s, AV_LOG_ERROR, "Failed to peek at preamble\n");
yading@11 135 return AVERROR(EIO);
yading@11 136 }
yading@11 137
yading@11 138 avio_seek(pb, -FLIC_PREAMBLE_SIZE, SEEK_CUR);
yading@11 139
yading@11 140 /* Time to figure out the framerate:
yading@11 141 * If the first preamble's magic number is 0xAAAA then this file is from
yading@11 142 * X-COM: Terror from the Deep. If on the other hand there is a FLIC chunk
yading@11 143 * magic number at offset 0x10 assume this file is from Magic Carpet instead.
yading@11 144 * If neither of the above is true then this is a normal FLIC file.
yading@11 145 */
yading@11 146 if (AV_RL16(&preamble[4]) == FLIC_TFTD_CHUNK_AUDIO) {
yading@11 147 /* TFTD videos have an extra 22050 Hz 8-bit mono audio stream */
yading@11 148 ast = avformat_new_stream(s, NULL);
yading@11 149 if (!ast)
yading@11 150 return AVERROR(ENOMEM);
yading@11 151
yading@11 152 flic->audio_stream_index = ast->index;
yading@11 153
yading@11 154 /* all audio frames are the same size, so use the size of the first chunk for block_align */
yading@11 155 ast->codec->block_align = AV_RL32(&preamble[0]);
yading@11 156 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 157 ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
yading@11 158 ast->codec->codec_tag = 0;
yading@11 159 ast->codec->sample_rate = FLIC_TFTD_SAMPLE_RATE;
yading@11 160 ast->codec->channels = 1;
yading@11 161 ast->codec->bit_rate = st->codec->sample_rate * 8;
yading@11 162 ast->codec->bits_per_coded_sample = 8;
yading@11 163 ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
yading@11 164 ast->codec->extradata_size = 0;
yading@11 165
yading@11 166 /* Since the header information is incorrect we have to figure out the
yading@11 167 * framerate using block_align and the fact that the audio is 22050 Hz.
yading@11 168 * We usually have two cases: 2205 -> 10 fps and 1470 -> 15 fps */
yading@11 169 avpriv_set_pts_info(st, 64, ast->codec->block_align, FLIC_TFTD_SAMPLE_RATE);
yading@11 170 avpriv_set_pts_info(ast, 64, 1, FLIC_TFTD_SAMPLE_RATE);
yading@11 171 } else if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
yading@11 172 avpriv_set_pts_info(st, 64, FLIC_MC_SPEED, 70);
yading@11 173
yading@11 174 /* rewind the stream since the first chunk is at offset 12 */
yading@11 175 avio_seek(pb, 12, SEEK_SET);
yading@11 176
yading@11 177 /* send over abbreviated FLIC header chunk */
yading@11 178 av_free(st->codec->extradata);
yading@11 179 st->codec->extradata_size = 12;
yading@11 180 st->codec->extradata = av_malloc(12);
yading@11 181 memcpy(st->codec->extradata, header, 12);
yading@11 182
yading@11 183 } else if (magic_number == FLIC_FILE_MAGIC_1) {
yading@11 184 avpriv_set_pts_info(st, 64, speed, 70);
yading@11 185 } else if ((magic_number == FLIC_FILE_MAGIC_2) ||
yading@11 186 (magic_number == FLIC_FILE_MAGIC_3)) {
yading@11 187 avpriv_set_pts_info(st, 64, speed, 1000);
yading@11 188 } else {
yading@11 189 av_log(s, AV_LOG_ERROR, "Invalid or unsupported magic chunk in file\n");
yading@11 190 return AVERROR_INVALIDDATA;
yading@11 191 }
yading@11 192
yading@11 193 return 0;
yading@11 194 }
yading@11 195
yading@11 196 static int flic_read_packet(AVFormatContext *s,
yading@11 197 AVPacket *pkt)
yading@11 198 {
yading@11 199 FlicDemuxContext *flic = s->priv_data;
yading@11 200 AVIOContext *pb = s->pb;
yading@11 201 int packet_read = 0;
yading@11 202 unsigned int size;
yading@11 203 int magic;
yading@11 204 int ret = 0;
yading@11 205 unsigned char preamble[FLIC_PREAMBLE_SIZE];
yading@11 206
yading@11 207 while (!packet_read) {
yading@11 208
yading@11 209 if ((ret = avio_read(pb, preamble, FLIC_PREAMBLE_SIZE)) !=
yading@11 210 FLIC_PREAMBLE_SIZE) {
yading@11 211 ret = AVERROR(EIO);
yading@11 212 break;
yading@11 213 }
yading@11 214
yading@11 215 size = AV_RL32(&preamble[0]);
yading@11 216 magic = AV_RL16(&preamble[4]);
yading@11 217
yading@11 218 if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) {
yading@11 219 if (av_new_packet(pkt, size)) {
yading@11 220 ret = AVERROR(EIO);
yading@11 221 break;
yading@11 222 }
yading@11 223 pkt->stream_index = flic->video_stream_index;
yading@11 224 pkt->pts = flic->frame_number++;
yading@11 225 pkt->pos = avio_tell(pb);
yading@11 226 memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE);
yading@11 227 ret = avio_read(pb, pkt->data + FLIC_PREAMBLE_SIZE,
yading@11 228 size - FLIC_PREAMBLE_SIZE);
yading@11 229 if (ret != size - FLIC_PREAMBLE_SIZE) {
yading@11 230 av_free_packet(pkt);
yading@11 231 ret = AVERROR(EIO);
yading@11 232 }
yading@11 233 packet_read = 1;
yading@11 234 } else if (magic == FLIC_TFTD_CHUNK_AUDIO) {
yading@11 235 if (av_new_packet(pkt, size)) {
yading@11 236 ret = AVERROR(EIO);
yading@11 237 break;
yading@11 238 }
yading@11 239
yading@11 240 /* skip useless 10B sub-header (yes, it's not accounted for in the chunk header) */
yading@11 241 avio_skip(pb, 10);
yading@11 242
yading@11 243 pkt->stream_index = flic->audio_stream_index;
yading@11 244 pkt->pos = avio_tell(pb);
yading@11 245 ret = avio_read(pb, pkt->data, size);
yading@11 246
yading@11 247 if (ret != size) {
yading@11 248 av_free_packet(pkt);
yading@11 249 ret = AVERROR(EIO);
yading@11 250 }
yading@11 251
yading@11 252 packet_read = 1;
yading@11 253 } else {
yading@11 254 /* not interested in this chunk */
yading@11 255 avio_skip(pb, size - 6);
yading@11 256 }
yading@11 257 }
yading@11 258
yading@11 259 return ret;
yading@11 260 }
yading@11 261
yading@11 262 AVInputFormat ff_flic_demuxer = {
yading@11 263 .name = "flic",
yading@11 264 .long_name = NULL_IF_CONFIG_SMALL("FLI/FLC/FLX animation"),
yading@11 265 .priv_data_size = sizeof(FlicDemuxContext),
yading@11 266 .read_probe = flic_probe,
yading@11 267 .read_header = flic_read_header,
yading@11 268 .read_packet = flic_read_packet,
yading@11 269 };