Mercurial > libavcodec.hg
comparison flicvideo.c @ 2907:f7114e03d8dd libavcodec
support for FLX and DTA extensions in the FLIC format, courtesy of
Steven Johnson (mplayer -at- sakuraindustries.com)
author | melanson |
---|---|
date | Thu, 13 Oct 2005 04:35:31 +0000 |
parents | faa53103dde0 |
children | ef2149182f1c |
comparison
equal
deleted
inserted
replaced
2906:e578b3572987 | 2907:f7114e03d8dd |
---|---|
24 * by Mike Melanson (melanson@pcisys.net) | 24 * by Mike Melanson (melanson@pcisys.net) |
25 * for more information on the .fli/.flc file format and all of its many | 25 * for more information on the .fli/.flc file format and all of its many |
26 * variations, visit: | 26 * variations, visit: |
27 * http://www.compuphase.com/flic.htm | 27 * http://www.compuphase.com/flic.htm |
28 * | 28 * |
29 * This decoder outputs PAL8 colorspace data. To use this decoder, be | 29 * This decoder outputs PAL8/RGB555/RGB565 and maybe one day RGB24 |
30 * colorspace data, depending on the FLC. To use this decoder, be | |
30 * sure that your demuxer sends the FLI file header to the decoder via | 31 * sure that your demuxer sends the FLI file header to the decoder via |
31 * the extradata chunk in AVCodecContext. The chunk should be 128 bytes | 32 * the extradata chunk in AVCodecContext. The chunk should be 128 bytes |
32 * large. The only exception is for FLI files from the game "Magic Carpet", | 33 * large. The only exception is for FLI files from the game "Magic Carpet", |
33 * in which the header is only 12 bytes. | 34 * in which the header is only 12 bytes. |
34 */ | 35 */ |
48 #define FLI_LC 12 | 49 #define FLI_LC 12 |
49 #define FLI_BLACK 13 | 50 #define FLI_BLACK 13 |
50 #define FLI_BRUN 15 | 51 #define FLI_BRUN 15 |
51 #define FLI_COPY 16 | 52 #define FLI_COPY 16 |
52 #define FLI_MINI 18 | 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) | |
53 | 62 |
54 #define CHECK_PIXEL_PTR(n) \ | 63 #define CHECK_PIXEL_PTR(n) \ |
55 if (pixel_ptr + n > pixel_limit) { \ | 64 if (pixel_ptr + n > pixel_limit) { \ |
56 av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \ | 65 av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \ |
57 pixel_ptr + n, pixel_limit); \ | 66 pixel_ptr + n, pixel_limit); \ |
69 | 78 |
70 static int flic_decode_init(AVCodecContext *avctx) | 79 static int flic_decode_init(AVCodecContext *avctx) |
71 { | 80 { |
72 FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data; | 81 FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data; |
73 unsigned char *fli_header = (unsigned char *)avctx->extradata; | 82 unsigned char *fli_header = (unsigned char *)avctx->extradata; |
83 int depth; | |
74 | 84 |
75 s->avctx = avctx; | 85 s->avctx = avctx; |
76 avctx->pix_fmt = PIX_FMT_PAL8; | |
77 avctx->has_b_frames = 0; | 86 avctx->has_b_frames = 0; |
87 | |
88 s->fli_type = LE_16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */ | |
89 depth = LE_16(&fli_header[12]); | |
90 | |
91 if (depth == 0) { | |
92 depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */ | |
93 } | |
78 | 94 |
79 if (s->avctx->extradata_size == 12) { | 95 if (s->avctx->extradata_size == 12) { |
80 /* special case for magic carpet FLIs */ | 96 /* special case for magic carpet FLIs */ |
81 s->fli_type = 0xAF13; | 97 s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE; |
82 } else if (s->avctx->extradata_size == 128) { | 98 } else if (s->avctx->extradata_size != 128) { |
83 s->fli_type = LE_16(&fli_header[4]); | |
84 } else { | |
85 av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n"); | 99 av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n"); |
86 return -1; | 100 return -1; |
87 } | 101 } |
88 | 102 |
103 if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) { | |
104 depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */ | |
105 } | |
106 | |
107 switch (depth) { | |
108 case 8 : avctx->pix_fmt = PIX_FMT_PAL8; break; | |
109 case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break; | |
110 case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break; | |
111 case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */ | |
112 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n"); | |
113 return -1; | |
114 break; | |
115 default : | |
116 av_log(avctx, AV_LOG_ERROR, "Unkown FLC/FLX depth of %d Bpp is unsupported.\n",depth); | |
117 return -1; | |
118 } | |
119 | |
89 s->frame.data[0] = NULL; | 120 s->frame.data[0] = NULL; |
90 s->new_palette = 0; | 121 s->new_palette = 0; |
91 | 122 |
92 return 0; | 123 return 0; |
93 } | 124 } |
94 | 125 |
95 static int flic_decode_frame(AVCodecContext *avctx, | 126 static int flic_decode_frame_8BPP(AVCodecContext *avctx, |
96 void *data, int *data_size, | 127 void *data, int *data_size, |
97 uint8_t *buf, int buf_size) | 128 uint8_t *buf, int buf_size) |
98 { | 129 { |
99 FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data; | 130 FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data; |
100 | 131 |
101 int stream_ptr = 0; | 132 int stream_ptr = 0; |
102 int stream_ptr_after_color_chunk; | 133 int stream_ptr_after_color_chunk; |
126 signed char byte_run; | 157 signed char byte_run; |
127 int pixel_skip; | 158 int pixel_skip; |
128 int pixel_countdown; | 159 int pixel_countdown; |
129 unsigned char *pixels; | 160 unsigned char *pixels; |
130 int pixel_limit; | 161 int pixel_limit; |
131 | 162 |
132 s->frame.reference = 1; | 163 s->frame.reference = 1; |
133 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | 164 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
134 if (avctx->reget_buffer(avctx, &s->frame) < 0) { | 165 if (avctx->reget_buffer(avctx, &s->frame) < 0) { |
135 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | 166 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); |
136 return -1; | 167 return -1; |
161 | 192 |
162 /* check special case: If this file is from the Magic Carpet | 193 /* check special case: If this file is from the Magic Carpet |
163 * game and uses 6-bit colors even though it reports 256-color | 194 * game and uses 6-bit colors even though it reports 256-color |
164 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during | 195 * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during |
165 * initialization) */ | 196 * initialization) */ |
166 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != 0xAF13)) | 197 if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE)) |
167 color_shift = 0; | 198 color_shift = 0; |
168 else | 199 else |
169 color_shift = 2; | 200 color_shift = 2; |
170 /* set up the palette */ | 201 /* set up the palette */ |
171 color_packets = LE_16(&buf[stream_ptr]); | 202 color_packets = LE_16(&buf[stream_ptr]); |
382 *(AVFrame*)data = s->frame; | 413 *(AVFrame*)data = s->frame; |
383 | 414 |
384 return buf_size; | 415 return buf_size; |
385 } | 416 } |
386 | 417 |
418 int flic_decode_frame_15_16BPP(AVCodecContext *avctx, | |
419 void *data, int *data_size, | |
420 uint8_t *buf, int buf_size) | |
421 { | |
422 /* Note, the only difference between the 15Bpp and 16Bpp */ | |
423 /* Format is the pixel format, the packets are processed the same. */ | |
424 FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data; | |
425 | |
426 int stream_ptr = 0; | |
427 int pixel_ptr; | |
428 unsigned char palette_idx1; | |
429 | |
430 unsigned int frame_size; | |
431 int num_chunks; | |
432 | |
433 unsigned int chunk_size; | |
434 int chunk_type; | |
435 | |
436 int i, j; | |
437 | |
438 int lines; | |
439 int compressed_lines; | |
440 signed short line_packets; | |
441 int y_ptr; | |
442 signed char byte_run; | |
443 int pixel_skip; | |
444 int pixel_countdown; | |
445 unsigned char *pixels; | |
446 int pixel; | |
447 int pixel_limit; | |
448 | |
449 s->frame.reference = 1; | |
450 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
451 if (avctx->reget_buffer(avctx, &s->frame) < 0) { | |
452 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
453 return -1; | |
454 } | |
455 | |
456 pixels = s->frame.data[0]; | |
457 pixel_limit = s->avctx->height * s->frame.linesize[0]; | |
458 | |
459 frame_size = LE_32(&buf[stream_ptr]); | |
460 stream_ptr += 6; /* skip the magic number */ | |
461 num_chunks = LE_16(&buf[stream_ptr]); | |
462 stream_ptr += 10; /* skip padding */ | |
463 | |
464 frame_size -= 16; | |
465 | |
466 /* iterate through the chunks */ | |
467 while ((frame_size > 0) && (num_chunks > 0)) { | |
468 chunk_size = LE_32(&buf[stream_ptr]); | |
469 stream_ptr += 4; | |
470 chunk_type = LE_16(&buf[stream_ptr]); | |
471 stream_ptr += 2; | |
472 | |
473 switch (chunk_type) { | |
474 case FLI_256_COLOR: | |
475 case FLI_COLOR: | |
476 /* For some reason, it seems that non-paletised flics do include one of these */ | |
477 /* chunks in their first frame. Why i do not know, it seems rather extraneous */ | |
478 /* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/ | |
479 stream_ptr = stream_ptr + chunk_size - 6; | |
480 break; | |
481 | |
482 case FLI_DELTA: | |
483 case FLI_DTA_LC: | |
484 y_ptr = 0; | |
485 compressed_lines = LE_16(&buf[stream_ptr]); | |
486 stream_ptr += 2; | |
487 while (compressed_lines > 0) { | |
488 line_packets = LE_16(&buf[stream_ptr]); | |
489 stream_ptr += 2; | |
490 if (line_packets < 0) { | |
491 line_packets = -line_packets; | |
492 y_ptr += line_packets * s->frame.linesize[0]; | |
493 } else { | |
494 compressed_lines--; | |
495 pixel_ptr = y_ptr; | |
496 pixel_countdown = s->avctx->width; | |
497 for (i = 0; i < line_packets; i++) { | |
498 /* account for the skip bytes */ | |
499 pixel_skip = buf[stream_ptr++]; | |
500 pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */ | |
501 pixel_countdown -= pixel_skip; | |
502 byte_run = buf[stream_ptr++]; | |
503 if (byte_run < 0) { | |
504 byte_run = -byte_run; | |
505 pixel = LE_16(&buf[stream_ptr]); | |
506 stream_ptr += 2; | |
507 CHECK_PIXEL_PTR(byte_run); | |
508 for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { | |
509 *((signed short*)(&pixels[pixel_ptr])) = pixel; | |
510 pixel_ptr += 2; | |
511 } | |
512 } else { | |
513 CHECK_PIXEL_PTR(byte_run); | |
514 for (j = 0; j < byte_run; j++, pixel_countdown--) { | |
515 *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]); | |
516 stream_ptr += 2; | |
517 pixel_ptr += 2; | |
518 } | |
519 } | |
520 } | |
521 | |
522 y_ptr += s->frame.linesize[0]; | |
523 } | |
524 } | |
525 break; | |
526 | |
527 case FLI_LC: | |
528 av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n"); | |
529 stream_ptr = stream_ptr + chunk_size - 6; | |
530 break; | |
531 | |
532 case FLI_BLACK: | |
533 /* set the whole frame to 0x0000 which is balck in both 15Bpp and 16Bpp modes. */ | |
534 memset(pixels, 0x0000, | |
535 s->frame.linesize[0] * s->avctx->height * 2); | |
536 break; | |
537 | |
538 case FLI_BRUN: | |
539 y_ptr = 0; | |
540 for (lines = 0; lines < s->avctx->height; lines++) { | |
541 pixel_ptr = y_ptr; | |
542 /* disregard the line packets; instead, iterate through all | |
543 * pixels on a row */ | |
544 stream_ptr++; | |
545 pixel_countdown = (s->avctx->width * 2); | |
546 | |
547 while (pixel_countdown > 0) { | |
548 byte_run = buf[stream_ptr++]; | |
549 if (byte_run > 0) { | |
550 palette_idx1 = buf[stream_ptr++]; | |
551 CHECK_PIXEL_PTR(byte_run); | |
552 for (j = 0; j < byte_run; j++) { | |
553 pixels[pixel_ptr++] = palette_idx1; | |
554 pixel_countdown--; | |
555 if (pixel_countdown < 0) | |
556 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", | |
557 pixel_countdown); | |
558 } | |
559 } else { /* copy bytes if byte_run < 0 */ | |
560 byte_run = -byte_run; | |
561 CHECK_PIXEL_PTR(byte_run); | |
562 for (j = 0; j < byte_run; j++) { | |
563 palette_idx1 = buf[stream_ptr++]; | |
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)\n", | |
568 pixel_countdown); | |
569 } | |
570 } | |
571 } | |
572 | |
573 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed. | |
574 * This doesnt give us any good oportunity to perform word endian conversion | |
575 * during decompression. So if its requried (ie, this isnt a LE target, we do | |
576 * a second pass over the line here, swapping the bytes. | |
577 */ | |
578 pixel = 0xFF00; | |
579 if (0xFF00 != LE_16(&pixel)) /* Check if its not an LE Target */ | |
580 { | |
581 pixel_ptr = y_ptr; | |
582 pixel_countdown = s->avctx->width; | |
583 while (pixel_countdown > 0) { | |
584 *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[pixel_ptr]); | |
585 pixel_ptr += 2; | |
586 } | |
587 } | |
588 y_ptr += s->frame.linesize[0]; | |
589 } | |
590 break; | |
591 | |
592 case FLI_DTA_BRUN: | |
593 y_ptr = 0; | |
594 for (lines = 0; lines < s->avctx->height; lines++) { | |
595 pixel_ptr = y_ptr; | |
596 /* disregard the line packets; instead, iterate through all | |
597 * pixels on a row */ | |
598 stream_ptr++; | |
599 pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */ | |
600 | |
601 while (pixel_countdown > 0) { | |
602 byte_run = buf[stream_ptr++]; | |
603 if (byte_run > 0) { | |
604 pixel = LE_16(&buf[stream_ptr]); | |
605 stream_ptr += 2; | |
606 CHECK_PIXEL_PTR(byte_run); | |
607 for (j = 0; j < byte_run; j++) { | |
608 *((signed short*)(&pixels[pixel_ptr])) = pixel; | |
609 pixel_ptr += 2; | |
610 pixel_countdown--; | |
611 if (pixel_countdown < 0) | |
612 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", | |
613 pixel_countdown); | |
614 } | |
615 } else { /* copy pixels if byte_run < 0 */ | |
616 byte_run = -byte_run; | |
617 CHECK_PIXEL_PTR(byte_run); | |
618 for (j = 0; j < byte_run; j++) { | |
619 *((signed short*)(&pixels[pixel_ptr])) = LE_16(&buf[stream_ptr]); | |
620 stream_ptr += 2; | |
621 pixel_ptr += 2; | |
622 pixel_countdown--; | |
623 if (pixel_countdown < 0) | |
624 av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", | |
625 pixel_countdown); | |
626 } | |
627 } | |
628 } | |
629 | |
630 y_ptr += s->frame.linesize[0]; | |
631 } | |
632 break; | |
633 | |
634 case FLI_COPY: | |
635 case FLI_DTA_COPY: | |
636 /* copy the chunk (uncompressed frame) */ | |
637 if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) { | |
638 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ | |
639 "bigger than image, skipping chunk\n", chunk_size - 6); | |
640 stream_ptr += chunk_size - 6; | |
641 } else { | |
642 | |
643 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; | |
644 y_ptr += s->frame.linesize[0]) { | |
645 | |
646 pixel_countdown = s->avctx->width; | |
647 pixel_ptr = 0; | |
648 while (pixel_countdown > 0) { | |
649 *((signed short*)(&pixels[y_ptr + pixel_ptr])) = LE_16(&buf[stream_ptr+pixel_ptr]); | |
650 pixel_ptr += 2; | |
651 pixel_countdown--; | |
652 } | |
653 stream_ptr += s->avctx->width*2; | |
654 } | |
655 } | |
656 break; | |
657 | |
658 case FLI_MINI: | |
659 /* some sort of a thumbnail? disregard this chunk... */ | |
660 stream_ptr += chunk_size - 6; | |
661 break; | |
662 | |
663 default: | |
664 av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); | |
665 break; | |
666 } | |
667 | |
668 frame_size -= chunk_size; | |
669 num_chunks--; | |
670 } | |
671 | |
672 /* by the end of the chunk, the stream ptr should equal the frame | |
673 * size (minus 1, possibly); if it doesn't, issue a warning */ | |
674 if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1)) | |
675 av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ | |
676 "and final chunk ptr = %d\n", buf_size, stream_ptr); | |
677 | |
678 | |
679 *data_size=sizeof(AVFrame); | |
680 *(AVFrame*)data = s->frame; | |
681 | |
682 return buf_size; | |
683 } | |
684 | |
685 static int flic_decode_frame_24BPP(AVCodecContext *avctx, | |
686 void *data, int *data_size, | |
687 uint8_t *buf, int buf_size) | |
688 { | |
689 av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n"); | |
690 return -1; | |
691 } | |
692 | |
693 static int flic_decode_frame(AVCodecContext *avctx, | |
694 void *data, int *data_size, | |
695 uint8_t *buf, int buf_size) | |
696 { | |
697 if (avctx->pix_fmt == PIX_FMT_PAL8) { | |
698 return flic_decode_frame_8BPP(avctx, data, data_size, | |
699 buf, buf_size); | |
700 } | |
701 else if ((avctx->pix_fmt == PIX_FMT_RGB555) || | |
702 (avctx->pix_fmt == PIX_FMT_RGB565)) { | |
703 return flic_decode_frame_15_16BPP(avctx, data, data_size, | |
704 buf, buf_size); | |
705 } | |
706 else if (avctx->pix_fmt == PIX_FMT_BGR24) { | |
707 return flic_decode_frame_24BPP(avctx, data, data_size, | |
708 buf, buf_size); | |
709 } | |
710 | |
711 /* Shouldnt get here, ever as the pix_fmt is processed */ | |
712 /* in flic_decode_init and the above if should deal with */ | |
713 /* the finite set of possibilites allowable by here. */ | |
714 /* but in case we do, just error out. */ | |
715 av_log(avctx, AV_LOG_ERROR, "Unknown Format of FLC. My Science cant explain how this happened\n"); | |
716 return -1; | |
717 } | |
718 | |
719 | |
387 static int flic_decode_end(AVCodecContext *avctx) | 720 static int flic_decode_end(AVCodecContext *avctx) |
388 { | 721 { |
389 FlicDecodeContext *s = avctx->priv_data; | 722 FlicDecodeContext *s = avctx->priv_data; |
390 | 723 |
391 if (s->frame.data[0]) | 724 if (s->frame.data[0]) |
402 flic_decode_init, | 735 flic_decode_init, |
403 NULL, | 736 NULL, |
404 flic_decode_end, | 737 flic_decode_end, |
405 flic_decode_frame, | 738 flic_decode_frame, |
406 CODEC_CAP_DR1, | 739 CODEC_CAP_DR1, |
740 NULL, | |
741 NULL, | |
742 NULL, | |
407 NULL | 743 NULL |
408 }; | 744 }; |