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
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)
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;
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]);
00087
00088 depth = 0;
00089 if (s->avctx->extradata_size == 12) {
00090
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;
00102 }
00103
00104 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
00105 depth = 15;
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;
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;
00180 num_chunks = AV_RL16(&buf[stream_ptr]);
00181 stream_ptr += 10;
00182
00183 frame_size -= 16;
00184
00185
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
00204
00205
00206
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
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
00217 palette_ptr += buf[stream_ptr++];
00218
00219
00220 color_changes = buf[stream_ptr++];
00221
00222
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
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
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
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
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
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
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
00354 memset(pixels, 0,
00355 s->frame.linesize[0] * s->avctx->height);
00356 break;
00357
00358 case FLI_BRUN:
00359
00360
00361 y_ptr = 0;
00362 for (lines = 0; lines < s->avctx->height; lines++) {
00363 pixel_ptr = y_ptr;
00364
00365
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 {
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
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
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
00433
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
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
00456
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;
00494 num_chunks = AV_RL16(&buf[stream_ptr]);
00495 stream_ptr += 10;
00496
00497 frame_size -= 16;
00498
00499
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
00510
00511
00512
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
00534 pixel_skip = buf[stream_ptr++];
00535 pixel_ptr += (pixel_skip*2);
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
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
00578
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 {
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
00609
00610
00611
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
00630
00631 stream_ptr++;
00632 pixel_countdown = s->avctx->width;
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 {
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
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
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
00706
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
00747
00748
00749
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 };