b5cd366b9689f34b83e990404bc4d9a0b235c16d
[ffmpeg.git] / libavcodec / flicvideo.c
1 /*
2  * FLI/FLC Animation Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 /**
22  * @file flic.c
23  * Autodesk Animator FLI/FLC Video Decoder
24  * by Mike Melanson (melanson@pcisys.net)
25  * for more information on the .fli/.flc file format and all of its many
26  * variations, visit:
27  *   http://www.compuphase.com/flic.htm
28  *
29  * This decoder outputs PAL8 colorspace data. To use this decoder, be
30  * sure that your demuxer sends the FLI file header to the decoder via
31  * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
32  * large. The only exception is for FLI files from the game "Magic Carpet",
33  * in which the header is only 12 bytes.
34  */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "common.h"
42 #include "avcodec.h"
43 #include "bswap.h"
44
45 #define FLI_256_COLOR 4
46 #define FLI_DELTA     7
47 #define FLI_COLOR     11
48 #define FLI_LC        12
49 #define FLI_BLACK     13
50 #define FLI_BRUN      15
51 #define FLI_COPY      16
52 #define FLI_MINI      18
53
54 #define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
55 #define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
56                    (((uint8_t*)(x))[2] << 16) | \
57                    (((uint8_t*)(x))[1] << 8) | \
58                     ((uint8_t*)(x))[0])
59
60 typedef struct FlicDecodeContext {
61     AVCodecContext *avctx;
62     AVFrame frame;
63     AVFrame prev_frame;
64
65     unsigned int palette[256];
66     int new_palette;
67     int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
68 } FlicDecodeContext;
69
70 static int flic_decode_init(AVCodecContext *avctx)
71 {
72     FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
73     unsigned char *fli_header = (unsigned char *)avctx->extradata;
74
75     s->avctx = avctx;
76     avctx->pix_fmt = PIX_FMT_PAL8;
77     avctx->has_b_frames = 0;
78
79     if (s->avctx->extradata_size == 12) {
80         /* special case for magic carpet FLIs */
81         s->fli_type = 0xAF13;
82     } else if (s->avctx->extradata_size == 128) {
83         s->fli_type = LE_16(&fli_header[4]);
84     } else {
85         printf (" FLI video: expected extradata of 12 or 128 bytes\n");
86         return -1;
87     }
88
89     s->frame.data[0] = s->prev_frame.data[0] = NULL;
90     s->new_palette = 0;
91
92     return 0;
93 }
94
95 static int flic_decode_frame(AVCodecContext *avctx,
96                              void *data, int *data_size,
97                              uint8_t *buf, int buf_size)
98 {
99     FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
100
101     int stream_ptr = 0;
102     int stream_ptr_after_color_chunk;
103     int pixel_ptr;
104     int palette_ptr;
105     unsigned char palette_idx1;
106     unsigned char palette_idx2;
107
108     unsigned int frame_size;
109     int num_chunks;
110
111     unsigned int chunk_size;
112     int chunk_type;
113
114     int i, j;
115
116     int color_packets;
117     int color_changes;
118     int color_shift;
119     unsigned char r, g, b;
120
121     int lines;
122     int compressed_lines;
123     int starting_line;
124     signed short line_packets;
125     int y_ptr;
126     signed char byte_run;
127     int pixel_skip;
128     int pixel_countdown;
129     int height_countdown;
130     unsigned char *pixels;
131     unsigned char *prev_pixels;
132
133     s->frame.reference = 1;
134     if (avctx->get_buffer(avctx, &s->frame) < 0) {
135         fprintf(stderr, "  FLI: get_buffer() failed\n");
136         return -1;
137     }
138
139     pixels = s->frame.data[0];
140     prev_pixels = s->prev_frame.data[0];
141
142     frame_size = LE_32(&buf[stream_ptr]);
143     stream_ptr += 6;  /* skip the magic number */
144     num_chunks = LE_16(&buf[stream_ptr]);
145     stream_ptr += 10;  /* skip padding */
146
147     frame_size -= 16;
148
149     /* if there is no data, copy previous frame */
150     if (frame_size == 0) {
151         memcpy(pixels, prev_pixels, s->frame.linesize[0] * s->avctx->height);
152     }
153
154     /* iterate through the chunks */
155     while ((frame_size > 0) && (num_chunks > 0)) {
156         chunk_size = LE_32(&buf[stream_ptr]);
157         stream_ptr += 4;
158         chunk_type = LE_16(&buf[stream_ptr]);
159         stream_ptr += 2;
160
161         switch (chunk_type) {
162         case FLI_256_COLOR:
163         case FLI_COLOR:
164             stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
165             s->new_palette = 1;
166
167             /* check special case: If this file is from the Magic Carpet 
168              * game and uses 6-bit colors even though it reports 256-color 
169              * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
170              * initialization) */
171             if ((chunk_type == FLI_256_COLOR) && (s->fli_type != 0xAF13))
172                 color_shift = 0;
173             else
174                 color_shift = 2;
175             /* set up the palette */
176             color_packets = LE_16(&buf[stream_ptr]);
177             stream_ptr += 2;
178             palette_ptr = 0;
179             for (i = 0; i < color_packets; i++) {
180                 /* first byte is how many colors to skip */
181                 palette_ptr += buf[stream_ptr++];
182
183                 /* next byte indicates how many entries to change */
184                 color_changes = buf[stream_ptr++];
185
186                 /* if there are 0 color changes, there are actually 256 */
187                 if (color_changes == 0)
188                     color_changes = 256;
189
190                 for (j = 0; j < color_changes; j++) {
191
192                     /* wrap around, for good measure */
193                     if (palette_ptr >= 256)
194                         palette_ptr = 0;
195
196                     r = buf[stream_ptr++] << color_shift;
197                     g = buf[stream_ptr++] << color_shift;
198                     b = buf[stream_ptr++] << color_shift;
199                     s->palette[palette_ptr++] = (r << 16) | (g << 8) | b;
200                 }
201             }
202
203             /* color chunks sometimes have weird 16-bit alignment issues;
204              * therefore, take the hardline approach and set the stream_ptr
205              * to the value calculated w.r.t. the size specified by the color
206              * chunk header */
207             stream_ptr = stream_ptr_after_color_chunk;
208
209             break;
210
211         case FLI_DELTA:
212             y_ptr = 0;
213             height_countdown = s->avctx->height;
214             compressed_lines = LE_16(&buf[stream_ptr]);
215             stream_ptr += 2;
216             while (compressed_lines > 0) {
217                 line_packets = LE_16(&buf[stream_ptr]);
218                 stream_ptr += 2;
219                 if (line_packets < 0) {
220                     line_packets = -line_packets;
221                     /* height_countdown was already decremented once on
222                      * this iteration */
223                     height_countdown -= line_packets;
224                     /* copy the skipped lines from the previous frame */
225                     while (line_packets--) {
226                         memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], 
227                             s->avctx->width);
228                         y_ptr += s->frame.linesize[0];
229                     }
230                 } else {
231                     height_countdown--;
232                     compressed_lines--;
233                     pixel_ptr = y_ptr;
234                     pixel_countdown = s->avctx->width;
235                     for (i = 0; i < line_packets; i++) {
236                         /* account for the skip bytes */
237                         pixel_skip = buf[stream_ptr++];
238                         memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
239                             pixel_skip);
240                         pixel_ptr += pixel_skip;
241                         pixel_countdown -= pixel_skip;
242                         byte_run = buf[stream_ptr++];
243                         if (byte_run < 0) {
244                             byte_run = -byte_run;
245                             palette_idx1 = buf[stream_ptr++];
246                             palette_idx2 = buf[stream_ptr++];
247                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
248                                 pixels[pixel_ptr++] = palette_idx1;
249                                 pixels[pixel_ptr++] = palette_idx2;
250                             }
251                         } else {
252                             for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
253                                 palette_idx1 = buf[stream_ptr++];
254                                 pixels[pixel_ptr++] = palette_idx1;
255                             }
256                         }
257                     }
258
259                     /* copy the remaining pixels in the line from the
260                      * previous frame */
261                     memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
262                         pixel_countdown);
263
264                     y_ptr += s->frame.linesize[0];
265                 }
266             }
267
268             /* copy the remainder of the lines from the previous frame */
269             while (height_countdown--) {
270                 memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
271                 y_ptr += s->frame.linesize[0];
272             }
273             break;
274
275         case FLI_LC:
276             /* line compressed */
277             height_countdown = s->avctx->height;
278             starting_line = LE_16(&buf[stream_ptr]);
279             stream_ptr += 2;
280
281             /* copy from the previous frame all of the lines prior to the
282              * starting line */
283             y_ptr = 0;
284             height_countdown -= starting_line;
285             while (starting_line--) {
286                 memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
287                 y_ptr += s->frame.linesize[0];
288             }
289
290             compressed_lines = LE_16(&buf[stream_ptr]);
291             stream_ptr += 2;
292             while (compressed_lines > 0) {
293                 pixel_ptr = y_ptr;
294                 pixel_countdown = s->avctx->width;
295                 line_packets = buf[stream_ptr++];
296                 if (line_packets > 0) {
297                     for (i = 0; i < line_packets; i++) {
298                         /* account for the skip bytes */
299                         pixel_skip = buf[stream_ptr++];
300                         memcpy(&pixels[pixel_ptr],
301                             &prev_pixels[pixel_ptr], pixel_skip);
302                         pixel_ptr += pixel_skip;
303                         pixel_countdown -= pixel_skip;
304                         byte_run = buf[stream_ptr++];
305                         if (byte_run > 0) {
306                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
307                                 palette_idx1 = buf[stream_ptr++];
308                                 pixels[pixel_ptr++] = palette_idx1;
309                             }
310                         } else {
311                             byte_run = -byte_run;
312                             palette_idx1 = buf[stream_ptr++];
313                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
314                                 pixels[pixel_ptr++] = palette_idx1;
315                             }
316                         }
317                     }
318                 }
319
320                 /* copy the remainder of the line from the previous frame */
321                 memcpy(&pixels[pixel_ptr], &prev_pixels[pixel_ptr],
322                     pixel_countdown);
323
324                 y_ptr += s->frame.linesize[0];
325                 compressed_lines--;
326                 height_countdown--;
327             }
328
329             /* copy the remainder of the lines from the previous frame */
330             while (height_countdown--) {
331                 memcpy(&pixels[y_ptr], &prev_pixels[y_ptr], s->avctx->width);
332                 y_ptr += s->frame.linesize[0];
333             }
334             break;
335
336         case FLI_BLACK:
337             /* set the whole frame to color 0 (which is usually black) */
338             memset(pixels, 0,
339                 s->frame.linesize[0] * s->avctx->height);
340             break;
341
342         case FLI_BRUN:
343             /* Byte run compression: This chunk type only occurs in the first
344              * FLI frame and it will update the entire frame. */
345             y_ptr = 0;
346             for (lines = 0; lines < s->avctx->height; lines++) {
347                 pixel_ptr = y_ptr;
348                 /* disregard the line packets; instead, iterate through all
349                  * pixels on a row */
350                 stream_ptr++;
351                 pixel_countdown = s->avctx->width;
352                 while (pixel_countdown > 0) {
353                     byte_run = buf[stream_ptr++];
354                     if (byte_run > 0) {
355                         palette_idx1 = buf[stream_ptr++];
356                         for (j = 0; j < byte_run; j++) {
357                             pixels[pixel_ptr++] = palette_idx1;
358                             pixel_countdown--;
359                             if (pixel_countdown < 0)
360                                 printf ("fli warning: pixel_countdown < 0 (%d)\n",
361                                     pixel_countdown);
362                         }
363                     } else {  /* copy bytes if byte_run < 0 */
364                         byte_run = -byte_run;
365                         for (j = 0; j < byte_run; j++) {
366                             palette_idx1 = buf[stream_ptr++];
367                             pixels[pixel_ptr++] = palette_idx1;
368                             pixel_countdown--;
369                             if (pixel_countdown < 0)
370                                 printf ("fli warning: pixel_countdown < 0 (%d)\n",
371                                     pixel_countdown);
372                         }
373                     }
374                 }
375
376                 y_ptr += s->frame.linesize[0];
377             }
378             break;
379
380         case FLI_COPY:
381             /* copy the chunk (uncompressed frame) to the ghost image and
382              * schedule the whole frame to be updated */
383             if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
384                 printf(
385                 "FLI: in chunk FLI_COPY : source data (%d bytes) bigger than" \
386                 " image, skipping chunk\n",
387                 chunk_size - 6);
388                 stream_ptr += chunk_size - 6;
389             } else {
390                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
391                      y_ptr += s->frame.linesize[0]) {
392                     memcpy(&pixels[y_ptr], &buf[stream_ptr],
393                         s->avctx->width);
394                     stream_ptr += s->avctx->width;
395                 }
396             }
397             break;
398
399         case FLI_MINI:
400             /* some sort of a thumbnail? disregard this chunk... */
401             stream_ptr += chunk_size - 6;
402             break;
403
404         default:
405             printf ("FLI: Unrecognized chunk type: %d\n", chunk_type);
406             break;
407         }
408
409         frame_size -= chunk_size;
410         num_chunks--;
411     }
412
413     /* by the end of the chunk, the stream ptr should equal the frame
414      * size (minus 1, possibly); if it doesn't, issue a warning */
415     if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
416         printf ("  warning: processed FLI chunk where chunk size = %d\n" \
417                 "    and final chunk ptr = %d\n",
418             buf_size, stream_ptr);
419
420     /* make the palette available on the way out */
421 //    if (s->new_palette) {
422     if (1) {
423         memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
424         s->frame.palette_has_changed = 1;
425         s->new_palette = 0;
426     }
427
428     if (s->prev_frame.data[0])
429         avctx->release_buffer(avctx, &s->prev_frame);
430
431     /* shuffle frames */
432     s->prev_frame = s->frame;
433
434     *data_size=sizeof(AVFrame);
435     *(AVFrame*)data = s->frame;
436
437     return buf_size;
438 }
439
440 static int flic_decode_end(AVCodecContext *avctx)
441 {
442     FlicDecodeContext *s = avctx->priv_data;
443
444     if (s->prev_frame.data[0])
445         avctx->release_buffer(avctx, &s->prev_frame);
446
447     return 0;
448 }
449
450 AVCodec flic_decoder = {
451     "flic",
452     CODEC_TYPE_VIDEO,
453     CODEC_ID_FLIC,
454     sizeof(FlicDecodeContext),
455     flic_decode_init,
456     NULL,
457     flic_decode_end,
458     flic_decode_frame,
459     CODEC_CAP_DR1,
460     NULL
461 };