Libav 0.7.1
|
00001 /* 00002 * FLI/FLC Animation Video Decoder 00003 * Copyright (C) 2003, 2004 the ffmpeg project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 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) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */ 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_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \ 00065 pixel_ptr + n, pixel_limit); \ 00066 return -1; \ 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; /* either 0xAF11 or 0xAF12, affects palette resolution */ 00076 } FlicDecodeContext; 00077 00078 static av_cold int flic_decode_init(AVCodecContext *avctx) 00079 { 00080 FlicDecodeContext *s = avctx->priv_data; 00081 unsigned char *fli_header = (unsigned char *)avctx->extradata; 00082 int depth; 00083 00084 s->avctx = avctx; 00085 00086 s->fli_type = AV_RL16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */ 00087 00088 depth = 0; 00089 if (s->avctx->extradata_size == 12) { 00090 /* special case for magic carpet FLIs */ 00091 s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE; 00092 depth = 8; 00093 } else if (s->avctx->extradata_size != 128) { 00094 av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n"); 00095 return -1; 00096 } else { 00097 depth = AV_RL16(&fli_header[12]); 00098 } 00099 00100 if (depth == 0) { 00101 depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */ 00102 } 00103 00104 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) { 00105 depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */ 00106 } 00107 00108 switch (depth) { 00109 case 8 : avctx->pix_fmt = PIX_FMT_PAL8; break; 00110 case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break; 00111 case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break; 00112 case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */ 00113 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n"); 00114 return -1; 00115 break; 00116 default : 00117 av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth); 00118 return -1; 00119 } 00120 00121 s->frame.data[0] = NULL; 00122 s->new_palette = 0; 00123 00124 return 0; 00125 } 00126 00127 static int flic_decode_frame_8BPP(AVCodecContext *avctx, 00128 void *data, int *data_size, 00129 const uint8_t *buf, int buf_size) 00130 { 00131 FlicDecodeContext *s = avctx->priv_data; 00132 00133 int stream_ptr = 0; 00134 int stream_ptr_after_color_chunk; 00135 int pixel_ptr; 00136 int palette_ptr; 00137 unsigned char palette_idx1; 00138 unsigned char palette_idx2; 00139 00140 unsigned int frame_size; 00141 int num_chunks; 00142 00143 unsigned int chunk_size; 00144 int chunk_type; 00145 00146 int i, j; 00147 00148 int color_packets; 00149 int color_changes; 00150 int color_shift; 00151 unsigned char r, g, b; 00152 00153 int lines; 00154 int compressed_lines; 00155 int starting_line; 00156 signed short line_packets; 00157 int y_ptr; 00158 int byte_run; 00159 int pixel_skip; 00160 int pixel_countdown; 00161 unsigned char *pixels; 00162 unsigned int pixel_limit; 00163 00164 s->frame.reference = 1; 00165 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00166 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 00167 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00168 return -1; 00169 } 00170 00171 pixels = s->frame.data[0]; 00172 pixel_limit = s->avctx->height * s->frame.linesize[0]; 00173 00174 frame_size = AV_RL32(&buf[stream_ptr]); 00175 stream_ptr += 6; /* skip the magic number */ 00176 num_chunks = AV_RL16(&buf[stream_ptr]); 00177 stream_ptr += 10; /* skip padding */ 00178 00179 frame_size -= 16; 00180 00181 /* iterate through the chunks */ 00182 while ((frame_size > 0) && (num_chunks > 0)) { 00183 chunk_size = AV_RL32(&buf[stream_ptr]); 00184 stream_ptr += 4; 00185 chunk_type = AV_RL16(&buf[stream_ptr]); 00186 stream_ptr += 2; 00187 00188 switch (chunk_type) { 00189 case FLI_256_COLOR: 00190 case FLI_COLOR: 00191 stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6; 00192 00193 /* check special case: If this file is from the Magic Carpet 00194 * game and uses 6-bit colors even though it reports 256-color 00195 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during 00196 * initialization) */ 00197 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE)) 00198 color_shift = 0; 00199 else 00200 color_shift = 2; 00201 /* set up the palette */ 00202 color_packets = AV_RL16(&buf[stream_ptr]); 00203 stream_ptr += 2; 00204 palette_ptr = 0; 00205 for (i = 0; i < color_packets; i++) { 00206 /* first byte is how many colors to skip */ 00207 palette_ptr += buf[stream_ptr++]; 00208 00209 /* next byte indicates how many entries to change */ 00210 color_changes = buf[stream_ptr++]; 00211 00212 /* if there are 0 color changes, there are actually 256 */ 00213 if (color_changes == 0) 00214 color_changes = 256; 00215 00216 for (j = 0; j < color_changes; j++) { 00217 unsigned int entry; 00218 00219 /* wrap around, for good measure */ 00220 if ((unsigned)palette_ptr >= 256) 00221 palette_ptr = 0; 00222 00223 r = buf[stream_ptr++] << color_shift; 00224 g = buf[stream_ptr++] << color_shift; 00225 b = buf[stream_ptr++] << color_shift; 00226 entry = (r << 16) | (g << 8) | b; 00227 if (s->palette[palette_ptr] != entry) 00228 s->new_palette = 1; 00229 s->palette[palette_ptr++] = entry; 00230 } 00231 } 00232 00233 /* color chunks sometimes have weird 16-bit alignment issues; 00234 * therefore, take the hardline approach and set the stream_ptr 00235 * to the value calculated w.r.t. the size specified by the color 00236 * chunk header */ 00237 stream_ptr = stream_ptr_after_color_chunk; 00238 00239 break; 00240 00241 case FLI_DELTA: 00242 y_ptr = 0; 00243 compressed_lines = AV_RL16(&buf[stream_ptr]); 00244 stream_ptr += 2; 00245 while (compressed_lines > 0) { 00246 line_packets = AV_RL16(&buf[stream_ptr]); 00247 stream_ptr += 2; 00248 if ((line_packets & 0xC000) == 0xC000) { 00249 // line skip opcode 00250 line_packets = -line_packets; 00251 y_ptr += line_packets * s->frame.linesize[0]; 00252 } else if ((line_packets & 0xC000) == 0x4000) { 00253 av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets); 00254 } else if ((line_packets & 0xC000) == 0x8000) { 00255 // "last byte" opcode 00256 pixel_ptr= y_ptr + s->frame.linesize[0] - 1; 00257 CHECK_PIXEL_PTR(0); 00258 pixels[pixel_ptr] = line_packets & 0xff; 00259 } else { 00260 compressed_lines--; 00261 pixel_ptr = y_ptr; 00262 CHECK_PIXEL_PTR(0); 00263 pixel_countdown = s->avctx->width; 00264 for (i = 0; i < line_packets; i++) { 00265 /* account for the skip bytes */ 00266 pixel_skip = buf[stream_ptr++]; 00267 pixel_ptr += pixel_skip; 00268 pixel_countdown -= pixel_skip; 00269 byte_run = (signed char)(buf[stream_ptr++]); 00270 if (byte_run < 0) { 00271 byte_run = -byte_run; 00272 palette_idx1 = buf[stream_ptr++]; 00273 palette_idx2 = buf[stream_ptr++]; 00274 CHECK_PIXEL_PTR(byte_run * 2); 00275 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 00276 pixels[pixel_ptr++] = palette_idx1; 00277 pixels[pixel_ptr++] = palette_idx2; 00278 } 00279 } else { 00280 CHECK_PIXEL_PTR(byte_run * 2); 00281 for (j = 0; j < byte_run * 2; j++, pixel_countdown--) { 00282 palette_idx1 = buf[stream_ptr++]; 00283 pixels[pixel_ptr++] = palette_idx1; 00284 } 00285 } 00286 } 00287 00288 y_ptr += s->frame.linesize[0]; 00289 } 00290 } 00291 break; 00292 00293 case FLI_LC: 00294 /* line compressed */ 00295 starting_line = AV_RL16(&buf[stream_ptr]); 00296 stream_ptr += 2; 00297 y_ptr = 0; 00298 y_ptr += starting_line * s->frame.linesize[0]; 00299 00300 compressed_lines = AV_RL16(&buf[stream_ptr]); 00301 stream_ptr += 2; 00302 while (compressed_lines > 0) { 00303 pixel_ptr = y_ptr; 00304 CHECK_PIXEL_PTR(0); 00305 pixel_countdown = s->avctx->width; 00306 line_packets = buf[stream_ptr++]; 00307 if (line_packets > 0) { 00308 for (i = 0; i < line_packets; i++) { 00309 /* account for the skip bytes */ 00310 pixel_skip = buf[stream_ptr++]; 00311 pixel_ptr += pixel_skip; 00312 pixel_countdown -= pixel_skip; 00313 byte_run = (signed char)(buf[stream_ptr++]); 00314 if (byte_run > 0) { 00315 CHECK_PIXEL_PTR(byte_run); 00316 for (j = 0; j < byte_run; j++, pixel_countdown--) { 00317 palette_idx1 = buf[stream_ptr++]; 00318 pixels[pixel_ptr++] = palette_idx1; 00319 } 00320 } else if (byte_run < 0) { 00321 byte_run = -byte_run; 00322 palette_idx1 = buf[stream_ptr++]; 00323 CHECK_PIXEL_PTR(byte_run); 00324 for (j = 0; j < byte_run; j++, pixel_countdown--) { 00325 pixels[pixel_ptr++] = palette_idx1; 00326 } 00327 } 00328 } 00329 } 00330 00331 y_ptr += s->frame.linesize[0]; 00332 compressed_lines--; 00333 } 00334 break; 00335 00336 case FLI_BLACK: 00337 /* set the whole frame to color 0 (which is usually black) */ 00338 memset(pixels, 0, 00339 s->frame.linesize[0] * s->avctx->height); 00340 break; 00341 00342 case FLI_BRUN: 00343 /* Byte run compression: This chunk type only occurs in the first 00344 * FLI frame and it will update the entire frame. */ 00345 y_ptr = 0; 00346 for (lines = 0; lines < s->avctx->height; lines++) { 00347 pixel_ptr = y_ptr; 00348 /* disregard the line packets; instead, iterate through all 00349 * pixels on a row */ 00350 stream_ptr++; 00351 pixel_countdown = s->avctx->width; 00352 while (pixel_countdown > 0) { 00353 byte_run = (signed char)(buf[stream_ptr++]); 00354 if (byte_run > 0) { 00355 palette_idx1 = buf[stream_ptr++]; 00356 CHECK_PIXEL_PTR(byte_run); 00357 for (j = 0; j < byte_run; j++) { 00358 pixels[pixel_ptr++] = palette_idx1; 00359 pixel_countdown--; 00360 if (pixel_countdown < 0) 00361 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 00362 pixel_countdown, lines); 00363 } 00364 } else { /* copy bytes if byte_run < 0 */ 00365 byte_run = -byte_run; 00366 CHECK_PIXEL_PTR(byte_run); 00367 for (j = 0; j < byte_run; j++) { 00368 palette_idx1 = buf[stream_ptr++]; 00369 pixels[pixel_ptr++] = palette_idx1; 00370 pixel_countdown--; 00371 if (pixel_countdown < 0) 00372 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 00373 pixel_countdown, lines); 00374 } 00375 } 00376 } 00377 00378 y_ptr += s->frame.linesize[0]; 00379 } 00380 break; 00381 00382 case FLI_COPY: 00383 /* copy the chunk (uncompressed frame) */ 00384 if (chunk_size - 6 > s->avctx->width * s->avctx->height) { 00385 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 00386 "bigger than image, skipping chunk\n", chunk_size - 6); 00387 stream_ptr += chunk_size - 6; 00388 } else { 00389 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; 00390 y_ptr += s->frame.linesize[0]) { 00391 memcpy(&pixels[y_ptr], &buf[stream_ptr], 00392 s->avctx->width); 00393 stream_ptr += s->avctx->width; 00394 } 00395 } 00396 break; 00397 00398 case FLI_MINI: 00399 /* some sort of a thumbnail? disregard this chunk... */ 00400 stream_ptr += chunk_size - 6; 00401 break; 00402 00403 default: 00404 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 00405 break; 00406 } 00407 00408 frame_size -= chunk_size; 00409 num_chunks--; 00410 } 00411 00412 /* by the end of the chunk, the stream ptr should equal the frame 00413 * size (minus 1, possibly); if it doesn't, issue a warning */ 00414 if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1)) 00415 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 00416 "and final chunk ptr = %d\n", buf_size, stream_ptr); 00417 00418 /* make the palette available on the way out */ 00419 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); 00420 if (s->new_palette) { 00421 s->frame.palette_has_changed = 1; 00422 s->new_palette = 0; 00423 } 00424 00425 *data_size=sizeof(AVFrame); 00426 *(AVFrame*)data = s->frame; 00427 00428 return buf_size; 00429 } 00430 00431 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, 00432 void *data, int *data_size, 00433 const uint8_t *buf, int buf_size) 00434 { 00435 /* Note, the only difference between the 15Bpp and 16Bpp */ 00436 /* Format is the pixel format, the packets are processed the same. */ 00437 FlicDecodeContext *s = avctx->priv_data; 00438 00439 int stream_ptr = 0; 00440 int pixel_ptr; 00441 unsigned char palette_idx1; 00442 00443 unsigned int frame_size; 00444 int num_chunks; 00445 00446 unsigned int chunk_size; 00447 int chunk_type; 00448 00449 int i, j; 00450 00451 int lines; 00452 int compressed_lines; 00453 signed short line_packets; 00454 int y_ptr; 00455 int byte_run; 00456 int pixel_skip; 00457 int pixel_countdown; 00458 unsigned char *pixels; 00459 int pixel; 00460 unsigned int pixel_limit; 00461 00462 s->frame.reference = 1; 00463 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 00464 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 00465 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00466 return -1; 00467 } 00468 00469 pixels = s->frame.data[0]; 00470 pixel_limit = s->avctx->height * s->frame.linesize[0]; 00471 00472 frame_size = AV_RL32(&buf[stream_ptr]); 00473 stream_ptr += 6; /* skip the magic number */ 00474 num_chunks = AV_RL16(&buf[stream_ptr]); 00475 stream_ptr += 10; /* skip padding */ 00476 00477 frame_size -= 16; 00478 00479 /* iterate through the chunks */ 00480 while ((frame_size > 0) && (num_chunks > 0)) { 00481 chunk_size = AV_RL32(&buf[stream_ptr]); 00482 stream_ptr += 4; 00483 chunk_type = AV_RL16(&buf[stream_ptr]); 00484 stream_ptr += 2; 00485 00486 switch (chunk_type) { 00487 case FLI_256_COLOR: 00488 case FLI_COLOR: 00489 /* For some reason, it seems that non-palettized flics do 00490 * include one of these chunks in their first frame. 00491 * Why I do not know, it seems rather extraneous. */ 00492 /* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/ 00493 stream_ptr = stream_ptr + chunk_size - 6; 00494 break; 00495 00496 case FLI_DELTA: 00497 case FLI_DTA_LC: 00498 y_ptr = 0; 00499 compressed_lines = AV_RL16(&buf[stream_ptr]); 00500 stream_ptr += 2; 00501 while (compressed_lines > 0) { 00502 line_packets = AV_RL16(&buf[stream_ptr]); 00503 stream_ptr += 2; 00504 if (line_packets < 0) { 00505 line_packets = -line_packets; 00506 y_ptr += line_packets * s->frame.linesize[0]; 00507 } else { 00508 compressed_lines--; 00509 pixel_ptr = y_ptr; 00510 CHECK_PIXEL_PTR(0); 00511 pixel_countdown = s->avctx->width; 00512 for (i = 0; i < line_packets; i++) { 00513 /* account for the skip bytes */ 00514 pixel_skip = buf[stream_ptr++]; 00515 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */ 00516 pixel_countdown -= pixel_skip; 00517 byte_run = (signed char)(buf[stream_ptr++]); 00518 if (byte_run < 0) { 00519 byte_run = -byte_run; 00520 pixel = AV_RL16(&buf[stream_ptr]); 00521 stream_ptr += 2; 00522 CHECK_PIXEL_PTR(2 * byte_run); 00523 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 00524 *((signed short*)(&pixels[pixel_ptr])) = pixel; 00525 pixel_ptr += 2; 00526 } 00527 } else { 00528 CHECK_PIXEL_PTR(2 * byte_run); 00529 for (j = 0; j < byte_run; j++, pixel_countdown--) { 00530 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]); 00531 stream_ptr += 2; 00532 pixel_ptr += 2; 00533 } 00534 } 00535 } 00536 00537 y_ptr += s->frame.linesize[0]; 00538 } 00539 } 00540 break; 00541 00542 case FLI_LC: 00543 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n"); 00544 stream_ptr = stream_ptr + chunk_size - 6; 00545 break; 00546 00547 case FLI_BLACK: 00548 /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */ 00549 memset(pixels, 0x0000, 00550 s->frame.linesize[0] * s->avctx->height); 00551 break; 00552 00553 case FLI_BRUN: 00554 y_ptr = 0; 00555 for (lines = 0; lines < s->avctx->height; lines++) { 00556 pixel_ptr = y_ptr; 00557 /* disregard the line packets; instead, iterate through all 00558 * pixels on a row */ 00559 stream_ptr++; 00560 pixel_countdown = (s->avctx->width * 2); 00561 00562 while (pixel_countdown > 0) { 00563 byte_run = (signed char)(buf[stream_ptr++]); 00564 if (byte_run > 0) { 00565 palette_idx1 = buf[stream_ptr++]; 00566 CHECK_PIXEL_PTR(byte_run); 00567 for (j = 0; j < byte_run; j++) { 00568 pixels[pixel_ptr++] = palette_idx1; 00569 pixel_countdown--; 00570 if (pixel_countdown < 0) 00571 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n", 00572 pixel_countdown, lines); 00573 } 00574 } else { /* copy bytes if byte_run < 0 */ 00575 byte_run = -byte_run; 00576 CHECK_PIXEL_PTR(byte_run); 00577 for (j = 0; j < byte_run; j++) { 00578 palette_idx1 = buf[stream_ptr++]; 00579 pixels[pixel_ptr++] = palette_idx1; 00580 pixel_countdown--; 00581 if (pixel_countdown < 0) 00582 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 00583 pixel_countdown, lines); 00584 } 00585 } 00586 } 00587 00588 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed. 00589 * This does not give us any good oportunity to perform word endian conversion 00590 * during decompression. So if it is required (i.e., this is not a LE target, we do 00591 * a second pass over the line here, swapping the bytes. 00592 */ 00593 #if HAVE_BIGENDIAN 00594 pixel_ptr = y_ptr; 00595 pixel_countdown = s->avctx->width; 00596 while (pixel_countdown > 0) { 00597 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]); 00598 pixel_ptr += 2; 00599 } 00600 #endif 00601 y_ptr += s->frame.linesize[0]; 00602 } 00603 break; 00604 00605 case FLI_DTA_BRUN: 00606 y_ptr = 0; 00607 for (lines = 0; lines < s->avctx->height; lines++) { 00608 pixel_ptr = y_ptr; 00609 /* disregard the line packets; instead, iterate through all 00610 * pixels on a row */ 00611 stream_ptr++; 00612 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */ 00613 00614 while (pixel_countdown > 0) { 00615 byte_run = (signed char)(buf[stream_ptr++]); 00616 if (byte_run > 0) { 00617 pixel = AV_RL16(&buf[stream_ptr]); 00618 stream_ptr += 2; 00619 CHECK_PIXEL_PTR(2 * byte_run); 00620 for (j = 0; j < byte_run; j++) { 00621 *((signed short*)(&pixels[pixel_ptr])) = pixel; 00622 pixel_ptr += 2; 00623 pixel_countdown--; 00624 if (pixel_countdown < 0) 00625 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 00626 pixel_countdown); 00627 } 00628 } else { /* copy pixels if byte_run < 0 */ 00629 byte_run = -byte_run; 00630 CHECK_PIXEL_PTR(2 * byte_run); 00631 for (j = 0; j < byte_run; j++) { 00632 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]); 00633 stream_ptr += 2; 00634 pixel_ptr += 2; 00635 pixel_countdown--; 00636 if (pixel_countdown < 0) 00637 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 00638 pixel_countdown); 00639 } 00640 } 00641 } 00642 00643 y_ptr += s->frame.linesize[0]; 00644 } 00645 break; 00646 00647 case FLI_COPY: 00648 case FLI_DTA_COPY: 00649 /* copy the chunk (uncompressed frame) */ 00650 if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) { 00651 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 00652 "bigger than image, skipping chunk\n", chunk_size - 6); 00653 stream_ptr += chunk_size - 6; 00654 } else { 00655 00656 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; 00657 y_ptr += s->frame.linesize[0]) { 00658 00659 pixel_countdown = s->avctx->width; 00660 pixel_ptr = 0; 00661 while (pixel_countdown > 0) { 00662 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = AV_RL16(&buf[stream_ptr+pixel_ptr]); 00663 pixel_ptr += 2; 00664 pixel_countdown--; 00665 } 00666 stream_ptr += s->avctx->width*2; 00667 } 00668 } 00669 break; 00670 00671 case FLI_MINI: 00672 /* some sort of a thumbnail? disregard this chunk... */ 00673 stream_ptr += chunk_size - 6; 00674 break; 00675 00676 default: 00677 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 00678 break; 00679 } 00680 00681 frame_size -= chunk_size; 00682 num_chunks--; 00683 } 00684 00685 /* by the end of the chunk, the stream ptr should equal the frame 00686 * size (minus 1, possibly); if it doesn't, issue a warning */ 00687 if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1)) 00688 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 00689 "and final chunk ptr = %d\n", buf_size, stream_ptr); 00690 00691 00692 *data_size=sizeof(AVFrame); 00693 *(AVFrame*)data = s->frame; 00694 00695 return buf_size; 00696 } 00697 00698 static int flic_decode_frame_24BPP(AVCodecContext *avctx, 00699 void *data, int *data_size, 00700 const uint8_t *buf, int buf_size) 00701 { 00702 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n"); 00703 return -1; 00704 } 00705 00706 static int flic_decode_frame(AVCodecContext *avctx, 00707 void *data, int *data_size, 00708 AVPacket *avpkt) 00709 { 00710 const uint8_t *buf = avpkt->data; 00711 int buf_size = avpkt->size; 00712 if (avctx->pix_fmt == PIX_FMT_PAL8) { 00713 return flic_decode_frame_8BPP(avctx, data, data_size, 00714 buf, buf_size); 00715 } 00716 else if ((avctx->pix_fmt == PIX_FMT_RGB555) || 00717 (avctx->pix_fmt == PIX_FMT_RGB565)) { 00718 return flic_decode_frame_15_16BPP(avctx, data, data_size, 00719 buf, buf_size); 00720 } 00721 else if (avctx->pix_fmt == PIX_FMT_BGR24) { 00722 return flic_decode_frame_24BPP(avctx, data, data_size, 00723 buf, buf_size); 00724 } 00725 00726 /* Should not get here, ever as the pix_fmt is processed */ 00727 /* in flic_decode_init and the above if should deal with */ 00728 /* the finite set of possibilites allowable by here. */ 00729 /* But in case we do, just error out. */ 00730 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n"); 00731 return -1; 00732 } 00733 00734 00735 static av_cold int flic_decode_end(AVCodecContext *avctx) 00736 { 00737 FlicDecodeContext *s = avctx->priv_data; 00738 00739 if (s->frame.data[0]) 00740 avctx->release_buffer(avctx, &s->frame); 00741 00742 return 0; 00743 } 00744 00745 AVCodec ff_flic_decoder = { 00746 "flic", 00747 AVMEDIA_TYPE_VIDEO, 00748 CODEC_ID_FLIC, 00749 sizeof(FlicDecodeContext), 00750 flic_decode_init, 00751 NULL, 00752 flic_decode_end, 00753 flic_decode_frame, 00754 CODEC_CAP_DR1, 00755 NULL, 00756 NULL, 00757 NULL, 00758 NULL, 00759 .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), 00760 };