]> git.sesse.net Git - ffmpeg/blob - libavcodec/flicvideo.c
revert bad checkin
[ffmpeg] / libavcodec / flicvideo.c
1 /*
2  * FLI/FLC Animation Video Decoder
3  * Copyright (C) 2003, 2004 the ffmpeg project
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 /**
24  * @file flic.c
25  * Autodesk Animator FLI/FLC Video Decoder
26  * by Mike Melanson (melanson@pcisys.net)
27  * for more information on the .fli/.flc file format and all of its many
28  * variations, visit:
29  *   http://www.compuphase.com/flic.htm
30  *
31  * This decoder outputs PAL8/RGB555/RGB565 and maybe one day RGB24
32  * colorspace data, depending on the FLC. To use this decoder, be
33  * sure that your demuxer sends the FLI file header to the decoder via
34  * the extradata chunk in AVCodecContext. The chunk should be 128 bytes
35  * large. The only exception is for FLI files from the game "Magic Carpet",
36  * in which the header is only 12 bytes.
37  */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include "common.h"
45 #include "avcodec.h"
46 #include "bswap.h"
47
48 #define FLI_256_COLOR 4
49 #define FLI_DELTA     7
50 #define FLI_COLOR     11
51 #define FLI_LC        12
52 #define FLI_BLACK     13
53 #define FLI_BRUN      15
54 #define FLI_COPY      16
55 #define FLI_MINI      18
56 #define FLI_DTA_BRUN  25
57 #define FLI_DTA_COPY  26
58 #define FLI_DTA_LC    27
59
60 #define FLI_TYPE_CODE     (0xAF11)
61 #define FLC_FLX_TYPE_CODE (0xAF12)
62 #define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */
63 #define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13)
64
65 #define CHECK_PIXEL_PTR(n) \
66     if (pixel_ptr + n > pixel_limit) { \
67         av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
68         pixel_ptr + n, pixel_limit); \
69         return -1; \
70     } \
71
72 typedef struct FlicDecodeContext {
73     AVCodecContext *avctx;
74     AVFrame frame;
75
76     unsigned int palette[256];
77     int new_palette;
78     int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
79 } FlicDecodeContext;
80
81 static int flic_decode_init(AVCodecContext *avctx)
82 {
83     FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
84     unsigned char *fli_header = (unsigned char *)avctx->extradata;
85     int depth;
86
87     s->avctx = avctx;
88     avctx->has_b_frames = 0;
89
90     s->fli_type = LE_16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
91     depth       = LE_16(&fli_header[12]);
92
93     if (depth == 0) {
94       depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
95     }
96
97     if (s->avctx->extradata_size == 12) {
98         /* special case for magic carpet FLIs */
99         s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
100     } else if (s->avctx->extradata_size != 128) {
101         av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
102         return -1;
103     }
104
105     if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
106         depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
107     }
108
109     switch (depth) {
110         case 8  : avctx->pix_fmt = PIX_FMT_PAL8; break;
111         case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
112         case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
113         case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
114                   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
115                   return -1;
116                   break;
117         default :
118                   av_log(avctx, AV_LOG_ERROR, "Unkown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
119                   return -1;
120     }
121
122     s->frame.data[0] = NULL;
123     s->new_palette = 0;
124
125     return 0;
126 }
127
128 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
129                                   void *data, int *data_size,
130                                   uint8_t *buf, int buf_size)
131 {
132     FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
133
134     int stream_ptr = 0;
135     int stream_ptr_after_color_chunk;
136     int pixel_ptr;
137     int palette_ptr;
138     unsigned char palette_idx1;
139     unsigned char palette_idx2;
140
141     unsigned int frame_size;
142     int num_chunks;
143
144     unsigned int chunk_size;
145     int chunk_type;
146
147     int i, j;
148
149     int color_packets;
150     int color_changes;
151     int color_shift;
152     unsigned char r, g, b;
153
154     int lines;
155     int compressed_lines;
156     int starting_line;
157     signed short line_packets;
158     int y_ptr;
159     signed char byte_run;
160     int pixel_skip;
161     int pixel_countdown;
162     unsigned char *pixels;
163     int pixel_limit;
164
165     s->frame.reference = 1;
166     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
167     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
168         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
169         return -1;
170     }
171
172     pixels = s->frame.data[0];
173     pixel_limit = s->avctx->height * s->frame.linesize[0];
174
175     frame_size = LE_32(&buf[stream_ptr]);
176     stream_ptr += 6;  /* skip the magic number */
177     num_chunks = LE_16(&buf[stream_ptr]);
178     stream_ptr += 10;  /* skip padding */
179
180     frame_size -= 16;
181
182     /* iterate through the chunks */
183     while ((frame_size > 0) && (num_chunks > 0)) {
184         chunk_size = LE_32(&buf[stream_ptr]);
185         stream_ptr += 4;
186         chunk_type = LE_16(&buf[stream_ptr]);
187         stream_ptr += 2;
188
189         switch (chunk_type) {
190         case FLI_256_COLOR:
191         case FLI_COLOR:
192             stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
193
194             /* check special case: If this file is from the Magic Carpet
195              * game and uses 6-bit colors even though it reports 256-color
196              * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
197              * initialization) */
198             if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
199                 color_shift = 0;
200             else
201                 color_shift = 2;
202             /* set up the palette */
203             color_packets = LE_16(&buf[stream_ptr]);
204             stream_ptr += 2;
205             palette_ptr = 0;
206             for (i = 0; i < color_packets; i++) {
207                 /* first byte is how many colors to skip */
208                 palette_ptr += buf[stream_ptr++];
209
210                 /* next byte indicates how many entries to change */
211                 color_changes = buf[stream_ptr++];
212
213                 /* if there are 0 color changes, there are actually 256 */
214                 if (color_changes == 0)
215                     color_changes = 256;
216
217                 for (j = 0; j < color_changes; j++) {
218                     unsigned int entry;
219
220                     /* wrap around, for good measure */
221                     if ((unsigned)palette_ptr >= 256)
222                         palette_ptr = 0;
223
224                     r = buf[stream_ptr++] << color_shift;
225                     g = buf[stream_ptr++] << color_shift;
226                     b = buf[stream_ptr++] << color_shift;
227                     entry = (r << 16) | (g << 8) | b;
228                     if (s->palette[palette_ptr] != entry)
229                         s->new_palette = 1;
230                     s->palette[palette_ptr++] = entry;
231                 }
232             }
233
234             /* color chunks sometimes have weird 16-bit alignment issues;
235              * therefore, take the hardline approach and set the stream_ptr
236              * to the value calculated w.r.t. the size specified by the color
237              * chunk header */
238             stream_ptr = stream_ptr_after_color_chunk;
239
240             break;
241
242         case FLI_DELTA:
243             y_ptr = 0;
244             compressed_lines = LE_16(&buf[stream_ptr]);
245             stream_ptr += 2;
246             while (compressed_lines > 0) {
247                 line_packets = LE_16(&buf[stream_ptr]);
248                 stream_ptr += 2;
249                 if (line_packets < 0) {
250                     line_packets = -line_packets;
251                     y_ptr += line_packets * s->frame.linesize[0];
252                 } else {
253                     compressed_lines--;
254                     pixel_ptr = y_ptr;
255                     pixel_countdown = s->avctx->width;
256                     for (i = 0; i < line_packets; i++) {
257                         /* account for the skip bytes */
258                         pixel_skip = buf[stream_ptr++];
259                         pixel_ptr += pixel_skip;
260                         pixel_countdown -= pixel_skip;
261                         byte_run = buf[stream_ptr++];
262                         if (byte_run < 0) {
263                             byte_run = -byte_run;
264                             palette_idx1 = buf[stream_ptr++];
265                             palette_idx2 = buf[stream_ptr++];
266                             CHECK_PIXEL_PTR(byte_run);
267                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
268                                 pixels[pixel_ptr++] = palette_idx1;
269                                 pixels[pixel_ptr++] = palette_idx2;
270                             }
271                         } else {
272                             CHECK_PIXEL_PTR(byte_run * 2);
273                             for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
274                                 palette_idx1 = buf[stream_ptr++];
275                                 pixels[pixel_ptr++] = palette_idx1;
276                             }
277                         }
278                     }
279
280                     y_ptr += s->frame.linesize[0];
281                 }
282             }
283             break;
284
285         case FLI_LC:
286             /* line compressed */
287             starting_line = LE_16(&buf[stream_ptr]);
288             stream_ptr += 2;
289             y_ptr = 0;
290             y_ptr += starting_line * s->frame.linesize[0];
291
292             compressed_lines = LE_16(&buf[stream_ptr]);
293             stream_ptr += 2;
294             while (compressed_lines > 0) {
295                 pixel_ptr = y_ptr;
296                 pixel_countdown = s->avctx->width;
297                 line_packets = buf[stream_ptr++];
298                 if (line_packets > 0) {
299                     for (i = 0; i < line_packets; i++) {
300                         /* account for the skip bytes */
301                         pixel_skip = buf[stream_ptr++];
302                         pixel_ptr += pixel_skip;
303                         pixel_countdown -= pixel_skip;
304                         byte_run = buf[stream_ptr++];
305                         if (byte_run > 0) {
306                             CHECK_PIXEL_PTR(byte_run);
307                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
308                                 palette_idx1 = buf[stream_ptr++];
309                                 pixels[pixel_ptr++] = palette_idx1;
310                             }
311                         } else {
312                             byte_run = -byte_run;
313                             palette_idx1 = buf[stream_ptr++];
314                             CHECK_PIXEL_PTR(byte_run);
315                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
316                                 pixels[pixel_ptr++] = palette_idx1;
317                             }
318                         }
319                     }
320                 }
321
322                 y_ptr += s->frame.linesize[0];
323                 compressed_lines--;
324             }
325             break;
326
327         case FLI_BLACK:
328             /* set the whole frame to color 0 (which is usually black) */
329             memset(pixels, 0,
330                 s->frame.linesize[0] * s->avctx->height);
331             break;
332
333         case FLI_BRUN:
334             /* Byte run compression: This chunk type only occurs in the first
335              * FLI frame and it will update the entire frame. */
336             y_ptr = 0;
337             for (lines = 0; lines < s->avctx->height; lines++) {
338                 pixel_ptr = y_ptr;
339                 /* disregard the line packets; instead, iterate through all
340                  * pixels on a row */
341                 stream_ptr++;
342                 pixel_countdown = s->avctx->width;
343                 while (pixel_countdown > 0) {
344                     byte_run = buf[stream_ptr++];
345                     if (byte_run > 0) {
346                         palette_idx1 = buf[stream_ptr++];
347                         CHECK_PIXEL_PTR(byte_run);
348                         for (j = 0; j < byte_run; j++) {
349                             pixels[pixel_ptr++] = palette_idx1;
350                             pixel_countdown--;
351                             if (pixel_countdown < 0)
352                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
353                                        pixel_countdown);
354                         }
355                     } else {  /* copy bytes if byte_run < 0 */
356                         byte_run = -byte_run;
357                         CHECK_PIXEL_PTR(byte_run);
358                         for (j = 0; j < byte_run; j++) {
359                             palette_idx1 = buf[stream_ptr++];
360                             pixels[pixel_ptr++] = palette_idx1;
361                             pixel_countdown--;
362                             if (pixel_countdown < 0)
363                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
364                                        pixel_countdown);
365                         }
366                     }
367                 }
368
369                 y_ptr += s->frame.linesize[0];
370             }
371             break;
372
373         case FLI_COPY:
374             /* copy the chunk (uncompressed frame) */
375             if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
376                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
377                        "bigger than image, skipping chunk\n", chunk_size - 6);
378                 stream_ptr += chunk_size - 6;
379             } else {
380                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
381                      y_ptr += s->frame.linesize[0]) {
382                     memcpy(&pixels[y_ptr], &buf[stream_ptr],
383                         s->avctx->width);
384                     stream_ptr += s->avctx->width;
385                 }
386             }
387             break;
388
389         case FLI_MINI:
390             /* some sort of a thumbnail? disregard this chunk... */
391             stream_ptr += chunk_size - 6;
392             break;
393
394         default:
395             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
396             break;
397         }
398
399         frame_size -= chunk_size;
400         num_chunks--;
401     }
402
403     /* by the end of the chunk, the stream ptr should equal the frame
404      * size (minus 1, possibly); if it doesn't, issue a warning */
405     if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
406         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
407                "and final chunk ptr = %d\n", buf_size, stream_ptr);
408
409     /* make the palette available on the way out */
410     memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
411     if (s->new_palette) {
412         s->frame.palette_has_changed = 1;
413         s->new_palette = 0;
414     }
415
416     *data_size=sizeof(AVFrame);
417     *(AVFrame*)data = s->frame;
418
419     return buf_size;
420 }
421
422 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
423                                       void *data, int *data_size,
424                                       uint8_t *buf, int buf_size)
425 {
426     /* Note, the only difference between the 15Bpp and 16Bpp */
427     /* Format is the pixel format, the packets are processed the same. */
428     FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
429
430     int stream_ptr = 0;
431     int pixel_ptr;
432     unsigned char palette_idx1;
433
434     unsigned int frame_size;
435     int num_chunks;
436
437     unsigned int chunk_size;
438     int chunk_type;
439
440     int i, j;
441
442     int lines;
443     int compressed_lines;
444     signed short line_packets;
445     int y_ptr;
446     signed char byte_run;
447     int pixel_skip;
448     int pixel_countdown;
449     unsigned char *pixels;
450     int pixel;
451     int pixel_limit;
452
453     s->frame.reference = 1;
454     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
455     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
456         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
457         return -1;
458     }
459
460     pixels = s->frame.data[0];
461     pixel_limit = s->avctx->height * s->frame.linesize[0];
462
463     frame_size = LE_32(&buf[stream_ptr]);
464     stream_ptr += 6;  /* skip the magic number */
465     num_chunks = LE_16(&buf[stream_ptr]);
466     stream_ptr += 10;  /* skip padding */
467
468     frame_size -= 16;
469
470     /* iterate through the chunks */
471     while ((frame_size > 0) && (num_chunks > 0)) {
472         chunk_size = LE_32(&buf[stream_ptr]);
473         stream_ptr += 4;
474         chunk_type = LE_16(&buf[stream_ptr]);
475         stream_ptr += 2;
476
477         switch (chunk_type) {
478         case FLI_256_COLOR:
479         case FLI_COLOR:
480             /* For some reason, it seems that non-paletised flics do include one of these */
481             /* chunks in their first frame.  Why i do not know, it seems rather extraneous */
482 /*            av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/
483             stream_ptr = stream_ptr + chunk_size - 6;
484             break;
485
486         case FLI_DELTA:
487         case FLI_DTA_LC:
488             y_ptr = 0;
489             compressed_lines = LE_16(&buf[stream_ptr]);
490             stream_ptr += 2;
491             while (compressed_lines > 0) {
492                 line_packets = LE_16(&buf[stream_ptr]);
493                 stream_ptr += 2;
494                 if (line_packets < 0) {
495                     line_packets = -line_packets;
496                     y_ptr += line_packets * s->frame.linesize[0];
497                 } else {
498                     compressed_lines--;
499                     pixel_ptr = y_ptr;
500                     pixel_countdown = s->avctx->width;
501                     for (i = 0; i < line_packets; i++) {
502                         /* account for the skip bytes */
503                         pixel_skip = buf[stream_ptr++];
504                         pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
505                         pixel_countdown -= pixel_skip;
506                         byte_run = buf[stream_ptr++];
507                         if (byte_run < 0) {
508                             byte_run = -byte_run;
509                             pixel    = LE_16(&buf[stream_ptr]);
510                             stream_ptr += 2;
511                             CHECK_PIXEL_PTR(byte_run);
512                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
513                                 *((signed short*)(&pixels[pixel_ptr])) = pixel;
514                                 pixel_ptr += 2;
515                             }
516                         } else {
517                             CHECK_PIXEL_PTR(byte_run);
518                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
519                                 *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
520                                 stream_ptr += 2;
521                                 pixel_ptr += 2;
522                             }
523                         }
524                     }
525
526                     y_ptr += s->frame.linesize[0];
527                 }
528             }
529             break;
530
531         case FLI_LC:
532             av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
533             stream_ptr = stream_ptr + chunk_size - 6;
534             break;
535
536         case FLI_BLACK:
537             /* set the whole frame to 0x0000 which is balck in both 15Bpp and 16Bpp modes. */
538             memset(pixels, 0x0000,
539                    s->frame.linesize[0] * s->avctx->height * 2);
540             break;
541
542         case FLI_BRUN:
543             y_ptr = 0;
544             for (lines = 0; lines < s->avctx->height; lines++) {
545                 pixel_ptr = y_ptr;
546                 /* disregard the line packets; instead, iterate through all
547                  * pixels on a row */
548                 stream_ptr++;
549                 pixel_countdown = (s->avctx->width * 2);
550
551                 while (pixel_countdown > 0) {
552                     byte_run = buf[stream_ptr++];
553                     if (byte_run > 0) {
554                         palette_idx1 = buf[stream_ptr++];
555                         CHECK_PIXEL_PTR(byte_run);
556                         for (j = 0; j < byte_run; j++) {
557                             pixels[pixel_ptr++] = palette_idx1;
558                             pixel_countdown--;
559                             if (pixel_countdown < 0)
560                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
561                                        pixel_countdown);
562                         }
563                     } else {  /* copy bytes if byte_run < 0 */
564                         byte_run = -byte_run;
565                         CHECK_PIXEL_PTR(byte_run);
566                         for (j = 0; j < byte_run; j++) {
567                             palette_idx1 = buf[stream_ptr++];
568                             pixels[pixel_ptr++] = palette_idx1;
569                             pixel_countdown--;
570                             if (pixel_countdown < 0)
571                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
572                                        pixel_countdown);
573                         }
574                     }
575                 }
576
577                 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
578                  * This doesnt give us any good oportunity to perform word endian conversion
579                  * during decompression. So if its requried (ie, this isnt a LE target, we do
580                  * a second pass over the line here, swapping the bytes.
581                  */
582                 pixel = 0xFF00;
583                 if (0xFF00 != LE_16(&pixel)) /* Check if its not an LE Target */
584                 {
585                   pixel_ptr = y_ptr;
586                   pixel_countdown = s->avctx->width;
587                   while (pixel_countdown > 0) {
588                     *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[pixel_ptr]);
589                     pixel_ptr += 2;
590                   }
591                 }
592                 y_ptr += s->frame.linesize[0];
593             }
594             break;
595
596         case FLI_DTA_BRUN:
597             y_ptr = 0;
598             for (lines = 0; lines < s->avctx->height; lines++) {
599                 pixel_ptr = y_ptr;
600                 /* disregard the line packets; instead, iterate through all
601                  * pixels on a row */
602                 stream_ptr++;
603                 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
604
605                 while (pixel_countdown > 0) {
606                     byte_run = buf[stream_ptr++];
607                     if (byte_run > 0) {
608                         pixel    = LE_16(&buf[stream_ptr]);
609                         stream_ptr += 2;
610                         CHECK_PIXEL_PTR(byte_run);
611                         for (j = 0; j < byte_run; j++) {
612                             *((signed short*)(&pixels[pixel_ptr])) = pixel;
613                             pixel_ptr += 2;
614                             pixel_countdown--;
615                             if (pixel_countdown < 0)
616                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
617                                        pixel_countdown);
618                         }
619                     } else {  /* copy pixels if byte_run < 0 */
620                         byte_run = -byte_run;
621                         CHECK_PIXEL_PTR(byte_run);
622                         for (j = 0; j < byte_run; j++) {
623                             *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]);
624                             stream_ptr += 2;
625                             pixel_ptr  += 2;
626                             pixel_countdown--;
627                             if (pixel_countdown < 0)
628                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
629                                        pixel_countdown);
630                         }
631                     }
632                 }
633
634                 y_ptr += s->frame.linesize[0];
635             }
636             break;
637
638         case FLI_COPY:
639         case FLI_DTA_COPY:
640             /* copy the chunk (uncompressed frame) */
641             if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
642                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
643                        "bigger than image, skipping chunk\n", chunk_size - 6);
644                 stream_ptr += chunk_size - 6;
645             } else {
646
647                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
648                      y_ptr += s->frame.linesize[0]) {
649
650                     pixel_countdown = s->avctx->width;
651                     pixel_ptr = 0;
652                     while (pixel_countdown > 0) {
653                       *((signed short*)(&pixels[y_ptr + pixel_ptr])) = LE_16(&buf[stream_ptr+pixel_ptr]);
654                       pixel_ptr += 2;
655                       pixel_countdown--;
656                     }
657                     stream_ptr += s->avctx->width*2;
658                 }
659             }
660             break;
661
662         case FLI_MINI:
663             /* some sort of a thumbnail? disregard this chunk... */
664             stream_ptr += chunk_size - 6;
665             break;
666
667         default:
668             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
669             break;
670         }
671
672         frame_size -= chunk_size;
673         num_chunks--;
674     }
675
676     /* by the end of the chunk, the stream ptr should equal the frame
677      * size (minus 1, possibly); if it doesn't, issue a warning */
678     if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
679         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
680                "and final chunk ptr = %d\n", buf_size, stream_ptr);
681
682
683     *data_size=sizeof(AVFrame);
684     *(AVFrame*)data = s->frame;
685
686     return buf_size;
687 }
688
689 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
690                                    void *data, int *data_size,
691                                    uint8_t *buf, int buf_size)
692 {
693   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
694   return -1;
695 }
696
697 static int flic_decode_frame(AVCodecContext *avctx,
698                              void *data, int *data_size,
699                              uint8_t *buf, int buf_size)
700 {
701     if (avctx->pix_fmt == PIX_FMT_PAL8) {
702       return flic_decode_frame_8BPP(avctx, data, data_size,
703                                     buf, buf_size);
704     }
705     else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
706              (avctx->pix_fmt == PIX_FMT_RGB565)) {
707       return flic_decode_frame_15_16BPP(avctx, data, data_size,
708                                         buf, buf_size);
709     }
710     else if (avctx->pix_fmt == PIX_FMT_BGR24) {
711       return flic_decode_frame_24BPP(avctx, data, data_size,
712                                      buf, buf_size);
713     }
714
715     /* Shouldnt get  here, ever as the pix_fmt is processed */
716     /* in flic_decode_init and the above if should deal with */
717     /* the finite set of possibilites allowable by here. */
718     /* but in case we do, just error out. */
719     av_log(avctx, AV_LOG_ERROR, "Unknown Format of FLC. My Science cant explain how this happened\n");
720     return -1;
721 }
722
723
724 static int flic_decode_end(AVCodecContext *avctx)
725 {
726     FlicDecodeContext *s = avctx->priv_data;
727
728     if (s->frame.data[0])
729         avctx->release_buffer(avctx, &s->frame);
730
731     return 0;
732 }
733
734 AVCodec flic_decoder = {
735     "flic",
736     CODEC_TYPE_VIDEO,
737     CODEC_ID_FLIC,
738     sizeof(FlicDecodeContext),
739     flic_decode_init,
740     NULL,
741     flic_decode_end,
742     flic_decode_frame,
743     CODEC_CAP_DR1,
744     NULL,
745     NULL,
746     NULL,
747     NULL
748 };