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_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;
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]);
00095
00096 depth = 0;
00097 if (s->avctx->extradata_size == 12) {
00098
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;
00107 }
00108
00109 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
00110 depth = 15;
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;
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);
00181 num_chunks = bytestream2_get_le16(&g2);
00182 bytestream2_skip(&g2, 8);
00183
00184 frame_size -= 16;
00185
00186
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
00197
00198
00199
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
00205 color_packets = bytestream2_get_le16(&g2);
00206 palette_ptr = 0;
00207 for (i = 0; i < color_packets; i++) {
00208
00209 palette_ptr += bytestream2_get_byte(&g2);
00210
00211
00212 color_changes = bytestream2_get_byte(&g2);
00213
00214
00215 if (color_changes == 0)
00216 color_changes = 256;
00217
00218 for (j = 0; j < color_changes; j++) {
00219 unsigned int entry;
00220
00221
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
00236
00237
00238
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
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
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
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
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
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
00335 memset(pixels, 0,
00336 s->frame.linesize[0] * s->avctx->height);
00337 break;
00338
00339 case FLI_BRUN:
00340
00341
00342 y_ptr = 0;
00343 for (lines = 0; lines < s->avctx->height; lines++) {
00344 pixel_ptr = y_ptr;
00345
00346
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 {
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
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
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
00408
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
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
00433
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);
00473 num_chunks = bytestream2_get_le16(&g2);
00474 bytestream2_skip(&g2, 8);
00475
00476 frame_size -= 16;
00477
00478
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
00487
00488
00489
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
00509 pixel_skip = bytestream2_get_byte(&g2);
00510 pixel_ptr += (pixel_skip*2);
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
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
00551
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 {
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
00582
00583
00584
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
00603
00604 bytestream2_skip(&g2, 1);
00605 pixel_countdown = s->avctx->width;
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 {
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
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
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
00676
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
00717
00718
00719
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 };