Browse code

yep, FLI support

Originally committed as revision 2519 to svn://svn.ffmpeg.org/ffmpeg/trunk

Mike Melanson authored on 2003/11/14 14:42:14
Showing 10 changed files
... ...
@@ -2,11 +2,14 @@ version <next>:
2 2
 - DV encoder, DV muxer
3 3
 - Microsoft RLE video decoder
4 4
 - Microsoft Video-1 decoder
5
+- Apple Graphics (SMC) decoder
5 6
 - Apple Video (RPZA) decoder
6 7
 - Cinepak decoder
7 8
 - Sega FILM (CPK) file demuxer
8
-- Westwood multimedia support (VQA/AUD file demuxer, audio decoder)
9
+- Westwood multimedia support (VQA & AUD files)
9 10
 - Id Quake II CIN playback support
11
+- 8BPS video decoder
12
+- FLIC playback support
10 13
 
11 14
 version 0.4.8:
12 15
 
... ...
@@ -613,6 +613,7 @@ library:
613 613
 @item Raw MJPEG @tab X  @tab  X 
614 614
 @item Raw MPEG video @tab X  @tab  X 
615 615
 @item Raw PCM8/16 bits, mulaw/Alaw@tab X  @tab  X 
616
+@item Raw CRI ADX audio @tab X  @tab  X 
616 617
 @item SUN AU format @tab X  @tab  X 
617 618
 @item NUT @tab X @tab X @tab NUT Open Container Format
618 619
 @item Quicktime        @tab X @tab  X 
... ...
@@ -635,6 +636,8 @@ library:
635 635
 @tab Multimedia formats used in Westwood Studios games
636 636
 @item Id Cinematic (.cin) @tab    @tab X
637 637
 @tab Used in Quake II
638
+@item FLIC format      @tab    @tab X
639
+@tab .fli/.flc files
638 640
 @end multitable
639 641
 
640 642
 @code{X} means that the encoding (resp. decoding) is supported.
... ...
@@ -695,6 +698,7 @@ following image formats are supported:
695 695
 @item Id RoQ                 @tab     @tab  X @tab used in Quake III, Jedi Knight 2, other computer games
696 696
 @item Xan/WC3                @tab     @tab  X @tab used in Wing Commander III .MVE files
697 697
 @item Interplay Video        @tab     @tab  X @tab used in Interplay .MVE files
698
+@item Apple Graphics         @tab     @tab  X @tab fourcc: 'smc '
698 699
 @item Apple Video            @tab     @tab  X @tab fourcc: rpza
699 700
 @item Cinepak                @tab     @tab  X
700 701
 @item Microsoft RLE          @tab     @tab  X
... ...
@@ -702,6 +706,7 @@ following image formats are supported:
702 702
 @item Westwood VQA           @tab     @tab  X
703 703
 @item Id Cinematic Video     @tab     @tab  X @tab used in Quake II
704 704
 @item Planar RGB             @tab     @tab  X @tab fourcc: 8BPS
705
+@item FLIC video             @tab     @tab  X
705 706
 @end multitable
706 707
 
707 708
 @code{X} means that the encoding (resp. decoding) is supported.
... ...
@@ -731,7 +736,10 @@ solutions.
731 731
 @item Duck DK4 IMA ADPCM     @tab      @tab X
732 732
 @tab used in some Sega Saturn console games
733 733
 @item Westwood Studios IMA ADPCM @tab      @tab X
734
-@tab used in Westwood Studios games likes Command and Conquer
734
+@tab used in Westwood Studios games like Command and Conquer
735
+@item CD-ROM XA ADPCM        @tab      @tab X
736
+@item CRI ADX ADPCM          @tab X    @tab X
737
+@tab used in Sega Dreamcast games
735 738
 @item RA144                  @tab      @tab X
736 739
 @tab Real 14400 bit/s codec
737 740
 @item RA288                  @tab      @tab X
... ...
@@ -19,7 +19,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \
19 19
       vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \
20 20
       roqvideo.o dpcm.o interplayvideo.o xan.o rpza.o cinepak.o msrle.o \
21 21
       msvideo1.o vqavideo.o idcinvideo.o adx.o rational.o faandct.o 8bps.o \
22
-      smc.o parser.o
22
+      smc.o parser.o flicvideo.o
23 23
 
24 24
 ifeq ($(AMR_NB),yes)
25 25
 ifeq ($(AMR_NB_FIXED),yes)
... ...
@@ -137,6 +137,7 @@ void avcodec_register_all(void)
137 137
     register_avcodec(&idcin_decoder);
138 138
     register_avcodec(&eightbps_decoder);
139 139
     register_avcodec(&smc_decoder);
140
+    register_avcodec(&flic_decoder);
140 141
 #ifdef CONFIG_AC3
141 142
     register_avcodec(&ac3_decoder);
142 143
 #endif
... ...
@@ -86,6 +86,7 @@ enum CodecID {
86 86
     CODEC_ID_IDCIN,
87 87
     CODEC_ID_8BPS,
88 88
     CODEC_ID_SMC,
89
+    CODEC_ID_FLIC,
89 90
 
90 91
     /* various pcm "codecs" */
91 92
     CODEC_ID_PCM_S16LE,
... ...
@@ -1574,6 +1575,7 @@ extern AVCodec vqa_decoder;
1574 1574
 extern AVCodec idcin_decoder;
1575 1575
 extern AVCodec eightbps_decoder;
1576 1576
 extern AVCodec smc_decoder;
1577
+extern AVCodec flic_decoder;
1577 1578
 extern AVCodec ra_144_decoder;
1578 1579
 extern AVCodec ra_288_decoder;
1579 1580
 extern AVCodec roq_dpcm_decoder;
1580 1581
new file mode 100644
... ...
@@ -0,0 +1,461 @@
0
+/*
1
+ * FLI/FLC Animation Video Decoder
2
+ * Copyright (C) 2003 the ffmpeg project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ *
18
+ */
19
+
20
+/**
21
+ * @file flic.c
22
+ * Autodesk Animator FLI/FLC Video Decoder
23
+ * by Mike Melanson (melanson@pcisys.net)
24
+ * for more information on the .fli/.flc file format and all of its many
25
+ * variations, visit:
26
+ *   http://www.compuphase.com/flic.htm
27
+ *
28
+ * This decoder outputs PAL8 colorspace data. To use this decoder, be
29
+ * sure that your demuxer sends the FLI file header to the decoder via
30
+ * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
31
+ * large. The only exception is for FLI files from the game "Magic Carpet",
32
+ * in which the header is only 12 bytes.
33
+ */
34
+
35
+#include <stdio.h>
36
+#include <stdlib.h>
37
+#include <string.h>
38
+#include <unistd.h>
39
+
40
+#include "common.h"
41
+#include "avcodec.h"
42
+#include "bswap.h"
43
+
44
+#define FLI_256_COLOR 4
45
+#define FLI_DELTA     7
46
+#define FLI_COLOR     11
47
+#define FLI_LC        12
48
+#define FLI_BLACK     13
49
+#define FLI_BRUN      15
50
+#define FLI_COPY      16
51
+#define FLI_MINI      18
52
+
53
+#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
54
+#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
55
+                   (((uint8_t*)(x))[2] << 16) | \
56
+                   (((uint8_t*)(x))[1] << 8) | \
57
+                    ((uint8_t*)(x))[0])
58
+
59
+typedef struct FlicDecodeContext {
60
+    AVCodecContext *avctx;
61
+    AVFrame frame;
62
+    AVFrame prev_frame;
63
+
64
+    unsigned int palette[256];
65
+    int new_palette;
66
+    int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
67
+} FlicDecodeContext;
68
+
69
+static int flic_decode_init(AVCodecContext *avctx)
70
+{
71
+    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
72
+    unsigned char *fli_header = (unsigned char *)avctx->extradata;
73
+
74
+    s->avctx = avctx;
75
+    avctx->pix_fmt = PIX_FMT_PAL8;
76
+    avctx->has_b_frames = 0;
77
+
78
+    if (s->avctx->extradata_size == 12) {
79
+        /* special case for magic carpet FLIs */
80
+        s->fli_type = 0xAF13;
81
+    } else if (s->avctx->extradata_size == 128) {
82
+        s->fli_type = LE_16(&fli_header[4]);
83
+    } else {
84
+        printf (" FLI video: expected extradata of 12 or 128 bytes\n");
85
+        return -1;
86
+    }
87
+
88
+    s->frame.data[0] = s->prev_frame.data[0] = NULL;
89
+    s->new_palette = 0;
90
+
91
+    return 0;
92
+}
93
+
94
+static int flic_decode_frame(AVCodecContext *avctx,
95
+                             void *data, int *data_size,
96
+                             uint8_t *buf, int buf_size)
97
+{
98
+    FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
99
+
100
+    int stream_ptr = 0;
101
+    int stream_ptr_after_color_chunk;
102
+    int pixel_ptr;
103
+    int palette_ptr;
104
+    unsigned char palette_idx1;
105
+    unsigned char palette_idx2;
106
+
107
+    unsigned int frame_size;
108
+    int num_chunks;
109
+
110
+    unsigned int chunk_size;
111
+    int chunk_type;
112
+
113
+    int i, j;
114
+
115
+    int color_packets;
116
+    int color_changes;
117
+    int color_shift;
118
+    unsigned char r, g, b;
119
+
120
+    int lines;
121
+    int compressed_lines;
122
+    int starting_line;
123
+    signed short line_packets;
124
+    int y_ptr;
125
+    signed char byte_run;
126
+    int pixel_skip;
127
+    int pixel_countdown;
128
+    int height_countdown;
129
+    unsigned char *pixels;
130
+    unsigned char *prev_pixels;
131
+
132
+    s->frame.reference = 1;
133
+    if (avctx->get_buffer(avctx, &s->frame) < 0) {
134
+        fprintf(stderr, "  FLI: get_buffer() failed\n");
135
+        return -1;
136
+    }
137
+
138
+    pixels = s->frame.data[0];
139
+    prev_pixels = s->prev_frame.data[0];
140
+
141
+    frame_size = LE_32(&buf[stream_ptr]);
142
+    stream_ptr += 6;  /* skip the magic number */
143
+    num_chunks = LE_16(&buf[stream_ptr]);
144
+    stream_ptr += 10;  /* skip padding */
145
+
146
+    frame_size -= 16;
147
+
148
+    /* if there is no data, copy previous frame */
149
+    if (frame_size == 0) {
150
+        memcpy(pixels, prev_pixels, s->frame.linesize[0] * s->avctx->height);
151
+    }
152
+
153
+    /* iterate through the chunks */
154
+    while ((frame_size > 0) && (num_chunks > 0)) {
155
+        chunk_size = LE_32(&buf[stream_ptr]);
156
+        stream_ptr += 4;
157
+        chunk_type = LE_16(&buf[stream_ptr]);
158
+        stream_ptr += 2;
159
+
160
+        switch (chunk_type) {
161
+        case FLI_256_COLOR:
162
+        case FLI_COLOR:
163
+            stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
164
+            s->new_palette = 1;
165
+
166
+            /* check special case: If this file is from the Magic Carpet 
167
+             * game and uses 6-bit colors even though it reports 256-color 
168
+             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
169
+             * initialization) */
170
+            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != 0xAF13))
171
+                color_shift = 0;
172
+            else
173
+                color_shift = 2;
174
+            /* set up the palette */
175
+            color_packets = LE_16(&buf[stream_ptr]);
176
+            stream_ptr += 2;
177
+            palette_ptr = 0;
178
+            for (i = 0; i < color_packets; i++) {
179
+                /* first byte is how many colors to skip */
180
+                palette_ptr += buf[stream_ptr++];
181
+
182
+                /* next byte indicates how many entries to change */
183
+                color_changes = buf[stream_ptr++];
184
+
185
+                /* if there are 0 color changes, there are actually 256 */
186
+                if (color_changes == 0)
187
+                    color_changes = 256;
188
+
189
+                for (j = 0; j < color_changes; j++) {
190
+
191
+                    /* wrap around, for good measure */
192
+                    if (palette_ptr >= 256)
193
+                        palette_ptr = 0;
194
+
195
+                    r = buf[stream_ptr++] << color_shift;
196
+                    g = buf[stream_ptr++] << color_shift;
197
+                    b = buf[stream_ptr++] << color_shift;
198
+                    s->palette[palette_ptr++] = (r << 16) | (g << 8) | b;
199
+                }
200
+            }
201
+
202
+            /* color chunks sometimes have weird 16-bit alignment issues;
203
+             * therefore, take the hardline approach and set the stream_ptr
204
+             * to the value calculated w.r.t. the size specified by the color
205
+             * chunk header */
206
+            stream_ptr = stream_ptr_after_color_chunk;
207
+
208
+            break;
209
+
210
+        case FLI_DELTA:
211
+            y_ptr = 0;
212
+            height_countdown = s->avctx->height;
213
+            compressed_lines = LE_16(&buf[stream_ptr]);
214
+            stream_ptr += 2;
215
+            while (compressed_lines > 0) {
216
+                line_packets = LE_16(&buf[stream_ptr]);
217
+                stream_ptr += 2;
218
+                if (line_packets < 0) {
219
+                    line_packets = -line_packets;
220
+                    /* height_countdown was already decremented once on
221
+                     * this iteration */
222
+                    height_countdown -= line_packets;
223
+                    /* copy the skipped lines from the previous frame */
224
+                    while (line_packets--) {
225
+                        memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], 
226
+                            s->avctx->width);
227
+                        y_ptr += s->frame.linesize[0];
228
+                    }
229
+                } else {
230
+                    height_countdown--;
231
+                    compressed_lines--;
232
+                    pixel_ptr = y_ptr;
233
+                    pixel_countdown = s->avctx->width;
234
+                    for (i = 0; i < line_packets; i++) {
235
+                        /* account for the skip bytes */
236
+                        pixel_skip = buf[stream_ptr++];
237
+                        memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
238
+                            pixel_skip);
239
+                        pixel_ptr += pixel_skip;
240
+                        pixel_countdown -= pixel_skip;
241
+                        byte_run = buf[stream_ptr++];
242
+                        if (byte_run < 0) {
243
+                            byte_run = -byte_run;
244
+                            palette_idx1 = buf[stream_ptr++];
245
+                            palette_idx2 = buf[stream_ptr++];
246
+                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
247
+                                pixels[pixel_ptr++] = palette_idx1;
248
+                                pixels[pixel_ptr++] = palette_idx2;
249
+                            }
250
+                        } else {
251
+                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
252
+                                palette_idx1 = buf[stream_ptr++];
253
+                                pixels[pixel_ptr++] = palette_idx1;
254
+                            }
255
+                        }
256
+                    }
257
+
258
+                    /* copy the remaining pixels in the line from the
259
+                     * previous frame */
260
+                    memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
261
+                        pixel_countdown);
262
+
263
+                    y_ptr += s->frame.linesize[0];
264
+                }
265
+            }
266
+
267
+            /* copy the remainder of the lines from the previous frame */
268
+            while (height_countdown--) {
269
+                memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
270
+                y_ptr += s->frame.linesize[0];
271
+            }
272
+            break;
273
+
274
+        case FLI_LC:
275
+            /* line compressed */
276
+            height_countdown = s->avctx->height;
277
+            starting_line = LE_16(&buf[stream_ptr]);
278
+            stream_ptr += 2;
279
+
280
+            /* copy from the previous frame all of the lines prior to the
281
+             * starting line */
282
+            y_ptr = 0;
283
+            height_countdown -= starting_line;
284
+            while (starting_line--) {
285
+                memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
286
+                y_ptr += s->frame.linesize[0];
287
+            }
288
+
289
+            compressed_lines = LE_16(&buf[stream_ptr]);
290
+            stream_ptr += 2;
291
+            while (compressed_lines > 0) {
292
+                pixel_ptr = y_ptr;
293
+                pixel_countdown = s->avctx->width;
294
+                line_packets = buf[stream_ptr++];
295
+                if (line_packets > 0) {
296
+                    for (i = 0; i < line_packets; i++) {
297
+                        /* account for the skip bytes */
298
+                        pixel_skip = buf[stream_ptr++];
299
+                        memcpy(&pixels[pixel_ptr],
300
+                            &prev_pixels[pixel_ptr], pixel_skip);
301
+                        pixel_ptr += pixel_skip;
302
+                        pixel_countdown -= pixel_skip;
303
+                        byte_run = buf[stream_ptr++];
304
+                        if (byte_run > 0) {
305
+                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
306
+                                palette_idx1 = buf[stream_ptr++];
307
+                                pixels[pixel_ptr++] = palette_idx1;
308
+                            }
309
+                        } else {
310
+                            byte_run = -byte_run;
311
+                            palette_idx1 = buf[stream_ptr++];
312
+                            for (j = 0; j < byte_run; j++, pixel_countdown--) {
313
+                                pixels[pixel_ptr++] = palette_idx1;
314
+                            }
315
+                        }
316
+                    }
317
+                }
318
+
319
+                /* copy the remainder of the line from the previous frame */
320
+                memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
321
+                    pixel_countdown);
322
+
323
+                y_ptr += s->frame.linesize[0];
324
+                compressed_lines--;
325
+                height_countdown--;
326
+            }
327
+
328
+            /* copy the remainder of the lines from the previous frame */
329
+            while (height_countdown--) {
330
+                memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
331
+                y_ptr += s->frame.linesize[0];
332
+            }
333
+            break;
334
+
335
+        case FLI_BLACK:
336
+            /* set the whole frame to color 0 (which is usually black) */
337
+            memset(pixels, 0,
338
+                s->frame.linesize[0] * s->avctx->height);
339
+            break;
340
+
341
+        case FLI_BRUN:
342
+            /* Byte run compression: This chunk type only occurs in the first
343
+             * FLI frame and it will update the entire frame. */
344
+            y_ptr = 0;
345
+            for (lines = 0; lines < s->avctx->height; lines++) {
346
+                pixel_ptr = y_ptr;
347
+                /* disregard the line packets; instead, iterate through all
348
+                 * pixels on a row */
349
+                stream_ptr++;
350
+                pixel_countdown = s->avctx->width;
351
+                while (pixel_countdown > 0) {
352
+                    byte_run = buf[stream_ptr++];
353
+                    if (byte_run > 0) {
354
+                        palette_idx1 = buf[stream_ptr++];
355
+                        for (j = 0; j < byte_run; j++) {
356
+                            pixels[pixel_ptr++] = palette_idx1;
357
+                            pixel_countdown--;
358
+                            if (pixel_countdown < 0)
359
+                                printf ("fli warning: pixel_countdown < 0 (%d)\n",
360
+                                    pixel_countdown);
361
+                        }
362
+                    } else {  /* copy bytes if byte_run < 0 */
363
+                        byte_run = -byte_run;
364
+                        for (j = 0; j < byte_run; j++) {
365
+                            palette_idx1 = buf[stream_ptr++];
366
+                            pixels[pixel_ptr++] = palette_idx1;
367
+                            pixel_countdown--;
368
+                            if (pixel_countdown < 0)
369
+                                printf ("fli warning: pixel_countdown < 0 (%d)\n",
370
+                                    pixel_countdown);
371
+                        }
372
+                    }
373
+                }
374
+
375
+                y_ptr += s->frame.linesize[0];
376
+            }
377
+            break;
378
+
379
+        case FLI_COPY:
380
+            /* copy the chunk (uncompressed frame) to the ghost image and
381
+             * schedule the whole frame to be updated */
382
+            if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
383
+                printf(
384
+                "FLI: in chunk FLI_COPY : source data (%d bytes) bigger than" \
385
+                " image, skipping chunk\n",
386
+                chunk_size - 6);
387
+                stream_ptr += chunk_size - 6;
388
+            } else {
389
+                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
390
+                     y_ptr += s->frame.linesize[0]) {
391
+                    memcpy(&pixels[y_ptr], &buf[stream_ptr],
392
+                        s->avctx->width);
393
+                    stream_ptr += s->avctx->width;
394
+                }
395
+            }
396
+            break;
397
+
398
+        case FLI_MINI:
399
+            /* some sort of a thumbnail? disregard this chunk... */
400
+            stream_ptr += chunk_size - 6;
401
+            break;
402
+
403
+        default:
404
+            printf ("FLI: Unrecognized chunk type: %d\n", chunk_type);
405
+            break;
406
+        }
407
+
408
+        frame_size -= chunk_size;
409
+        num_chunks--;
410
+    }
411
+
412
+    /* by the end of the chunk, the stream ptr should equal the frame
413
+     * size (minus 1, possibly); if it doesn't, issue a warning */
414
+    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
415
+        printf ("  warning: processed FLI chunk where chunk size = %d\n" \
416
+                "    and final chunk ptr = %d\n",
417
+            buf_size, stream_ptr);
418
+
419
+    /* make the palette available on the way out */
420
+//    if (s->new_palette) {
421
+    if (1) {
422
+        memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
423
+        s->frame.palette_has_changed = 1;
424
+        s->new_palette = 0;
425
+    }
426
+
427
+    if (s->prev_frame.data[0])
428
+        avctx->release_buffer(avctx, &s->prev_frame);
429
+
430
+    /* shuffle frames */
431
+    s->prev_frame = s->frame;
432
+
433
+    *data_size=sizeof(AVFrame);
434
+    *(AVFrame*)data = s->frame;
435
+
436
+    return buf_size;
437
+}
438
+
439
+static int flic_decode_end(AVCodecContext *avctx)
440
+{
441
+    FlicDecodeContext *s = avctx->priv_data;
442
+
443
+    if (s->prev_frame.data[0])
444
+        avctx->release_buffer(avctx, &s->prev_frame);
445
+
446
+    return 0;
447
+}
448
+
449
+AVCodec flic_decoder = {
450
+    "flic",
451
+    CODEC_TYPE_VIDEO,
452
+    CODEC_ID_FLIC,
453
+    sizeof(FlicDecodeContext),
454
+    flic_decode_init,
455
+    NULL,
456
+    flic_decode_end,
457
+    flic_decode_frame,
458
+    CODEC_CAP_DR1,
459
+    NULL
460
+};
... ...
@@ -15,7 +15,7 @@ PPOBJS=
15 15
 OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o raw.o rm.o \
16 16
       avienc.o avidec.o wav.o swf.o au.o gif.o mov.o mpjpeg.o dv.o \
17 17
       yuv4mpeg.o 4xm.o flvenc.o flvdec.o movenc.o psxstr.o idroq.o ipmovie.o \
18
-      nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o
18
+      nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o
19 19
 
20 20
 ifeq ($(CONFIG_RISKY),yes)
21 21
 OBJS+= asf.o
... ...
@@ -69,6 +69,7 @@ void av_register_all(void)
69 69
     westwood_init();
70 70
     film_init();
71 71
     idcin_init();
72
+    flic_init();
72 73
 
73 74
 #if defined(AMR_NB) || defined(AMR_NB_FIXED) || defined(AMR_WB)
74 75
     amr_init();
... ...
@@ -479,6 +479,9 @@ int film_init(void);
479 479
 /* idcin.c */
480 480
 int idcin_init(void);
481 481
 
482
+/* flic.c */
483
+int flic_init(void);
484
+
482 485
 #include "rtp.h"
483 486
 
484 487
 #include "rtsp.h"
485 488
new file mode 100644
... ...
@@ -0,0 +1,228 @@
0
+/*
1
+ * FLI/FLC Animation File Demuxer
2
+ * Copyright (c) 2003 The ffmpeg Project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ */
18
+
19
+/**
20
+ * @file flic.c
21
+ * FLI/FLC file demuxer
22
+ * by Mike Melanson (melanson@pcisys.net)
23
+ * for more information on the .fli/.flc file format and all of its many
24
+ * variations, visit:
25
+ *   http://www.compuphase.com/flic.htm
26
+ *
27
+ * This demuxer handles standard 0xAF11- and 0xAF12-type FLIs. It also
28
+ * handles special FLIs from the PC game "Magic Carpet".
29
+ */
30
+
31
+#include "avformat.h"
32
+
33
+#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
34
+#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
35
+                   (((uint8_t*)(x))[2] << 16) | \
36
+                   (((uint8_t*)(x))[1] << 8) | \
37
+                    ((uint8_t*)(x))[0])
38
+
39
+#define FLIC_FILE_MAGIC_1 0xAF11
40
+#define FLIC_FILE_MAGIC_2 0xAF12
41
+#define FLIC_CHUNK_MAGIC_1 0xF1FA
42
+#define FLIC_CHUNK_MAGIC_2 0xF5FA
43
+#define FLIC_MC_PTS_INC 6000  /* pts increment for Magic Carpet game FLIs */
44
+#define FLIC_DEFAULT_PTS_INC 6000  /* for FLIs that have 0 speed */
45
+
46
+#define FLIC_HEADER_SIZE 128
47
+#define FLIC_PREAMBLE_SIZE 6
48
+
49
+typedef struct FlicDemuxContext {
50
+    int frame_pts_inc;
51
+    int64_t pts;
52
+    int video_stream_index;
53
+} FlicDemuxContext;
54
+
55
+static int flic_probe(AVProbeData *p)
56
+{
57
+    int magic_number;
58
+
59
+    if (p->buf_size < 6)
60
+        return 0;
61
+
62
+    magic_number = LE_16(&p->buf[4]);
63
+    if ((magic_number != FLIC_FILE_MAGIC_1) &&
64
+        (magic_number != FLIC_FILE_MAGIC_2))
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)
84
+        return -EIO;
85
+
86
+    magic_number = LE_16(&header[4]);
87
+    speed = LE_32(&header[0x10]);
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;
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]);
99
+
100
+    if (!st->codec.width || !st->codec.height)
101
+        return AVERROR_INVALIDDATA;
102
+
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);
107
+
108
+    /* set the pts reference (1 pts = 1/90000) */
109
+    s->pts_num = 1;
110
+    s->pts_den = 90000;
111
+
112
+    /* Time to figure out the framerate: If there is a FLIC chunk magic
113
+     * number at offset 0x10, assume this is from the Bullfrog game,
114
+     * Magic Carpet. */
115
+    if (LE_16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
116
+
117
+        flic->frame_pts_inc = FLIC_MC_PTS_INC;
118
+
119
+        /* rewind the stream since the first chunk is at offset 12 */
120
+        url_fseek(pb, 12, SEEK_SET);
121
+
122
+        /* send over abbreviated FLIC header chunk */
123
+        av_free(st->codec.extradata);
124
+        st->codec.extradata_size = 12;
125
+        st->codec.extradata = av_malloc(12);
126
+        memcpy(st->codec.extradata, header, 12);
127
+
128
+    } else if (magic_number == FLIC_FILE_MAGIC_1) {
129
+        /*
130
+         * in this case, the speed (n) is number of 1/70s ticks between frames:
131
+         *
132
+         *    pts        n * frame #
133
+         *  --------  =  -----------  => pts = n * (90000/70) * frame #
134
+         *   90000           70
135
+         *
136
+         *  therefore, the frame pts increment = n * 1285.7
137
+         */
138
+        flic->frame_pts_inc = speed * 1285.7;
139
+    } else if (magic_number == FLIC_FILE_MAGIC_2) {
140
+        /*
141
+         * in this case, the speed (n) is number of milliseconds between frames:
142
+         *
143
+         *    pts        n * frame #
144
+         *  --------  =  -----------  => pts = n * 90 * frame #
145
+         *   90000          1000
146
+         *
147
+         *  therefore, the frame pts increment = n * 90
148
+         */
149
+        flic->frame_pts_inc = speed * 90;
150
+    } else
151
+        return AVERROR_INVALIDDATA;
152
+
153
+    if (flic->frame_pts_inc == 0)
154
+        flic->frame_pts_inc = FLIC_DEFAULT_PTS_INC;
155
+
156
+    return 0;
157
+}
158
+
159
+static int flic_read_packet(AVFormatContext *s,
160
+                            AVPacket *pkt)
161
+{
162
+    FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
163
+    ByteIOContext *pb = &s->pb;
164
+    int packet_read = 0;
165
+    unsigned int size;
166
+    int magic;
167
+    int ret = 0;
168
+    unsigned char preamble[FLIC_PREAMBLE_SIZE];
169
+
170
+    while (!packet_read) {
171
+
172
+        if ((ret = get_buffer(pb, preamble, FLIC_PREAMBLE_SIZE)) !=
173
+            FLIC_PREAMBLE_SIZE) {
174
+            ret = -EIO;
175
+            break;
176
+        }
177
+
178
+        size = LE_32(&preamble[0]);
179
+        magic = LE_16(&preamble[4]);
180
+
181
+        if ((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) {
182
+            if (av_new_packet(pkt, size)) {
183
+                ret = -EIO;
184
+                break;
185
+            }
186
+            pkt->stream_index = flic->video_stream_index;
187
+            pkt->pts = flic->pts;
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) {
192
+                av_free_packet(pkt);
193
+                ret = -EIO;
194
+            }
195
+            flic->pts += flic->frame_pts_inc;
196
+            packet_read = 1;
197
+        } else {
198
+            /* not interested in this chunk */
199
+            url_fseek(pb, size - 6, SEEK_CUR);
200
+        }
201
+    }
202
+
203
+    return ret;
204
+}
205
+
206
+static int flic_read_close(AVFormatContext *s)
207
+{
208
+//    FlicDemuxContext *flic = (FlicDemuxContext *)s->priv_data;
209
+
210
+    return 0;
211
+}
212
+
213
+static AVInputFormat flic_iformat = {
214
+    "flic",
215
+    "FLI/FLC animation format",
216
+    sizeof(FlicDemuxContext),
217
+    flic_probe,
218
+    flic_read_header,
219
+    flic_read_packet,
220
+    flic_read_close,
221
+};
222
+
223
+int flic_init(void)
224
+{
225
+    av_register_input_format(&flic_iformat);
226
+    return 0;
227
+}