1/* 2 * FLI/FLC Animation Video Decoder 3 * Copyright (C) 2003, 2004 the ffmpeg project 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Autodesk Animator FLI/FLC Video Decoder 25 * by Mike Melanson (melanson@pcisys.net) 26 * for more information on the .fli/.flc file format and all of its many 27 * variations, visit: 28 * http://www.compuphase.com/flic.htm 29 * 30 * This decoder outputs PAL8/RGB555/RGB565 and maybe one day RGB24 31 * colorspace data, depending on the FLC. To use this decoder, be 32 * sure that your demuxer sends the FLI file header to the decoder via 33 * the extradata chunk in AVCodecContext. The chunk should be 128 bytes 34 * large. The only exception is for FLI files from the game "Magic Carpet", 35 * in which the header is only 12 bytes. 36 */ 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41 42#include "libavutil/intreadwrite.h" 43#include "avcodec.h" 44 45#define FLI_256_COLOR 4 46#define FLI_DELTA 7 47#define FLI_COLOR 11 48#define FLI_LC 12 49#define FLI_BLACK 13 50#define FLI_BRUN 15 51#define FLI_COPY 16 52#define FLI_MINI 18 53#define FLI_DTA_BRUN 25 54#define FLI_DTA_COPY 26 55#define FLI_DTA_LC 27 56 57#define FLI_TYPE_CODE (0xAF11) 58#define FLC_FLX_TYPE_CODE (0xAF12) 59#define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */ 60#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13) 61 62#define CHECK_PIXEL_PTR(n) \ 63 if (pixel_ptr + n > pixel_limit) { \ 64 av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \ 65 pixel_ptr + n, pixel_limit); \ 66 return -1; \ 67 } \ 68 69typedef struct FlicDecodeContext { 70 AVCodecContext *avctx; 71 AVFrame frame; 72 73 unsigned int palette[256]; 74 int new_palette; 75 int fli_type; /* either 0xAF11 or 0xAF12, affects palette resolution */ 76} FlicDecodeContext; 77 78static av_cold int flic_decode_init(AVCodecContext *avctx) 79{ 80 FlicDecodeContext *s = avctx->priv_data; 81 unsigned char *fli_header = (unsigned char *)avctx->extradata; 82 int depth; 83 84 s->avctx = avctx; 85 86 s->fli_type = AV_RL16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */ 87 88 depth = 0; 89 if (s->avctx->extradata_size == 12) { 90 /* special case for magic carpet FLIs */ 91 s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE; 92 depth = 8; 93 } else if (s->avctx->extradata_size != 128) { 94 av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n"); 95 return -1; 96 } else { 97 depth = AV_RL16(&fli_header[12]); 98 } 99 100 if (depth == 0) { 101 depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */ 102 } 103 104 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) { 105 depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */ 106 } 107 108 switch (depth) { 109 case 8 : avctx->pix_fmt = PIX_FMT_PAL8; break; 110 case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break; 111 case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break; 112 case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */ 113 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n"); 114 return -1; 115 break; 116 default : 117 av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth); 118 return -1; 119 } 120 121 s->frame.data[0] = NULL; 122 s->new_palette = 0; 123 124 return 0; 125} 126 127static int flic_decode_frame_8BPP(AVCodecContext *avctx, 128 void *data, int *data_size, 129 const uint8_t *buf, int buf_size) 130{ 131 FlicDecodeContext *s = avctx->priv_data; 132 133 int stream_ptr = 0; 134 int stream_ptr_after_color_chunk; 135 int pixel_ptr; 136 int palette_ptr; 137 unsigned char palette_idx1; 138 unsigned char palette_idx2; 139 140 unsigned int frame_size; 141 int num_chunks; 142 143 unsigned int chunk_size; 144 int chunk_type; 145 146 int i, j; 147 148 int color_packets; 149 int color_changes; 150 int color_shift; 151 unsigned char r, g, b; 152 153 int lines; 154 int compressed_lines; 155 int starting_line; 156 signed short line_packets; 157 int y_ptr; 158 int byte_run; 159 int pixel_skip; 160 int pixel_countdown; 161 unsigned char *pixels; 162 int pixel_limit; 163 164 s->frame.reference = 1; 165 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 166 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 167 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 168 return -1; 169 } 170 171 pixels = s->frame.data[0]; 172 pixel_limit = s->avctx->height * s->frame.linesize[0]; 173 174 frame_size = AV_RL32(&buf[stream_ptr]); 175 stream_ptr += 6; /* skip the magic number */ 176 num_chunks = AV_RL16(&buf[stream_ptr]); 177 stream_ptr += 10; /* skip padding */ 178 179 frame_size -= 16; 180 181 /* iterate through the chunks */ 182 while ((frame_size > 0) && (num_chunks > 0)) { 183 chunk_size = AV_RL32(&buf[stream_ptr]); 184 stream_ptr += 4; 185 chunk_type = AV_RL16(&buf[stream_ptr]); 186 stream_ptr += 2; 187 188 switch (chunk_type) { 189 case FLI_256_COLOR: 190 case FLI_COLOR: 191 stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6; 192 193 /* check special case: If this file is from the Magic Carpet 194 * game and uses 6-bit colors even though it reports 256-color 195 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during 196 * initialization) */ 197 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE)) 198 color_shift = 0; 199 else 200 color_shift = 2; 201 /* set up the palette */ 202 color_packets = AV_RL16(&buf[stream_ptr]); 203 stream_ptr += 2; 204 palette_ptr = 0; 205 for (i = 0; i < color_packets; i++) { 206 /* first byte is how many colors to skip */ 207 palette_ptr += buf[stream_ptr++]; 208 209 /* next byte indicates how many entries to change */ 210 color_changes = buf[stream_ptr++]; 211 212 /* if there are 0 color changes, there are actually 256 */ 213 if (color_changes == 0) 214 color_changes = 256; 215 216 for (j = 0; j < color_changes; j++) { 217 unsigned int entry; 218 219 /* wrap around, for good measure */ 220 if ((unsigned)palette_ptr >= 256) 221 palette_ptr = 0; 222 223 r = buf[stream_ptr++] << color_shift; 224 g = buf[stream_ptr++] << color_shift; 225 b = buf[stream_ptr++] << color_shift; 226 entry = (r << 16) | (g << 8) | b; 227 if (s->palette[palette_ptr] != entry) 228 s->new_palette = 1; 229 s->palette[palette_ptr++] = entry; 230 } 231 } 232 233 /* color chunks sometimes have weird 16-bit alignment issues; 234 * therefore, take the hardline approach and set the stream_ptr 235 * to the value calculated w.r.t. the size specified by the color 236 * chunk header */ 237 stream_ptr = stream_ptr_after_color_chunk; 238 239 break; 240 241 case FLI_DELTA: 242 y_ptr = 0; 243 compressed_lines = AV_RL16(&buf[stream_ptr]); 244 stream_ptr += 2; 245 while (compressed_lines > 0) { 246 line_packets = AV_RL16(&buf[stream_ptr]); 247 stream_ptr += 2; 248 if ((line_packets & 0xC000) == 0xC000) { 249 // line skip opcode 250 line_packets = -line_packets; 251 y_ptr += line_packets * s->frame.linesize[0]; 252 } else if ((line_packets & 0xC000) == 0x4000) { 253 av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets); 254 } else if ((line_packets & 0xC000) == 0x8000) { 255 // "last byte" opcode 256 pixels[y_ptr + s->frame.linesize[0] - 1] = line_packets & 0xff; 257 } else { 258 compressed_lines--; 259 pixel_ptr = y_ptr; 260 pixel_countdown = s->avctx->width; 261 for (i = 0; i < line_packets; i++) { 262 /* account for the skip bytes */ 263 pixel_skip = buf[stream_ptr++]; 264 pixel_ptr += pixel_skip; 265 pixel_countdown -= pixel_skip; 266 byte_run = (signed char)(buf[stream_ptr++]); 267 if (byte_run < 0) { 268 byte_run = -byte_run; 269 palette_idx1 = buf[stream_ptr++]; 270 palette_idx2 = buf[stream_ptr++]; 271 CHECK_PIXEL_PTR(byte_run); 272 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 273 pixels[pixel_ptr++] = palette_idx1; 274 pixels[pixel_ptr++] = palette_idx2; 275 } 276 } else { 277 CHECK_PIXEL_PTR(byte_run * 2); 278 for (j = 0; j < byte_run * 2; j++, pixel_countdown--) { 279 palette_idx1 = buf[stream_ptr++]; 280 pixels[pixel_ptr++] = palette_idx1; 281 } 282 } 283 } 284 285 y_ptr += s->frame.linesize[0]; 286 } 287 } 288 break; 289 290 case FLI_LC: 291 /* line compressed */ 292 starting_line = AV_RL16(&buf[stream_ptr]); 293 stream_ptr += 2; 294 y_ptr = 0; 295 y_ptr += starting_line * s->frame.linesize[0]; 296 297 compressed_lines = AV_RL16(&buf[stream_ptr]); 298 stream_ptr += 2; 299 while (compressed_lines > 0) { 300 pixel_ptr = y_ptr; 301 pixel_countdown = s->avctx->width; 302 line_packets = buf[stream_ptr++]; 303 if (line_packets > 0) { 304 for (i = 0; i < line_packets; i++) { 305 /* account for the skip bytes */ 306 pixel_skip = buf[stream_ptr++]; 307 pixel_ptr += pixel_skip; 308 pixel_countdown -= pixel_skip; 309 byte_run = (signed char)(buf[stream_ptr++]); 310 if (byte_run > 0) { 311 CHECK_PIXEL_PTR(byte_run); 312 for (j = 0; j < byte_run; j++, pixel_countdown--) { 313 palette_idx1 = buf[stream_ptr++]; 314 pixels[pixel_ptr++] = palette_idx1; 315 } 316 } else if (byte_run < 0) { 317 byte_run = -byte_run; 318 palette_idx1 = buf[stream_ptr++]; 319 CHECK_PIXEL_PTR(byte_run); 320 for (j = 0; j < byte_run; j++, pixel_countdown--) { 321 pixels[pixel_ptr++] = palette_idx1; 322 } 323 } 324 } 325 } 326 327 y_ptr += s->frame.linesize[0]; 328 compressed_lines--; 329 } 330 break; 331 332 case FLI_BLACK: 333 /* set the whole frame to color 0 (which is usually black) */ 334 memset(pixels, 0, 335 s->frame.linesize[0] * s->avctx->height); 336 break; 337 338 case FLI_BRUN: 339 /* Byte run compression: This chunk type only occurs in the first 340 * FLI frame and it will update the entire frame. */ 341 y_ptr = 0; 342 for (lines = 0; lines < s->avctx->height; lines++) { 343 pixel_ptr = y_ptr; 344 /* disregard the line packets; instead, iterate through all 345 * pixels on a row */ 346 stream_ptr++; 347 pixel_countdown = s->avctx->width; 348 while (pixel_countdown > 0) { 349 byte_run = (signed char)(buf[stream_ptr++]); 350 if (byte_run > 0) { 351 palette_idx1 = buf[stream_ptr++]; 352 CHECK_PIXEL_PTR(byte_run); 353 for (j = 0; j < byte_run; j++) { 354 pixels[pixel_ptr++] = palette_idx1; 355 pixel_countdown--; 356 if (pixel_countdown < 0) 357 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 358 pixel_countdown, lines); 359 } 360 } else { /* copy bytes if byte_run < 0 */ 361 byte_run = -byte_run; 362 CHECK_PIXEL_PTR(byte_run); 363 for (j = 0; j < byte_run; j++) { 364 palette_idx1 = buf[stream_ptr++]; 365 pixels[pixel_ptr++] = palette_idx1; 366 pixel_countdown--; 367 if (pixel_countdown < 0) 368 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 369 pixel_countdown, lines); 370 } 371 } 372 } 373 374 y_ptr += s->frame.linesize[0]; 375 } 376 break; 377 378 case FLI_COPY: 379 /* copy the chunk (uncompressed frame) */ 380 if (chunk_size - 6 > s->avctx->width * s->avctx->height) { 381 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 382 "bigger than image, skipping chunk\n", chunk_size - 6); 383 stream_ptr += chunk_size - 6; 384 } else { 385 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; 386 y_ptr += s->frame.linesize[0]) { 387 memcpy(&pixels[y_ptr], &buf[stream_ptr], 388 s->avctx->width); 389 stream_ptr += s->avctx->width; 390 } 391 } 392 break; 393 394 case FLI_MINI: 395 /* some sort of a thumbnail? disregard this chunk... */ 396 stream_ptr += chunk_size - 6; 397 break; 398 399 default: 400 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 401 break; 402 } 403 404 frame_size -= chunk_size; 405 num_chunks--; 406 } 407 408 /* by the end of the chunk, the stream ptr should equal the frame 409 * size (minus 1, possibly); if it doesn't, issue a warning */ 410 if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1)) 411 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 412 "and final chunk ptr = %d\n", buf_size, stream_ptr); 413 414 /* make the palette available on the way out */ 415 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); 416 if (s->new_palette) { 417 s->frame.palette_has_changed = 1; 418 s->new_palette = 0; 419 } 420 421 *data_size=sizeof(AVFrame); 422 *(AVFrame*)data = s->frame; 423 424 return buf_size; 425} 426 427static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, 428 void *data, int *data_size, 429 const uint8_t *buf, int buf_size) 430{ 431 /* Note, the only difference between the 15Bpp and 16Bpp */ 432 /* Format is the pixel format, the packets are processed the same. */ 433 FlicDecodeContext *s = avctx->priv_data; 434 435 int stream_ptr = 0; 436 int pixel_ptr; 437 unsigned char palette_idx1; 438 439 unsigned int frame_size; 440 int num_chunks; 441 442 unsigned int chunk_size; 443 int chunk_type; 444 445 int i, j; 446 447 int lines; 448 int compressed_lines; 449 signed short line_packets; 450 int y_ptr; 451 int byte_run; 452 int pixel_skip; 453 int pixel_countdown; 454 unsigned char *pixels; 455 int pixel; 456 int pixel_limit; 457 458 s->frame.reference = 1; 459 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 460 if (avctx->reget_buffer(avctx, &s->frame) < 0) { 461 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 462 return -1; 463 } 464 465 pixels = s->frame.data[0]; 466 pixel_limit = s->avctx->height * s->frame.linesize[0]; 467 468 frame_size = AV_RL32(&buf[stream_ptr]); 469 stream_ptr += 6; /* skip the magic number */ 470 num_chunks = AV_RL16(&buf[stream_ptr]); 471 stream_ptr += 10; /* skip padding */ 472 473 frame_size -= 16; 474 475 /* iterate through the chunks */ 476 while ((frame_size > 0) && (num_chunks > 0)) { 477 chunk_size = AV_RL32(&buf[stream_ptr]); 478 stream_ptr += 4; 479 chunk_type = AV_RL16(&buf[stream_ptr]); 480 stream_ptr += 2; 481 482 switch (chunk_type) { 483 case FLI_256_COLOR: 484 case FLI_COLOR: 485 /* For some reason, it seems that non-palettized flics do 486 * include one of these chunks in their first frame. 487 * Why I do not know, it seems rather extraneous. */ 488/* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/ 489 stream_ptr = stream_ptr + chunk_size - 6; 490 break; 491 492 case FLI_DELTA: 493 case FLI_DTA_LC: 494 y_ptr = 0; 495 compressed_lines = AV_RL16(&buf[stream_ptr]); 496 stream_ptr += 2; 497 while (compressed_lines > 0) { 498 line_packets = AV_RL16(&buf[stream_ptr]); 499 stream_ptr += 2; 500 if (line_packets < 0) { 501 line_packets = -line_packets; 502 y_ptr += line_packets * s->frame.linesize[0]; 503 } else { 504 compressed_lines--; 505 pixel_ptr = y_ptr; 506 pixel_countdown = s->avctx->width; 507 for (i = 0; i < line_packets; i++) { 508 /* account for the skip bytes */ 509 pixel_skip = buf[stream_ptr++]; 510 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */ 511 pixel_countdown -= pixel_skip; 512 byte_run = (signed char)(buf[stream_ptr++]); 513 if (byte_run < 0) { 514 byte_run = -byte_run; 515 pixel = AV_RL16(&buf[stream_ptr]); 516 stream_ptr += 2; 517 CHECK_PIXEL_PTR(byte_run); 518 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { 519 *((signed short*)(&pixels[pixel_ptr])) = pixel; 520 pixel_ptr += 2; 521 } 522 } else { 523 CHECK_PIXEL_PTR(byte_run); 524 for (j = 0; j < byte_run; j++, pixel_countdown--) { 525 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]); 526 stream_ptr += 2; 527 pixel_ptr += 2; 528 } 529 } 530 } 531 532 y_ptr += s->frame.linesize[0]; 533 } 534 } 535 break; 536 537 case FLI_LC: 538 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n"); 539 stream_ptr = stream_ptr + chunk_size - 6; 540 break; 541 542 case FLI_BLACK: 543 /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */ 544 memset(pixels, 0x0000, 545 s->frame.linesize[0] * s->avctx->height); 546 break; 547 548 case FLI_BRUN: 549 y_ptr = 0; 550 for (lines = 0; lines < s->avctx->height; lines++) { 551 pixel_ptr = y_ptr; 552 /* disregard the line packets; instead, iterate through all 553 * pixels on a row */ 554 stream_ptr++; 555 pixel_countdown = (s->avctx->width * 2); 556 557 while (pixel_countdown > 0) { 558 byte_run = (signed char)(buf[stream_ptr++]); 559 if (byte_run > 0) { 560 palette_idx1 = buf[stream_ptr++]; 561 CHECK_PIXEL_PTR(byte_run); 562 for (j = 0; j < byte_run; j++) { 563 pixels[pixel_ptr++] = palette_idx1; 564 pixel_countdown--; 565 if (pixel_countdown < 0) 566 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n", 567 pixel_countdown, lines); 568 } 569 } else { /* copy bytes if byte_run < 0 */ 570 byte_run = -byte_run; 571 CHECK_PIXEL_PTR(byte_run); 572 for (j = 0; j < byte_run; j++) { 573 palette_idx1 = buf[stream_ptr++]; 574 pixels[pixel_ptr++] = palette_idx1; 575 pixel_countdown--; 576 if (pixel_countdown < 0) 577 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", 578 pixel_countdown, lines); 579 } 580 } 581 } 582 583 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed. 584 * This does not give us any good oportunity to perform word endian conversion 585 * during decompression. So if it is required (i.e., this is not a LE target, we do 586 * a second pass over the line here, swapping the bytes. 587 */ 588#if HAVE_BIGENDIAN 589 pixel_ptr = y_ptr; 590 pixel_countdown = s->avctx->width; 591 while (pixel_countdown > 0) { 592 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]); 593 pixel_ptr += 2; 594 } 595#endif 596 y_ptr += s->frame.linesize[0]; 597 } 598 break; 599 600 case FLI_DTA_BRUN: 601 y_ptr = 0; 602 for (lines = 0; lines < s->avctx->height; lines++) { 603 pixel_ptr = y_ptr; 604 /* disregard the line packets; instead, iterate through all 605 * pixels on a row */ 606 stream_ptr++; 607 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */ 608 609 while (pixel_countdown > 0) { 610 byte_run = (signed char)(buf[stream_ptr++]); 611 if (byte_run > 0) { 612 pixel = AV_RL16(&buf[stream_ptr]); 613 stream_ptr += 2; 614 CHECK_PIXEL_PTR(byte_run); 615 for (j = 0; j < byte_run; j++) { 616 *((signed short*)(&pixels[pixel_ptr])) = pixel; 617 pixel_ptr += 2; 618 pixel_countdown--; 619 if (pixel_countdown < 0) 620 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 621 pixel_countdown); 622 } 623 } else { /* copy pixels if byte_run < 0 */ 624 byte_run = -byte_run; 625 CHECK_PIXEL_PTR(byte_run); 626 for (j = 0; j < byte_run; j++) { 627 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]); 628 stream_ptr += 2; 629 pixel_ptr += 2; 630 pixel_countdown--; 631 if (pixel_countdown < 0) 632 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", 633 pixel_countdown); 634 } 635 } 636 } 637 638 y_ptr += s->frame.linesize[0]; 639 } 640 break; 641 642 case FLI_COPY: 643 case FLI_DTA_COPY: 644 /* copy the chunk (uncompressed frame) */ 645 if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) { 646 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ 647 "bigger than image, skipping chunk\n", chunk_size - 6); 648 stream_ptr += chunk_size - 6; 649 } else { 650 651 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; 652 y_ptr += s->frame.linesize[0]) { 653 654 pixel_countdown = s->avctx->width; 655 pixel_ptr = 0; 656 while (pixel_countdown > 0) { 657 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = AV_RL16(&buf[stream_ptr+pixel_ptr]); 658 pixel_ptr += 2; 659 pixel_countdown--; 660 } 661 stream_ptr += s->avctx->width*2; 662 } 663 } 664 break; 665 666 case FLI_MINI: 667 /* some sort of a thumbnail? disregard this chunk... */ 668 stream_ptr += chunk_size - 6; 669 break; 670 671 default: 672 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); 673 break; 674 } 675 676 frame_size -= chunk_size; 677 num_chunks--; 678 } 679 680 /* by the end of the chunk, the stream ptr should equal the frame 681 * size (minus 1, possibly); if it doesn't, issue a warning */ 682 if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1)) 683 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ 684 "and final chunk ptr = %d\n", buf_size, stream_ptr); 685 686 687 *data_size=sizeof(AVFrame); 688 *(AVFrame*)data = s->frame; 689 690 return buf_size; 691} 692 693static int flic_decode_frame_24BPP(AVCodecContext *avctx, 694 void *data, int *data_size, 695 const uint8_t *buf, int buf_size) 696{ 697 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n"); 698 return -1; 699} 700 701static int flic_decode_frame(AVCodecContext *avctx, 702 void *data, int *data_size, 703 AVPacket *avpkt) 704{ 705 const uint8_t *buf = avpkt->data; 706 int buf_size = avpkt->size; 707 if (avctx->pix_fmt == PIX_FMT_PAL8) { 708 return flic_decode_frame_8BPP(avctx, data, data_size, 709 buf, buf_size); 710 } 711 else if ((avctx->pix_fmt == PIX_FMT_RGB555) || 712 (avctx->pix_fmt == PIX_FMT_RGB565)) { 713 return flic_decode_frame_15_16BPP(avctx, data, data_size, 714 buf, buf_size); 715 } 716 else if (avctx->pix_fmt == PIX_FMT_BGR24) { 717 return flic_decode_frame_24BPP(avctx, data, data_size, 718 buf, buf_size); 719 } 720 721 /* Should not get here, ever as the pix_fmt is processed */ 722 /* in flic_decode_init and the above if should deal with */ 723 /* the finite set of possibilites allowable by here. */ 724 /* But in case we do, just error out. */ 725 av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n"); 726 return -1; 727} 728 729 730static av_cold int flic_decode_end(AVCodecContext *avctx) 731{ 732 FlicDecodeContext *s = avctx->priv_data; 733 734 if (s->frame.data[0]) 735 avctx->release_buffer(avctx, &s->frame); 736 737 return 0; 738} 739 740AVCodec flic_decoder = { 741 "flic", 742 AVMEDIA_TYPE_VIDEO, 743 CODEC_ID_FLIC, 744 sizeof(FlicDecodeContext), 745 flic_decode_init, 746 NULL, 747 flic_decode_end, 748 flic_decode_frame, 749 CODEC_CAP_DR1, 750 NULL, 751 NULL, 752 NULL, 753 NULL, 754 .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), 755}; 756