00001 /* 00002 * FLI/FLC Animation Video Decoder 00003 * Copyright (C) 2003, 2004 the ffmpeg project 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */ 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; /* either 0xAF11 or 0xAF12, affects palette resolution */ 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]); /* Might be overridden if a Magic Carpet FLC */ 00095 00096 depth = 0; 00097 if (s->avctx->extradata_size == 12) { 00098 /* special case for magic carpet FLIs */ 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; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */ 00107 } 00108 00109 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) { 00110 depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */ 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; /* Supposedly BGR, but havent any files to test with */ 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 avcodec_get_frame_defaults(&s->frame); 00126 s->frame.data[0] = NULL; 00127 s->new_palette = 0; 00128 00129 return 0; 00130 } 00131 00132 static int flic_decode_frame_8BPP(AVCodecContext *avctx, 00133 void *data, int *data_size, 00134 const uint8_t *buf, int buf_size) 00135 { 00136 FlicDecodeContext *s = avctx->priv_data; 00137 00138 GetByteContext g2; 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 = 3; 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 if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE)) 00180 return AVERROR_INVALIDDATA; 00181 frame_size = bytestream2_get_le32(&g2); 00182 if (frame_size > buf_size) 00183 frame_size = buf_size; 00184 bytestream2_skip(&g2, 2); /* skip the magic number */ 00185 num_chunks = bytestream2_get_le16(&g2); 00186 bytestream2_skip(&g2, 8); /* skip padding */ 00187 00188 frame_size -= 16; 00189 00190 /* iterate through the chunks */ 00191 while ((frame_size >= 6) && (num_chunks > 0)) { 00192 int stream_ptr_after_chunk; 00193 chunk_size = bytestream2_get_le32(&g2); 00194 if (chunk_size > frame_size) { 00195 av_log(avctx, AV_LOG_WARNING, 00196 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size); 00197 chunk_size = frame_size; 00198 } 00199 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size; 00200 00201 chunk_type = bytestream2_get_le16(&g2); 00202 00203 switch (chunk_type) { 00204 case FLI_256_COLOR: 00205 case FLI_COLOR: 00206 /* check special case: If this file is from the Magic Carpet 00207 * game and uses 6-bit colors even though it reports 256-color 00208 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during 00209 * initialization) */ 00210 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE)) 00211 color_shift = 0; 00212 else 00213 color_shift = 2; 00214 /* set up the palette */ 00215 color_packets = bytestream2_get_le16(&g2); 00216 palette_ptr = 0; 00217 for (i = 0; i < color_packets; i++) { 00218 /* first byte is how many colors to skip */ 00219 palette_ptr += bytestream2_get_byte(&g2); 00220 00221 /* next byte indicates how many entries to change */ 00222 color_changes = bytestream2_get_byte(&g2); 00223 00224 /* if there are 0 color changes, there are actually 256 */ 00225 if (color_changes == 0) 00226 color_changes = 256; 00227 00228 if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk) 00229 break; 00230 00231 for (j = 0; j < color_changes; j++) { 00232 unsigned int entry; 00233 00234 /* wrap around, for good measure */ 00235 if ((unsigned)palette_ptr >= 256) 00236 palette_ptr = 0; 00237 00238 r = bytestream2_get_byte(&g2) << color_shift; 00239 g = bytestream2_get_byte(&g2) << color_shift; 00240 b = bytestream2_get_byte(&g2) << 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 = bytestream2_get_le16(&g2); 00254 while (compressed_lines > 0) { 00255 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) 00256 break; 00257 line_packets = bytestream2_get_le16(&g2); 00258 if ((line_packets & 0xC000) == 0xC000) { 00259 // line skip opcode 00260 line_packets = -line_packets; 00261 y_ptr += line_packets * s->frame.linesize[0]; 00262 } else if ((line_packets & 0xC000) == 0x4000) { 00263 av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets); 00264 } else if ((line_packets & 0xC000) == 0x8000) { 00265 // "last byte" opcode 00266 pixel_ptr= y_ptr + s->frame.linesize[0] - 1; 00267 CHECK_PIXEL_PTR(0); 00268 pixels[pixel_ptr] = line_packets & 0xff; 00269 } else { 00270 compressed_lines--; 00271 pixel_ptr = y_ptr; 00272 CHECK_PIXEL_PTR(0); 00273 pixel_countdown = s->avctx->width; 00274 for (i = 0; i < line_packets; i++) { 00275 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) 00276 break; 00277 /* account for the skip bytes */ 00278 pixel_skip = bytestream2_get_byte(&g2); 00279 pixel_ptr += pixel_skip; 00280 pixel_countdown -= pixel_skip; 00281 byte_run = sign_extend(bytestream2_get_byte(&g2), 8); 00282 if (byte_run < 0) { 00283 byte_run = -byte_run; 00284 palette_idx1 = bytestream2_get_byte(&g2); 00285 palette_idx2 = bytestream2_get_byte(&g2); 00286 CHECK_PIXEL_PTR(byte_run * 2); 00287 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 00288 pixels[pixel_ptr++] = palette_idx1; 00289 pixels[pixel_ptr++] = palette_idx2; 00290 } 00291 } else { 00292 CHECK_PIXEL_PTR(byte_run * 2); 00293 if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk) 00294 break; 00295 for (j = 0; j < byte_run * 2; j++, pixel_countdown--) { 00296 pixels[pixel_ptr++] = bytestream2_get_byte(&g2); 00297 } 00298 } 00299 } 00300 00301 y_ptr += s->frame.linesize[0]; 00302 } 00303 } 00304 break; 00305 00306 case FLI_LC: 00307 /* line compressed */ 00308 starting_line = bytestream2_get_le16(&g2); 00309 y_ptr = 0; 00310 y_ptr += starting_line * s->frame.linesize[0]; 00311 00312 compressed_lines = bytestream2_get_le16(&g2); 00313 while (compressed_lines > 0) { 00314 pixel_ptr = y_ptr; 00315 CHECK_PIXEL_PTR(0); 00316 pixel_countdown = s->avctx->width; 00317 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) 00318 break; 00319 line_packets = bytestream2_get_byte(&g2); 00320 if (line_packets > 0) { 00321 for (i = 0; i < line_packets; i++) { 00322 /* account for the skip bytes */ 00323 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) 00324 break; 00325 pixel_skip = bytestream2_get_byte(&g2); 00326 pixel_ptr += pixel_skip; 00327 pixel_countdown -= pixel_skip; 00328 byte_run = sign_extend(bytestream2_get_byte(&g2),8); 00329 if (byte_run > 0) { 00330 CHECK_PIXEL_PTR(byte_run); 00331 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) 00332 break; 00333 for (j = 0; j < byte_run; j++, pixel_countdown--) { 00334 pixels[pixel_ptr++] = bytestream2_get_byte(&g2); 00335 } 00336 } else if (byte_run < 0) { 00337 byte_run = -byte_run; 00338 palette_idx1 = bytestream2_get_byte(&g2); 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 /* set the whole frame to color 0 (which is usually black) */ 00354 memset(pixels, 0, 00355 s->frame.linesize[0] * s->avctx->height); 00356 break; 00357 00358 case FLI_BRUN: 00359 /* Byte run compression: This chunk type only occurs in the first 00360 * FLI frame and it will update the entire frame. */ 00361 y_ptr = 0; 00362 for (lines = 0; lines < s->avctx->height; lines++) { 00363 pixel_ptr = y_ptr; 00364 /* disregard the line packets; instead, iterate through all 00365 * pixels on a row */ 00366 bytestream2_skip(&g2, 1); 00367 pixel_countdown = s->avctx->width; 00368 while (pixel_countdown > 0) { 00369 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) 00370 break; 00371 byte_run = sign_extend(bytestream2_get_byte(&g2), 8); 00372 if (byte_run > 0) { 00373 palette_idx1 = bytestream2_get_byte(&g2); 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 { /* copy bytes if byte_run < 0 */ 00383 byte_run = -byte_run; 00384 CHECK_PIXEL_PTR(byte_run); 00385 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) 00386 break; 00387 for (j = 0; j < byte_run; j++) { 00388 pixels[pixel_ptr++] = bytestream2_get_byte(&g2); 00389 pixel_countdown--; 00390 if (pixel_countdown < 0) 00391 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 00392 pixel_countdown, lines); 00393 } 00394 } 00395 } 00396 00397 y_ptr += s->frame.linesize[0]; 00398 } 00399 break; 00400 00401 case FLI_COPY: 00402 /* copy the chunk (uncompressed frame) */ 00403 if (chunk_size - 6 != s->avctx->width * s->avctx->height) { 00404 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 00405 "has incorrect size, skipping chunk\n", chunk_size - 6); 00406 bytestream2_skip(&g2, 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 bytestream2_get_buffer(&g2, &pixels[y_ptr], 00411 s->avctx->width); 00412 } 00413 } 00414 break; 00415 00416 case FLI_MINI: 00417 /* some sort of a thumbnail? disregard this chunk... */ 00418 break; 00419 00420 default: 00421 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 00422 break; 00423 } 00424 00425 if (stream_ptr_after_chunk - bytestream2_tell(&g2) > 0) 00426 bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2)); 00427 00428 frame_size -= chunk_size; 00429 num_chunks--; 00430 } 00431 00432 /* by the end of the chunk, the stream ptr should equal the frame 00433 * size (minus 1, possibly); if it doesn't, issue a warning */ 00434 if ((bytestream2_get_bytes_left(&g2) != 0) && 00435 (bytestream2_get_bytes_left(&g2) != 1)) 00436 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 00437 "and final chunk ptr = %d\n", buf_size, 00438 buf_size - bytestream2_get_bytes_left(&g2)); 00439 00440 /* make the palette available on the way out */ 00441 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); 00442 if (s->new_palette) { 00443 s->frame.palette_has_changed = 1; 00444 s->new_palette = 0; 00445 } 00446 00447 *data_size=sizeof(AVFrame); 00448 *(AVFrame*)data = s->frame; 00449 00450 return buf_size; 00451 } 00452 00453 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, 00454 void *data, int *data_size, 00455 const uint8_t *buf, int buf_size) 00456 { 00457 /* Note, the only difference between the 15Bpp and 16Bpp */ 00458 /* Format is the pixel format, the packets are processed the same. */ 00459 FlicDecodeContext *s = avctx->priv_data; 00460 00461 GetByteContext g2; 00462 int pixel_ptr; 00463 unsigned char palette_idx1; 00464 00465 unsigned int frame_size; 00466 int num_chunks; 00467 00468 unsigned int chunk_size; 00469 int chunk_type; 00470 00471 int i, j; 00472 00473 int lines; 00474 int compressed_lines; 00475 signed short line_packets; 00476 int y_ptr; 00477 int byte_run; 00478 int pixel_skip; 00479 int pixel_countdown; 00480 unsigned char *pixels; 00481 int pixel; 00482 unsigned int pixel_limit; 00483 00484 bytestream2_init(&g2, buf, buf_size); 00485 00486 s->frame.reference = 3; 00487 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00488 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 00489 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00490 return -1; 00491 } 00492 00493 pixels = s->frame.data[0]; 00494 pixel_limit = s->avctx->height * s->frame.linesize[0]; 00495 00496 frame_size = bytestream2_get_le32(&g2); 00497 bytestream2_skip(&g2, 2); /* skip the magic number */ 00498 num_chunks = bytestream2_get_le16(&g2); 00499 bytestream2_skip(&g2, 8); /* skip padding */ 00500 if (frame_size > buf_size) 00501 frame_size = buf_size; 00502 00503 frame_size -= 16; 00504 00505 /* iterate through the chunks */ 00506 while ((frame_size > 0) && (num_chunks > 0)) { 00507 int stream_ptr_after_chunk; 00508 chunk_size = bytestream2_get_le32(&g2); 00509 if (chunk_size > frame_size) { 00510 av_log(avctx, AV_LOG_WARNING, 00511 "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size); 00512 chunk_size = frame_size; 00513 } 00514 stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size; 00515 00516 chunk_type = bytestream2_get_le16(&g2); 00517 00518 00519 switch (chunk_type) { 00520 case FLI_256_COLOR: 00521 case FLI_COLOR: 00522 /* For some reason, it seems that non-palettized flics do 00523 * include one of these chunks in their first frame. 00524 * Why I do not know, it seems rather extraneous. */ 00525 /* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/ 00526 bytestream2_skip(&g2, chunk_size - 6); 00527 break; 00528 00529 case FLI_DELTA: 00530 case FLI_DTA_LC: 00531 y_ptr = 0; 00532 compressed_lines = bytestream2_get_le16(&g2); 00533 while (compressed_lines > 0) { 00534 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) 00535 break; 00536 line_packets = bytestream2_get_le16(&g2); 00537 if (line_packets < 0) { 00538 line_packets = -line_packets; 00539 y_ptr += line_packets * s->frame.linesize[0]; 00540 } else { 00541 compressed_lines--; 00542 pixel_ptr = y_ptr; 00543 CHECK_PIXEL_PTR(0); 00544 pixel_countdown = s->avctx->width; 00545 for (i = 0; i < line_packets; i++) { 00546 /* account for the skip bytes */ 00547 if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) 00548 break; 00549 pixel_skip = bytestream2_get_byte(&g2); 00550 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */ 00551 pixel_countdown -= pixel_skip; 00552 byte_run = sign_extend(bytestream2_get_byte(&g2), 8); 00553 if (byte_run < 0) { 00554 byte_run = -byte_run; 00555 pixel = bytestream2_get_le16(&g2); 00556 CHECK_PIXEL_PTR(2 * byte_run); 00557 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 00558 *((signed short*)(&pixels[pixel_ptr])) = pixel; 00559 pixel_ptr += 2; 00560 } 00561 } else { 00562 if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk) 00563 break; 00564 CHECK_PIXEL_PTR(2 * byte_run); 00565 for (j = 0; j < byte_run; j++, pixel_countdown--) { 00566 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2); 00567 pixel_ptr += 2; 00568 } 00569 } 00570 } 00571 00572 y_ptr += s->frame.linesize[0]; 00573 } 00574 } 00575 break; 00576 00577 case FLI_LC: 00578 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n"); 00579 bytestream2_skip(&g2, chunk_size - 6); 00580 break; 00581 00582 case FLI_BLACK: 00583 /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */ 00584 memset(pixels, 0x0000, 00585 s->frame.linesize[0] * s->avctx->height); 00586 break; 00587 00588 case FLI_BRUN: 00589 y_ptr = 0; 00590 for (lines = 0; lines < s->avctx->height; lines++) { 00591 pixel_ptr = y_ptr; 00592 /* disregard the line packets; instead, iterate through all 00593 * pixels on a row */ 00594 bytestream2_skip(&g2, 1); 00595 pixel_countdown = (s->avctx->width * 2); 00596 00597 while (pixel_countdown > 0) { 00598 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) 00599 break; 00600 byte_run = sign_extend(bytestream2_get_byte(&g2), 8); 00601 if (byte_run > 0) { 00602 palette_idx1 = bytestream2_get_byte(&g2); 00603 CHECK_PIXEL_PTR(byte_run); 00604 for (j = 0; j < byte_run; j++) { 00605 pixels[pixel_ptr++] = palette_idx1; 00606 pixel_countdown--; 00607 if (pixel_countdown < 0) 00608 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n", 00609 pixel_countdown, lines); 00610 } 00611 } else { /* copy bytes if byte_run < 0 */ 00612 byte_run = -byte_run; 00613 if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) 00614 break; 00615 CHECK_PIXEL_PTR(byte_run); 00616 for (j = 0; j < byte_run; j++) { 00617 palette_idx1 = bytestream2_get_byte(&g2); 00618 pixels[pixel_ptr++] = palette_idx1; 00619 pixel_countdown--; 00620 if (pixel_countdown < 0) 00621 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 00622 pixel_countdown, lines); 00623 } 00624 } 00625 } 00626 00627 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed. 00628 * This does not give us any good oportunity to perform word endian conversion 00629 * during decompression. So if it is required (i.e., this is not a LE target, we do 00630 * a second pass over the line here, swapping the bytes. 00631 */ 00632 #if HAVE_BIGENDIAN 00633 pixel_ptr = y_ptr; 00634 pixel_countdown = s->avctx->width; 00635 while (pixel_countdown > 0) { 00636 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]); 00637 pixel_ptr += 2; 00638 } 00639 #endif 00640 y_ptr += s->frame.linesize[0]; 00641 } 00642 break; 00643 00644 case FLI_DTA_BRUN: 00645 y_ptr = 0; 00646 for (lines = 0; lines < s->avctx->height; lines++) { 00647 pixel_ptr = y_ptr; 00648 /* disregard the line packets; instead, iterate through all 00649 * pixels on a row */ 00650 bytestream2_skip(&g2, 1); 00651 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */ 00652 00653 while (pixel_countdown > 0) { 00654 if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) 00655 break; 00656 byte_run = sign_extend(bytestream2_get_byte(&g2), 8); 00657 if (byte_run > 0) { 00658 pixel = bytestream2_get_le16(&g2); 00659 CHECK_PIXEL_PTR(2 * byte_run); 00660 for (j = 0; j < byte_run; j++) { 00661 *((signed short*)(&pixels[pixel_ptr])) = pixel; 00662 pixel_ptr += 2; 00663 pixel_countdown--; 00664 if (pixel_countdown < 0) 00665 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 00666 pixel_countdown); 00667 } 00668 } else { /* copy pixels if byte_run < 0 */ 00669 byte_run = -byte_run; 00670 if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk) 00671 break; 00672 CHECK_PIXEL_PTR(2 * byte_run); 00673 for (j = 0; j < byte_run; j++) { 00674 *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2); 00675 pixel_ptr += 2; 00676 pixel_countdown--; 00677 if (pixel_countdown < 0) 00678 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 00679 pixel_countdown); 00680 } 00681 } 00682 } 00683 00684 y_ptr += s->frame.linesize[0]; 00685 } 00686 break; 00687 00688 case FLI_COPY: 00689 case FLI_DTA_COPY: 00690 /* copy the chunk (uncompressed frame) */ 00691 if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) { 00692 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 00693 "bigger than image, skipping chunk\n", chunk_size - 6); 00694 bytestream2_skip(&g2, chunk_size - 6); 00695 } else { 00696 00697 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; 00698 y_ptr += s->frame.linesize[0]) { 00699 00700 pixel_countdown = s->avctx->width; 00701 pixel_ptr = 0; 00702 while (pixel_countdown > 0) { 00703 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2); 00704 pixel_ptr += 2; 00705 pixel_countdown--; 00706 } 00707 } 00708 } 00709 break; 00710 00711 case FLI_MINI: 00712 /* some sort of a thumbnail? disregard this chunk... */ 00713 bytestream2_skip(&g2, chunk_size - 6); 00714 break; 00715 00716 default: 00717 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 00718 break; 00719 } 00720 00721 frame_size -= chunk_size; 00722 num_chunks--; 00723 } 00724 00725 /* by the end of the chunk, the stream ptr should equal the frame 00726 * size (minus 1, possibly); if it doesn't, issue a warning */ 00727 if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1)) 00728 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 00729 "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2)); 00730 00731 00732 *data_size=sizeof(AVFrame); 00733 *(AVFrame*)data = s->frame; 00734 00735 return buf_size; 00736 } 00737 00738 static int flic_decode_frame_24BPP(AVCodecContext *avctx, 00739 void *data, int *data_size, 00740 const uint8_t *buf, int buf_size) 00741 { 00742 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n"); 00743 return -1; 00744 } 00745 00746 static int flic_decode_frame(AVCodecContext *avctx, 00747 void *data, int *data_size, 00748 AVPacket *avpkt) 00749 { 00750 const uint8_t *buf = avpkt->data; 00751 int buf_size = avpkt->size; 00752 if (avctx->pix_fmt == PIX_FMT_PAL8) { 00753 return flic_decode_frame_8BPP(avctx, data, data_size, 00754 buf, buf_size); 00755 } 00756 else if ((avctx->pix_fmt == PIX_FMT_RGB555) || 00757 (avctx->pix_fmt == PIX_FMT_RGB565)) { 00758 return flic_decode_frame_15_16BPP(avctx, data, data_size, 00759 buf, buf_size); 00760 } 00761 else if (avctx->pix_fmt == PIX_FMT_BGR24) { 00762 return flic_decode_frame_24BPP(avctx, data, data_size, 00763 buf, buf_size); 00764 } 00765 00766 /* Should not get here, ever as the pix_fmt is processed */ 00767 /* in flic_decode_init and the above if should deal with */ 00768 /* the finite set of possibilites allowable by here. */ 00769 /* But in case we do, just error out. */ 00770 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n"); 00771 return -1; 00772 } 00773 00774 00775 static av_cold int flic_decode_end(AVCodecContext *avctx) 00776 { 00777 FlicDecodeContext *s = avctx->priv_data; 00778 00779 if (s->frame.data[0]) 00780 avctx->release_buffer(avctx, &s->frame); 00781 00782 return 0; 00783 } 00784 00785 AVCodec ff_flic_decoder = { 00786 .name = "flic", 00787 .type = AVMEDIA_TYPE_VIDEO, 00788 .id = CODEC_ID_FLIC, 00789 .priv_data_size = sizeof(FlicDecodeContext), 00790 .init = flic_decode_init, 00791 .close = flic_decode_end, 00792 .decode = flic_decode_frame, 00793 .capabilities = CODEC_CAP_DR1, 00794 .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), 00795 };