summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2016-05-12 23:54:26 +0200
committerPaul B Mahol <onemda@gmail.com>2016-05-13 23:28:19 +0200
commit01ead2a6396357aa3f7ab7066880eb219a5dc1f6 (patch)
tree443f4aeb21784b5b55cd5c3ae786285abd6ec5dc
parent8ba257bac642583e62094955539d1a4ff03eb440 (diff)
avcodec/iff: implement 3rd delta ANIM decompression
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r--libavcodec/iff.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/libavcodec/iff.c b/libavcodec/iff.c
index 9875b26408..3225524e73 100644
--- a/libavcodec/iff.c
+++ b/libavcodec/iff.c
@@ -706,6 +706,59 @@ static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, i
}
}
+static void decode_short_horizontal_delta(uint8_t *dst,
+ const uint8_t *buf, const uint8_t *buf_end,
+ int w, int bpp, int dst_size)
+{
+ int planepitch = FFALIGN(w, 16) >> 3;
+ int pitch = planepitch * bpp;
+ GetByteContext ptrs, gb;
+ PutByteContext pb;
+ unsigned ofssrc, pos;
+ int i, k;
+
+ bytestream2_init(&ptrs, buf, buf_end - buf);
+ bytestream2_init_writer(&pb, dst, dst_size);
+
+ for (k = 0; k < bpp; k++) {
+ ofssrc = bytestream2_get_be32(&ptrs);
+ pos = 0;
+
+ if (!ofssrc)
+ continue;
+
+ if (ofssrc >= buf_end - buf)
+ continue;
+
+ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+ while (bytestream2_peek_be16(&gb) != 0xFFFF && bytestream2_get_bytes_left(&gb) > 3) {
+ int16_t offset = bytestream2_get_be16(&gb);
+ unsigned noffset;
+
+ if (offset >= 0) {
+ unsigned data = bytestream2_get_be16(&gb);
+
+ pos += offset * 2;
+ noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
+ bytestream2_seek_p(&pb, noffset, SEEK_SET);
+ bytestream2_put_be16(&pb, data);
+ } else {
+ uint16_t count = bytestream2_get_be16(&gb);
+
+ pos += 2 * -(offset + 2);
+ for (i = 0; i < count; i++) {
+ uint16_t data = bytestream2_get_be16(&gb);
+
+ pos += 2;
+ noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
+ bytestream2_seek_p(&pb, noffset, SEEK_SET);
+ bytestream2_put_be16(&pb, data);
+ }
+ }
+ }
+ }
+}
+
static void decode_byte_vertical_delta(uint8_t *dst,
const uint8_t *buf, const uint8_t *buf_end,
int w, int bpp, int dst_size)
@@ -1458,6 +1511,10 @@ static int decode_frame(AVCodecContext *avctx,
} else
return unsupported(avctx);
break;
+ case 0x300:
+ case 0x301:
+ decode_short_horizontal_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+ break;
case 0x500:
case 0x501:
decode_byte_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);