2 * FLI/FLC Animation File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
5 * This file is part of FFmpeg.
7 * FFmpeg 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.
12 * FFmpeg 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
28 * http://www.compuphase.com/flic.htm
30 * This demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also
31 * handles special FLIs from the PC game "Magic Carpet".
36 #define FLIC_FILE_MAGIC_1 0xAF11
37 #define FLIC_FILE_MAGIC_2 0xAF12
38 #define FLIC_FILE_MAGIC_3 0xAF44 /* Flic Type for Extended FLX Format which
39 originated in Dave's Targa Animator (DTA) */
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 */
45 #define FLIC_HEADER_SIZE 128
46 #define FLIC_PREAMBLE_SIZE 6
48 typedef struct FlicDemuxContext
{
51 int video_stream_index
;
54 static int flic_probe(AVProbeData
*p
)
61 magic_number
= LE_16(&p
->buf
[4]);
62 if ((magic_number
!= FLIC_FILE_MAGIC_1
) &&
63 (magic_number
!= FLIC_FILE_MAGIC_2
) &&
64 (magic_number
!= FLIC_FILE_MAGIC_3
))
67 return AVPROBE_SCORE_MAX
;
70 static int flic_read_header(AVFormatContext
*s
,
71 AVFormatParameters
*ap
)
73 FlicDemuxContext
*flic
= (FlicDemuxContext
*)s
->priv_data
;
74 ByteIOContext
*pb
= &s
->pb
;
75 unsigned char header
[FLIC_HEADER_SIZE
];
82 /* load the whole header and pull out the width and height */
83 if (get_buffer(pb
, header
, FLIC_HEADER_SIZE
) != FLIC_HEADER_SIZE
)
86 magic_number
= LE_16(&header
[4]);
87 speed
= LE_32(&header
[0x10]);
89 /* initialize the decoder streams */
90 st
= av_new_stream(s
, 0);
93 flic
->video_stream_index
= st
->index
;
94 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
95 st
->codec
->codec_id
= CODEC_ID_FLIC
;
96 st
->codec
->codec_tag
= 0; /* no fourcc */
97 st
->codec
->width
= LE_16(&header
[0x08]);
98 st
->codec
->height
= LE_16(&header
[0x0A]);
100 if (!st
->codec
->width
|| !st
->codec
->height
)
101 return AVERROR_INVALIDDATA
;
103 /* send over the whole 128-byte FLIC header */
104 st
->codec
->extradata_size
= FLIC_HEADER_SIZE
;
105 st
->codec
->extradata
= av_malloc(FLIC_HEADER_SIZE
);
106 memcpy(st
->codec
->extradata
, header
, FLIC_HEADER_SIZE
);
108 av_set_pts_info(st
, 33, 1, 90000);
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,
113 if (LE_16(&header
[0x10]) == FLIC_CHUNK_MAGIC_1
) {
115 flic
->frame_pts_inc
= FLIC_MC_PTS_INC
;
117 /* rewind the stream since the first chunk is at offset 12 */
118 url_fseek(pb
, 12, SEEK_SET
);
120 /* send over abbreviated FLIC header chunk */
121 av_free(st
->codec
->extradata
);
122 st
->codec
->extradata_size
= 12;
123 st
->codec
->extradata
= av_malloc(12);
124 memcpy(st
->codec
->extradata
, header
, 12);
126 } else if (magic_number
== FLIC_FILE_MAGIC_1
) {
128 * in this case, the speed (n) is number of 1/70s ticks between frames:
131 * -------- = ----------- => pts = n * (90000/70) * frame #
134 * therefore, the frame pts increment = n * 1285.7
136 flic
->frame_pts_inc
= speed
* 1285.7;
137 } else if ((magic_number
== FLIC_FILE_MAGIC_2
) ||
138 (magic_number
== FLIC_FILE_MAGIC_3
)) {
140 * in this case, the speed (n) is number of milliseconds between frames:
143 * -------- = ----------- => pts = n * 90 * frame #
146 * therefore, the frame pts increment = n * 90
148 flic
->frame_pts_inc
= speed
* 90;
150 return AVERROR_INVALIDDATA
;
152 if (flic
->frame_pts_inc
== 0)
153 flic
->frame_pts_inc
= FLIC_DEFAULT_PTS_INC
;
158 static int flic_read_packet(AVFormatContext
*s
,
161 FlicDemuxContext
*flic
= (FlicDemuxContext
*)s
->priv_data
;
162 ByteIOContext
*pb
= &s
->pb
;
167 unsigned char preamble
[FLIC_PREAMBLE_SIZE
];
169 while (!packet_read
) {
171 if ((ret
= get_buffer(pb
, preamble
, FLIC_PREAMBLE_SIZE
)) !=
172 FLIC_PREAMBLE_SIZE
) {
177 size
= LE_32(&preamble
[0]);
178 magic
= LE_16(&preamble
[4]);
180 if (((magic
== FLIC_CHUNK_MAGIC_1
) || (magic
== FLIC_CHUNK_MAGIC_2
)) && size
> FLIC_PREAMBLE_SIZE
) {
181 if (av_new_packet(pkt
, size
)) {
185 pkt
->stream_index
= flic
->video_stream_index
;
186 pkt
->pts
= flic
->pts
;
187 pkt
->pos
= url_ftell(pb
);
188 memcpy(pkt
->data
, preamble
, FLIC_PREAMBLE_SIZE
);
189 ret
= get_buffer(pb
, pkt
->data
+ FLIC_PREAMBLE_SIZE
,
190 size
- FLIC_PREAMBLE_SIZE
);
191 if (ret
!= size
- FLIC_PREAMBLE_SIZE
) {
195 flic
->pts
+= flic
->frame_pts_inc
;
198 /* not interested in this chunk */
199 url_fseek(pb
, size
- 6, SEEK_CUR
);
206 static int flic_read_close(AVFormatContext
*s
)
208 // FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
213 AVInputFormat flic_demuxer
= {
215 "FLI/FLC/FLX animation format",
216 sizeof(FlicDemuxContext
),