diff options
author | Peter Ross <pross@xvid.org> | 2012-11-18 18:44:04 +1100 |
---|---|---|
committer | Peter Ross <pross@xvid.org> | 2012-11-20 09:49:49 +1100 |
commit | ed27ed9f4f72564f3653ac230cf57697de77f804 (patch) | |
tree | ebcbc5efa4a0229f9683da1cc902eaac7757ea50 | |
parent | a74ae4691a45c49cfc071ba7280fdcac30feb933 (diff) | |
download | ffmpeg-ed27ed9f4f72564f3653ac230cf57697de77f804.tar.gz |
iff: DEEP RLE 32-bit decoder
Fixes ticket #1046.
Signed-off-by: Peter Ross <pross@xvid.org>
-rw-r--r-- | libavcodec/iff.c | 57 | ||||
-rw-r--r-- | libavformat/iff.c | 2 |
2 files changed, 58 insertions, 1 deletions
diff --git a/libavcodec/iff.c b/libavcodec/iff.c index 9582f9d25d..c196cf6017 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -598,6 +598,55 @@ static int decode_frame_ilbm(AVCodecContext *avctx, return buf_size; } +/** + * Decode DEEP RLE 32-bit buffer + * @param[out] dst Destination buffer + * @param[in] src Source buffer + * @param src_size Source buffer size (bytes) + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + */ +static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) +{ + const uint8_t *src_end = src + src_size; + int x = 0, y = 0, i; + while (src + 5 <= src_end) { + int opcode; + opcode = *(int8_t *)src++; + if (opcode >= 0) { + int size = opcode + 1; + for (i = 0; i < size; i++) { + int length = FFMIN(size - i, width); + memcpy(dst + y*linesize + x * 4, src, length * 4); + src += length * 4; + x += length; + i += length; + if (x >= width) { + x = 0; + y += 1; + if (y >= height) + return; + } + } + } else { + int size = -opcode + 1; + uint32_t pixel = AV_RL32(src); + for (i = 0; i < size; i++) { + *(uint32_t *)(dst + y*linesize + x * 4) = pixel; + x += 1; + if (x >= width) { + x = 0; + y += 1; + if (y >= height) + return; + } + } + src += 4; + } + } +} + static int decode_frame_byterun1(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) @@ -683,6 +732,14 @@ static int decode_frame_byterun1(AVCodecContext *avctx, av_log_ask_for_sample(avctx, "unsupported bpp\n"); return AVERROR_INVALIDDATA; } + } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (av_get_bits_per_pixel(desc) == 32) + decode_deep_rle32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0]); + else { + av_log_ask_for_sample(avctx, "unsupported bpp\n"); + return AVERROR_INVALIDDATA; + } } *data_size = sizeof(AVFrame); diff --git a/libavformat/iff.c b/libavformat/iff.c index 53e104d84a..b748f49006 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -272,7 +272,7 @@ static int iff_read_header(AVFormatContext *s) st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); iff->bitmap_compression = avio_rb16(pb); - if (iff->bitmap_compression != 0) { + if (iff->bitmap_compression > 1) { av_log(s, AV_LOG_ERROR, "compression %i not supported\n", iff->bitmap_compression); return AVERROR_PATCHWELCOME; |