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