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