X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fiff.c;h=96649db42c6d1e7392bf37b73fc4ea334a92cf97;hb=78d16eb45217f7ce811d1b05afe56427dd40021b;hp=c1c451cf6c49231bfd468c44a2504d4a45c6b722;hpb=444e65299ba5cbf390439e27ce2cb91dff0e5aa7;p=ffmpeg diff --git a/libavcodec/iff.c b/libavcodec/iff.c index c1c451cf6c4..96649db42c6 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -413,7 +413,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx))) return err; s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary - s->planebuf = av_malloc(s->planesize + AV_INPUT_BUFFER_PADDING_SIZE); + s->planebuf = av_malloc(s->planesize * avctx->height + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->planebuf) return AVERROR(ENOMEM); @@ -557,6 +557,76 @@ static int decode_byterun(uint8_t *dst, int dst_size, return bytestream2_tell(gb); } +static int decode_byterun2(uint8_t *dst, int height, int line_size, + GetByteContext *gb) +{ + GetByteContext cmds; + unsigned count; + int i, y_pos = 0, x_pos = 0; + + if (bytestream2_get_be32(gb) != MKBETAG('V', 'D', 'A', 'T')) + return 0; + + bytestream2_skip(gb, 4); + count = bytestream2_get_be16(gb) - 2; + if (bytestream2_get_bytes_left(gb) < count) + return 0; + + bytestream2_init(&cmds, gb->buffer, count); + bytestream2_skip(gb, count); + + for (i = 0; i < count && x_pos < line_size; i++) { + int8_t cmd = bytestream2_get_byte(&cmds); + int l, r; + + if (cmd == 0) { + l = bytestream2_get_be16(gb); + while (l-- > 0 && x_pos < line_size) { + dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb); + dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb); + if (y_pos >= height) { + y_pos = 0; + x_pos += 2; + } + } + } else if (cmd < 0) { + l = -cmd; + while (l-- > 0 && x_pos < line_size) { + dst[x_pos + y_pos * line_size ] = bytestream2_get_byte(gb); + dst[x_pos + y_pos++ * line_size + 1] = bytestream2_get_byte(gb); + if (y_pos >= height) { + y_pos = 0; + x_pos += 2; + } + } + } else if (cmd == 1) { + l = bytestream2_get_be16(gb); + r = bytestream2_get_be16(gb); + while (l-- > 0 && x_pos < line_size) { + dst[x_pos + y_pos * line_size ] = r >> 8; + dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF; + if (y_pos >= height) { + y_pos = 0; + x_pos += 2; + } + } + } else { + l = cmd; + r = bytestream2_get_be16(gb); + while (l-- > 0 && x_pos < line_size) { + dst[x_pos + y_pos * line_size ] = r >> 8; + dst[x_pos + y_pos++ * line_size + 1] = r & 0xFF; + if (y_pos >= height) { + y_pos = 0; + x_pos += 2; + } + } + } + } + + return bytestream2_tell(gb); +} + #define DECODE_RGBX_COMMON(type) \ if (!length) { \ length = bytestream2_get_byte(gb); \ @@ -1623,6 +1693,19 @@ static int decode_frame(AVCodecContext *avctx, return unsupported(avctx); } break; + case 0x2: + if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') && avctx->pix_fmt == AV_PIX_FMT_PAL8) { + for (plane = 0; plane < s->bpp; plane++) { + decode_byterun2(s->planebuf, avctx->height, s->planesize, gb); + for (y = 0; y < avctx->height; y++) { + uint8_t *row = &frame->data[0][y * frame->linesize[0]]; + decodeplane8(row, s->planebuf + s->planesize * y, s->planesize, plane); + } + } + } else { + return unsupported(avctx); + } + break; case 0x4: if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32) decode_rgb8(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]);