Signed-off-by: Paul B Mahol <onemda@gmail.com>
Paul B Mahol authored on 2016/05/11 06:48:50... | ... |
@@ -33,6 +33,7 @@ version <next>: |
33 | 33 |
- VAAPI-accelerated H.264/HEVC/MJPEG encoding |
34 | 34 |
- DTS Express (LBR) decoder |
35 | 35 |
- Generic OpenMAX IL encoder with support for Raspberry Pi |
36 |
+- IFF ANIM demuxer & decoder |
|
36 | 37 |
|
37 | 38 |
version 3.0: |
38 | 39 |
- Common Encryption (CENC) MP4 encoding and decoding support |
... | ... |
@@ -887,7 +887,7 @@ static const AVCodecDescriptor codec_descriptors[] = { |
887 | 887 |
.id = AV_CODEC_ID_IFF_ILBM, |
888 | 888 |
.type = AVMEDIA_TYPE_VIDEO, |
889 | 889 |
.name = "iff_ilbm", |
890 |
- .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"), |
|
890 |
+ .long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM"), |
|
891 | 891 |
.props = AV_CODEC_PROP_LOSSY, |
892 | 892 |
}, |
893 | 893 |
{ |
... | ... |
@@ -1,7 +1,8 @@ |
1 | 1 |
/* |
2 |
- * IFF ACBM/DEEP/ILBM/PBM bitmap decoder |
|
2 |
+ * IFF ACBM/ANIM/DEEP/ILBM/PBM bitmap decoder |
|
3 | 3 |
* Copyright (c) 2010 Peter Ross <pross@xvid.org> |
4 | 4 |
* Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> |
5 |
+ * Copyright (c) 2016 Paul B Mahol |
|
5 | 6 |
* |
6 | 7 |
* This file is part of FFmpeg. |
7 | 8 |
* |
... | ... |
@@ -22,7 +23,7 @@ |
22 | 22 |
|
23 | 23 |
/** |
24 | 24 |
* @file |
25 |
- * IFF ACBM/DEEP/ILBM/PBM bitmap decoder |
|
25 |
+ * IFF ACBM/ANIM/DEEP/ILBM/PBM bitmap decoder |
|
26 | 26 |
*/ |
27 | 27 |
|
28 | 28 |
#include <stdint.h> |
... | ... |
@@ -30,8 +31,8 @@ |
30 | 30 |
#include "libavutil/imgutils.h" |
31 | 31 |
#include "bytestream.h" |
32 | 32 |
#include "avcodec.h" |
33 |
-#include "get_bits.h" |
|
34 | 33 |
#include "internal.h" |
34 |
+#include "mathops.h" |
|
35 | 35 |
|
36 | 36 |
// TODO: masking bits |
37 | 37 |
typedef enum { |
... | ... |
@@ -50,6 +51,7 @@ typedef struct IffContext { |
50 | 50 |
uint32_t *mask_buf; ///< temporary buffer for palette indices |
51 | 51 |
uint32_t *mask_palbuf; ///< masking palette table |
52 | 52 |
unsigned compression; ///< delta compression method used |
53 |
+ unsigned is_short; ///< short compression method used |
|
53 | 54 |
unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) |
54 | 55 |
unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) |
55 | 56 |
unsigned flags; ///< 1 for EHB, 0 is no extra half darkening |
... | ... |
@@ -57,6 +59,11 @@ typedef struct IffContext { |
57 | 57 |
unsigned masking; ///< TODO: masking method used |
58 | 58 |
int init; // 1 if buffer and palette data already initialized, 0 otherwise |
59 | 59 |
int16_t tvdc[16]; ///< TVDC lookup table |
60 |
+ GetByteContext gb; |
|
61 |
+ uint8_t *video[2]; |
|
62 |
+ unsigned video_size; |
|
63 |
+ uint32_t *pal[2]; |
|
64 |
+ int first; |
|
60 | 65 |
} IffContext; |
61 | 66 |
|
62 | 67 |
#define LUT8_PART(plane, v) \ |
... | ... |
@@ -189,10 +196,11 @@ static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) |
189 | 189 |
* @return >= 0 in case of success, a negative error code otherwise |
190 | 190 |
*/ |
191 | 191 |
static int extract_header(AVCodecContext *const avctx, |
192 |
- const AVPacket *const avpkt) { |
|
193 |
- const uint8_t *buf; |
|
194 |
- unsigned buf_size; |
|
192 |
+ const AVPacket *const avpkt) |
|
193 |
+{ |
|
195 | 194 |
IffContext *s = avctx->priv_data; |
195 |
+ const uint8_t *buf; |
|
196 |
+ unsigned buf_size = 0; |
|
196 | 197 |
int i, palette_size; |
197 | 198 |
|
198 | 199 |
if (avctx->extradata_size < 2) { |
... | ... |
@@ -201,20 +209,51 @@ static int extract_header(AVCodecContext *const avctx, |
201 | 201 |
} |
202 | 202 |
palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); |
203 | 203 |
|
204 |
- if (avpkt) { |
|
205 |
- int image_size; |
|
206 |
- if (avpkt->size < 2) |
|
207 |
- return AVERROR_INVALIDDATA; |
|
208 |
- image_size = avpkt->size - AV_RB16(avpkt->data); |
|
209 |
- buf = avpkt->data; |
|
210 |
- buf_size = bytestream_get_be16(&buf); |
|
211 |
- if (buf_size <= 1 || image_size <= 1) { |
|
212 |
- av_log(avctx, AV_LOG_ERROR, |
|
213 |
- "Invalid image size received: %u -> image data offset: %d\n", |
|
214 |
- buf_size, image_size); |
|
215 |
- return AVERROR_INVALIDDATA; |
|
204 |
+ if (avpkt && avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
205 |
+ uint32_t chunk_id; |
|
206 |
+ uint64_t data_size; |
|
207 |
+ GetByteContext *gb = &s->gb; |
|
208 |
+ |
|
209 |
+ bytestream2_skip(gb, 4); |
|
210 |
+ while (bytestream2_get_bytes_left(gb) >= 1) { |
|
211 |
+ chunk_id = bytestream2_get_le32(gb); |
|
212 |
+ data_size = bytestream2_get_be32(gb); |
|
213 |
+ |
|
214 |
+ if (chunk_id == MKTAG('B', 'M', 'H', 'D')) { |
|
215 |
+ bytestream2_skip(gb, data_size + (data_size & 1)); |
|
216 |
+ } else if (chunk_id == MKTAG('A', 'N', 'H', 'D')) { |
|
217 |
+ if (data_size < 40) |
|
218 |
+ return AVERROR_INVALIDDATA; |
|
219 |
+ |
|
220 |
+ s->compression = (bytestream2_get_byte(gb) << 8) | (s->compression & 0xFF); |
|
221 |
+ bytestream2_skip(gb, 19); |
|
222 |
+ s->is_short = !(bytestream2_get_be32(gb) & 1); |
|
223 |
+ data_size -= 24; |
|
224 |
+ bytestream2_skip(gb, data_size + (data_size & 1)); |
|
225 |
+ } else if (chunk_id == MKTAG('D', 'L', 'T', 'A') || |
|
226 |
+ chunk_id == MKTAG('B', 'O', 'D', 'Y')) { |
|
227 |
+ if (chunk_id == MKTAG('B','O','D','Y')) |
|
228 |
+ s->compression &= 0xFF; |
|
229 |
+ break; |
|
230 |
+ } else if (chunk_id == MKTAG('C', 'M', 'A', 'P')) { |
|
231 |
+ int count = data_size / 3; |
|
232 |
+ uint32_t *pal = s->pal[0]; |
|
233 |
+ |
|
234 |
+ if (count > 256) |
|
235 |
+ return AVERROR_INVALIDDATA; |
|
236 |
+ if (s->ham) { |
|
237 |
+ for (i = 0; i < count; i++) |
|
238 |
+ pal[i] = 0xFF000000 | bytestream2_get_le24(gb); |
|
239 |
+ } else { |
|
240 |
+ for (i = 0; i < count; i++) |
|
241 |
+ pal[i] = 0xFF000000 | bytestream2_get_be24(gb); |
|
242 |
+ } |
|
243 |
+ bytestream2_skip(gb, data_size & 1); |
|
244 |
+ } else { |
|
245 |
+ bytestream2_skip(gb, data_size + (data_size&1)); |
|
246 |
+ } |
|
216 | 247 |
} |
217 |
- } else { |
|
248 |
+ } else if (!avpkt) { |
|
218 | 249 |
buf = avctx->extradata; |
219 | 250 |
buf_size = bytestream_get_be16(&buf); |
220 | 251 |
if (buf_size <= 1 || palette_size < 0) { |
... | ... |
@@ -323,10 +362,13 @@ static int extract_header(AVCodecContext *const avctx, |
323 | 323 |
static av_cold int decode_end(AVCodecContext *avctx) |
324 | 324 |
{ |
325 | 325 |
IffContext *s = avctx->priv_data; |
326 |
- av_frame_free(&s->frame); |
|
327 | 326 |
av_freep(&s->planebuf); |
328 | 327 |
av_freep(&s->ham_buf); |
329 | 328 |
av_freep(&s->ham_palbuf); |
329 |
+ av_freep(&s->video[0]); |
|
330 |
+ av_freep(&s->video[1]); |
|
331 |
+ av_freep(&s->pal[0]); |
|
332 |
+ av_freep(&s->pal[1]); |
|
330 | 333 |
return 0; |
331 | 334 |
} |
332 | 335 |
|
... | ... |
@@ -371,10 +413,16 @@ static av_cold int decode_init(AVCodecContext *avctx) |
371 | 371 |
return AVERROR(ENOMEM); |
372 | 372 |
|
373 | 373 |
s->bpp = avctx->bits_per_coded_sample; |
374 |
- s->frame = av_frame_alloc(); |
|
375 |
- if (!s->frame) { |
|
376 |
- decode_end(avctx); |
|
377 |
- return AVERROR(ENOMEM); |
|
374 |
+ |
|
375 |
+ if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
376 |
+ s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp; |
|
377 |
+ s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); |
|
378 |
+ s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); |
|
379 |
+ s->pal[0] = av_calloc(256, sizeof(*s->pal[0])); |
|
380 |
+ s->pal[1] = av_calloc(256, sizeof(*s->pal[1])); |
|
381 |
+ if (!s->video[0] || !s->video[1] || !s->pal[0] || !s->pal[1]) |
|
382 |
+ return AVERROR(ENOMEM); |
|
383 |
+ s->first = 1; |
|
378 | 384 |
} |
379 | 385 |
|
380 | 386 |
if ((err = extract_header(avctx, NULL)) < 0) |
... | ... |
@@ -480,20 +528,18 @@ static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf, |
480 | 480 |
* @return number of consumed bytes in byterun1 compressed bitstream |
481 | 481 |
*/ |
482 | 482 |
static int decode_byterun(uint8_t *dst, int dst_size, |
483 |
- const uint8_t *buf, const uint8_t *const buf_end) |
|
483 |
+ GetByteContext *gb) |
|
484 | 484 |
{ |
485 |
- const uint8_t *const buf_start = buf; |
|
486 | 485 |
unsigned x; |
487 |
- for (x = 0; x < dst_size && buf < buf_end;) { |
|
486 |
+ for (x = 0; x < dst_size && bytestream2_get_bytes_left(gb) > 0;) { |
|
488 | 487 |
unsigned length; |
489 |
- const int8_t value = *buf++; |
|
488 |
+ const int8_t value = bytestream2_get_byte(gb); |
|
490 | 489 |
if (value >= 0) { |
491 |
- length = FFMIN3(value + 1, dst_size - x, buf_end - buf); |
|
492 |
- memcpy(dst + x, buf, length); |
|
493 |
- buf += length; |
|
490 |
+ length = FFMIN3(value + 1, dst_size - x, bytestream2_get_bytes_left(gb)); |
|
491 |
+ bytestream2_get_buffer(gb, dst + x, length); |
|
494 | 492 |
} else if (value > -128) { |
495 | 493 |
length = FFMIN(-value + 1, dst_size - x); |
496 |
- memset(dst + x, *buf++, length); |
|
494 |
+ memset(dst + x, bytestream2_get_byte(gb), length); |
|
497 | 495 |
} else { // noop |
498 | 496 |
continue; |
499 | 497 |
} |
... | ... |
@@ -503,7 +549,7 @@ static int decode_byterun(uint8_t *dst, int dst_size, |
503 | 503 |
av_log(NULL, AV_LOG_WARNING, "decode_byterun ended before plane size\n"); |
504 | 504 |
memset(dst+x, 0, dst_size - x); |
505 | 505 |
} |
506 |
- return buf - buf_start; |
|
506 |
+ return bytestream2_tell(gb); |
|
507 | 507 |
} |
508 | 508 |
|
509 | 509 |
#define DECODE_RGBX_COMMON(type) \ |
... | ... |
@@ -660,10 +706,525 @@ static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, i |
660 | 660 |
} |
661 | 661 |
} |
662 | 662 |
|
663 |
+static void decode_byte_vertical_delta(uint8_t *dst, |
|
664 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
665 |
+ int w, int bpp, int dst_size) |
|
666 |
+{ |
|
667 |
+ int ncolumns = ((w + 15) / 16) * 2; |
|
668 |
+ int dstpitch = ncolumns * bpp; |
|
669 |
+ unsigned ofsdst, ofssrc, opcode, x; |
|
670 |
+ GetByteContext ptrs, gb; |
|
671 |
+ PutByteContext pb; |
|
672 |
+ int i, j, k; |
|
673 |
+ |
|
674 |
+ bytestream2_init(&ptrs, buf, buf_end - buf); |
|
675 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
676 |
+ |
|
677 |
+ for (k = 0; k < bpp; k++) { |
|
678 |
+ ofssrc = bytestream2_get_be32(&ptrs); |
|
679 |
+ |
|
680 |
+ if (!ofssrc) |
|
681 |
+ continue; |
|
682 |
+ |
|
683 |
+ if (ofssrc >= buf_end - buf) |
|
684 |
+ continue; |
|
685 |
+ |
|
686 |
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); |
|
687 |
+ for (j = 0; j < ncolumns; j++) { |
|
688 |
+ ofsdst = j + k * ncolumns; |
|
689 |
+ |
|
690 |
+ i = bytestream2_get_byte(&gb); |
|
691 |
+ while (i > 0) { |
|
692 |
+ opcode = bytestream2_get_byte(&gb); |
|
693 |
+ |
|
694 |
+ if (opcode == 0) { |
|
695 |
+ opcode = bytestream2_get_byte(&gb); |
|
696 |
+ x = bytestream2_get_byte(&gb); |
|
697 |
+ |
|
698 |
+ while (opcode) { |
|
699 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
700 |
+ bytestream2_put_byte(&pb, x); |
|
701 |
+ ofsdst += dstpitch; |
|
702 |
+ opcode--; |
|
703 |
+ } |
|
704 |
+ } else if (opcode < 0x80) { |
|
705 |
+ ofsdst += opcode * dstpitch; |
|
706 |
+ } else { |
|
707 |
+ opcode &= 0x7f; |
|
708 |
+ |
|
709 |
+ while (opcode) { |
|
710 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
711 |
+ bytestream2_put_byte(&pb, bytestream2_get_byte(&gb)); |
|
712 |
+ ofsdst += dstpitch; |
|
713 |
+ opcode--; |
|
714 |
+ } |
|
715 |
+ } |
|
716 |
+ i--; |
|
717 |
+ } |
|
718 |
+ } |
|
719 |
+ } |
|
720 |
+} |
|
721 |
+ |
|
722 |
+static void decode_delta_j(uint8_t *dst, |
|
723 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
724 |
+ int w, int h, int bpp, int dst_size) |
|
725 |
+{ |
|
726 |
+ int32_t pitch; |
|
727 |
+ uint8_t *end = dst + dst_size, *ptr; |
|
728 |
+ uint32_t type, flag, cols, groups, rows, bytes; |
|
729 |
+ uint32_t offset; |
|
730 |
+ int planepitch_byte = (w + 7) / 8; |
|
731 |
+ int planepitch = ((w + 15) / 16) * 2; |
|
732 |
+ int kludge_j, b, g, r, d; |
|
733 |
+ GetByteContext gb; |
|
734 |
+ |
|
735 |
+ pitch = planepitch * bpp; |
|
736 |
+ kludge_j = w < 320 ? (320 - w) / 8 / 2 : 0; |
|
737 |
+ |
|
738 |
+ bytestream2_init(&gb, buf, buf_end - buf); |
|
739 |
+ |
|
740 |
+ while (bytestream2_get_bytes_left(&gb) >= 2) { |
|
741 |
+ type = bytestream2_get_be16(&gb); |
|
742 |
+ |
|
743 |
+ switch (type) { |
|
744 |
+ case 0: |
|
745 |
+ return; |
|
746 |
+ case 1: |
|
747 |
+ flag = bytestream2_get_be16(&gb); |
|
748 |
+ cols = bytestream2_get_be16(&gb); |
|
749 |
+ groups = bytestream2_get_be16(&gb); |
|
750 |
+ |
|
751 |
+ for (g = 0; g < groups; g++) { |
|
752 |
+ offset = bytestream2_get_be16(&gb); |
|
753 |
+ |
|
754 |
+ if (kludge_j) |
|
755 |
+ offset = ((offset / (320 / 8)) * pitch) + (offset % (320 / 8)) - kludge_j; |
|
756 |
+ else |
|
757 |
+ offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte); |
|
758 |
+ |
|
759 |
+ ptr = dst + offset; |
|
760 |
+ if (ptr >= end) |
|
761 |
+ return; |
|
762 |
+ |
|
763 |
+ for (b = 0; b < cols; b++) { |
|
764 |
+ for (d = 0; d < bpp; d++) { |
|
765 |
+ uint8_t value = bytestream2_get_byte(&gb); |
|
766 |
+ |
|
767 |
+ if (flag) |
|
768 |
+ ptr[0] ^= value; |
|
769 |
+ else |
|
770 |
+ ptr[0] = value; |
|
771 |
+ |
|
772 |
+ ptr += planepitch; |
|
773 |
+ if (ptr >= end) |
|
774 |
+ return; |
|
775 |
+ } |
|
776 |
+ } |
|
777 |
+ if ((cols * bpp) & 1) |
|
778 |
+ bytestream2_skip(&gb, 1); |
|
779 |
+ } |
|
780 |
+ break; |
|
781 |
+ case 2: |
|
782 |
+ flag = bytestream2_get_be16(&gb); |
|
783 |
+ rows = bytestream2_get_be16(&gb); |
|
784 |
+ bytes = bytestream2_get_be16(&gb); |
|
785 |
+ groups = bytestream2_get_be16(&gb); |
|
786 |
+ |
|
787 |
+ for (g = 0; g < groups; g++) { |
|
788 |
+ offset = bytestream2_get_be16(&gb); |
|
789 |
+ |
|
790 |
+ if (kludge_j) |
|
791 |
+ offset = ((offset / (320 / 8)) * pitch) + (offset % (320/ 8)) - kludge_j; |
|
792 |
+ else |
|
793 |
+ offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte); |
|
794 |
+ |
|
795 |
+ for (r = 0; r < rows; r++) { |
|
796 |
+ for (d = 0; d < bpp; d++) { |
|
797 |
+ ptr = dst + offset + (r * pitch) + d * planepitch; |
|
798 |
+ if (ptr >= end) |
|
799 |
+ return; |
|
800 |
+ |
|
801 |
+ for (b = 0; b < bytes; b++) { |
|
802 |
+ uint8_t value = bytestream2_get_byte(&gb); |
|
803 |
+ |
|
804 |
+ if (flag) |
|
805 |
+ ptr[0] ^= value; |
|
806 |
+ else |
|
807 |
+ ptr[0] = value; |
|
808 |
+ |
|
809 |
+ ptr++; |
|
810 |
+ if (ptr >= end) |
|
811 |
+ return; |
|
812 |
+ } |
|
813 |
+ } |
|
814 |
+ } |
|
815 |
+ if ((rows * bytes * bpp) & 1) |
|
816 |
+ bytestream2_skip(&gb, 1); |
|
817 |
+ } |
|
818 |
+ break; |
|
819 |
+ default: |
|
820 |
+ return; |
|
821 |
+ } |
|
822 |
+ } |
|
823 |
+} |
|
824 |
+ |
|
825 |
+static void decode_short_vertical_delta(uint8_t *dst, |
|
826 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
827 |
+ int w, int bpp, int dst_size) |
|
828 |
+{ |
|
829 |
+ int ncolumns = (w + 15) >> 4; |
|
830 |
+ int dstpitch = ncolumns * bpp * 2; |
|
831 |
+ unsigned ofsdst, ofssrc, ofsdata, opcode, x; |
|
832 |
+ GetByteContext ptrs, gb, dptrs, dgb; |
|
833 |
+ PutByteContext pb; |
|
834 |
+ int i, j, k; |
|
835 |
+ |
|
836 |
+ if (buf_end - buf <= 64) |
|
837 |
+ return; |
|
838 |
+ |
|
839 |
+ bytestream2_init(&ptrs, buf, buf_end - buf); |
|
840 |
+ bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32); |
|
841 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
842 |
+ |
|
843 |
+ for (k = 0; k < bpp; k++) { |
|
844 |
+ ofssrc = bytestream2_get_be32(&ptrs); |
|
845 |
+ ofsdata = bytestream2_get_be32(&dptrs); |
|
846 |
+ |
|
847 |
+ if (!ofssrc) |
|
848 |
+ continue; |
|
849 |
+ |
|
850 |
+ if (ofssrc >= buf_end - buf) |
|
851 |
+ return; |
|
852 |
+ |
|
853 |
+ if (ofsdata >= buf_end - buf) |
|
854 |
+ return; |
|
855 |
+ |
|
856 |
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); |
|
857 |
+ bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata)); |
|
858 |
+ for (j = 0; j < ncolumns; j++) { |
|
859 |
+ ofsdst = (j + k * ncolumns) * 2; |
|
860 |
+ |
|
861 |
+ i = bytestream2_get_byte(&gb); |
|
862 |
+ while (i > 0) { |
|
863 |
+ opcode = bytestream2_get_byte(&gb); |
|
864 |
+ |
|
865 |
+ if (opcode == 0) { |
|
866 |
+ opcode = bytestream2_get_byte(&gb); |
|
867 |
+ x = bytestream2_get_be16(&dgb); |
|
868 |
+ |
|
869 |
+ while (opcode) { |
|
870 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
871 |
+ bytestream2_put_be16(&pb, x); |
|
872 |
+ ofsdst += dstpitch; |
|
873 |
+ opcode--; |
|
874 |
+ } |
|
875 |
+ } else if (opcode < 0x80) { |
|
876 |
+ ofsdst += opcode * dstpitch; |
|
877 |
+ } else { |
|
878 |
+ opcode &= 0x7f; |
|
879 |
+ |
|
880 |
+ while (opcode) { |
|
881 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
882 |
+ bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb)); |
|
883 |
+ ofsdst += dstpitch; |
|
884 |
+ opcode--; |
|
885 |
+ } |
|
886 |
+ } |
|
887 |
+ i--; |
|
888 |
+ } |
|
889 |
+ } |
|
890 |
+ } |
|
891 |
+} |
|
892 |
+ |
|
893 |
+static void decode_long_vertical_delta(uint8_t *dst, |
|
894 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
895 |
+ int w, int bpp, int dst_size) |
|
896 |
+{ |
|
897 |
+ int ncolumns = (w + 31) >> 5; |
|
898 |
+ int dstpitch = ((w + 15) / 16 * 2) * bpp; |
|
899 |
+ unsigned ofsdst, ofssrc, ofsdata, opcode, x; |
|
900 |
+ GetByteContext ptrs, gb, dptrs, dgb; |
|
901 |
+ PutByteContext pb; |
|
902 |
+ int i, j, k, h; |
|
903 |
+ |
|
904 |
+ if (buf_end - buf <= 64) |
|
905 |
+ return; |
|
906 |
+ |
|
907 |
+ h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0; |
|
908 |
+ bytestream2_init(&ptrs, buf, buf_end - buf); |
|
909 |
+ bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32); |
|
910 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
911 |
+ |
|
912 |
+ for (k = 0; k < bpp; k++) { |
|
913 |
+ ofssrc = bytestream2_get_be32(&ptrs); |
|
914 |
+ ofsdata = bytestream2_get_be32(&dptrs); |
|
915 |
+ |
|
916 |
+ if (!ofssrc) |
|
917 |
+ continue; |
|
918 |
+ |
|
919 |
+ if (ofssrc >= buf_end - buf) |
|
920 |
+ return; |
|
921 |
+ |
|
922 |
+ if (ofsdata >= buf_end - buf) |
|
923 |
+ return; |
|
924 |
+ |
|
925 |
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); |
|
926 |
+ bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata)); |
|
927 |
+ for (j = 0; j < ncolumns; j++) { |
|
928 |
+ ofsdst = (j + k * ncolumns) * 4 - h * (2 * k); |
|
929 |
+ |
|
930 |
+ i = bytestream2_get_byte(&gb); |
|
931 |
+ while (i > 0) { |
|
932 |
+ opcode = bytestream2_get_byte(&gb); |
|
933 |
+ |
|
934 |
+ if (opcode == 0) { |
|
935 |
+ opcode = bytestream2_get_byte(&gb); |
|
936 |
+ if (h && (j == (ncolumns - 1))) { |
|
937 |
+ x = bytestream2_get_be16(&dgb); |
|
938 |
+ bytestream2_skip(&dgb, 2); |
|
939 |
+ } else { |
|
940 |
+ x = bytestream2_get_be32(&dgb); |
|
941 |
+ } |
|
942 |
+ |
|
943 |
+ while (opcode) { |
|
944 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
945 |
+ if (h && (j == (ncolumns - 1))) { |
|
946 |
+ bytestream2_put_be16(&pb, x); |
|
947 |
+ } else { |
|
948 |
+ bytestream2_put_be32(&pb, x); |
|
949 |
+ } |
|
950 |
+ ofsdst += dstpitch; |
|
951 |
+ opcode--; |
|
952 |
+ } |
|
953 |
+ } else if (opcode < 0x80) { |
|
954 |
+ ofsdst += opcode * dstpitch; |
|
955 |
+ } else { |
|
956 |
+ opcode &= 0x7f; |
|
957 |
+ |
|
958 |
+ while (opcode) { |
|
959 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
960 |
+ if (h && (j == (ncolumns - 1))) { |
|
961 |
+ bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb)); |
|
962 |
+ bytestream2_skip(&dgb, 2); |
|
963 |
+ } else { |
|
964 |
+ bytestream2_put_be32(&pb, bytestream2_get_be32(&dgb)); |
|
965 |
+ } |
|
966 |
+ ofsdst += dstpitch; |
|
967 |
+ opcode--; |
|
968 |
+ } |
|
969 |
+ } |
|
970 |
+ i--; |
|
971 |
+ } |
|
972 |
+ } |
|
973 |
+ } |
|
974 |
+} |
|
975 |
+ |
|
976 |
+static void decode_short_vertical_delta2(uint8_t *dst, |
|
977 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
978 |
+ int w, int bpp, int dst_size) |
|
979 |
+{ |
|
980 |
+ int ncolumns = (w + 15) >> 4; |
|
981 |
+ int dstpitch = ncolumns * bpp * 2; |
|
982 |
+ unsigned ofsdst, ofssrc, opcode, x; |
|
983 |
+ GetByteContext ptrs, gb; |
|
984 |
+ PutByteContext pb; |
|
985 |
+ int i, j, k; |
|
986 |
+ |
|
987 |
+ bytestream2_init(&ptrs, buf, buf_end - buf); |
|
988 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
989 |
+ |
|
990 |
+ for (k = 0; k < bpp; k++) { |
|
991 |
+ ofssrc = bytestream2_get_be32(&ptrs); |
|
992 |
+ |
|
993 |
+ if (!ofssrc) |
|
994 |
+ continue; |
|
995 |
+ |
|
996 |
+ if (ofssrc >= buf_end - buf) |
|
997 |
+ continue; |
|
998 |
+ |
|
999 |
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); |
|
1000 |
+ for (j = 0; j < ncolumns; j++) { |
|
1001 |
+ ofsdst = (j + k * ncolumns) * 2; |
|
1002 |
+ |
|
1003 |
+ i = bytestream2_get_be16(&gb); |
|
1004 |
+ while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) { |
|
1005 |
+ opcode = bytestream2_get_be16(&gb); |
|
1006 |
+ |
|
1007 |
+ if (opcode == 0) { |
|
1008 |
+ opcode = bytestream2_get_be16(&gb); |
|
1009 |
+ x = bytestream2_get_be16(&gb); |
|
1010 |
+ |
|
1011 |
+ while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) { |
|
1012 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
1013 |
+ bytestream2_put_be16(&pb, x); |
|
1014 |
+ ofsdst += dstpitch; |
|
1015 |
+ opcode--; |
|
1016 |
+ } |
|
1017 |
+ } else if (opcode < 0x8000) { |
|
1018 |
+ ofsdst += opcode * dstpitch; |
|
1019 |
+ } else { |
|
1020 |
+ opcode &= 0x7fff; |
|
1021 |
+ |
|
1022 |
+ while (opcode && bytestream2_get_bytes_left(&gb) > 1 && |
|
1023 |
+ bytestream2_get_bytes_left_p(&pb) > 1) { |
|
1024 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
1025 |
+ bytestream2_put_be16(&pb, bytestream2_get_be16(&gb)); |
|
1026 |
+ ofsdst += dstpitch; |
|
1027 |
+ opcode--; |
|
1028 |
+ } |
|
1029 |
+ } |
|
1030 |
+ i--; |
|
1031 |
+ } |
|
1032 |
+ } |
|
1033 |
+ } |
|
1034 |
+} |
|
1035 |
+ |
|
1036 |
+static void decode_long_vertical_delta2(uint8_t *dst, |
|
1037 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
1038 |
+ int w, int bpp, int dst_size) |
|
1039 |
+{ |
|
1040 |
+ int ncolumns = (w + 31) >> 5; |
|
1041 |
+ int dstpitch = ((w + 15) / 16 * 2) * bpp; |
|
1042 |
+ unsigned ofsdst, ofssrc, opcode, x; |
|
1043 |
+ unsigned skip = 0x80000000, mask = skip - 1; |
|
1044 |
+ GetByteContext ptrs, gb; |
|
1045 |
+ PutByteContext pb; |
|
1046 |
+ int i, j, k, h; |
|
1047 |
+ |
|
1048 |
+ h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0; |
|
1049 |
+ bytestream2_init(&ptrs, buf, buf_end - buf); |
|
1050 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
1051 |
+ |
|
1052 |
+ for (k = 0; k < bpp; k++) { |
|
1053 |
+ ofssrc = bytestream2_get_be32(&ptrs); |
|
1054 |
+ |
|
1055 |
+ if (!ofssrc) |
|
1056 |
+ continue; |
|
1057 |
+ |
|
1058 |
+ if (ofssrc >= buf_end - buf) |
|
1059 |
+ continue; |
|
1060 |
+ |
|
1061 |
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); |
|
1062 |
+ for (j = 0; j < ncolumns; j++) { |
|
1063 |
+ ofsdst = (j + k * ncolumns) * 4 - h * (2 * k); |
|
1064 |
+ |
|
1065 |
+ if (h && (j == (ncolumns - 1))) { |
|
1066 |
+ skip = 0x8000; |
|
1067 |
+ mask = skip - 1; |
|
1068 |
+ } |
|
1069 |
+ |
|
1070 |
+ i = bytestream2_get_be32(&gb); |
|
1071 |
+ while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) { |
|
1072 |
+ opcode = bytestream2_get_be32(&gb); |
|
1073 |
+ |
|
1074 |
+ if (opcode == 0) { |
|
1075 |
+ if (h && (j == ncolumns - 1)) { |
|
1076 |
+ opcode = bytestream2_get_be16(&gb); |
|
1077 |
+ x = bytestream2_get_be16(&gb); |
|
1078 |
+ } else { |
|
1079 |
+ opcode = bytestream2_get_be32(&gb); |
|
1080 |
+ x = bytestream2_get_be32(&gb); |
|
1081 |
+ } |
|
1082 |
+ |
|
1083 |
+ while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) { |
|
1084 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
1085 |
+ if (h && (j == ncolumns - 1)) |
|
1086 |
+ bytestream2_put_be16(&pb, x); |
|
1087 |
+ else |
|
1088 |
+ bytestream2_put_be32(&pb, x); |
|
1089 |
+ ofsdst += dstpitch; |
|
1090 |
+ opcode--; |
|
1091 |
+ } |
|
1092 |
+ } else if (opcode < skip) { |
|
1093 |
+ ofsdst += opcode * dstpitch; |
|
1094 |
+ } else { |
|
1095 |
+ opcode &= mask; |
|
1096 |
+ |
|
1097 |
+ while (opcode && bytestream2_get_bytes_left(&gb) > 1 && |
|
1098 |
+ bytestream2_get_bytes_left_p(&pb) > 1) { |
|
1099 |
+ bytestream2_seek_p(&pb, ofsdst, SEEK_SET); |
|
1100 |
+ if (h && (j == ncolumns - 1)) { |
|
1101 |
+ bytestream2_put_be16(&pb, bytestream2_get_be16(&gb)); |
|
1102 |
+ } else { |
|
1103 |
+ bytestream2_put_be32(&pb, bytestream2_get_be32(&gb)); |
|
1104 |
+ } |
|
1105 |
+ ofsdst += dstpitch; |
|
1106 |
+ opcode--; |
|
1107 |
+ } |
|
1108 |
+ } |
|
1109 |
+ i--; |
|
1110 |
+ } |
|
1111 |
+ } |
|
1112 |
+ } |
|
1113 |
+} |
|
1114 |
+ |
|
1115 |
+static void decode_delta_l(uint8_t *dst, |
|
1116 |
+ const uint8_t *buf, const uint8_t *buf_end, |
|
1117 |
+ int w, int flag, int bpp, int dst_size) |
|
1118 |
+{ |
|
1119 |
+ GetByteContext off0, off1, dgb, ogb; |
|
1120 |
+ PutByteContext pb; |
|
1121 |
+ unsigned poff0, poff1; |
|
1122 |
+ int i, k, dstpitch; |
|
1123 |
+ int planepitch_byte = (w + 7) / 8; |
|
1124 |
+ int planepitch = ((w + 15) / 16) * 2; |
|
1125 |
+ int pitch = planepitch * bpp; |
|
1126 |
+ |
|
1127 |
+ if (buf_end - buf <= 64) |
|
1128 |
+ return; |
|
1129 |
+ |
|
1130 |
+ bytestream2_init(&off0, buf, buf_end - buf); |
|
1131 |
+ bytestream2_init(&off1, buf + 32, buf_end - (buf + 32)); |
|
1132 |
+ bytestream2_init_writer(&pb, dst, dst_size); |
|
1133 |
+ |
|
1134 |
+ dstpitch = flag ? (((w + 7) / 8) * bpp): 2; |
|
1135 |
+ |
|
1136 |
+ for (k = 0; k < bpp; k++) { |
|
1137 |
+ poff0 = bytestream2_get_be32(&off0); |
|
1138 |
+ poff1 = bytestream2_get_be32(&off1); |
|
1139 |
+ |
|
1140 |
+ if (!poff0) |
|
1141 |
+ continue; |
|
1142 |
+ |
|
1143 |
+ if (2LL * poff0 >= buf_end - buf) |
|
1144 |
+ return; |
|
1145 |
+ |
|
1146 |
+ if (2LL * poff1 >= buf_end - buf) |
|
1147 |
+ return; |
|
1148 |
+ |
|
1149 |
+ bytestream2_init(&dgb, buf + 2 * poff0, buf_end - (buf + 2 * poff0)); |
|
1150 |
+ bytestream2_init(&ogb, buf + 2 * poff1, buf_end - (buf + 2 * poff1)); |
|
1151 |
+ |
|
1152 |
+ while ((bytestream2_peek_be16(&ogb)) != 0xFFFF) { |
|
1153 |
+ uint16_t offset = bytestream2_get_be16(&ogb); |
|
1154 |
+ int16_t cnt = bytestream2_get_be16(&ogb); |
|
1155 |
+ uint16_t data; |
|
1156 |
+ |
|
1157 |
+ offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch; |
|
1158 |
+ if (cnt < 0) { |
|
1159 |
+ bytestream2_seek_p(&pb, offset, SEEK_SET); |
|
1160 |
+ cnt = -cnt; |
|
1161 |
+ data = bytestream2_get_be16(&dgb); |
|
1162 |
+ for (i = 0; i < cnt; i++) { |
|
1163 |
+ bytestream2_put_be16(&pb, data); |
|
1164 |
+ bytestream2_skip_p(&pb, dstpitch - 2); |
|
1165 |
+ } |
|
1166 |
+ } else { |
|
1167 |
+ bytestream2_seek_p(&pb, offset, SEEK_SET); |
|
1168 |
+ for (i = 0; i < cnt; i++) { |
|
1169 |
+ data = bytestream2_get_be16(&dgb); |
|
1170 |
+ bytestream2_put_be16(&pb, data); |
|
1171 |
+ bytestream2_skip_p(&pb, dstpitch - 2); |
|
1172 |
+ } |
|
1173 |
+ } |
|
1174 |
+ } |
|
1175 |
+ } |
|
1176 |
+} |
|
1177 |
+ |
|
663 | 1178 |
static int unsupported(AVCodecContext *avctx) |
664 | 1179 |
{ |
665 | 1180 |
IffContext *s = avctx->priv_data; |
666 |
- avpriv_request_sample(avctx, "bitmap (compression %i, bpp %i, ham %i)", s->compression, s->bpp, s->ham); |
|
1181 |
+ avpriv_request_sample(avctx, "bitmap (compression 0x%0x, bpp %i, ham %i)", s->compression, s->bpp, s->ham); |
|
667 | 1182 |
return AVERROR_INVALIDDATA; |
668 | 1183 |
} |
669 | 1184 |
|
... | ... |
@@ -672,23 +1233,30 @@ static int decode_frame(AVCodecContext *avctx, |
672 | 672 |
AVPacket *avpkt) |
673 | 673 |
{ |
674 | 674 |
IffContext *s = avctx->priv_data; |
675 |
- const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL; |
|
676 |
- const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0; |
|
675 |
+ AVFrame *frame = data; |
|
676 |
+ const uint8_t *buf = avpkt->data; |
|
677 |
+ int buf_size = avpkt->size; |
|
677 | 678 |
const uint8_t *buf_end = buf + buf_size; |
678 | 679 |
int y, plane, res; |
679 |
- GetByteContext gb; |
|
680 |
+ GetByteContext *gb = &s->gb; |
|
680 | 681 |
const AVPixFmtDescriptor *desc; |
681 | 682 |
|
683 |
+ bytestream2_init(gb, avpkt->data, avpkt->size); |
|
684 |
+ |
|
682 | 685 |
if ((res = extract_header(avctx, avpkt)) < 0) |
683 | 686 |
return res; |
684 |
- if ((res = ff_reget_buffer(avctx, s->frame)) < 0) |
|
687 |
+ |
|
688 |
+ if ((res = ff_get_buffer(avctx, frame, 0)) < 0) |
|
685 | 689 |
return res; |
690 |
+ s->frame = frame; |
|
686 | 691 |
|
692 |
+ buf += bytestream2_tell(gb); |
|
693 |
+ buf_size -= bytestream2_tell(gb); |
|
687 | 694 |
desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
688 | 695 |
|
689 | 696 |
if (!s->init && avctx->bits_per_coded_sample <= 8 && |
690 | 697 |
avctx->pix_fmt == AV_PIX_FMT_PAL8) { |
691 |
- if ((res = cmap_read_palette(avctx, (uint32_t *)s->frame->data[1])) < 0) |
|
698 |
+ if ((res = cmap_read_palette(avctx, (uint32_t *)frame->data[1])) < 0) |
|
692 | 699 |
return res; |
693 | 700 |
} else if (!s->init && avctx->bits_per_coded_sample <= 8 && |
694 | 701 |
avctx->pix_fmt == AV_PIX_FMT_RGB32) { |
... | ... |
@@ -697,22 +1265,33 @@ static int decode_frame(AVCodecContext *avctx, |
697 | 697 |
} |
698 | 698 |
s->init = 1; |
699 | 699 |
|
700 |
+ if (s->compression <= 0xff && avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
701 |
+ if (avctx->pix_fmt == AV_PIX_FMT_PAL8) |
|
702 |
+ memcpy(s->pal[0], s->frame->data[1], 256 * 4); |
|
703 |
+ } |
|
704 |
+ |
|
705 |
+ if (s->compression > 0xff && s->first) { |
|
706 |
+ memcpy(s->video[1], s->video[0], s->video_size); |
|
707 |
+ memcpy(s->pal[1], s->pal[0], 256 * 4); |
|
708 |
+ s->first = 0; |
|
709 |
+ } |
|
710 |
+ |
|
700 | 711 |
switch (s->compression) { |
701 |
- case 0: |
|
712 |
+ case 0x0: |
|
702 | 713 |
if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) { |
703 | 714 |
if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
704 |
- memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); |
|
715 |
+ memset(frame->data[0], 0, avctx->height * frame->linesize[0]); |
|
705 | 716 |
for (plane = 0; plane < s->bpp; plane++) { |
706 | 717 |
for (y = 0; y < avctx->height && buf < buf_end; y++) { |
707 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
718 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
708 | 719 |
decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); |
709 | 720 |
buf += s->planesize; |
710 | 721 |
} |
711 | 722 |
} |
712 | 723 |
} else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 |
713 |
- memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); |
|
724 |
+ memset(frame->data[0], 0, avctx->height * frame->linesize[0]); |
|
714 | 725 |
for (y = 0; y < avctx->height; y++) { |
715 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
726 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
716 | 727 |
memset(s->ham_buf, 0, s->planesize * 8); |
717 | 728 |
for (plane = 0; plane < s->bpp; plane++) { |
718 | 729 |
const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize; |
... | ... |
@@ -728,7 +1307,7 @@ static int decode_frame(AVCodecContext *avctx, |
728 | 728 |
int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3); |
729 | 729 |
int x; |
730 | 730 |
for (y = 0; y < avctx->height && buf < buf_end; y++) { |
731 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
731 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
732 | 732 |
memcpy(row, buf, FFMIN(raw_width, buf_end - buf)); |
733 | 733 |
buf += raw_width; |
734 | 734 |
if (avctx->pix_fmt == AV_PIX_FMT_BGR32) { |
... | ... |
@@ -736,10 +1315,13 @@ static int decode_frame(AVCodecContext *avctx, |
736 | 736 |
row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4); |
737 | 737 |
} |
738 | 738 |
} |
739 |
- } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved |
|
739 |
+ } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved |
|
740 |
+ avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
740 | 741 |
if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
742 |
+ if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) |
|
743 |
+ memcpy(s->video[0], buf, FFMIN(buf_end - buf, s->video_size)); |
|
741 | 744 |
for (y = 0; y < avctx->height; y++) { |
742 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
745 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
743 | 746 |
memset(row, 0, avctx->width); |
744 | 747 |
for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { |
745 | 748 |
decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); |
... | ... |
@@ -748,7 +1330,7 @@ static int decode_frame(AVCodecContext *avctx, |
748 | 748 |
} |
749 | 749 |
} else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 |
750 | 750 |
for (y = 0; y < avctx->height; y++) { |
751 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
751 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
752 | 752 |
memset(s->ham_buf, 0, s->planesize * 8); |
753 | 753 |
for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { |
754 | 754 |
decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane); |
... | ... |
@@ -758,7 +1340,7 @@ static int decode_frame(AVCodecContext *avctx, |
758 | 758 |
} |
759 | 759 |
} else { // AV_PIX_FMT_BGR32 |
760 | 760 |
for (y = 0; y < avctx->height; y++) { |
761 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
761 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
762 | 762 |
memset(row, 0, avctx->width << 2); |
763 | 763 |
for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { |
764 | 764 |
decodeplane32((uint32_t *)row, buf, |
... | ... |
@@ -770,13 +1352,13 @@ static int decode_frame(AVCodecContext *avctx, |
770 | 770 |
} else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM |
771 | 771 |
if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
772 | 772 |
for (y = 0; y < avctx->height && buf_end > buf; y++) { |
773 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
773 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
774 | 774 |
memcpy(row, buf, FFMIN(avctx->width, buf_end - buf)); |
775 | 775 |
buf += avctx->width + (avctx->width % 2); // padding if odd |
776 | 776 |
} |
777 | 777 |
} else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 |
778 | 778 |
for (y = 0; y < avctx->height && buf_end > buf; y++) { |
779 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
779 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
780 | 780 |
memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf)); |
781 | 781 |
buf += avctx->width + (avctx->width & 1); // padding if odd |
782 | 782 |
decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); |
... | ... |
@@ -785,43 +1367,55 @@ static int decode_frame(AVCodecContext *avctx, |
785 | 785 |
return unsupported(avctx); |
786 | 786 |
} |
787 | 787 |
break; |
788 |
- case 1: |
|
789 |
- if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved |
|
788 |
+ case 0x1: |
|
789 |
+ if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved |
|
790 |
+ avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
790 | 791 |
if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
792 |
+ uint8_t *video = s->video[0]; |
|
793 |
+ |
|
791 | 794 |
for (y = 0; y < avctx->height; y++) { |
792 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
795 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
793 | 796 |
memset(row, 0, avctx->width); |
794 | 797 |
for (plane = 0; plane < s->bpp; plane++) { |
795 |
- buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); |
|
798 |
+ buf += decode_byterun(s->planebuf, s->planesize, gb); |
|
799 |
+ if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
800 |
+ memcpy(video, s->planebuf, s->planesize); |
|
801 |
+ video += s->planesize; |
|
802 |
+ } |
|
796 | 803 |
decodeplane8(row, s->planebuf, s->planesize, plane); |
797 | 804 |
} |
798 | 805 |
} |
799 | 806 |
} else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32 |
800 | 807 |
for (y = 0; y < avctx->height; y++) { |
801 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
808 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
802 | 809 |
memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t)); |
803 | 810 |
for (plane = 0; plane < s->bpp; plane++) { |
804 |
- buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); |
|
811 |
+ buf += decode_byterun(s->planebuf, s->planesize, gb); |
|
805 | 812 |
decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane); |
806 | 813 |
} |
807 | 814 |
lookup_pal_indicies((uint32_t *)row, s->mask_buf, s->mask_palbuf, avctx->width); |
808 | 815 |
} |
809 | 816 |
} else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 |
817 |
+ uint8_t *video = s->video[0]; |
|
810 | 818 |
for (y = 0; y < avctx->height; y++) { |
811 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
819 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
812 | 820 |
memset(s->ham_buf, 0, s->planesize * 8); |
813 | 821 |
for (plane = 0; plane < s->bpp; plane++) { |
814 |
- buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); |
|
822 |
+ buf += decode_byterun(s->planebuf, s->planesize, gb); |
|
823 |
+ if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { |
|
824 |
+ memcpy(video, s->planebuf, s->planesize); |
|
825 |
+ video += s->planesize; |
|
826 |
+ } |
|
815 | 827 |
decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane); |
816 | 828 |
} |
817 | 829 |
decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); |
818 | 830 |
} |
819 | 831 |
} else { // AV_PIX_FMT_BGR32 |
820 | 832 |
for (y = 0; y < avctx->height; y++) { |
821 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
833 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
822 | 834 |
memset(row, 0, avctx->width << 2); |
823 | 835 |
for (plane = 0; plane < s->bpp; plane++) { |
824 |
- buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); |
|
836 |
+ buf += decode_byterun(s->planebuf, s->planesize, gb); |
|
825 | 837 |
decodeplane32((uint32_t *)row, s->planebuf, s->planesize, plane); |
826 | 838 |
} |
827 | 839 |
} |
... | ... |
@@ -829,48 +1423,129 @@ static int decode_frame(AVCodecContext *avctx, |
829 | 829 |
} else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM |
830 | 830 |
if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
831 | 831 |
for (y = 0; y < avctx->height; y++) { |
832 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
833 |
- buf += decode_byterun(row, avctx->width, buf, buf_end); |
|
832 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
833 |
+ buf += decode_byterun(row, avctx->width, gb); |
|
834 | 834 |
} |
835 | 835 |
} else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 |
836 | 836 |
for (y = 0; y < avctx->height; y++) { |
837 |
- uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; |
|
838 |
- buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end); |
|
837 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
838 |
+ buf += decode_byterun(s->ham_buf, avctx->width, gb); |
|
839 | 839 |
decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); |
840 | 840 |
} |
841 | 841 |
} else |
842 | 842 |
return unsupported(avctx); |
843 | 843 |
} else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { // IFF-DEEP |
844 | 844 |
if (av_get_bits_per_pixel(desc) == 32) |
845 |
- decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]); |
|
845 |
+ decode_deep_rle32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0]); |
|
846 | 846 |
else |
847 | 847 |
return unsupported(avctx); |
848 | 848 |
} |
849 | 849 |
break; |
850 |
- case 4: |
|
851 |
- bytestream2_init(&gb, buf, buf_size); |
|
850 |
+ case 0x4: |
|
852 | 851 |
if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32) |
853 |
- decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); |
|
852 |
+ decode_rgb8(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]); |
|
854 | 853 |
else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N') && avctx->pix_fmt == AV_PIX_FMT_RGB444) |
855 |
- decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); |
|
854 |
+ decode_rgbn(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]); |
|
856 | 855 |
else |
857 | 856 |
return unsupported(avctx); |
858 | 857 |
break; |
859 |
- case 5: |
|
858 |
+ case 0x5: |
|
860 | 859 |
if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { |
861 | 860 |
if (av_get_bits_per_pixel(desc) == 32) |
862 |
- decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc); |
|
861 |
+ decode_deep_tvdc32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0], s->tvdc); |
|
863 | 862 |
else |
864 | 863 |
return unsupported(avctx); |
865 | 864 |
} else |
866 | 865 |
return unsupported(avctx); |
867 | 866 |
break; |
867 |
+ case 0x500: |
|
868 |
+ case 0x501: |
|
869 |
+ decode_byte_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); |
|
870 |
+ break; |
|
871 |
+ case 0x700: |
|
872 |
+ case 0x701: |
|
873 |
+ if (s->is_short) |
|
874 |
+ decode_short_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); |
|
875 |
+ else |
|
876 |
+ decode_long_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); |
|
877 |
+ break; |
|
878 |
+ case 0x800: |
|
879 |
+ case 0x801: |
|
880 |
+ if (s->is_short) |
|
881 |
+ decode_short_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); |
|
882 |
+ else |
|
883 |
+ decode_long_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size); |
|
884 |
+ break; |
|
885 |
+ case 0x4a00: |
|
886 |
+ case 0x4a01: |
|
887 |
+ decode_delta_j(s->video[0], buf, buf_end, avctx->width, avctx->height, s->bpp, s->video_size); |
|
888 |
+ break; |
|
889 |
+ case 0x6c00: |
|
890 |
+ case 0x6c01: |
|
891 |
+ decode_delta_l(s->video[0], buf, buf_end, avctx->width, s->is_short, s->bpp, s->video_size); |
|
892 |
+ break; |
|
868 | 893 |
default: |
869 | 894 |
return unsupported(avctx); |
870 | 895 |
} |
871 | 896 |
|
872 |
- if ((res = av_frame_ref(data, s->frame)) < 0) |
|
873 |
- return res; |
|
897 |
+ if (s->compression > 0xff) { |
|
898 |
+ if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
|
899 |
+ buf = s->video[0]; |
|
900 |
+ for (y = 0; y < avctx->height; y++) { |
|
901 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
902 |
+ memset(row, 0, avctx->width); |
|
903 |
+ for (plane = 0; plane < s->bpp; plane++) { |
|
904 |
+ decodeplane8(row, buf, s->planesize, plane); |
|
905 |
+ buf += s->planesize; |
|
906 |
+ } |
|
907 |
+ } |
|
908 |
+ memcpy(frame->data[1], s->pal[0], 256 * 4); |
|
909 |
+ } else if (s->ham) { |
|
910 |
+ int i, count = 1 << s->ham; |
|
911 |
+ |
|
912 |
+ buf = s->video[0]; |
|
913 |
+ memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof(uint32_t)); |
|
914 |
+ for (i = 0; i < count; i++) { |
|
915 |
+ s->ham_palbuf[i*2+1] = s->pal[0][i]; |
|
916 |
+ } |
|
917 |
+ for (i = 0; i < count; i++) { |
|
918 |
+ uint32_t tmp = i << (8 - s->ham); |
|
919 |
+ tmp |= tmp >> s->ham; |
|
920 |
+ s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; |
|
921 |
+ s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; |
|
922 |
+ s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; |
|
923 |
+ s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16; |
|
924 |
+ s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp; |
|
925 |
+ s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8; |
|
926 |
+ } |
|
927 |
+ if (s->masking == MASK_HAS_MASK) { |
|
928 |
+ for (i = 0; i < 8 * (1 << s->ham); i++) |
|
929 |
+ s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000; |
|
930 |
+ } |
|
931 |
+ for (y = 0; y < avctx->height; y++) { |
|
932 |
+ uint8_t *row = &frame->data[0][y * frame->linesize[0]]; |
|
933 |
+ memset(s->ham_buf, 0, s->planesize * 8); |
|
934 |
+ for (plane = 0; plane < s->bpp; plane++) { |
|
935 |
+ decodeplane8(s->ham_buf, buf, s->planesize, plane); |
|
936 |
+ buf += s->planesize; |
|
937 |
+ } |
|
938 |
+ decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); |
|
939 |
+ } |
|
940 |
+ } else { |
|
941 |
+ return unsupported(avctx); |
|
942 |
+ } |
|
943 |
+ |
|
944 |
+ FFSWAP(uint8_t *, s->video[0], s->video[1]); |
|
945 |
+ FFSWAP(uint32_t *, s->pal[0], s->pal[1]); |
|
946 |
+ } |
|
947 |
+ |
|
948 |
+ if (avpkt->flags & AV_PKT_FLAG_KEY) { |
|
949 |
+ frame->key_frame = 1; |
|
950 |
+ frame->pict_type = AV_PICTURE_TYPE_I; |
|
951 |
+ } else { |
|
952 |
+ frame->key_frame = 0; |
|
953 |
+ frame->pict_type = AV_PICTURE_TYPE_P; |
|
954 |
+ } |
|
874 | 955 |
|
875 | 956 |
*got_frame = 1; |
876 | 957 |
|
... | ... |
@@ -880,7 +1555,7 @@ static int decode_frame(AVCodecContext *avctx, |
880 | 880 |
#if CONFIG_IFF_ILBM_DECODER |
881 | 881 |
AVCodec ff_iff_ilbm_decoder = { |
882 | 882 |
.name = "iff", |
883 |
- .long_name = NULL_IF_CONFIG_SMALL("IFF"), |
|
883 |
+ .long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM"), |
|
884 | 884 |
.type = AVMEDIA_TYPE_VIDEO, |
885 | 885 |
.id = AV_CODEC_ID_IFF_ILBM, |
886 | 886 |
.priv_data_size = sizeof(IffContext), |
... | ... |
@@ -60,6 +60,8 @@ |
60 | 60 |
#define ID_RGBN MKTAG('R','G','B','N') |
61 | 61 |
#define ID_DSD MKTAG('D','S','D',' ') |
62 | 62 |
#define ID_ANIM MKTAG('A','N','I','M') |
63 |
+#define ID_ANHD MKTAG('A','N','H','D') |
|
64 |
+#define ID_DLTA MKTAG('D','L','T','A') |
|
63 | 65 |
|
64 | 66 |
#define ID_FORM MKTAG('F','O','R','M') |
65 | 67 |
#define ID_FRM8 MKTAG('F','R','M','8') |
... | ... |
@@ -113,6 +115,7 @@ typedef struct IffDemuxContext { |
113 | 113 |
unsigned transparency; ///< transparency color index in palette |
114 | 114 |
unsigned masking; ///< masking method used |
115 | 115 |
uint8_t tvdc[32]; ///< TVDC lookup table |
116 |
+ int64_t pts; |
|
116 | 117 |
} IffDemuxContext; |
117 | 118 |
|
118 | 119 |
/* Metadata string read */ |
... | ... |
@@ -147,7 +150,6 @@ static int iff_probe(AVProbeData *p) |
147 | 147 |
AV_RL32(d+8) == ID_DEEP || |
148 | 148 |
AV_RL32(d+8) == ID_ILBM || |
149 | 149 |
AV_RL32(d+8) == ID_RGB8 || |
150 |
- AV_RL32(d+8) == ID_RGB8 || |
|
151 | 150 |
AV_RL32(d+8) == ID_ANIM || |
152 | 151 |
AV_RL32(d+8) == ID_RGBN)) || |
153 | 152 |
(AV_RL32(d) == ID_FRM8 && AV_RL32(d+12) == ID_DSD)) |
... | ... |
@@ -367,8 +369,7 @@ static int iff_read_header(AVFormatContext *s) |
367 | 367 |
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content |
368 | 368 |
st->codecpar->codec_tag = avio_rl32(pb); |
369 | 369 |
if (st->codecpar->codec_tag == ID_ANIM) { |
370 |
- avio_skip(pb, 8); |
|
371 |
- st->codecpar->codec_tag = avio_rl32(pb); |
|
370 |
+ avio_skip(pb, 12); |
|
372 | 371 |
} |
373 | 372 |
iff->bitmap_compression = -1; |
374 | 373 |
iff->svx8_compression = -1; |
... | ... |
@@ -484,6 +485,9 @@ static int iff_read_header(AVFormatContext *s) |
484 | 484 |
} |
485 | 485 |
break; |
486 | 486 |
|
487 |
+ case ID_ANHD: |
|
488 |
+ break; |
|
489 |
+ |
|
487 | 490 |
case ID_DPEL: |
488 | 491 |
if (data_size < 4 || (data_size & 3)) |
489 | 492 |
return AVERROR_INVALIDDATA; |
... | ... |
@@ -626,7 +630,10 @@ static int iff_read_header(AVFormatContext *s) |
626 | 626 |
avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); |
627 | 627 |
} |
628 | 628 |
|
629 |
- avio_seek(pb, iff->body_pos, SEEK_SET); |
|
629 |
+ if (st->codecpar->codec_tag == ID_ANIM) |
|
630 |
+ avio_seek(pb, 12, SEEK_SET); |
|
631 |
+ else |
|
632 |
+ avio_seek(pb, iff->body_pos, SEEK_SET); |
|
630 | 633 |
|
631 | 634 |
switch(st->codecpar->codec_type) { |
632 | 635 |
case AVMEDIA_TYPE_AUDIO: |
... | ... |
@@ -672,6 +679,8 @@ static int iff_read_header(AVFormatContext *s) |
672 | 672 |
|
673 | 673 |
case AVMEDIA_TYPE_VIDEO: |
674 | 674 |
iff->bpp = st->codecpar->bits_per_coded_sample; |
675 |
+ if (st->codecpar->codec_tag == ID_ANIM) |
|
676 |
+ avpriv_set_pts_info(st, 32, 1, 60); |
|
675 | 677 |
if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { |
676 | 678 |
iff->ham = iff->bpp > 6 ? 6 : 4; |
677 | 679 |
st->codecpar->bits_per_coded_sample = 24; |
... | ... |
@@ -705,6 +714,28 @@ static int iff_read_header(AVFormatContext *s) |
705 | 705 |
return 0; |
706 | 706 |
} |
707 | 707 |
|
708 |
+static unsigned get_anim_duration(uint8_t *buf, int size) |
|
709 |
+{ |
|
710 |
+ GetByteContext gb; |
|
711 |
+ |
|
712 |
+ bytestream2_init(&gb, buf, size); |
|
713 |
+ bytestream2_skip(&gb, 4); |
|
714 |
+ while (bytestream2_get_bytes_left(&gb) > 8) { |
|
715 |
+ unsigned chunk = bytestream2_get_le32(&gb); |
|
716 |
+ unsigned size = bytestream2_get_be32(&gb); |
|
717 |
+ |
|
718 |
+ if (chunk == ID_ANHD) { |
|
719 |
+ if (size < 40) |
|
720 |
+ break; |
|
721 |
+ bytestream2_skip(&gb, 14); |
|
722 |
+ return bytestream2_get_be32(&gb); |
|
723 |
+ } else { |
|
724 |
+ bytestream2_skip(&gb, size + size & 1); |
|
725 |
+ } |
|
726 |
+ } |
|
727 |
+ return 10; |
|
728 |
+} |
|
729 |
+ |
|
708 | 730 |
static int iff_read_packet(AVFormatContext *s, |
709 | 731 |
AVPacket *pkt) |
710 | 732 |
{ |
... | ... |
@@ -714,8 +745,12 @@ static int iff_read_packet(AVFormatContext *s, |
714 | 714 |
int ret; |
715 | 715 |
int64_t pos = avio_tell(pb); |
716 | 716 |
|
717 |
- if (pos >= iff->body_end) |
|
717 |
+ if (st->codecpar->codec_tag == ID_ANIM) { |
|
718 |
+ if (avio_feof(pb)) |
|
719 |
+ return AVERROR_EOF; |
|
720 |
+ } else if (pos >= iff->body_end) { |
|
718 | 721 |
return AVERROR_EOF; |
722 |
+ } |
|
719 | 723 |
|
720 | 724 |
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
721 | 725 |
if (st->codecpar->codec_tag == ID_DSD || st->codecpar->codec_tag == ID_MAUD) { |
... | ... |
@@ -725,28 +760,39 @@ static int iff_read_packet(AVFormatContext *s, |
725 | 725 |
return AVERROR_INVALIDDATA; |
726 | 726 |
ret = av_get_packet(pb, pkt, iff->body_size); |
727 | 727 |
} |
728 |
- } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
|
729 |
- uint8_t *buf; |
|
728 |
+ } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && |
|
729 |
+ st->codecpar->codec_tag == ID_ANIM) { |
|
730 |
+ uint64_t data_size, orig_pos; |
|
731 |
+ uint32_t chunk_id = 0; |
|
730 | 732 |
|
731 |
- if (iff->body_size > INT_MAX - 2) |
|
732 |
- return AVERROR_INVALIDDATA; |
|
733 |
- if (av_new_packet(pkt, iff->body_size + 2) < 0) { |
|
734 |
- return AVERROR(ENOMEM); |
|
735 |
- } |
|
733 |
+ while (!avio_feof(pb)) { |
|
734 |
+ if (avio_feof(pb)) |
|
735 |
+ return AVERROR_EOF; |
|
736 |
+ |
|
737 |
+ chunk_id = avio_rl32(pb); |
|
738 |
+ data_size = avio_rb32(pb); |
|
739 |
+ orig_pos = avio_tell(pb); |
|
736 | 740 |
|
737 |
- buf = pkt->data; |
|
738 |
- bytestream_put_be16(&buf, 2); |
|
739 |
- ret = avio_read(pb, buf, iff->body_size); |
|
740 |
- if (ret<0) { |
|
741 |
- av_packet_unref(pkt); |
|
742 |
- } else if (ret < iff->body_size) |
|
743 |
- av_shrink_packet(pkt, ret + 2); |
|
741 |
+ if (chunk_id == ID_FORM) |
|
742 |
+ break; |
|
743 |
+ else |
|
744 |
+ avio_skip(pb, data_size); |
|
745 |
+ } |
|
746 |
+ ret = av_get_packet(pb, pkt, data_size); |
|
747 |
+ pkt->pos = orig_pos; |
|
748 |
+ pkt->duration = get_anim_duration(pkt->data, pkt->size); |
|
749 |
+ if (pos == 12) |
|
750 |
+ pkt->flags |= AV_PKT_FLAG_KEY; |
|
751 |
+ } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && |
|
752 |
+ st->codecpar->codec_tag != ID_ANIM) { |
|
753 |
+ ret = av_get_packet(pb, pkt, iff->body_size); |
|
754 |
+ pkt->pos = pos; |
|
755 |
+ if (pos == iff->body_pos) |
|
756 |
+ pkt->flags |= AV_PKT_FLAG_KEY; |
|
744 | 757 |
} else { |
745 | 758 |
av_assert0(0); |
746 | 759 |
} |
747 | 760 |
|
748 |
- if (pos == iff->body_pos) |
|
749 |
- pkt->flags |= AV_PKT_FLAG_KEY; |
|
750 | 761 |
if (ret < 0) |
751 | 762 |
return ret; |
752 | 763 |
pkt->stream_index = 0; |