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