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 = 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 };