Mercurial > libavformat.hg
annotate flic.c @ 1960:c0289552590f libavformat
Change the vhook code to send real timestamps to the filters instead of the
current time of day, which is useless, and which the filters could just as
easily query for themselves.
patch by Bobby Bingham, uhmmmm gmail com
author | diego |
---|---|
date | Thu, 29 Mar 2007 05:24:35 +0000 |
parents | 9cd35d039830 |
children | 1a3c9056982a |
rev | line source |
---|---|
315 | 1 /* |
2 * FLI/FLC Animation File Demuxer | |
3 * Copyright (c) 2003 The ffmpeg Project | |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
315 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
315 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
315 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
885
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
315 | 20 */ |
21 | |
22 /** | |
23 * @file flic.c | |
24 * FLI/FLC file demuxer | |
25 * by Mike Melanson (melanson@pcisys.net) | |
26 * for more information on the .fli/.flc file format and all of its many | |
27 * variations, visit: | |
28 * http://www.compuphase.com/flic.htm | |
29 * | |
30 * This demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also | |
31 * handles special FLIs from the PC game "Magic Carpet". | |
32 */ | |
33 | |
34 #include "avformat.h" | |
35 | |
36 #define FLIC_FILE_MAGIC_1 0xAF11 | |
37 #define FLIC_FILE_MAGIC_2 0xAF12 | |
885 | 38 #define FLIC_FILE_MAGIC_3 0xAF44 /* Flic Type for Extended FLX Format which |
864
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
39 originated in Dave's Targa Animator (DTA) */ |
315 | 40 #define FLIC_CHUNK_MAGIC_1 0xF1FA |
41 #define FLIC_CHUNK_MAGIC_2 0xF5FA | |
42 #define FLIC_MC_PTS_INC 6000 /* pts increment for Magic Carpet game FLIs */ | |
43 #define FLIC_DEFAULT_PTS_INC 6000 /* for FLIs that have 0 speed */ | |
44 | |
45 #define FLIC_HEADER_SIZE 128 | |
46 #define FLIC_PREAMBLE_SIZE 6 | |
47 | |
48 typedef struct FlicDemuxContext { | |
49 int frame_pts_inc; | |
50 int64_t pts; | |
51 int video_stream_index; | |
52 } FlicDemuxContext; | |
53 | |
54 static int flic_probe(AVProbeData *p) | |
55 { | |
56 int magic_number; | |
57 | |
58 if (p->buf_size < 6) | |
59 return 0; | |
60 | |
1673 | 61 magic_number = AV_RL16(&p->buf[4]); |
315 | 62 if ((magic_number != FLIC_FILE_MAGIC_1) && |
864
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
63 (magic_number != FLIC_FILE_MAGIC_2) && |
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
64 (magic_number != FLIC_FILE_MAGIC_3)) |
315 | 65 return 0; |
66 | |
67 return AVPROBE_SCORE_MAX; | |
68 } | |
69 | |
70 static int flic_read_header(AVFormatContext *s, | |
71 AVFormatParameters *ap) | |
72 { | |
73 FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data; | |
74 ByteIOContext *pb = &s->pb; | |
75 unsigned char header[FLIC_HEADER_SIZE]; | |
76 AVStream *st; | |
77 int speed; | |
78 int magic_number; | |
79 | |
80 flic->pts = 0; | |
81 | |
82 /* load the whole header and pull out the width and height */ | |
83 if (get_buffer(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE) | |
482 | 84 return AVERROR_IO; |
315 | 85 |
1673 | 86 magic_number = AV_RL16(&header[4]); |
87 speed = AV_RL32(&header[0x10]); | |
315 | 88 |
89 /* initialize the decoder streams */ | |
90 st = av_new_stream(s, 0); | |
91 if (!st) | |
92 return AVERROR_NOMEM; | |
93 flic->video_stream_index = st->index; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
94 st->codec->codec_type = CODEC_TYPE_VIDEO; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
95 st->codec->codec_id = CODEC_ID_FLIC; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
96 st->codec->codec_tag = 0; /* no fourcc */ |
1673 | 97 st->codec->width = AV_RL16(&header[0x08]); |
98 st->codec->height = AV_RL16(&header[0x0A]); | |
315 | 99 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
100 if (!st->codec->width || !st->codec->height) |
315 | 101 return AVERROR_INVALIDDATA; |
102 | |
103 /* send over the whole 128-byte FLIC header */ | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
104 st->codec->extradata_size = FLIC_HEADER_SIZE; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
105 st->codec->extradata = av_malloc(FLIC_HEADER_SIZE); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
106 memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE); |
315 | 107 |
462
b69898ffc92a
move time_base (pts_num/pts_den) from AVFormatContext -> AVStream
michael
parents:
386
diff
changeset
|
108 av_set_pts_info(st, 33, 1, 90000); |
315 | 109 |
110 /* Time to figure out the framerate: If there is a FLIC chunk magic | |
111 * number at offset 0x10, assume this is from the Bullfrog game, | |
112 * Magic Carpet. */ | |
1673 | 113 if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) { |
315 | 114 |
115 flic->frame_pts_inc = FLIC_MC_PTS_INC; | |
116 | |
117 /* rewind the stream since the first chunk is at offset 12 */ | |
118 url_fseek(pb, 12, SEEK_SET); | |
119 | |
120 /* send over abbreviated FLIC header chunk */ | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
121 av_free(st->codec->extradata); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
122 st->codec->extradata_size = 12; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
123 st->codec->extradata = av_malloc(12); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
124 memcpy(st->codec->extradata, header, 12); |
315 | 125 |
126 } else if (magic_number == FLIC_FILE_MAGIC_1) { | |
127 /* | |
128 * in this case, the speed (n) is number of 1/70s ticks between frames: | |
129 * | |
130 * pts n * frame # | |
131 * -------- = ----------- => pts = n * (90000/70) * frame # | |
132 * 90000 70 | |
133 * | |
134 * therefore, the frame pts increment = n * 1285.7 | |
135 */ | |
136 flic->frame_pts_inc = speed * 1285.7; | |
864
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
137 } else if ((magic_number == FLIC_FILE_MAGIC_2) || |
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
138 (magic_number == FLIC_FILE_MAGIC_3)) { |
315 | 139 /* |
140 * in this case, the speed (n) is number of milliseconds between frames: | |
141 * | |
142 * pts n * frame # | |
143 * -------- = ----------- => pts = n * 90 * frame # | |
144 * 90000 1000 | |
145 * | |
146 * therefore, the frame pts increment = n * 90 | |
147 */ | |
148 flic->frame_pts_inc = speed * 90; | |
1801 | 149 } else { |
150 av_log(s, AV_LOG_INFO, "Invalid or unsupported magic chunk in file\n"); | |
315 | 151 return AVERROR_INVALIDDATA; |
1801 | 152 } |
315 | 153 |
154 if (flic->frame_pts_inc == 0) | |
155 flic->frame_pts_inc = FLIC_DEFAULT_PTS_INC; | |
156 | |
157 return 0; | |
158 } | |
159 | |
160 static int flic_read_packet(AVFormatContext *s, | |
161 AVPacket *pkt) | |
162 { | |
163 FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data; | |
164 ByteIOContext *pb = &s->pb; | |
165 int packet_read = 0; | |
166 unsigned int size; | |
167 int magic; | |
168 int ret = 0; | |
169 unsigned char preamble[FLIC_PREAMBLE_SIZE]; | |
170 | |
171 while (!packet_read) { | |
172 | |
173 if ((ret = get_buffer(pb, preamble, FLIC_PREAMBLE_SIZE)) != | |
174 FLIC_PREAMBLE_SIZE) { | |
482 | 175 ret = AVERROR_IO; |
315 | 176 break; |
177 } | |
178 | |
1673 | 179 size = AV_RL32(&preamble[0]); |
180 magic = AV_RL16(&preamble[4]); | |
315 | 181 |
643 | 182 if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) { |
315 | 183 if (av_new_packet(pkt, size)) { |
482 | 184 ret = AVERROR_IO; |
315 | 185 break; |
186 } | |
187 pkt->stream_index = flic->video_stream_index; | |
188 pkt->pts = flic->pts; | |
885 | 189 pkt->pos = url_ftell(pb); |
315 | 190 memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE); |
885 | 191 ret = get_buffer(pb, pkt->data + FLIC_PREAMBLE_SIZE, |
315 | 192 size - FLIC_PREAMBLE_SIZE); |
193 if (ret != size - FLIC_PREAMBLE_SIZE) { | |
194 av_free_packet(pkt); | |
482 | 195 ret = AVERROR_IO; |
315 | 196 } |
197 flic->pts += flic->frame_pts_inc; | |
198 packet_read = 1; | |
199 } else { | |
200 /* not interested in this chunk */ | |
201 url_fseek(pb, size - 6, SEEK_CUR); | |
202 } | |
203 } | |
204 | |
205 return ret; | |
206 } | |
207 | |
208 static int flic_read_close(AVFormatContext *s) | |
209 { | |
210 // FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data; | |
211 | |
212 return 0; | |
213 } | |
214 | |
1169 | 215 AVInputFormat flic_demuxer = { |
315 | 216 "flic", |
864
00a3ba030166
support for FLX and DTA extensions in the FLIC format, courtesy of
melanson
parents:
820
diff
changeset
|
217 "FLI/FLC/FLX animation format", |
315 | 218 sizeof(FlicDemuxContext), |
219 flic_probe, | |
220 flic_read_header, | |
221 flic_read_packet, | |
222 flic_read_close, | |
223 }; |