aboutsummaryrefslogtreecommitdiff
path: root/libavcodec/exr.c
diff options
context:
space:
mode:
authorPaul B Mahol2012-07-11 23:33:34 +0000
committerPaul B Mahol2012-07-12 17:36:55 +0000
commitf7e26cca892cb764f821d564bdb8df43c7cbc766 (patch)
treed3a873969996ea40e338e94eb42ac08c67e7df23 /libavcodec/exr.c
parent26d7232722b01c05473d1cc5be8c1fa5ad4a9885 (diff)
exr: rle decompression
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavcodec/exr.c')
-rw-r--r--libavcodec/exr.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index aa77b8e9d5..905d389d03 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -34,6 +34,7 @@
#include "avcodec.h"
#include "bytestream.h"
+#include "mathops.h"
#include "libavutil/imgutils.h"
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,
void *data,
int *data_size,
@@ -366,10 +403,10 @@ static int decode_frame(AVCodecContext *avctx,
s->compr = *buf;
switch (s->compr) {
case EXR_RAW:
+ case EXR_RLE:
case EXR_ZIP1:
case EXR_ZIP16:
break;
- case EXR_RLE:
case EXR_PIZ:
case EXR_B44:
default:
@@ -431,6 +468,7 @@ static int decode_frame(AVCodecContext *avctx,
switch (s->compr) {
case EXR_RAW:
+ case EXR_RLE:
case EXR_ZIP1:
scan_lines_per_block = 1;
break;
@@ -508,7 +546,14 @@ static int decode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n");
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);
reorder_pixels(s->tmp, s->uncompressed_data, uncompressed_size);