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 = AV_PIX_FMT_PAL8; break;
00133 case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
00134 case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
00135 case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24;
00136 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
00137 return AVERROR_PATCHWELCOME;
00138 default :
00139 av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
00140 return AVERROR_INVALIDDATA;
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 *got_frame,
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, ret;
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 ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00191 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00192 return ret;
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 = 0xFFU << 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 *got_frame = 1;
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 *got_frame,
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, ret;
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 ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
00506 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00507 return ret;
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 av_dlog(avctx,
00543 "Unexpected Palette chunk %d in non-palettized FLC\n",
00544 chunk_type);
00545 bytestream2_skip(&g2, chunk_size - 6);
00546 break;
00547
00548 case FLI_DELTA:
00549 case FLI_DTA_LC:
00550 y_ptr = 0;
00551 compressed_lines = bytestream2_get_le16(&g2);
00552 while (compressed_lines > 0) {
00553 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00554 break;
00555 line_packets = bytestream2_get_le16(&g2);
00556 if (line_packets < 0) {
00557 line_packets = -line_packets;
00558 y_ptr += line_packets * s->frame.linesize[0];
00559 } else {
00560 compressed_lines--;
00561 pixel_ptr = y_ptr;
00562 CHECK_PIXEL_PTR(0);
00563 pixel_countdown = s->avctx->width;
00564 for (i = 0; i < line_packets; i++) {
00565
00566 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk)
00567 break;
00568 pixel_skip = bytestream2_get_byte(&g2);
00569 pixel_ptr += (pixel_skip*2);
00570 pixel_countdown -= pixel_skip;
00571 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00572 if (byte_run < 0) {
00573 byte_run = -byte_run;
00574 pixel = bytestream2_get_le16(&g2);
00575 CHECK_PIXEL_PTR(2 * byte_run);
00576 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
00577 *((signed short*)(&pixels[pixel_ptr])) = pixel;
00578 pixel_ptr += 2;
00579 }
00580 } else {
00581 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk)
00582 break;
00583 CHECK_PIXEL_PTR(2 * byte_run);
00584 for (j = 0; j < byte_run; j++, pixel_countdown--) {
00585 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
00586 pixel_ptr += 2;
00587 }
00588 }
00589 }
00590
00591 y_ptr += s->frame.linesize[0];
00592 }
00593 }
00594 break;
00595
00596 case FLI_LC:
00597 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
00598 bytestream2_skip(&g2, chunk_size - 6);
00599 break;
00600
00601 case FLI_BLACK:
00602
00603 memset(pixels, 0x0000,
00604 s->frame.linesize[0] * s->avctx->height);
00605 break;
00606
00607 case FLI_BRUN:
00608 y_ptr = 0;
00609 for (lines = 0; lines < s->avctx->height; lines++) {
00610 pixel_ptr = y_ptr;
00611
00612
00613 bytestream2_skip(&g2, 1);
00614 pixel_countdown = (s->avctx->width * 2);
00615
00616 while (pixel_countdown > 0) {
00617 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00618 break;
00619 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00620 if (byte_run > 0) {
00621 palette_idx1 = bytestream2_get_byte(&g2);
00622 CHECK_PIXEL_PTR(byte_run);
00623 for (j = 0; j < byte_run; j++) {
00624 pixels[pixel_ptr++] = palette_idx1;
00625 pixel_countdown--;
00626 if (pixel_countdown < 0)
00627 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
00628 pixel_countdown, lines);
00629 }
00630 } else {
00631 byte_run = -byte_run;
00632 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk)
00633 break;
00634 CHECK_PIXEL_PTR(byte_run);
00635 for (j = 0; j < byte_run; j++) {
00636 palette_idx1 = bytestream2_get_byte(&g2);
00637 pixels[pixel_ptr++] = palette_idx1;
00638 pixel_countdown--;
00639 if (pixel_countdown < 0)
00640 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
00641 pixel_countdown, lines);
00642 }
00643 }
00644 }
00645
00646
00647
00648
00649
00650
00651 #if HAVE_BIGENDIAN
00652 pixel_ptr = y_ptr;
00653 pixel_countdown = s->avctx->width;
00654 while (pixel_countdown > 0) {
00655 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
00656 pixel_ptr += 2;
00657 }
00658 #endif
00659 y_ptr += s->frame.linesize[0];
00660 }
00661 break;
00662
00663 case FLI_DTA_BRUN:
00664 y_ptr = 0;
00665 for (lines = 0; lines < s->avctx->height; lines++) {
00666 pixel_ptr = y_ptr;
00667
00668
00669 bytestream2_skip(&g2, 1);
00670 pixel_countdown = s->avctx->width;
00671
00672 while (pixel_countdown > 0) {
00673 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
00674 break;
00675 byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
00676 if (byte_run > 0) {
00677 pixel = bytestream2_get_le16(&g2);
00678 CHECK_PIXEL_PTR(2 * byte_run);
00679 for (j = 0; j < byte_run; j++) {
00680 *((signed short*)(&pixels[pixel_ptr])) = pixel;
00681 pixel_ptr += 2;
00682 pixel_countdown--;
00683 if (pixel_countdown < 0)
00684 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00685 pixel_countdown);
00686 }
00687 } else {
00688 byte_run = -byte_run;
00689 if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk)
00690 break;
00691 CHECK_PIXEL_PTR(2 * byte_run);
00692 for (j = 0; j < byte_run; j++) {
00693 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2);
00694 pixel_ptr += 2;
00695 pixel_countdown--;
00696 if (pixel_countdown < 0)
00697 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
00698 pixel_countdown);
00699 }
00700 }
00701 }
00702
00703 y_ptr += s->frame.linesize[0];
00704 }
00705 break;
00706
00707 case FLI_COPY:
00708 case FLI_DTA_COPY:
00709
00710 if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
00711 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
00712 "bigger than image, skipping chunk\n", chunk_size - 6);
00713 bytestream2_skip(&g2, chunk_size - 6);
00714 } else {
00715
00716 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
00717 y_ptr += s->frame.linesize[0]) {
00718
00719 pixel_countdown = s->avctx->width;
00720 pixel_ptr = 0;
00721 while (pixel_countdown > 0) {
00722 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2);
00723 pixel_ptr += 2;
00724 pixel_countdown--;
00725 }
00726 }
00727 }
00728 break;
00729
00730 case FLI_MINI:
00731
00732 bytestream2_skip(&g2, chunk_size - 6);
00733 break;
00734
00735 default:
00736 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
00737 break;
00738 }
00739
00740 frame_size -= chunk_size;
00741 num_chunks--;
00742 }
00743
00744
00745
00746 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1))
00747 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
00748 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
00749
00750
00751 *got_frame = 1;
00752 *(AVFrame*)data = s->frame;
00753
00754 return buf_size;
00755 }
00756
00757 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
00758 void *data, int *got_frame,
00759 const uint8_t *buf, int buf_size)
00760 {
00761 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
00762 return AVERROR_PATCHWELCOME;
00763 }
00764
00765 static int flic_decode_frame(AVCodecContext *avctx,
00766 void *data, int *got_frame,
00767 AVPacket *avpkt)
00768 {
00769 const uint8_t *buf = avpkt->data;
00770 int buf_size = avpkt->size;
00771 if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
00772 return flic_decode_frame_8BPP(avctx, data, got_frame,
00773 buf, buf_size);
00774 }
00775 else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
00776 (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
00777 return flic_decode_frame_15_16BPP(avctx, data, got_frame,
00778 buf, buf_size);
00779 }
00780 else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
00781 return flic_decode_frame_24BPP(avctx, data, got_frame,
00782 buf, buf_size);
00783 }
00784
00785
00786
00787
00788
00789 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
00790 return AVERROR_INVALIDDATA;
00791 }
00792
00793
00794 static av_cold int flic_decode_end(AVCodecContext *avctx)
00795 {
00796 FlicDecodeContext *s = avctx->priv_data;
00797
00798 if (s->frame.data[0])
00799 avctx->release_buffer(avctx, &s->frame);
00800
00801 return 0;
00802 }
00803
00804 AVCodec ff_flic_decoder = {
00805 .name = "flic",
00806 .type = AVMEDIA_TYPE_VIDEO,
00807 .id = AV_CODEC_ID_FLIC,
00808 .priv_data_size = sizeof(FlicDecodeContext),
00809 .init = flic_decode_init,
00810 .close = flic_decode_end,
00811 .decode = flic_decode_frame,
00812 .capabilities = CODEC_CAP_DR1,
00813 .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
00814 };