]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ffv1dec.c
exr: fix out-of-bounds read
[ffmpeg] / libavcodec / ffv1dec.c
index 1e67fd39e9290eb0dedef511bf2814f7e02f6cbc..d8f35c34b99e379f3cc3731379abbc20a926d39a 100644 (file)
@@ -97,88 +97,15 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
     return ret;
 }
 
-static av_always_inline void decode_line(FFV1Context *s, int w,
-                                         int16_t *sample[2],
-                                         int plane_index, int bits)
-{
-    PlaneContext *const p = &s->plane[plane_index];
-    RangeCoder *const c   = &s->c;
-    int x;
-    int run_count = 0;
-    int run_mode  = 0;
-    int run_index = s->run_index;
-
-    if (s->slice_coding_mode == 1) {
-        int i;
-        for (x = 0; x < w; x++) {
-            int v = 0;
-            for (i=0; i<bits; i++) {
-                uint8_t state = 128;
-                v += v + get_rac(c, &state);
-            }
-            sample[1][x] = v;
-        }
-        return;
-    }
-
-    for (x = 0; x < w; x++) {
-        int diff, context, sign;
+#define TYPE int16_t
+#define RENAME(name) name
+#include "ffv1dec_template.c"
+#undef TYPE
+#undef RENAME
 
-        context = get_context(p, sample[1] + x, sample[0] + x, sample[1] + x);
-        if (context < 0) {
-            context = -context;
-            sign    = 1;
-        } else
-            sign = 0;
-
-        av_assert2(context < p->context_count);
-
-        if (s->ac != AC_GOLOMB_RICE) {
-            diff = get_symbol_inline(c, p->state[context], 1);
-        } else {
-            if (context == 0 && run_mode == 0)
-                run_mode = 1;
-
-            if (run_mode) {
-                if (run_count == 0 && run_mode == 1) {
-                    if (get_bits1(&s->gb)) {
-                        run_count = 1 << ff_log2_run[run_index];
-                        if (x + run_count <= w)
-                            run_index++;
-                    } else {
-                        if (ff_log2_run[run_index])
-                            run_count = get_bits(&s->gb, ff_log2_run[run_index]);
-                        else
-                            run_count = 0;
-                        if (run_index)
-                            run_index--;
-                        run_mode = 2;
-                    }
-                }
-                run_count--;
-                if (run_count < 0) {
-                    run_mode  = 0;
-                    run_count = 0;
-                    diff      = get_vlc_symbol(&s->gb, &p->vlc_state[context],
-                                               bits);
-                    if (diff >= 0)
-                        diff++;
-                } else
-                    diff = 0;
-            } else
-                diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits);
-
-            ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
-                    run_count, run_index, run_mode, x, get_bits_count(&s->gb));
-        }
-
-        if (sign)
-            diff = -diff;
-
-        sample[1][x] = av_mod_uintp2(predict(sample[1] + x, sample[0] + x) + diff, bits);
-    }
-    s->run_index = run_index;
-}
+#define TYPE int32_t
+#define RENAME(name) name ## 32
+#include "ffv1dec_template.c"
 
 static void decode_plane(FFV1Context *s, uint8_t *src,
                          int w, int h, int stride, int plane_index,
@@ -223,62 +150,6 @@ static void decode_plane(FFV1Context *s, uint8_t *src,
     }
 }
 
-static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3])
-{
-    int x, y, p;
-    int16_t *sample[4][2];
-    int lbd    = s->avctx->bits_per_raw_sample <= 8;
-    int bits   = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
-    int offset = 1 << bits;
-
-    for (x = 0; x < 4; x++) {
-        sample[x][0] = s->sample_buffer +  x * 2      * (w + 6) + 3;
-        sample[x][1] = s->sample_buffer + (x * 2 + 1) * (w + 6) + 3;
-    }
-
-    s->run_index = 0;
-
-    memset(s->sample_buffer, 0, 8 * (w + 6) * sizeof(*s->sample_buffer));
-
-    for (y = 0; y < h; y++) {
-        for (p = 0; p < 3 + s->transparency; p++) {
-            int16_t *temp = sample[p][0]; // FIXME: try a normal buffer
-
-            sample[p][0] = sample[p][1];
-            sample[p][1] = temp;
-
-            sample[p][1][-1]= sample[p][0][0  ];
-            sample[p][0][ w]= sample[p][0][w-1];
-            if (lbd && s->slice_coding_mode == 0)
-                decode_line(s, w, sample[p], (p + 1)/2, 9);
-            else
-                decode_line(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
-        }
-        for (x = 0; x < w; x++) {
-            int g = sample[0][1][x];
-            int b = sample[1][1][x];
-            int r = sample[2][1][x];
-            int a = sample[3][1][x];
-
-            if (s->slice_coding_mode != 1) {
-                b -= offset;
-                r -= offset;
-                g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
-                b += g;
-                r += g;
-            }
-
-            if (lbd)
-                *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24);
-            else {
-                *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b;
-                *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g;
-                *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r;
-            }
-        }
-    }
-}
-
 static int decode_slice_header(FFV1Context *f, FFV1Context *fs)
 {
     RangeCoder *c = &fs->c;
@@ -450,6 +321,11 @@ static int decode_slice(AVCodecContext *c, void *arg)
     } else if (f->colorspace == 0) {
          decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0]    , width, height, p->linesize[0], 0, 2);
          decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
+    } else if (f->use32bit) {
+        uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0],
+                               p->data[1] + ps * x + y * p->linesize[1],
+                               p->data[2] + ps * x + y * p->linesize[2] };
+        decode_rgb_frame32(fs, planes, width, height, p->linesize);
     } else {
         uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0],
                                p->data[1] + ps * x + y * p->linesize[1],
@@ -780,6 +656,10 @@ static int read_header(FFV1Context *f)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP12;
         else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP14;
+        else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency) {
+            f->avctx->pix_fmt = AV_PIX_FMT_GBRP16;
+            f->use32bit = 1;
+        }
     } else {
         av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
         return AVERROR(ENOSYS);