Merge commit '7c25523cc8e618e77dc84d960e41e9644eaf8c33'
[ffmpeg.git] / libavcodec / utvideodec.c
index 0f58c83..26c3f8a 100644 (file)
@@ -2,20 +2,20 @@
  * Ut Video decoder
  * Copyright (c) 2011 Konstantin Shishkov
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <inttypes.h>
 #include <stdlib.h>
 
-#include "libavutil/intreadwrite.h"
+#define UNCHECKED_BITSTREAM_READER 1
 
+#include "libavutil/intreadwrite.h"
 #include "avcodec.h"
-#include "bitstream.h"
 #include "bswapdsp.h"
 #include "bytestream.h"
+#include "get_bits.h"
 #include "internal.h"
 #include "thread.h"
 #include "utvideo.h"
@@ -74,8 +75,8 @@ static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym)
         syms[i]  = he[i].sym;
         code += 0x80000000u >> (he[i].len - 1);
     }
-
-    return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 11), last + 1,
+#define VLC_BITS 11
+    return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1,
                               bits,  sizeof(*bits),  sizeof(*bits),
                               codes, sizeof(*codes), sizeof(*codes),
                               syms,  sizeof(*syms),  sizeof(*syms), 0);
@@ -102,13 +103,14 @@ static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
         *fsym = he[0].sym;
         return 0;
     }
-    if (he[0].len > 32)
-        return -1;
 
     last = 255;
     while (he[last].len == 255 && last)
         last--;
 
+    if (he[last].len > 32)
+        return -1;
+
     code = 1;
     for (i = last; i >= 0; i--) {
         codes[i] = code >> (32 - he[i].len);
@@ -117,22 +119,22 @@ static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
         code += 0x80000000u >> (he[i].len - 1);
     }
 
-    return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 9), last + 1,
+    return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1,
                               bits,  sizeof(*bits),  sizeof(*bits),
                               codes, sizeof(*codes), sizeof(*codes),
                               syms,  sizeof(*syms),  sizeof(*syms), 0);
 }
 
 static int decode_plane10(UtvideoContext *c, int plane_no,
-                          uint16_t *dst, int step, int stride,
+                          uint16_t *dst, int step, ptrdiff_t stride,
                           int width, int height,
                           const uint8_t *src, const uint8_t *huff,
                           int use_pred)
 {
-    BitstreamContext bc;
     int i, j, slice, pix, ret;
     int sstart, send;
     VLC vlc;
+    GetBitContext gb;
     int prev, fsym;
 
     if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) {
@@ -185,23 +187,17 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
             goto fail;
         }
 
-        memcpy(c->slice_bits, src + slice_data_start + c->slices * 4,
-               slice_size);
         memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
         c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
-                          (uint32_t *) c->slice_bits,
+                          (uint32_t *)(src + slice_data_start + c->slices * 4),
                           (slice_data_end - slice_data_start + 3) >> 2);
-        bitstream_init8(&bc, c->slice_bits, slice_size);
+        init_get_bits(&gb, c->slice_bits, slice_size * 8);
 
         prev = 0x200;
         for (j = sstart; j < send; j++) {
-            for (i = 0; i < width * step; i += step) {
-                if (bitstream_bits_left(&bc) <= 0) {
-                    av_log(c->avctx, AV_LOG_ERROR,
-                           "Slice decoding ran out of bits\n");
-                    goto fail;
-                }
-                pix = bitstream_read_vlc(&bc, vlc.table, vlc.bits, 3);
+            int ws = width * step;
+            for (i = 0; i < ws; i += step) {
+                pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
                 if (pix < 0) {
                     av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
                     goto fail;
@@ -214,10 +210,15 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
                 dest[i] = pix;
             }
             dest += stride;
+            if (get_bits_left(&gb) < 0) {
+                av_log(c->avctx, AV_LOG_ERROR,
+                        "Slice decoding ran out of bits\n");
+                goto fail;
+            }
         }
-        if (bitstream_bits_left(&bc) > 32)
+        if (get_bits_left(&gb) > 32)
             av_log(c->avctx, AV_LOG_WARNING,
-                   "%d bits left after decoding slice\n", bitstream_bits_left(&bc));
+                   "%d bits left after decoding slice\n", get_bits_left(&gb));
     }
 
     ff_free_vlc(&vlc);
@@ -228,7 +229,7 @@ fail:
     return AVERROR_INVALIDDATA;
 }
 
-static int compute_cmask(int plane_no, int interlaced, int pix_fmt)
+static int compute_cmask(int plane_no, int interlaced, enum AVPixelFormat pix_fmt)
 {
     const int is_luma = (pix_fmt == AV_PIX_FMT_YUV420P) && !plane_no;
 
@@ -246,7 +247,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
     int i, j, slice, pix;
     int sstart, send;
     VLC vlc;
-    BitstreamContext bc;
+    GetBitContext gb;
     int prev, fsym;
     const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt);
 
@@ -301,23 +302,17 @@ static int decode_plane(UtvideoContext *c, int plane_no,
             goto fail;
         }
 
-        memcpy(c->slice_bits, src + slice_data_start + c->slices * 4,
-               slice_size);
         memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
         c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
-                          (uint32_t *) c->slice_bits,
+                          (uint32_t *)(src + slice_data_start + c->slices * 4),
                           (slice_data_end - slice_data_start + 3) >> 2);
-        bitstream_init8(&bc, c->slice_bits, slice_size);
+        init_get_bits(&gb, c->slice_bits, slice_size * 8);
 
         prev = 0x80;
         for (j = sstart; j < send; j++) {
-            for (i = 0; i < width * step; i += step) {
-                if (bitstream_bits_left(&bc) <= 0) {
-                    av_log(c->avctx, AV_LOG_ERROR,
-                           "Slice decoding ran out of bits\n");
-                    goto fail;
-                }
-                pix = bitstream_read_vlc(&bc, vlc.table, vlc.bits, 4);
+            int ws = width * step;
+            for (i = 0; i < ws; i += step) {
+                pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
                 if (pix < 0) {
                     av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
                     goto fail;
@@ -328,11 +323,16 @@ static int decode_plane(UtvideoContext *c, int plane_no,
                 }
                 dest[i] = pix;
             }
+            if (get_bits_left(&gb) < 0) {
+                av_log(c->avctx, AV_LOG_ERROR,
+                        "Slice decoding ran out of bits\n");
+                goto fail;
+            }
             dest += stride;
         }
-        if (bitstream_bits_left(&bc) > 32)
+        if (get_bits_left(&gb) > 32)
             av_log(c->avctx, AV_LOG_WARNING,
-                   "%d bits left after decoding slice\n", bitstream_bits_left(&bc));
+                   "%d bits left after decoding slice\n", get_bits_left(&gb));
     }
 
     ff_free_vlc(&vlc);
@@ -343,49 +343,12 @@ fail:
     return AVERROR_INVALIDDATA;
 }
 
-static void restore_rgb_planes(uint8_t *src, int step, ptrdiff_t stride,
-                               int width, int height)
-{
-    int i, j;
-    uint8_t r, g, b;
-
-    for (j = 0; j < height; j++) {
-        for (i = 0; i < width * step; i += step) {
-            r = src[i];
-            g = src[i + 1];
-            b = src[i + 2];
-            src[i]     = r + g - 0x80;
-            src[i + 2] = b + g - 0x80;
-        }
-        src += stride;
-    }
-}
-
-static void restore_rgb_planes10(AVFrame *frame, int width, int height)
-{
-    uint16_t *src_r = (uint16_t *)frame->data[2];
-    uint16_t *src_g = (uint16_t *)frame->data[0];
-    uint16_t *src_b = (uint16_t *)frame->data[1];
-    int r, g, b;
-    int i, j;
-
-    for (j = 0; j < height; j++) {
-        for (i = 0; i < width; i++) {
-            r = src_r[i];
-            g = src_g[i];
-            b = src_b[i];
-            src_r[i] = (r + g - 0x200) & 0x3FF;
-            src_b[i] = (b + g - 0x200) & 0x3FF;
-        }
-        src_r += frame->linesize[2] / 2;
-        src_g += frame->linesize[0] / 2;
-        src_b += frame->linesize[1] / 2;
-    }
-}
+#undef A
+#undef B
+#undef C
 
-static void restore_median_planar(UtvideoContext *c, uint8_t *src,
-                                  ptrdiff_t stride, int width, int height,
-                                  int slices, int rmode)
+static void restore_median_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
+                                  int width, int height, int slices, int rmode)
 {
     int i, j, slice;
     int A, B, C;
@@ -404,7 +367,7 @@ static void restore_median_planar(UtvideoContext *c, uint8_t *src,
 
         // first line - left neighbour prediction
         bsrc[0] += 0x80;
-        c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0);
+        c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
         bsrc += stride;
         if (slice_height <= 1)
             continue;
@@ -421,7 +384,7 @@ static void restore_median_planar(UtvideoContext *c, uint8_t *src,
         bsrc += stride;
         // the rest of lines use continuous median prediction
         for (j = 2; j < slice_height; j++) {
-            c->hdspdec.add_hfyu_median_pred(bsrc, bsrc - stride,
+            c->llviddsp.add_median_pred(bsrc, bsrc - stride,
                                             bsrc, width, &A, &B);
             bsrc += stride;
         }
@@ -432,16 +395,15 @@ static void restore_median_planar(UtvideoContext *c, uint8_t *src,
  * so restoring function should take care of possible padding between
  * two parts of the same "line".
  */
-static void restore_median_planar_il(UtvideoContext *c, uint8_t *src,
-                                     ptrdiff_t stride, int width, int height,
-                                     int slices, int rmode)
+static void restore_median_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
+                                     int width, int height, int slices, int rmode)
 {
     int i, j, slice;
     int A, B, C;
     uint8_t *bsrc;
     int slice_start, slice_height;
     const int cmask   = ~(rmode ? 3 : 1);
-    const int stride2 = stride << 1;
+    const ptrdiff_t stride2 = stride << 1;
 
     for (slice = 0; slice < slices; slice++) {
         slice_start    = ((slice * height) / slices) & cmask;
@@ -455,8 +417,8 @@ static void restore_median_planar_il(UtvideoContext *c, uint8_t *src,
 
         // first line - left neighbour prediction
         bsrc[0] += 0x80;
-        A = c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0);
-        c->hdspdec.add_hfyu_left_pred(bsrc + stride, bsrc + stride, width, A);
+        A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
+        c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
         bsrc += stride2;
         if (slice_height <= 1)
             continue;
@@ -470,148 +432,20 @@ static void restore_median_planar_il(UtvideoContext *c, uint8_t *src,
             C        = B;
             A        = bsrc[i];
         }
-        c->hdspdec.add_hfyu_median_pred(bsrc + stride, bsrc - stride,
+        c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
                                         bsrc + stride, width, &A, &B);
         bsrc += stride2;
         // the rest of lines use continuous median prediction
         for (j = 2; j < slice_height; j++) {
-            c->hdspdec.add_hfyu_median_pred(bsrc, bsrc - stride2,
+            c->llviddsp.add_median_pred(bsrc, bsrc - stride2,
                                             bsrc, width, &A, &B);
-            c->hdspdec.add_hfyu_median_pred(bsrc + stride, bsrc - stride,
+            c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
                                             bsrc + stride, width, &A, &B);
             bsrc += stride2;
         }
     }
 }
 
-static void restore_median_packed(uint8_t *src, int step, ptrdiff_t stride,
-                                  int width, int height,
-                                  int slices, int rmode)
-{
-    int i, j, slice;
-    int A, B, C;
-    uint8_t *bsrc;
-    int slice_start, slice_height;
-    const int cmask = ~rmode;
-
-    for (slice = 0; slice < slices; slice++) {
-        slice_start  = ((slice * height) / slices) & cmask;
-        slice_height = ((((slice + 1) * height) / slices) & cmask) -
-                       slice_start;
-        if (!slice_height)
-            continue;
-
-        bsrc = src + slice_start * stride;
-
-        // first line - left neighbour prediction
-        bsrc[0] += 0x80;
-        A = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            bsrc[i] += A;
-            A        = bsrc[i];
-        }
-        bsrc += stride;
-        if (slice_height == 1)
-            continue;
-        // second line - first element has top prediction, the rest uses median
-        C        = bsrc[-stride];
-        bsrc[0] += C;
-        A        = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            B        = bsrc[i - stride];
-            bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
-            C        = B;
-            A        = bsrc[i];
-        }
-        bsrc += stride;
-        // the rest of lines use continuous median prediction
-        for (j = 2; j < slice_height; j++) {
-            for (i = 0; i < width * step; i += step) {
-                B        = bsrc[i - stride];
-                bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
-                C        = B;
-                A        = bsrc[i];
-            }
-            bsrc += stride;
-        }
-    }
-}
-
-/* UtVideo interlaced mode treats every two lines as a single one,
- * so restoring function should take care of possible padding between
- * two parts of the same "line".
- */
-static void restore_median_packed_il(uint8_t *src, int step, ptrdiff_t stride,
-                                     int width, int height,
-                                     int slices, int rmode)
-{
-    int i, j, slice;
-    int A, B, C;
-    uint8_t *bsrc;
-    int slice_start, slice_height;
-    const int cmask   = ~(rmode ? 3 : 1);
-    const ptrdiff_t stride2 = stride << 1;
-
-    for (slice = 0; slice < slices; slice++) {
-        slice_start    = ((slice * height) / slices) & cmask;
-        slice_height   = ((((slice + 1) * height) / slices) & cmask) -
-                         slice_start;
-        slice_height >>= 1;
-        if (!slice_height)
-            continue;
-
-        bsrc = src + slice_start * stride;
-
-        // first line - left neighbour prediction
-        bsrc[0] += 0x80;
-        A        = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            bsrc[i] += A;
-            A        = bsrc[i];
-        }
-        for (i = 0; i < width * step; i += step) {
-            bsrc[stride + i] += A;
-            A                 = bsrc[stride + i];
-        }
-        bsrc += stride2;
-        if (slice_height == 1)
-            continue;
-        // second line - first element has top prediction, the rest uses median
-        C        = bsrc[-stride2];
-        bsrc[0] += C;
-        A        = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            B        = bsrc[i - stride2];
-            bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
-            C        = B;
-            A        = bsrc[i];
-        }
-        for (i = 0; i < width * step; i += step) {
-            B                 = bsrc[i - stride];
-            bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C));
-            C                 = B;
-            A                 = bsrc[stride + i];
-        }
-        bsrc += stride2;
-        // the rest of lines use continuous median prediction
-        for (j = 2; j < slice_height; j++) {
-            for (i = 0; i < width * step; i += step) {
-                B        = bsrc[i - stride2];
-                bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
-                C        = B;
-                A        = bsrc[i];
-            }
-            for (i = 0; i < width * step; i += step) {
-                B                 = bsrc[i - stride];
-                bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C));
-                C                 = B;
-                A                 = bsrc[i + stride];
-            }
-            bsrc += stride2;
-        }
-    }
-}
-
 static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
                                     int width, int height, int slices, int rmode)
 {
@@ -632,7 +466,7 @@ static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t s
 
         // first line - left neighbour prediction
         bsrc[0] += 0x80;
-        c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0);
+        c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
         bsrc += stride;
         if (slice_height <= 1)
             continue;
@@ -672,8 +506,8 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_
 
         // first line - left neighbour prediction
         bsrc[0] += 0x80;
-        A = c->hdspdec.add_hfyu_left_pred(bsrc, bsrc, width, 0);
-        c->hdspdec.add_hfyu_left_pred(bsrc + stride, bsrc + stride, width, A);
+        A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
+        c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
         bsrc += stride2;
         if (slice_height <= 1)
             continue;
@@ -686,7 +520,11 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_
                 C = bsrc[i - 1];
                 bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
             }
-            for (i = 0; i < width; i++) {
+            A = bsrc[-stride];
+            B = bsrc[-(1 + stride + stride - width)];
+            C = bsrc[width - 1];
+            bsrc[stride] = (A - B + C + bsrc[stride]) & 0xFF;
+            for (i = 1; i < width; i++) {
                 A = bsrc[i - stride];
                 B = bsrc[i - (1 + stride)];
                 C = bsrc[i - 1 + stride];
@@ -697,104 +535,6 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_
     }
 }
 
-static void restore_gradient_packed(uint8_t *src, int step, ptrdiff_t stride,
-                                    int width, int height, int slices, int rmode)
-{
-    int i, j, slice;
-    int A, B, C;
-    uint8_t *bsrc;
-    int slice_start, slice_height;
-    const int cmask = ~rmode;
-
-    for (slice = 0; slice < slices; slice++) {
-        slice_start  = ((slice * height) / slices) & cmask;
-        slice_height = ((((slice + 1) * height) / slices) & cmask) -
-                       slice_start;
-
-        if (!slice_height)
-            continue;
-        bsrc = src + slice_start * stride;
-
-        // first line - left neighbour prediction
-        bsrc[0] += 0x80;
-        A = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            bsrc[i] += A;
-            A        = bsrc[i];
-        }
-        bsrc += stride;
-        if (slice_height <= 1)
-            continue;
-        for (j = 1; j < slice_height; j++) {
-            // second line - first element has top prediction, the rest uses gradient
-            C        = bsrc[-stride];
-            bsrc[0] += C;
-            for (i = step; i < width * step; i += step) {
-                A = bsrc[i - stride];
-                B = bsrc[i - (stride + step)];
-                C = bsrc[i - step];
-                bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
-            }
-            bsrc += stride;
-        }
-    }
-}
-
-static void restore_gradient_packed_il(uint8_t *src, int step, ptrdiff_t stride,
-                                       int width, int height, int slices, int rmode)
-{
-    int i, j, slice;
-    int A, B, C;
-    uint8_t *bsrc;
-    int slice_start, slice_height;
-    const int cmask   = ~(rmode ? 3 : 1);
-    const ptrdiff_t stride2 = stride << 1;
-
-    for (slice = 0; slice < slices; slice++) {
-        slice_start    = ((slice * height) / slices) & cmask;
-        slice_height   = ((((slice + 1) * height) / slices) & cmask) -
-                         slice_start;
-        slice_height >>= 1;
-        if (!slice_height)
-            continue;
-
-        bsrc = src + slice_start * stride;
-
-        // first line - left neighbour prediction
-        bsrc[0] += 0x80;
-        A        = bsrc[0];
-        for (i = step; i < width * step; i += step) {
-            bsrc[i] += A;
-            A        = bsrc[i];
-        }
-        for (i = 0; i < width * step; i += step) {
-            bsrc[stride + i] += A;
-            A                 = bsrc[stride + i];
-        }
-        bsrc += stride2;
-        if (slice_height <= 1)
-            continue;
-        for (j = 1; j < slice_height; j++) {
-            // second line - first element has top prediction, the rest uses gradient
-            C        = bsrc[-stride2];
-            bsrc[0] += C;
-            for (i = step; i < width * step; i += step) {
-                A = bsrc[i - stride2];
-                B = bsrc[i - (stride2 + step)];
-                C = bsrc[i - step];
-                bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
-            }
-            for (i = 0; i < width * step; i += step) {
-                A = bsrc[i - stride];
-                B = bsrc[i - (step + stride)];
-                C = bsrc[i - step + stride];
-                bsrc[i + stride] = (A - B + C + bsrc[i + stride]) & 0xFF;
-            }
-            bsrc += stride2;
-        }
-    }
-}
-
 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                         AVPacket *avpkt)
 {
@@ -808,12 +548,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     GetByteContext gb;
     ThreadFrame frame = { .f = data };
 
-    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
         return ret;
-    }
-
-    ff_thread_finish_setup(avctx);
 
     /* parse plane structure to get frame flags and validate slice offsets */
     bytestream2_init(&gb, buf, buf_size);
@@ -884,6 +620,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 
     c->frame_pred = (c->frame_info >> 8) & 3;
 
+    max_slice_size += 4*avctx->width;
+
     av_fast_malloc(&c->slice_bits, &c->slice_bits_size,
                    max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE);
 
@@ -893,42 +631,42 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     }
 
     switch (c->avctx->pix_fmt) {
-    case AV_PIX_FMT_RGB24:
-    case AV_PIX_FMT_RGBA:
+    case AV_PIX_FMT_GBRP:
+    case AV_PIX_FMT_GBRAP:
         for (i = 0; i < c->planes; i++) {
-            ret = decode_plane(c, i, frame.f->data[0] + ff_ut_rgb_order[i],
-                               c->planes, frame.f->linesize[0], avctx->width,
+            ret = decode_plane(c, i, frame.f->data[i], 1,
+                               frame.f->linesize[i], avctx->width,
                                avctx->height, plane_start[i],
                                c->frame_pred == PRED_LEFT);
             if (ret)
                 return ret;
             if (c->frame_pred == PRED_MEDIAN) {
                 if (!c->interlaced) {
-                    restore_median_packed(frame.f->data[0] + ff_ut_rgb_order[i],
-                                          c->planes, frame.f->linesize[0], avctx->width,
+                    restore_median_planar(c, frame.f->data[i],
+                                          frame.f->linesize[i], avctx->width,
                                           avctx->height, c->slices, 0);
                 } else {
-                    restore_median_packed_il(frame.f->data[0] + ff_ut_rgb_order[i],
-                                             c->planes, frame.f->linesize[0],
+                    restore_median_planar_il(c, frame.f->data[i],
+                                             frame.f->linesize[i],
                                              avctx->width, avctx->height, c->slices,
                                              0);
                 }
             } else if (c->frame_pred == PRED_GRADIENT) {
                 if (!c->interlaced) {
-                    restore_gradient_packed(frame.f->data[0] + ff_ut_rgb_order[i],
-                                            c->planes, frame.f->linesize[0],
-                                            avctx->width, avctx->height,
-                                            c->slices, 0);
+                    restore_gradient_planar(c, frame.f->data[i],
+                                            frame.f->linesize[i], avctx->width,
+                                            avctx->height, c->slices, 0);
                 } else {
-                    restore_gradient_packed_il(frame.f->data[0] + ff_ut_rgb_order[i],
-                                               c->planes, frame.f->linesize[0],
-                                               avctx->width, avctx->height,
-                                               c->slices, 0);
+                    restore_gradient_planar_il(c, frame.f->data[i],
+                                               frame.f->linesize[i],
+                                               avctx->width, avctx->height, c->slices,
+                                               0);
                 }
             }
         }
-        restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0],
-                           avctx->width, avctx->height);
+        c->utdsp.restore_rgb_planes(frame.f->data[2], frame.f->data[0], frame.f->data[1],
+                                    frame.f->linesize[2], frame.f->linesize[0], frame.f->linesize[1],
+                                    avctx->width, avctx->height);
         break;
     case AV_PIX_FMT_GBRAP10:
     case AV_PIX_FMT_GBRP10:
@@ -941,7 +679,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             if (ret)
                 return ret;
         }
-        restore_rgb_planes10(frame.f, avctx->width, avctx->height);
+        c->utdsp.restore_rgb_planes10((uint16_t *)frame.f->data[2], (uint16_t *)frame.f->data[0], (uint16_t *)frame.f->data[1],
+                                      frame.f->linesize[2] / 2, frame.f->linesize[0] / 2, frame.f->linesize[1] / 2,
+                                      avctx->width, avctx->height);
         break;
     case AV_PIX_FMT_YUV420P:
         for (i = 0; i < 3; i++) {
@@ -964,8 +704,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             } else if (c->frame_pred == PRED_GRADIENT) {
                 if (!c->interlaced) {
                     restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i],
-                                            avctx->width >> !!i,
-                                            avctx->height >> !!i,
+                                            avctx->width >> !!i, avctx->height >> !!i,
                                             c->slices, !i);
                 } else {
                     restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i],
@@ -1063,8 +802,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     c->avctx = avctx;
 
+    ff_utvideodsp_init(&c->utdsp);
     ff_bswapdsp_init(&c->bdsp);
-    ff_huffyuvdsp_init(&c->hdspdec);
+    ff_llviddsp_init(&c->llviddsp);
 
     if (avctx->extradata_size >= 16) {
         av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
@@ -1102,11 +842,11 @@ static av_cold int decode_init(AVCodecContext *avctx)
     switch (avctx->codec_tag) {
     case MKTAG('U', 'L', 'R', 'G'):
         c->planes      = 3;
-        avctx->pix_fmt = AV_PIX_FMT_RGB24;
+        avctx->pix_fmt = AV_PIX_FMT_GBRP;
         break;
     case MKTAG('U', 'L', 'R', 'A'):
         c->planes      = 4;
-        avctx->pix_fmt = AV_PIX_FMT_RGBA;
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP;
         break;
     case MKTAG('U', 'L', 'Y', '0'):
         c->planes      = 3;