From ef55dc925fd82cd5811108ae59bdac532470eb11 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 7 Mar 2025 16:12:42 +0100
Subject: [PATCH 01/17] avcodec/vlc: Merge VLCElem and RL_VLC_ELEM

It will simplify creating RL-VLCs (which until now used
a stack-based VLC as temporary buffer).

Notice that there would be another option to merge them, namely:
struct VLCElem {
    union {
        VLCBaseType sym;
        int16_t level;
    };
    int8_t len;
    uint8_t run;
};

The main difference to the current patch is that this would change
the type of the length field of VLCElem to int8_t from int16_t.
It turns out that that this would entail additional sign extensions
on ppc, see https://godbolt.org/z/behWYEYE7. I have therefore refrained
from doing so, although it would make the patch simpler.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/cfhd.h     |  2 +-
 libavcodec/cfhddata.c | 10 +++++-----
 libavcodec/dvdec.c    | 12 ++++++------
 libavcodec/get_bits.h |  6 +++---
 libavcodec/mpeg12.c   |  2 +-
 libavcodec/rl.c       |  2 +-
 libavcodec/vlc.h      | 22 +++++++++++++++-------
 7 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/libavcodec/cfhd.h b/libavcodec/cfhd.h
index 9b09c91262..586d3360b6 100644
--- a/libavcodec/cfhd.h
+++ b/libavcodec/cfhd.h
@@ -98,7 +98,7 @@ enum CFHDParam {
 
 typedef struct CFHD_RL_VLC_ELEM {
     int16_t level;
-    int8_t len;
+    int8_t len8;
     uint16_t run;
 } CFHD_RL_VLC_ELEM;
 
diff --git a/libavcodec/cfhddata.c b/libavcodec/cfhddata.c
index a3948a14ca..72b14baf27 100644
--- a/libavcodec/cfhddata.c
+++ b/libavcodec/cfhddata.c
@@ -136,22 +136,22 @@ static av_cold int cfhd_init_vlc(CFHD_RL_VLC_ELEM out[], unsigned out_size,
     /** Similar to dv.c, generate signed VLC tables **/
 
     for (unsigned i = j = 0; i < table_size; i++, j++) {
-        tmp[j].len   = table_vlc[i].len;
+        tmp[j].len8  = table_vlc[i].len;
         tmp[j].run   = table_vlc[i].run;
         tmp[j].level = table_vlc[i].level;
 
         /* Don't include the zero level nor escape bits */
         if (table_vlc[i].level && table_vlc[i].run) {
-            tmp[j].len++;
+            tmp[j].len8++;
             j++;
-            tmp[j].len   =  table_vlc[i].len + 1;
+            tmp[j].len8  =  table_vlc[i].len + 1;
             tmp[j].run   =  table_vlc[i].run;
             tmp[j].level = -table_vlc[i].level;
         }
     }
 
     ret = ff_vlc_init_from_lengths(&vlc, VLC_BITS, j,
-                                   &tmp[0].len, sizeof(tmp[0]),
+                                   &tmp[0].len8, sizeof(tmp[0]),
                                    NULL, 0, 0, 0, 0, logctx);
     if (ret < 0)
         return ret;
@@ -169,7 +169,7 @@ static av_cold int cfhd_init_vlc(CFHD_RL_VLC_ELEM out[], unsigned out_size,
             run   = tmp[code].run;
             level = tmp[code].level;
         }
-        out[i].len   = len;
+        out[i].len8  = len;
         out[i].level = level;
         out[i].run   = run;
     }
diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c
index 8297b6d2f3..242708c70a 100644
--- a/libavcodec/dvdec.c
+++ b/libavcodec/dvdec.c
@@ -159,15 +159,15 @@ static av_cold void dv_init_static(void)
 
     /* it's faster to include sign bit in a generic VLC parsing scheme */
     for (i = 0, j = 0; i < NB_DV_VLC; i++, j++) {
-        tmp[j].len   = ff_dv_vlc_len[i];
+        tmp[j].len8  = ff_dv_vlc_len[i];
         tmp[j].run   = ff_dv_vlc_run[i];
         tmp[j].level = ff_dv_vlc_level[i];
 
         if (ff_dv_vlc_level[i]) {
-            tmp[j].len++;
+            tmp[j].len8++;
 
             j++;
-            tmp[j].len   =  ff_dv_vlc_len[i] + 1;
+            tmp[j].len8  =  ff_dv_vlc_len[i] + 1;
             tmp[j].run   =  ff_dv_vlc_run[i];
             tmp[j].level = -ff_dv_vlc_level[i];
         }
@@ -176,7 +176,7 @@ static av_cold void dv_init_static(void)
     /* NOTE: as a trick, we use the fact the no codes are unused
      * to accelerate the parsing of partial codes */
     ff_vlc_init_from_lengths(&dv_vlc, TEX_VLC_BITS, j,
-                             &tmp[0].len, sizeof(tmp[0]),
+                             &tmp[0].len8, sizeof(tmp[0]),
                              NULL, 0, 0, 0, VLC_INIT_USE_STATIC, NULL);
     av_assert1(dv_vlc.table_size == 1664);
 
@@ -193,7 +193,7 @@ static av_cold void dv_init_static(void)
             run   = tmp[code].run + 1;
             level = tmp[code].level;
         }
-        dv_rl_vlc[i].len   = len;
+        dv_rl_vlc[i].len8  = len;
         dv_rl_vlc[i].level = level;
         dv_rl_vlc[i].run   = run;
     }
@@ -301,7 +301,7 @@ static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, int16_t *block)
                 pos, SHOW_UBITS(re, gb, 16), re_index);
         /* our own optimized GET_RL_VLC */
         index   = NEG_USR32(re_cache, TEX_VLC_BITS);
-        vlc_len = dv_rl_vlc[index].len;
+        vlc_len = dv_rl_vlc[index].len8;
         if (vlc_len < 0) {
             index = NEG_USR32((unsigned) re_cache << TEX_VLC_BITS, -vlc_len) +
                     dv_rl_vlc[index].level;
diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index 39d8e5bc1e..1954296569 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -594,7 +594,7 @@ static inline const uint8_t *align_get_bits(GetBitContext *s)
                                                                 \
         index = SHOW_UBITS(name, gb, bits);                     \
         level = table[index].level;                             \
-        n     = table[index].len;                               \
+        n     = table[index].len8;                              \
                                                                 \
         if (max_depth > 1 && n < 0) {                           \
             SKIP_BITS(name, gb, bits);                          \
@@ -606,7 +606,7 @@ static inline const uint8_t *align_get_bits(GetBitContext *s)
                                                                 \
             index = SHOW_UBITS(name, gb, nb_bits) + level;      \
             level = table[index].level;                         \
-            n     = table[index].len;                           \
+            n     = table[index].len8;                          \
             if (max_depth > 2 && n < 0) {                       \
                 LAST_SKIP_BITS(name, gb, nb_bits);              \
                 if (need_update) {                              \
@@ -616,7 +616,7 @@ static inline const uint8_t *align_get_bits(GetBitContext *s)
                                                                 \
                 index = SHOW_UBITS(name, gb, nb_bits) + level;  \
                 level = table[index].level;                     \
-                n     = table[index].len;                       \
+                n     = table[index].len8;                      \
             }                                                   \
         }                                                       \
         run = table[index].run;                                 \
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index 444ea83f3c..0d4a36be04 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -119,7 +119,7 @@ av_cold void ff_init_2d_vlc_rl(const uint16_t table_vlc[][2], RL_VLC_ELEM rl_vlc
                 level = table_level[code];
             }
         }
-        rl_vlc[i].len   = len;
+        rl_vlc[i].len8  = len;
         rl_vlc[i].level = level;
         rl_vlc[i].run   = run;
     }
diff --git a/libavcodec/rl.c b/libavcodec/rl.c
index a78242d488..b45cf117c1 100644
--- a/libavcodec/rl.c
+++ b/libavcodec/rl.c
@@ -118,7 +118,7 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
                     if (code >= rl->last) run += 192;
                 }
             }
-            rl->rl_vlc[q][i].len   = len;
+            rl->rl_vlc[q][i].len8  = len;
             rl->rl_vlc[q][i].level = level;
             rl->rl_vlc[q][i].run   = run;
         }
diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h
index bf7b0e65b4..7eecd9651f 100644
--- a/libavcodec/vlc.h
+++ b/libavcodec/vlc.h
@@ -30,9 +30,23 @@
 typedef int16_t VLCBaseType;
 
 typedef struct VLCElem {
-    VLCBaseType sym, len;
+    union {
+        /// The struct is for use as ordinary VLC (with get_vlc2())
+        struct {
+            VLCBaseType sym;
+            VLCBaseType len;
+        };
+        /// This struct is for use as run-length VLC (with GET_RL_VLC)
+        struct {
+            int16_t level;
+            int8_t   len8;
+            uint8_t   run;
+        };
+    };
 } VLCElem;
 
+typedef VLCElem RL_VLC_ELEM;
+
 typedef struct VLC {
     int bits;
     VLCElem *table;
@@ -53,12 +67,6 @@ typedef struct VLC_MULTI {
     int table_size, table_allocated;
 } VLC_MULTI;
 
-typedef struct RL_VLC_ELEM {
-    int16_t level;
-    int8_t len;
-    uint8_t run;
-} RL_VLC_ELEM;
-
 #define vlc_init(vlc, nb_bits, nb_codes,                \
                  bits, bits_wrap, bits_size,            \
                  codes, codes_wrap, codes_size,         \
-- 
2.45.2