[FFmpeg-cvslog] exr: rle decompression

Paul B Mahol git at videolan.org
Thu Jul 12 19:37:43 CEST 2012


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Jul 11 23:33:34 2012 +0000| [f7e26cca892cb764f821d564bdb8df43c7cbc766] | committer: Paul B Mahol

exr: rle decompression

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=f7e26cca892cb764f821d564bdb8df43c7cbc766
---

 libavcodec/exr.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index aa77b8e..905d389 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);
 



More information about the ffmpeg-cvslog mailing list