diff options
author | Paul B Mahol <onemda@gmail.com> | 2018-10-14 12:57:03 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2018-10-14 14:19:56 +0200 |
commit | 40c4b9dad0f8a38c4e09f2083bcb046d15498977 (patch) | |
tree | 1f82da64d5e60ea178ac19d93371df545b603123 | |
parent | fa7289e718e438b91683fa0b81adb4aef782339d (diff) | |
download | ffmpeg-40c4b9dad0f8a38c4e09f2083bcb046d15498977.tar.gz |
avcodec/imm4: improve decoding of some files
-rw-r--r-- | libavcodec/imm4.c | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/libavcodec/imm4.c b/libavcodec/imm4.c index 7f6c7ecab7..a4e9b5d4d2 100644 --- a/libavcodec/imm4.c +++ b/libavcodec/imm4.c @@ -43,7 +43,8 @@ typedef struct IMM4Context { int changed_size; int factor; - unsigned sindex; + unsigned lo; + unsigned hi; ScanTable intra_scantable; DECLARE_ALIGNED(32, int16_t, block)[6][64]; @@ -138,7 +139,7 @@ static int get_cbphi(GetBitContext *gb, int x) } static int decode_block(AVCodecContext *avctx, GetBitContext *gb, - int block, int factor, int flag) + int block, int factor, int flag, int offset) { IMM4Context *s = avctx->priv_data; const uint8_t *scantable = s->intra_scantable.permutated; @@ -164,7 +165,7 @@ static int decode_block(AVCodecContext *avctx, GetBitContext *gb, i += len; if (i >= 64) break; - s->block[block][scantable[i]] = factor * factor2; + s->block[block][scantable[i]] = offset * (factor2 < 0 ? -1 : 1) + factor * factor2; if (last) break; } @@ -173,7 +174,7 @@ static int decode_block(AVCodecContext *avctx, GetBitContext *gb, } static int decode_blocks(AVCodecContext *avctx, GetBitContext *gb, - unsigned cbp, int flag) + unsigned cbp, int flag, int offset) { IMM4Context *s = avctx->priv_data; const uint8_t *scantable = s->intra_scantable.permutated; @@ -193,7 +194,7 @@ static int decode_blocks(AVCodecContext *avctx, GetBitContext *gb, } if (cbp & (1 << (5 - i))) { - ret = decode_block(avctx, gb, i, s->factor, flag); + ret = decode_block(avctx, gb, i, s->factor, flag, offset); if (ret < 0) return ret; } @@ -205,9 +206,26 @@ static int decode_blocks(AVCodecContext *avctx, GetBitContext *gb, static int decode_intra(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame) { IMM4Context *s = avctx->priv_data; - int ret, x, y; + int ret, x, y, offset = 0; - s->factor = intra_cb[s->sindex]; + if (s->hi == 0) { + if (s->lo > 2) + return AVERROR_INVALIDDATA; + s->factor = intra_cb[s->lo]; + } else { + if (s->hi == 1) { + s->factor = s->lo * 2; + } else { + s->factor = s->lo * 2; + } + } + + if (s->hi) { + offset = s->factor; + offset >>= 1; + if (!(offset & 1)) + offset--; + } for (y = 0; y < avctx->height; y += 16) { for (x = 0; x < avctx->width; x += 16) { @@ -218,7 +236,7 @@ static int decode_intra(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame cbphi = get_cbphi(gb, 1); - ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0); + ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset); if (ret < 0) return ret; @@ -244,9 +262,26 @@ static int decode_inter(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame, AVFrame *prev) { IMM4Context *s = avctx->priv_data; - int ret, x, y; + int ret, x, y, offset = 0; - s->factor = inter_cb[s->sindex]; + if (s->hi == 0) { + if (s->lo > 2) + return AVERROR_INVALIDDATA; + s->factor = inter_cb[s->lo]; + } else { + if (s->hi == 1) { + s->factor = s->lo * 2; + } else { + s->factor = s->lo * 2; + } + } + + if (s->hi) { + offset = s->factor; + offset >>= 1; + if (!(offset & 1)) + offset--; + } for (y = 0; y < avctx->height; y += 16) { for (x = 0; x < avctx->width; x += 16) { @@ -278,7 +313,7 @@ static int decode_inter(AVCodecContext *avctx, GetBitContext *gb, cbplo = value >> 4; cbphi = get_cbphi(gb, reverse); if (intra_block) { - ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0); + ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset); if (ret < 0) return ret; @@ -296,7 +331,7 @@ static int decode_inter(AVCodecContext *avctx, GetBitContext *gb, frame->linesize[2], s->block[5]); } else { skip_bits(gb, 2); - ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 1); + ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 1, offset); if (ret < 0) return ret; @@ -400,9 +435,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, s->changed_size = 1; skip_bits_long(gb, 24 * 8); type = get_bits_long(gb, 32); - skip_bits(gb, 16); - s->sindex = get_bits(gb, 16); - s->sindex = FFMIN(s->sindex, 2); + s->hi = get_bits(gb, 16); + s->lo = get_bits(gb, 16); switch (type) { case 0x19781977: |