exr: rle decompression

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol 2012-07-11 23:33:34 +00:00
parent 26d7232722
commit f7e26cca89

View File

@ -34,6 +34,7 @@
#include "avcodec.h" #include "avcodec.h"
#include "bytestream.h" #include "bytestream.h"
#include "mathops.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
enum ExrCompr { enum ExrCompr {
@ -183,6 +184,42 @@ static void reorder_pixels(uint8_t *src, uint8_t *dst, int size)
} }
} }
static int rle_uncompress(const uint8_t *src, int ssize, uint8_t *dst, int dsize)
{
int8_t *d = (int8_t *)dst;
int8_t *s = (int8_t *)src;
int8_t *dend = d + dsize;
int count;
while (ssize > 0) {
count = *s++;
if (count < 0) {
count = -count;
if ((dsize -= count ) < 0 ||
(ssize -= count + 1) < 0)
return -1;
while (count--)
*d++ = *s++;
} else {
count++;
if ((dsize -= count) < 0 ||
(ssize -= 2 ) < 0)
return -1;
while (count--)
*d++ = *s;
s++;
}
}
return dend != d;
}
static int decode_frame(AVCodecContext *avctx, static int decode_frame(AVCodecContext *avctx,
void *data, void *data,
int *data_size, int *data_size,
@ -366,10 +403,10 @@ static int decode_frame(AVCodecContext *avctx,
s->compr = *buf; s->compr = *buf;
switch (s->compr) { switch (s->compr) {
case EXR_RAW: case EXR_RAW:
case EXR_RLE:
case EXR_ZIP1: case EXR_ZIP1:
case EXR_ZIP16: case EXR_ZIP16:
break; break;
case EXR_RLE:
case EXR_PIZ: case EXR_PIZ:
case EXR_B44: case EXR_B44:
default: default:
@ -431,6 +468,7 @@ static int decode_frame(AVCodecContext *avctx,
switch (s->compr) { switch (s->compr) {
case EXR_RAW: case EXR_RAW:
case EXR_RLE:
case EXR_ZIP1: case EXR_ZIP1:
scan_lines_per_block = 1; scan_lines_per_block = 1;
break; break;
@ -508,7 +546,14 @@ static int decode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n");
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
} else if (s->compr == EXR_RLE && data_size < uncompressed_size) {
if (rle_uncompress(avpkt->data + line_offset, data_size, s->tmp, uncompressed_size)) {
av_log(avctx, AV_LOG_ERROR, "error during rle decompression\n");
return AVERROR(EINVAL);
}
}
if (s->compr != EXR_RAW && data_size < uncompressed_size) {
predictor(s->tmp, uncompressed_size); predictor(s->tmp, uncompressed_size);
reorder_pixels(s->tmp, s->uncompressed_data, uncompressed_size); reorder_pixels(s->tmp, s->uncompressed_data, uncompressed_size);