00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
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) 
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_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \
00067         pixel_ptr + n, pixel_limit); \
00068         return AVERROR_INVALIDDATA; \
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;  
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 != 0 &&
00087         avctx->extradata_size != 12 &&
00088         avctx->extradata_size != 128 &&
00089         avctx->extradata_size != 256 &&
00090         avctx->extradata_size != 904 &&
00091         avctx->extradata_size != 1024) {
00092         av_log(avctx, AV_LOG_ERROR, "Unexpected extradata size %d\n", avctx->extradata_size);
00093         return AVERROR_INVALIDDATA;
00094     }
00095 
00096     s->avctx = avctx;
00097 
00098     if (s->avctx->extradata_size == 12) {
00099         
00100         s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
00101         depth = 8;
00102     } else if (avctx->extradata_size == 1024) {
00103         uint8_t *ptr = avctx->extradata;
00104         int i;
00105 
00106         for (i = 0; i < 256; i++) {
00107             s->palette[i] = AV_RL32(ptr);
00108             ptr += 4;
00109         }
00110         depth = 8;
00111         
00112     } else if (avctx->extradata_size == 0 ||
00113                avctx->extradata_size == 256 ||
00114         
00115                avctx->extradata_size == 904) {
00116         s->fli_type = FLI_TYPE_CODE;
00117         depth = 8;
00118     } else {
00119         s->fli_type = AV_RL16(&fli_header[4]);
00120         depth = AV_RL16(&fli_header[12]);
00121     }
00122 
00123     if (depth == 0) {
00124         depth = 8; 
00125     }
00126 
00127     if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
00128         depth = 15; 
00129     }
00130 
00131     switch (depth) {
00132         case 8  : avctx->pix_fmt = PIX_FMT_PAL8; break;
00133         case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
00134         case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
00135         case 24 : avctx->pix_fmt = PIX_FMT_BGR24; 
00136                   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
00137                   return -1;
00138         default :
00139                   av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
00140                   return -1;
00141     }
00142 
00143     avcodec_get_frame_defaults(&s->frame);
00144     s->frame.data[0] = NULL;
00145     s->new_palette = 0;
00146 
00147     return 0;
00148 }
00149 
00150 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
00151                                   void *data, int *data_size,
00152                                   const uint8_t *buf, int buf_size)
00153 {
00154     FlicDecodeContext *s = avctx->priv_data;
00155 
00156     GetByteContext g2;
00157     int pixel_ptr;
00158     int palette_ptr;
00159     unsigned char palette_idx1;
00160     unsigned char palette_idx2;
00161 
00162     unsigned int frame_size;
00163     int num_chunks;
00164 
00165     unsigned int chunk_size;
00166     int chunk_type;
00167 
00168     int i, j;
00169 
00170     int color_packets;
00171     int color_changes;
00172     int color_shift;
00173     unsigned char r, g, b;
00174 
00175     int lines;
00176     int compressed_lines;
00177     int starting_line;
00178     signed short line_packets;
00179     int y_ptr;
00180     int byte_run;
00181     int pixel_skip;
00182     int pixel_countdown;
00183     unsigned char *pixels;
00184     unsigned int pixel_limit;
00185 
00186     bytestream2_init(&g2, buf, buf_size);
00187 
00188     s->frame.reference = 3;
00189     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00190     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00191         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00192         return -1;
00193     }
00194 
00195     pixels = s->frame.data[0];
00196     pixel_limit = s->avctx->height * s->frame.linesize[0];
00197     if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE))
00198         return AVERROR_INVALIDDATA;
00199     frame_size = bytestream2_get_le32(&g2);
00200     if (frame_size > buf_size)
00201         frame_size = buf_size;
00202     bytestream2_skip(&g2, 2); 
00203     num_chunks = bytestream2_get_le16(&g2);
00204     bytestream2_skip(&g2, 8);  
00205 
00206     frame_size -= 16;
00207 
00208     
00209     while ((frame_size >= 6) && (num_chunks > 0)) {
00210         int stream_ptr_after_chunk;
00211         chunk_size = bytestream2_get_le32(&g2);
00212         if (chunk_size > frame_size) {
00213             av_log(avctx, AV_LOG_WARNING,
00214                    "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
00215             chunk_size = frame_size;
00216         }
00217         stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
00218 
00219         chunk_type = bytestream2_get_le16(&g2);
00220 
00221         switch (chunk_type) {
00222         case FLI_256_COLOR:
00223         case FLI_COLOR:
00224             
00225 
00226 
00227 
00228             if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
00229                 color_shift = 0;
00230             else
00231                 color_shift = 2;
00232             
00233             color_packets = bytestream2_get_le16(&g2);
00234             palette_ptr = 0;
00235             for (i = 0; i < color_packets; i++) {
00236                 
00237                 palette_ptr += bytestream2_get_byte(&g2);
00238 
00239                 
00240                 color_changes = bytestream2_get_byte(&g2);
00241 
00242                 
00243                 if (color_changes == 0)
00244                     color_changes = 256;
00245 
00246                 if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk)
00247                     break;
00248 
00249                 for (j = 0; j < color_changes; j++) {
00250                     unsigned int entry;
00251 
00252                     
00253                     if ((unsigned)palette_ptr >= 256)
00254                         palette_ptr = 0;
00255 
00256                     r = bytestream2_get_byte(&g2) << color_shift;
00257                     g = bytestream2_get_byte(&g2) << color_shift;
00258                     b = bytestream2_get_byte(&g2) << color_shift;
00259                     entry = 0xFF << 24 | r << 16 | g << 8 | b;
00260                     if (color_shift == 2)
00261                         entry |= entry >> 6 & 0x30303;
00262                     if (s->palette[palette_ptr] != entry)
00263                         s->new_palette = 1;
00264                     s->palette[palette_ptr++] = entry;
00265                 }
00266             }
00267             break;
00268 
00269         case FLI_DELTA:
00270             y_ptr = 0;
00271             compressed_lines = bytestream2_get_le16(&g2);
00272             while (compressed_lines > 0) {
00273                 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00274                     break;
00275                 line_packets = bytestream2_get_le16(&g2);
00276                 if ((line_packets & 0xC000) == 0xC000) {
00277                     
00278                     line_packets = -line_packets;
00279                     y_ptr += line_packets * s->frame.linesize[0];
00280                 } else if ((line_packets & 0xC000) == 0x4000) {
00281                     av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
00282                 } else if ((line_packets & 0xC000) == 0x8000) {
00283                     
00284                     pixel_ptr= y_ptr + s->frame.linesize[0] - 1;
00285                     CHECK_PIXEL_PTR(0);
00286                     pixels[pixel_ptr] = line_packets & 0xff;
00287                 } else {
00288                     compressed_lines--;
00289                     pixel_ptr = y_ptr;
00290                     CHECK_PIXEL_PTR(0);
00291                     pixel_countdown = s->avctx->width;
00292                     for (i = 0; i < line_packets; i++) {
00293                         if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00294                             break;
00295                         
00296                         pixel_skip = bytestream2_get_byte(&g2);
00297                         pixel_ptr += pixel_skip;
00298                         pixel_countdown -= pixel_skip;
00299                         byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00300                         if (byte_run < 0) {
00301                             byte_run = -byte_run;
00302                             palette_idx1 = bytestream2_get_byte(&g2);
00303                             palette_idx2 = bytestream2_get_byte(&g2);
00304                             CHECK_PIXEL_PTR(byte_run * 2);
00305                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
00306                                 pixels[pixel_ptr++] = palette_idx1;
00307                                 pixels[pixel_ptr++] = palette_idx2;
00308                             }
00309                         } else {
00310                             CHECK_PIXEL_PTR(byte_run * 2);
00311                             if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk)
00312                                 break;
00313                             for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
00314                                 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
00315                             }
00316                         }
00317                     }
00318 
00319                     y_ptr += s->frame.linesize[0];
00320                 }
00321             }
00322             break;
00323 
00324         case FLI_LC:
00325             
00326             starting_line = bytestream2_get_le16(&g2);
00327             y_ptr = 0;
00328             y_ptr += starting_line * s->frame.linesize[0];
00329 
00330             compressed_lines = bytestream2_get_le16(&g2);
00331             while (compressed_lines > 0) {
00332                 pixel_ptr = y_ptr;
00333                 CHECK_PIXEL_PTR(0);
00334                 pixel_countdown = s->avctx->width;
00335                 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00336                     break;
00337                 line_packets = bytestream2_get_byte(&g2);
00338                 if (line_packets > 0) {
00339                     for (i = 0; i < line_packets; i++) {
00340                         
00341                         if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00342                             break;
00343                         pixel_skip = bytestream2_get_byte(&g2);
00344                         pixel_ptr += pixel_skip;
00345                         pixel_countdown -= pixel_skip;
00346                         byte_run = sign_extend(bytestream2_get_byte(&g2),8);
00347                         if (byte_run > 0) {
00348                             CHECK_PIXEL_PTR(byte_run);
00349                             if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
00350                                 break;
00351                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00352                                 pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
00353                             }
00354                         } else if (byte_run < 0) {
00355                             byte_run = -byte_run;
00356                             palette_idx1 = bytestream2_get_byte(&g2);
00357                             CHECK_PIXEL_PTR(byte_run);
00358                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00359                                 pixels[pixel_ptr++] = palette_idx1;
00360                             }
00361                         }
00362                     }
00363                 }
00364 
00365                 y_ptr += s->frame.linesize[0];
00366                 compressed_lines--;
00367             }
00368             break;
00369 
00370         case FLI_BLACK:
00371             
00372             memset(pixels, 0,
00373                 s->frame.linesize[0] * s->avctx->height);
00374             break;
00375 
00376         case FLI_BRUN:
00377             
00378 
00379             y_ptr = 0;
00380             for (lines = 0; lines < s->avctx->height; lines++) {
00381                 pixel_ptr = y_ptr;
00382                 
00383 
00384                  bytestream2_skip(&g2, 1);
00385                 pixel_countdown = s->avctx->width;
00386                 while (pixel_countdown > 0) {
00387                     if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00388                         break;
00389                     byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00390                     if (byte_run > 0) {
00391                         palette_idx1 = bytestream2_get_byte(&g2);
00392                         CHECK_PIXEL_PTR(byte_run);
00393                         for (j = 0; j < byte_run; j++) {
00394                             pixels[pixel_ptr++] = palette_idx1;
00395                             pixel_countdown--;
00396                             if (pixel_countdown < 0)
00397                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00398                                        pixel_countdown, lines);
00399                         }
00400                     } else {  
00401                         byte_run = -byte_run;
00402                         CHECK_PIXEL_PTR(byte_run);
00403                         if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
00404                             break;
00405                         for (j = 0; j < byte_run; j++) {
00406                             pixels[pixel_ptr++] = bytestream2_get_byte(&g2);
00407                             pixel_countdown--;
00408                             if (pixel_countdown < 0)
00409                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00410                                        pixel_countdown, lines);
00411                         }
00412                     }
00413                 }
00414 
00415                 y_ptr += s->frame.linesize[0];
00416             }
00417             break;
00418 
00419         case FLI_COPY:
00420             
00421             if (chunk_size - 6 != s->avctx->width * s->avctx->height) {
00422                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
00423                        "has incorrect size, skipping chunk\n", chunk_size - 6);
00424                 bytestream2_skip(&g2, chunk_size - 6);
00425             } else {
00426                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
00427                      y_ptr += s->frame.linesize[0]) {
00428                     bytestream2_get_buffer(&g2, &pixels[y_ptr],
00429                                            s->avctx->width);
00430                 }
00431             }
00432             break;
00433 
00434         case FLI_MINI:
00435             
00436             break;
00437 
00438         default:
00439             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
00440             break;
00441         }
00442 
00443         if (stream_ptr_after_chunk - bytestream2_tell(&g2) > 0)
00444             bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2));
00445 
00446         frame_size -= chunk_size;
00447         num_chunks--;
00448     }
00449 
00450     
00451 
00452     if (bytestream2_get_bytes_left(&g2) > 2)
00453         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
00454                "and final chunk ptr = %d\n", buf_size,
00455                buf_size - bytestream2_get_bytes_left(&g2));
00456 
00457     
00458     memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00459     if (s->new_palette) {
00460         s->frame.palette_has_changed = 1;
00461         s->new_palette = 0;
00462     }
00463 
00464     *data_size=sizeof(AVFrame);
00465     *(AVFrame*)data = s->frame;
00466 
00467     return buf_size;
00468 }
00469 
00470 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
00471                                       void *data, int *data_size,
00472                                       const uint8_t *buf, int buf_size)
00473 {
00474     
00475     
00476     FlicDecodeContext *s = avctx->priv_data;
00477 
00478     GetByteContext g2;
00479     int pixel_ptr;
00480     unsigned char palette_idx1;
00481 
00482     unsigned int frame_size;
00483     int num_chunks;
00484 
00485     unsigned int chunk_size;
00486     int chunk_type;
00487 
00488     int i, j;
00489 
00490     int lines;
00491     int compressed_lines;
00492     signed short line_packets;
00493     int y_ptr;
00494     int byte_run;
00495     int pixel_skip;
00496     int pixel_countdown;
00497     unsigned char *pixels;
00498     int pixel;
00499     unsigned int pixel_limit;
00500 
00501     bytestream2_init(&g2, buf, buf_size);
00502 
00503     s->frame.reference = 3;
00504     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00505     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00506         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00507         return -1;
00508     }
00509 
00510     pixels = s->frame.data[0];
00511     pixel_limit = s->avctx->height * s->frame.linesize[0];
00512 
00513     frame_size = bytestream2_get_le32(&g2);
00514     bytestream2_skip(&g2, 2);  
00515     num_chunks = bytestream2_get_le16(&g2);
00516     bytestream2_skip(&g2, 8);  
00517     if (frame_size > buf_size)
00518         frame_size = buf_size;
00519 
00520     frame_size -= 16;
00521 
00522     
00523     while ((frame_size > 0) && (num_chunks > 0)) {
00524         int stream_ptr_after_chunk;
00525         chunk_size = bytestream2_get_le32(&g2);
00526         if (chunk_size > frame_size) {
00527             av_log(avctx, AV_LOG_WARNING,
00528                    "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
00529             chunk_size = frame_size;
00530         }
00531         stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size;
00532 
00533         chunk_type = bytestream2_get_le16(&g2);
00534 
00535 
00536         switch (chunk_type) {
00537         case FLI_256_COLOR:
00538         case FLI_COLOR:
00539             
00540 
00541 
00542 
00543             bytestream2_skip(&g2, chunk_size - 6);
00544             break;
00545 
00546         case FLI_DELTA:
00547         case FLI_DTA_LC:
00548             y_ptr = 0;
00549             compressed_lines = bytestream2_get_le16(&g2);
00550             while (compressed_lines > 0) {
00551                 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00552                     break;
00553                 line_packets = bytestream2_get_le16(&g2);
00554                 if (line_packets < 0) {
00555                     line_packets = -line_packets;
00556                     y_ptr += line_packets * s->frame.linesize[0];
00557                 } else {
00558                     compressed_lines--;
00559                     pixel_ptr = y_ptr;
00560                     CHECK_PIXEL_PTR(0);
00561                     pixel_countdown = s->avctx->width;
00562                     for (i = 0; i < line_packets; i++) {
00563                         
00564                         if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00565                             break;
00566                         pixel_skip = bytestream2_get_byte(&g2);
00567                         pixel_ptr += (pixel_skip*2); 
00568                         pixel_countdown -= pixel_skip;
00569                         byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00570                         if (byte_run < 0) {
00571                             byte_run = -byte_run;
00572                             pixel    = bytestream2_get_le16(&g2);
00573                             CHECK_PIXEL_PTR(2 * byte_run);
00574                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
00575                                 *((signed short*)(&pixels[pixel_ptr])) = pixel;
00576                                 pixel_ptr += 2;
00577                             }
00578                         } else {
00579                             if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
00580                                 break;
00581                             CHECK_PIXEL_PTR(2 * byte_run);
00582                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
00583                                 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
00584                                 pixel_ptr += 2;
00585                             }
00586                         }
00587                     }
00588 
00589                     y_ptr += s->frame.linesize[0];
00590                 }
00591             }
00592             break;
00593 
00594         case FLI_LC:
00595             av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
00596             bytestream2_skip(&g2, chunk_size - 6);
00597             break;
00598 
00599         case FLI_BLACK:
00600             
00601             memset(pixels, 0x0000,
00602                    s->frame.linesize[0] * s->avctx->height);
00603             break;
00604 
00605         case FLI_BRUN:
00606             y_ptr = 0;
00607             for (lines = 0; lines < s->avctx->height; lines++) {
00608                 pixel_ptr = y_ptr;
00609                 
00610 
00611                 bytestream2_skip(&g2, 1);
00612                 pixel_countdown = (s->avctx->width * 2);
00613 
00614                 while (pixel_countdown > 0) {
00615                     if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00616                         break;
00617                     byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00618                     if (byte_run > 0) {
00619                         palette_idx1 = bytestream2_get_byte(&g2);
00620                         CHECK_PIXEL_PTR(byte_run);
00621                         for (j = 0; j < byte_run; j++) {
00622                             pixels[pixel_ptr++] = palette_idx1;
00623                             pixel_countdown--;
00624                             if (pixel_countdown < 0)
00625                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
00626                                        pixel_countdown, lines);
00627                         }
00628                     } else {  
00629                         byte_run = -byte_run;
00630                         if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
00631                             break;
00632                         CHECK_PIXEL_PTR(byte_run);
00633                         for (j = 0; j < byte_run; j++) {
00634                             palette_idx1 = bytestream2_get_byte(&g2);
00635                             pixels[pixel_ptr++] = palette_idx1;
00636                             pixel_countdown--;
00637                             if (pixel_countdown < 0)
00638                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00639                                        pixel_countdown, lines);
00640                         }
00641                     }
00642                 }
00643 
00644                 
00645 
00646 
00647 
00648 
00649 #if HAVE_BIGENDIAN
00650                 pixel_ptr = y_ptr;
00651                 pixel_countdown = s->avctx->width;
00652                 while (pixel_countdown > 0) {
00653                     *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
00654                     pixel_ptr += 2;
00655                 }
00656 #endif
00657                 y_ptr += s->frame.linesize[0];
00658             }
00659             break;
00660 
00661         case FLI_DTA_BRUN:
00662             y_ptr = 0;
00663             for (lines = 0; lines < s->avctx->height; lines++) {
00664                 pixel_ptr = y_ptr;
00665                 
00666 
00667                 bytestream2_skip(&g2, 1);
00668                 pixel_countdown = s->avctx->width; 
00669 
00670                 while (pixel_countdown > 0) {
00671                     if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00672                         break;
00673                     byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00674                     if (byte_run > 0) {
00675                         pixel    = bytestream2_get_le16(&g2);
00676                         CHECK_PIXEL_PTR(2 * byte_run);
00677                         for (j = 0; j < byte_run; j++) {
00678                             *((signed short*)(&pixels[pixel_ptr])) = pixel;
00679                             pixel_ptr += 2;
00680                             pixel_countdown--;
00681                             if (pixel_countdown < 0)
00682                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00683                                        pixel_countdown);
00684                         }
00685                     } else {  
00686                         byte_run = -byte_run;
00687                         if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
00688                             break;
00689                         CHECK_PIXEL_PTR(2 * byte_run);
00690                         for (j = 0; j < byte_run; j++) {
00691                             *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
00692                             pixel_ptr  += 2;
00693                             pixel_countdown--;
00694                             if (pixel_countdown < 0)
00695                                 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00696                                        pixel_countdown);
00697                         }
00698                     }
00699                 }
00700 
00701                 y_ptr += s->frame.linesize[0];
00702             }
00703             break;
00704 
00705         case FLI_COPY:
00706         case FLI_DTA_COPY:
00707             
00708             if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
00709                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
00710                        "bigger than image, skipping chunk\n", chunk_size - 6);
00711                 bytestream2_skip(&g2, chunk_size - 6);
00712             } else {
00713 
00714                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
00715                      y_ptr += s->frame.linesize[0]) {
00716 
00717                     pixel_countdown = s->avctx->width;
00718                     pixel_ptr = 0;
00719                     while (pixel_countdown > 0) {
00720                       *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
00721                       pixel_ptr += 2;
00722                       pixel_countdown--;
00723                     }
00724                 }
00725             }
00726             break;
00727 
00728         case FLI_MINI:
00729             
00730             bytestream2_skip(&g2, chunk_size - 6);
00731             break;
00732 
00733         default:
00734             av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
00735             break;
00736         }
00737 
00738         frame_size -= chunk_size;
00739         num_chunks--;
00740     }
00741 
00742     
00743 
00744     if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
00745         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
00746                "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
00747 
00748 
00749     *data_size=sizeof(AVFrame);
00750     *(AVFrame*)data = s->frame;
00751 
00752     return buf_size;
00753 }
00754 
00755 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
00756                                    void *data, int *data_size,
00757                                    const uint8_t *buf, int buf_size)
00758 {
00759   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
00760   return -1;
00761 }
00762 
00763 static int flic_decode_frame(AVCodecContext *avctx,
00764                              void *data, int *data_size,
00765                              AVPacket *avpkt)
00766 {
00767     const uint8_t *buf = avpkt->data;
00768     int buf_size = avpkt->size;
00769     if (avctx->pix_fmt == PIX_FMT_PAL8) {
00770       return flic_decode_frame_8BPP(avctx, data, data_size,
00771                                     buf, buf_size);
00772     }
00773     else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
00774              (avctx->pix_fmt == PIX_FMT_RGB565)) {
00775       return flic_decode_frame_15_16BPP(avctx, data, data_size,
00776                                         buf, buf_size);
00777     }
00778     else if (avctx->pix_fmt == PIX_FMT_BGR24) {
00779       return flic_decode_frame_24BPP(avctx, data, data_size,
00780                                      buf, buf_size);
00781     }
00782 
00783     
00784     
00785     
00786     
00787     av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
00788     return -1;
00789 }
00790 
00791 
00792 static av_cold int flic_decode_end(AVCodecContext *avctx)
00793 {
00794     FlicDecodeContext *s = avctx->priv_data;
00795 
00796     if (s->frame.data[0])
00797         avctx->release_buffer(avctx, &s->frame);
00798 
00799     return 0;
00800 }
00801 
00802 AVCodec ff_flic_decoder = {
00803     .name           = "flic",
00804     .type           = AVMEDIA_TYPE_VIDEO,
00805     .id             = AV_CODEC_ID_FLIC,
00806     .priv_data_size = sizeof(FlicDecodeContext),
00807     .init           = flic_decode_init,
00808     .close          = flic_decode_end,
00809     .decode         = flic_decode_frame,
00810     .capabilities   = CODEC_CAP_DR1,
00811     .long_name      = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
00812 };