[FFmpeg-cvslog] avcodec/utvideodec: add vlc multi support

Christophe Gisquet git at videolan.org
Thu Sep 7 01:19:29 EEST 2023


ffmpeg | branch: master | Christophe Gisquet <christophe.gisquet at gmail.com> | Sun Jul  9 12:56:35 2017 +0000| [da888b790af779a7489068c25f9e7ab8ac653d41] | committer: Paul B Mahol

avcodec/utvideodec: add vlc multi support

Faster decoding, by average 50% faster overall.

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

 libavcodec/utvideo.h    |  1 +
 libavcodec/utvideodec.c | 92 ++++++++++++++++++++++++-------------------------
 2 files changed, 46 insertions(+), 47 deletions(-)

diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h
index 9da9329ff3..e5160aa394 100644
--- a/libavcodec/utvideo.h
+++ b/libavcodec/utvideo.h
@@ -81,6 +81,7 @@ typedef struct UtvideoContext {
     ptrdiff_t slice_stride;
     uint8_t *slice_bits, *slice_buffer[4];
     int      slice_bits_size;
+    void    *buffer;
 
     const uint8_t *packed_stream[4][256];
     size_t packed_stream_size[4][256];
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c
index 1f00c58950..ab390be0fa 100644
--- a/libavcodec/utvideodec.c
+++ b/libavcodec/utvideodec.c
@@ -46,7 +46,7 @@ typedef struct HuffEntry {
 } HuffEntry;
 
 static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc,
-                      int *fsym, unsigned nb_elems)
+                      VLC_MULTI *multi, int *fsym, unsigned nb_elems)
 {
     int i;
     HuffEntry he[1024];
@@ -82,11 +82,35 @@ static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc,
         he[--codes_count[bits[i]]] = (HuffEntry) { bits[i], i };
 
 #define VLC_BITS 11
-    return ff_init_vlc_from_lengths(vlc, VLC_BITS, codes_count[0],
+    return ff_init_vlc_multi_from_lengths(vlc, multi, VLC_BITS, nb_elems, codes_count[0],
                                     &he[0].len, sizeof(*he),
                                     &he[0].sym, sizeof(*he), 2, 0, 0, c->avctx);
 }
 
+#define READ_PLANE(b, end) \
+{ \
+    buf = !use_pred ? dest : c->buffer; \
+    i = 0; \
+    for (; CACHED_BITSTREAM_READER && i < width-end && get_bits_left(&gb) > 0;) {\
+        ret = get_vlc_multi(&gb, (uint8_t *)buf + i * b, multi.table, \
+                            vlc.table, VLC_BITS, 3); \
+        if (ret > 0) \
+            i += ret; \
+        if (ret <= 0) \
+            goto fail; \
+    } \
+    for (; i < width && get_bits_left(&gb) > 0; i++) \
+        buf[i] = get_vlc2(&gb, vlc.table, VLC_BITS, 3); \
+    if (use_pred) { \
+        if (b == 2) \
+            c->llviddsp.add_left_pred_int16((uint16_t *)dest, (const uint16_t *)buf, 0x3ff, width, prev); \
+        else \
+            c->llviddsp.add_left_pred((uint8_t *)dest, (const uint8_t *)buf, width, prev); \
+    } \
+    prev = dest[width-1]; \
+    dest += stride; \
+}
+
 static int decode_plane10(UtvideoContext *c, int plane_no,
                           uint16_t *dst, ptrdiff_t stride,
                           int width, int height,
@@ -95,11 +119,12 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
 {
     int i, j, slice, pix, ret;
     int sstart, send;
+    VLC_MULTI multi;
     VLC vlc;
     GetBitContext gb;
     int prev, fsym;
 
-    if ((ret = build_huff(c, huff, &vlc, &fsym, 1024)) < 0) {
+    if ((ret = build_huff(c, huff, &vlc, &multi, &fsym, 1024)) < 0) {
         av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
         return ret;
     }
@@ -131,7 +156,7 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
 
     send = 0;
     for (slice = 0; slice < c->slices; slice++) {
-        uint16_t *dest;
+        uint16_t *dest, *buf;
         int slice_data_start, slice_data_end, slice_size;
 
         sstart = send;
@@ -156,37 +181,20 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
         init_get_bits(&gb, c->slice_bits, slice_size * 8);
 
         prev = 0x200;
-        for (j = sstart; j < send; j++) {
-            for (i = 0; i < width; i++) {
-                pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
-                if (pix < 0) {
-                    av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
-                    goto fail;
-                }
-                if (use_pred) {
-                    prev += pix;
-                    prev &= 0x3FF;
-                    pix   = prev;
-                }
-                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;
-            }
-        }
+        for (j = sstart; j < send; j++)
+            READ_PLANE(2, 3)
         if (get_bits_left(&gb) > 32)
             av_log(c->avctx, AV_LOG_WARNING,
                    "%d bits left after decoding slice\n", get_bits_left(&gb));
     }
 
     ff_free_vlc(&vlc);
+    ff_free_vlc_multi(&multi);
 
     return 0;
 fail:
     ff_free_vlc(&vlc);
+    ff_free_vlc_multi(&multi);
     return AVERROR_INVALIDDATA;
 }
 
@@ -207,6 +215,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
 {
     int i, j, slice, pix;
     int sstart, send;
+    VLC_MULTI multi;
     VLC vlc;
     GetBitContext gb;
     int ret, prev, fsym;
@@ -259,7 +268,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
         return 0;
     }
 
-    if (build_huff(c, src, &vlc, &fsym, 256)) {
+    if (build_huff(c, src, &vlc, &multi, &fsym, 256)) {
         av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
         return AVERROR_INVALIDDATA;
     }
@@ -292,7 +301,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
 
     send = 0;
     for (slice = 0; slice < c->slices; slice++) {
-        uint8_t *dest;
+        uint8_t *dest, *buf;
         int slice_data_start, slice_data_end, slice_size;
 
         sstart = send;
@@ -317,36 +326,20 @@ static int decode_plane(UtvideoContext *c, int plane_no,
         init_get_bits(&gb, c->slice_bits, slice_size * 8);
 
         prev = 0x80;
-        for (j = sstart; j < send; j++) {
-            for (i = 0; i < width; i++) {
-                pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
-                if (pix < 0) {
-                    av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
-                    goto fail;
-                }
-                if (use_pred) {
-                    prev += pix;
-                    pix   = prev;
-                }
-                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;
-        }
+        for (j = sstart; j < send; j++)
+            READ_PLANE(1, 5)
         if (get_bits_left(&gb) > 32)
             av_log(c->avctx, AV_LOG_WARNING,
                    "%d bits left after decoding slice\n", get_bits_left(&gb));
     }
 
     ff_free_vlc(&vlc);
+    ff_free_vlc_multi(&multi);
 
     return 0;
 fail:
     ff_free_vlc(&vlc);
+    ff_free_vlc_multi(&multi);
     return AVERROR_INVALIDDATA;
 }
 
@@ -992,6 +985,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
         return AVERROR_INVALIDDATA;
     }
 
+    c->buffer = av_calloc(avctx->width, c->pro?2:1);
+    if (!c->buffer)
+        return AVERROR(ENOMEM);
+
     av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &h_shift, &v_shift);
     if ((avctx->width  & ((1<<h_shift)-1)) ||
         (avctx->height & ((1<<v_shift)-1))) {
@@ -1047,6 +1044,7 @@ static av_cold int decode_end(AVCodecContext *avctx)
     UtvideoContext * const c = avctx->priv_data;
 
     av_freep(&c->slice_bits);
+    av_freep(&c->buffer);
 
     return 0;
 }



More information about the ffmpeg-cvslog mailing list