• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/flicvideo.c

Go to the documentation of this file.
00001 /*
00002  * FLI/FLC Animation Video Decoder
00003  * Copyright (C) 2003, 2004 the ffmpeg project
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 
00042 #include "libavutil/intreadwrite.h"
00043 #include "avcodec.h"
00044 
00045 #define FLI_256_COLOR 4
00046 #define FLI_DELTA     7
00047 #define FLI_COLOR     11
00048 #define FLI_LC        12
00049 #define FLI_BLACK     13
00050 #define FLI_BRUN      15
00051 #define FLI_COPY      16
00052 #define FLI_MINI      18
00053 #define FLI_DTA_BRUN  25
00054 #define FLI_DTA_COPY  26
00055 #define FLI_DTA_LC    27
00056 
00057 #define FLI_TYPE_CODE     (0xAF11)
00058 #define FLC_FLX_TYPE_CODE (0xAF12)
00059 #define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */
00060 #define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13)
00061 
00062 #define CHECK_PIXEL_PTR(n) \
00063     if (pixel_ptr + n > pixel_limit) { \
00064         av_log (s->avctx, AV_LOG_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \
00065         pixel_ptr + n, pixel_limit); \
00066         return AVERROR_INVALIDDATA; \
00067     } \
00068 
00069 typedef struct FlicDecodeContext {
00070     AVCodecContext *avctx;
00071     AVFrame frame;
00072 
00073     unsigned int palette[256];
00074     int new_palette;
00075     int fli_type;  /* either 0xAF11 or 0xAF12, affects palette resolution */
00076 } FlicDecodeContext;
00077 
00078 static av_cold int flic_decode_init(AVCodecContext *avctx)
00079 {
00080     FlicDecodeContext *s = avctx->priv_data;
00081     unsigned char *fli_header = (unsigned char *)avctx->extradata;
00082     int depth;
00083 
00084     s->avctx = avctx;
00085 
00086     s->fli_type = AV_RL16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
00087 
00088     depth = 0;
00089     if (s->avctx->extradata_size == 12) {
00090         /* special case for magic carpet FLIs */
00091         s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
00092         depth = 8;
00093     } else if (s->avctx->extradata_size != 128) {
00094         av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
00095         return -1;
00096     } else {
00097         depth = AV_RL16(&fli_header[12]);
00098     }
00099 
00100     if (depth == 0) {
00101         depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
00102     }
00103 
00104     if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
00105         depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
00106     }
00107 
00108     switch (depth) {
00109         case 8  : avctx->pix_fmt = PIX_FMT_PAL8; break;
00110         case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
00111         case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
00112         case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
00113                   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
00114                   return -1;
00115                   break;
00116         default :
00117                   av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
00118                   return -1;
00119     }
00120 
00121     avcodec_get_frame_defaults(&s->frame);
00122     s->frame.data[0] = NULL;
00123     s->new_palette = 0;
00124 
00125     return 0;
00126 }
00127 
00128 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
00129                                   void *data, int *data_size,
00130                                   const uint8_t *buf, int buf_size)
00131 {
00132     FlicDecodeContext *s = avctx->priv_data;
00133 
00134     int stream_ptr = 0;
00135     int pixel_ptr;
00136     int palette_ptr;
00137     unsigned char palette_idx1;
00138     unsigned char palette_idx2;
00139 
00140     unsigned int frame_size;
00141     int num_chunks;
00142 
00143     unsigned int chunk_size;
00144     int chunk_type;
00145 
00146     int i, j;
00147 
00148     int color_packets;
00149     int color_changes;
00150     int color_shift;
00151     unsigned char r, g, b;
00152 
00153     int lines;
00154     int compressed_lines;
00155     int starting_line;
00156     signed short line_packets;
00157     int y_ptr;
00158     int byte_run;
00159     int pixel_skip;
00160     int pixel_countdown;
00161     unsigned char *pixels;
00162     unsigned int pixel_limit;
00163 
00164     s->frame.reference = 1;
00165     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00166     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00167         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00168         return -1;
00169     }
00170 
00171     pixels = s->frame.data[0];
00172     pixel_limit = s->avctx->height * s->frame.linesize[0];
00173 
00174     if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE))
00175         return AVERROR_INVALIDDATA;
00176     frame_size = AV_RL32(&buf[stream_ptr]);
00177     if (frame_size > buf_size)
00178         frame_size = buf_size;
00179     stream_ptr += 6;  /* skip the magic number */
00180     num_chunks = AV_RL16(&buf[stream_ptr]);
00181     stream_ptr += 10;  /* skip padding */
00182 
00183     frame_size -= 16;
00184 
00185     /* iterate through the chunks */
00186     while ((frame_size >= 6) && (num_chunks > 0)) {
00187         int stream_ptr_after_chunk;
00188         chunk_size = AV_RL32(&buf[stream_ptr]);
00189         if (chunk_size > frame_size) {
00190             av_log(avctx, AV_LOG_WARNING,
00191                    "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
00192             chunk_size = frame_size;
00193         }
00194         stream_ptr_after_chunk = stream_ptr + chunk_size;
00195 
00196         stream_ptr += 4;
00197         chunk_type = AV_RL16(&buf[stream_ptr]);
00198         stream_ptr += 2;
00199 
00200         switch (chunk_type) {
00201         case FLI_256_COLOR:
00202         case FLI_COLOR:
00203             /* check special case: If this file is from the Magic Carpet
00204              * game and uses 6-bit colors even though it reports 256-color
00205              * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
00206              * initialization) */
00207             if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
00208                 color_shift = 0;
00209             else
00210                 color_shift = 2;
00211             /* set up the palette */
00212             color_packets = AV_RL16(&buf[stream_ptr]);
00213             stream_ptr += 2;
00214             palette_ptr = 0;
00215             for (i = 0; i < color_packets; i++) {
00216                 /* first byte is how many colors to skip */
00217                 palette_ptr += buf[stream_ptr++];
00218 
00219                 /* next byte indicates how many entries to change */
00220                 color_changes = buf[stream_ptr++];
00221 
00222                 /* if there are 0 color changes, there are actually 256 */
00223                 if (color_changes == 0)
00224                     color_changes = 256;
00225 
00226                 if (stream_ptr + color_changes * 3 > stream_ptr_after_chunk)
00227                     break;
00228 
00229                 for (j = 0; j < color_changes; j++) {
00230                     unsigned int entry;
00231 
00232                     /* wrap around, for good measure */
00233                     if ((unsigned)palette_ptr >= 256)
00234                         palette_ptr = 0;
00235 
00236                     r = buf[stream_ptr++] << color_shift;
00237                     g = buf[stream_ptr++] << color_shift;
00238                     b = buf[stream_ptr++] << color_shift;
00239                     entry = (r << 16) | (g << 8) | b;
00240                     if (s->palette[palette_ptr] != entry)
00241                         s->new_palette = 1;
00242                     s->palette[palette_ptr++] = entry;
00243                 }
00244             }
00245             break;
00246 
00247         case FLI_DELTA:
00248             y_ptr = 0;
00249             compressed_lines = AV_RL16(&buf[stream_ptr]);
00250             stream_ptr += 2;
00251             while (compressed_lines > 0) {
00252                 if (stream_ptr + 2 > stream_ptr_after_chunk)
00253                     break;
00254                 line_packets = AV_RL16(&buf[stream_ptr]);
00255                 stream_ptr += 2;
00256                 if ((line_packets & 0xC000) == 0xC000) {
00257                     // line skip opcode
00258                     line_packets = -line_packets;
00259                     y_ptr += line_packets * s->frame.linesize[0];
00260                 } else if ((line_packets & 0xC000) == 0x4000) {
00261                     av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
00262                 } else if ((line_packets & 0xC000) == 0x8000) {
00263                     // "last byte" opcode
00264                     pixel_ptr= y_ptr + s->frame.linesize[0] - 1;
00265                     CHECK_PIXEL_PTR(0);
00266                     pixels[pixel_ptr] = line_packets & 0xff;
00267                 } else {
00268                     compressed_lines--;
00269                     pixel_ptr = y_ptr;
00270                     CHECK_PIXEL_PTR(0);
00271                     pixel_countdown = s->avctx->width;
00272                     for (i = 0; i < line_packets; i++) {
00273                         if (stream_ptr + 2 > stream_ptr_after_chunk)
00274                             break;
00275                         /* account for the skip bytes */
00276                         pixel_skip = buf[stream_ptr++];
00277                         pixel_ptr += pixel_skip;
00278                         pixel_countdown -= pixel_skip;
00279                         byte_run = (signed char)(buf[stream_ptr++]);
00280                         if (byte_run < 0) {
00281                             byte_run = -byte_run;
00282                             palette_idx1 = buf[stream_ptr++];
00283                             palette_idx2 = buf[stream_ptr++];
00284                             CHECK_PIXEL_PTR(byte_run * 2);
00285                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
00286                                 pixels[pixel_ptr++] = palette_idx1;
00287                                 pixels[pixel_ptr++] = palette_idx2;
00288                             }
00289                         } else {
00290                             CHECK_PIXEL_PTR(byte_run * 2);
00291                             if (stream_ptr + byte_run * 2 > stream_ptr_after_chunk)
00292                                 break;
00293                             for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
00294                                 palette_idx1 = buf[stream_ptr++];
00295                                 pixels[pixel_ptr++] = palette_idx1;
00296                             }
00297                         }
00298                     }
00299 
00300                     y_ptr += s->frame.linesize[0];
00301                 }
00302             }
00303             break;
00304 
00305         case FLI_LC:
00306             /* line compressed */
00307             starting_line = AV_RL16(&buf[stream_ptr]);
00308             stream_ptr += 2;
00309             y_ptr = 0;
00310             y_ptr += starting_line * s->frame.linesize[0];
00311 
00312             compressed_lines = AV_RL16(&buf[stream_ptr]);
00313             stream_ptr += 2;
00314             while (compressed_lines > 0) {
00315                 pixel_ptr = y_ptr;
00316                 CHECK_PIXEL_PTR(0);
00317                 pixel_countdown = s->avctx->width;
00318                 line_packets = buf[stream_ptr++];
00319                 if (stream_ptr + 2 * line_packets > stream_ptr_after_chunk)
00320                     break;
00321                 if (line_packets > 0) {
00322                     for (i = 0; i < line_packets; i++) {
00323                         /* account for the skip bytes */
00324                         pixel_skip = buf[stream_ptr++];
00325                         pixel_ptr += pixel_skip;
00326                         pixel_countdown -= pixel_skip;
00327                         byte_run = (signed char)(buf[stream_ptr++]);
00328                         if (byte_run > 0) {
00329                             CHECK_PIXEL_PTR(byte_run);
00330                             if (stream_ptr + byte_run > stream_ptr_after_chunk)
00331                                 break;
00332                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00333                                 palette_idx1 = buf[stream_ptr++];
00334                                 pixels[pixel_ptr++] = palette_idx1;
00335                             }
00336                         } else if (byte_run < 0) {
00337                             byte_run = -byte_run;
00338                             palette_idx1 = buf[stream_ptr++];
00339                             CHECK_PIXEL_PTR(byte_run);
00340                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00341                                 pixels[pixel_ptr++] = palette_idx1;
00342                             }
00343                         }
00344                     }
00345                 }
00346 
00347                 y_ptr += s->frame.linesize[0];
00348                 compressed_lines--;
00349             }
00350             break;
00351 
00352         case FLI_BLACK:
00353             /* set the whole frame to color 0 (which is usually black) */
00354             memset(pixels, 0,
00355                 s->frame.linesize[0] * s->avctx->height);
00356             break;
00357 
00358         case FLI_BRUN:
00359             /* Byte run compression: This chunk type only occurs in the first
00360              * FLI frame and it will update the entire frame. */
00361             y_ptr = 0;
00362             for (lines = 0; lines < s->avctx->height; lines++) {
00363                 pixel_ptr = y_ptr;
00364                 /* disregard the line packets; instead, iterate through all
00365                  * pixels on a row */
00366                 stream_ptr++;
00367                 pixel_countdown = s->avctx->width;
00368                 while (pixel_countdown > 0) {
00369                     if (stream_ptr + 1 > stream_ptr_after_chunk)
00370                         break;
00371                     byte_run = (signed char)(buf[stream_ptr++]);
00372                     if (byte_run > 0) {
00373                         palette_idx1 = buf[stream_ptr++];
00374                         CHECK_PIXEL_PTR(byte_run);
00375                         for (j = 0; j < byte_run; j++) {
00376                             pixels[pixel_ptr++] = palette_idx1;
00377                             pixel_countdown--;
00378                             if (pixel_countdown < 0)
00379                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00380                                        pixel_countdown, lines);
00381                         }
00382                     } else {  /* copy bytes if byte_run < 0 */
00383                         byte_run = -byte_run;
00384                         CHECK_PIXEL_PTR(byte_run);
00385                         if (stream_ptr + byte_run > stream_ptr_after_chunk)
00386                             break;
00387                         for (j = 0; j < byte_run; j++) {
00388                             palette_idx1 = buf[stream_ptr++];
00389                             pixels[pixel_ptr++] = palette_idx1;
00390                             pixel_countdown--;
00391                             if (pixel_countdown < 0)
00392                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00393                                        pixel_countdown, lines);
00394                         }
00395                     }
00396                 }
00397 
00398                 y_ptr += s->frame.linesize[0];
00399             }
00400             break;
00401 
00402         case FLI_COPY:
00403             /* copy the chunk (uncompressed frame) */
00404             if (chunk_size - 6 != s->avctx->width * s->avctx->height) {
00405                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
00406                        "has incorrect size, skipping chunk\n", chunk_size - 6);
00407             } else {
00408                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
00409                      y_ptr += s->frame.linesize[0]) {
00410                     memcpy(&pixels[y_ptr], &buf[stream_ptr],
00411                         s->avctx->width);
00412                     stream_ptr += s->avctx->width;
00413                 }
00414             }
00415             break;
00416 
00417         case FLI_MINI:
00418             /* some sort of a thumbnail? disregard this chunk... */
00419             break;
00420 
00421         default:
00422             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
00423             break;
00424         }
00425 
00426         stream_ptr = stream_ptr_after_chunk;
00427 
00428         frame_size -= chunk_size;
00429         num_chunks--;
00430     }
00431 
00432     /* by the end of the chunk, the stream ptr should equal the frame
00433      * size (minus 1, possibly); if it doesn't, issue a warning */
00434     if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
00435         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
00436                "and final chunk ptr = %d\n", buf_size, stream_ptr);
00437 
00438     /* make the palette available on the way out */
00439     memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00440     if (s->new_palette) {
00441         s->frame.palette_has_changed = 1;
00442         s->new_palette = 0;
00443     }
00444 
00445     *data_size=sizeof(AVFrame);
00446     *(AVFrame*)data = s->frame;
00447 
00448     return buf_size;
00449 }
00450 
00451 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
00452                                       void *data, int *data_size,
00453                                       const uint8_t *buf, int buf_size)
00454 {
00455     /* Note, the only difference between the 15Bpp and 16Bpp */
00456     /* Format is the pixel format, the packets are processed the same. */
00457     FlicDecodeContext *s = avctx->priv_data;
00458 
00459     int stream_ptr = 0;
00460     int pixel_ptr;
00461     unsigned char palette_idx1;
00462 
00463     unsigned int frame_size;
00464     int num_chunks;
00465 
00466     unsigned int chunk_size;
00467     int chunk_type;
00468 
00469     int i, j;
00470 
00471     int lines;
00472     int compressed_lines;
00473     signed short line_packets;
00474     int y_ptr;
00475     int byte_run;
00476     int pixel_skip;
00477     int pixel_countdown;
00478     unsigned char *pixels;
00479     int pixel;
00480     unsigned int pixel_limit;
00481 
00482     s->frame.reference = 1;
00483     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00484     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00485         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00486         return -1;
00487     }
00488 
00489     pixels = s->frame.data[0];
00490     pixel_limit = s->avctx->height * s->frame.linesize[0];
00491 
00492     frame_size = AV_RL32(&buf[stream_ptr]);
00493     stream_ptr += 6;  /* skip the magic number */
00494     num_chunks = AV_RL16(&buf[stream_ptr]);
00495     stream_ptr += 10;  /* skip padding */
00496 
00497     frame_size -= 16;
00498 
00499     /* iterate through the chunks */
00500     while ((frame_size > 0) && (num_chunks > 0)) {
00501         chunk_size = AV_RL32(&buf[stream_ptr]);
00502         stream_ptr += 4;
00503         chunk_type = AV_RL16(&buf[stream_ptr]);
00504         stream_ptr += 2;
00505 
00506         switch (chunk_type) {
00507         case FLI_256_COLOR:
00508         case FLI_COLOR:
00509             /* For some reason, it seems that non-palettized flics do
00510              * include one of these chunks in their first frame.
00511              * Why I do not know, it seems rather extraneous. */
00512 /*            av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/
00513             stream_ptr = stream_ptr + chunk_size - 6;
00514             break;
00515 
00516         case FLI_DELTA:
00517         case FLI_DTA_LC:
00518             y_ptr = 0;
00519             compressed_lines = AV_RL16(&buf[stream_ptr]);
00520             stream_ptr += 2;
00521             while (compressed_lines > 0) {
00522                 line_packets = AV_RL16(&buf[stream_ptr]);
00523                 stream_ptr += 2;
00524                 if (line_packets < 0) {
00525                     line_packets = -line_packets;
00526                     y_ptr += line_packets * s->frame.linesize[0];
00527                 } else {
00528                     compressed_lines--;
00529                     pixel_ptr = y_ptr;
00530                     CHECK_PIXEL_PTR(0);
00531                     pixel_countdown = s->avctx->width;
00532                     for (i = 0; i < line_packets; i++) {
00533                         /* account for the skip bytes */
00534                         pixel_skip = buf[stream_ptr++];
00535                         pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
00536                         pixel_countdown -= pixel_skip;
00537                         byte_run = (signed char)(buf[stream_ptr++]);
00538                         if (byte_run < 0) {
00539                             byte_run = -byte_run;
00540                             pixel    = AV_RL16(&buf[stream_ptr]);
00541                             stream_ptr += 2;
00542                             CHECK_PIXEL_PTR(2 * byte_run);
00543                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
00544                                 *((signed short*)(&pixels[pixel_ptr])) = pixel;
00545                                 pixel_ptr += 2;
00546                             }
00547                         } else {
00548                             CHECK_PIXEL_PTR(2 * byte_run);
00549                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00550                                 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
00551                                 stream_ptr += 2;
00552                                 pixel_ptr += 2;
00553                             }
00554                         }
00555                     }
00556 
00557                     y_ptr += s->frame.linesize[0];
00558                 }
00559             }
00560             break;
00561 
00562         case FLI_LC:
00563             av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
00564             stream_ptr = stream_ptr + chunk_size - 6;
00565             break;
00566 
00567         case FLI_BLACK:
00568             /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
00569             memset(pixels, 0x0000,
00570                    s->frame.linesize[0] * s->avctx->height);
00571             break;
00572 
00573         case FLI_BRUN:
00574             y_ptr = 0;
00575             for (lines = 0; lines < s->avctx->height; lines++) {
00576                 pixel_ptr = y_ptr;
00577                 /* disregard the line packets; instead, iterate through all
00578                  * pixels on a row */
00579                 stream_ptr++;
00580                 pixel_countdown = (s->avctx->width * 2);
00581 
00582                 while (pixel_countdown > 0) {
00583                     byte_run = (signed char)(buf[stream_ptr++]);
00584                     if (byte_run > 0) {
00585                         palette_idx1 = buf[stream_ptr++];
00586                         CHECK_PIXEL_PTR(byte_run);
00587                         for (j = 0; j < byte_run; j++) {
00588                             pixels[pixel_ptr++] = palette_idx1;
00589                             pixel_countdown--;
00590                             if (pixel_countdown < 0)
00591                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
00592                                        pixel_countdown, lines);
00593                         }
00594                     } else {  /* copy bytes if byte_run < 0 */
00595                         byte_run = -byte_run;
00596                         CHECK_PIXEL_PTR(byte_run);
00597                         for (j = 0; j < byte_run; j++) {
00598                             palette_idx1 = buf[stream_ptr++];
00599                             pixels[pixel_ptr++] = palette_idx1;
00600                             pixel_countdown--;
00601                             if (pixel_countdown < 0)
00602                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00603                                        pixel_countdown, lines);
00604                         }
00605                     }
00606                 }
00607 
00608                 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
00609                  * This does not give us any good oportunity to perform word endian conversion
00610                  * during decompression. So if it is required (i.e., this is not a LE target, we do
00611                  * a second pass over the line here, swapping the bytes.
00612                  */
00613 #if HAVE_BIGENDIAN
00614                 pixel_ptr = y_ptr;
00615                 pixel_countdown = s->avctx->width;
00616                 while (pixel_countdown > 0) {
00617                     *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
00618                     pixel_ptr += 2;
00619                 }
00620 #endif
00621                 y_ptr += s->frame.linesize[0];
00622             }
00623             break;
00624 
00625         case FLI_DTA_BRUN:
00626             y_ptr = 0;
00627             for (lines = 0; lines < s->avctx->height; lines++) {
00628                 pixel_ptr = y_ptr;
00629                 /* disregard the line packets; instead, iterate through all
00630                  * pixels on a row */
00631                 stream_ptr++;
00632                 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
00633 
00634                 while (pixel_countdown > 0) {
00635                     byte_run = (signed char)(buf[stream_ptr++]);
00636                     if (byte_run > 0) {
00637                         pixel    = AV_RL16(&buf[stream_ptr]);
00638                         stream_ptr += 2;
00639                         CHECK_PIXEL_PTR(2 * byte_run);
00640                         for (j = 0; j < byte_run; j++) {
00641                             *((signed short*)(&pixels[pixel_ptr])) = pixel;
00642                             pixel_ptr += 2;
00643                             pixel_countdown--;
00644                             if (pixel_countdown < 0)
00645                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00646                                        pixel_countdown);
00647                         }
00648                     } else {  /* copy pixels if byte_run < 0 */
00649                         byte_run = -byte_run;
00650                         CHECK_PIXEL_PTR(2 * byte_run);
00651                         for (j = 0; j < byte_run; j++) {
00652                             *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
00653                             stream_ptr += 2;
00654                             pixel_ptr  += 2;
00655                             pixel_countdown--;
00656                             if (pixel_countdown < 0)
00657                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00658                                        pixel_countdown);
00659                         }
00660                     }
00661                 }
00662 
00663                 y_ptr += s->frame.linesize[0];
00664             }
00665             break;
00666 
00667         case FLI_COPY:
00668         case FLI_DTA_COPY:
00669             /* copy the chunk (uncompressed frame) */
00670             if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
00671                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
00672                        "bigger than image, skipping chunk\n", chunk_size - 6);
00673                 stream_ptr += chunk_size - 6;
00674             } else {
00675 
00676                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
00677                      y_ptr += s->frame.linesize[0]) {
00678 
00679                     pixel_countdown = s->avctx->width;
00680                     pixel_ptr = 0;
00681                     while (pixel_countdown > 0) {
00682                       *((signed short*)(&pixels[y_ptr + pixel_ptr])) = AV_RL16(&buf[stream_ptr+pixel_ptr]);
00683                       pixel_ptr += 2;
00684                       pixel_countdown--;
00685                     }
00686                     stream_ptr += s->avctx->width*2;
00687                 }
00688             }
00689             break;
00690 
00691         case FLI_MINI:
00692             /* some sort of a thumbnail? disregard this chunk... */
00693             stream_ptr += chunk_size - 6;
00694             break;
00695 
00696         default:
00697             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
00698             break;
00699         }
00700 
00701         frame_size -= chunk_size;
00702         num_chunks--;
00703     }
00704 
00705     /* by the end of the chunk, the stream ptr should equal the frame
00706      * size (minus 1, possibly); if it doesn't, issue a warning */
00707     if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
00708         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
00709                "and final chunk ptr = %d\n", buf_size, stream_ptr);
00710 
00711 
00712     *data_size=sizeof(AVFrame);
00713     *(AVFrame*)data = s->frame;
00714 
00715     return buf_size;
00716 }
00717 
00718 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
00719                                    void *data, int *data_size,
00720                                    const uint8_t *buf, int buf_size)
00721 {
00722   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
00723   return -1;
00724 }
00725 
00726 static int flic_decode_frame(AVCodecContext *avctx,
00727                              void *data, int *data_size,
00728                              AVPacket *avpkt)
00729 {
00730     const uint8_t *buf = avpkt->data;
00731     int buf_size = avpkt->size;
00732     if (avctx->pix_fmt == PIX_FMT_PAL8) {
00733       return flic_decode_frame_8BPP(avctx, data, data_size,
00734                                     buf, buf_size);
00735     }
00736     else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
00737              (avctx->pix_fmt == PIX_FMT_RGB565)) {
00738       return flic_decode_frame_15_16BPP(avctx, data, data_size,
00739                                         buf, buf_size);
00740     }
00741     else if (avctx->pix_fmt == PIX_FMT_BGR24) {
00742       return flic_decode_frame_24BPP(avctx, data, data_size,
00743                                      buf, buf_size);
00744     }
00745 
00746     /* Should not get  here, ever as the pix_fmt is processed */
00747     /* in flic_decode_init and the above if should deal with */
00748     /* the finite set of possibilites allowable by here. */
00749     /* But in case we do, just error out. */
00750     av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
00751     return -1;
00752 }
00753 
00754 
00755 static av_cold int flic_decode_end(AVCodecContext *avctx)
00756 {
00757     FlicDecodeContext *s = avctx->priv_data;
00758 
00759     if (s->frame.data[0])
00760         avctx->release_buffer(avctx, &s->frame);
00761 
00762     return 0;
00763 }
00764 
00765 AVCodec ff_flic_decoder = {
00766     "flic",
00767     AVMEDIA_TYPE_VIDEO,
00768     CODEC_ID_FLIC,
00769     sizeof(FlicDecodeContext),
00770     flic_decode_init,
00771     NULL,
00772     flic_decode_end,
00773     flic_decode_frame,
00774     CODEC_CAP_DR1,
00775     NULL,
00776     NULL,
00777     NULL,
00778     NULL,
00779     .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
00780 };

Generated on Wed Apr 11 2012 07:31:33 for FFmpeg by  doxygen 1.7.1