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