From 1275029955768a373c571a261ed5f9aab362d124 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Wed, 9 Apr 2025 16:26:56 +0200
Subject: [PATCH 01/10] avcodec/hq{xvlc,_hqadata}: Deduplicate and hardcode cbp
 table

This table is so small (32 elements amounting to 128 bytes)
that it is more efficient size-wise to hardcode it instead
of initializing it at runtime.

Also stop duplicating it in hq_hqa.o and hqx.o.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/Makefile     |  4 ++--
 libavcodec/hq_common.c  | 44 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/hq_common.h  | 29 +++++++++++++++++++++++++++
 libavcodec/hq_hqa.c     | 10 +++-------
 libavcodec/hq_hqadata.h |  9 ---------
 libavcodec/hqx.c        |  7 +++----
 libavcodec/hqxvlc.h     | 16 +--------------
 7 files changed, 82 insertions(+), 37 deletions(-)
 create mode 100644 libavcodec/hq_common.c
 create mode 100644 libavcodec/hq_common.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3c3ac640e0..5ec2b7f5ad 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -465,8 +465,8 @@ OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER)    += v4l2_m2m_dec.o
 OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER)    += v4l2_m2m_enc.o
 OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)      += hnm4video.o
-OBJS-$(CONFIG_HQ_HQA_DECODER)          += hq_hqa.o hq_hqadsp.o canopus.o
-OBJS-$(CONFIG_HQX_DECODER)             += hqx.o hqxdsp.o canopus.o
+OBJS-$(CONFIG_HQ_HQA_DECODER)          += hq_hqa.o hq_hqadsp.o hq_common.o canopus.o
+OBJS-$(CONFIG_HQX_DECODER)             += hqx.o hqxdsp.o hq_common.o canopus.o
 OBJS-$(CONFIG_HUFFYUV_DECODER)         += huffyuv.o huffyuvdec.o
 OBJS-$(CONFIG_HUFFYUV_ENCODER)         += huffyuv.o huffyuvenc.o
 OBJS-$(CONFIG_HYMT_DECODER)            += huffyuv.o huffyuvdec.o
diff --git a/libavcodec/hq_common.c b/libavcodec/hq_common.c
new file mode 100644
index 0000000000..3cb793f2f6
--- /dev/null
+++ b/libavcodec/hq_common.c
@@ -0,0 +1,44 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * 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.
+ *
+ * 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hq_common.h"
+
+#define REPEAT(x) x x
+#define ELEM(_sym, _len) {.sym = _sym, .len = _len },
+#define LEN5(sym) ELEM(sym, 5)
+#define LEN4(sym) REPEAT(ELEM(sym, 4))
+#define LEN2(sym) REPEAT(REPEAT(REPEAT(ELEM(sym, 2))))
+
+const VLCElem ff_hq_cbp_vlc[1 << HQ_CBP_VLC_BITS] = {
+    LEN2(0xF)
+    LEN4(0x0)
+    LEN4(0xE)
+    LEN4(0xD)
+    LEN4(0xB)
+    LEN4(0x7)
+    LEN4(0x3)
+    LEN4(0xC)
+    LEN4(0x5)
+    LEN4(0xA)
+    LEN5(0x9)
+    LEN5(0x6)
+    LEN5(0x1)
+    LEN5(0x2)
+    LEN5(0x4)
+    LEN5(0x8)
+};
\ No newline at end of file
diff --git a/libavcodec/hq_common.h b/libavcodec/hq_common.h
new file mode 100644
index 0000000000..e438ac7d07
--- /dev/null
+++ b/libavcodec/hq_common.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * 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.
+ *
+ * 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_HQ_COMMON_H
+#define AVCODEC_HQ_COMMON_H
+
+#include "vlc.h"
+#include "libavutil/attributes_internal.h"
+
+#define HQ_CBP_VLC_BITS 5
+
+EXTERN const VLCElem ff_hq_cbp_vlc[1 << HQ_CBP_VLC_BITS];
+
+#endif /* AVCODEC_HQ_COMMON_H */
diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c
index 738ed9868d..76af754115 100644
--- a/libavcodec/hq_hqa.c
+++ b/libavcodec/hq_hqa.c
@@ -30,6 +30,7 @@
 #include "codec_internal.h"
 #include "decode.h"
 #include "get_bits.h"
+#include "hq_common.h"
 #include "hq_hqadata.h"
 #include "hq_hqadsp.h"
 #include "vlc.h"
@@ -58,7 +59,6 @@ typedef struct HQContext {
 } HQContext;
 
 static VLCElem hq_ac_vlc[1184];
-static VLCElem hqa_cbp_vlc[32];
 
 static inline void put_blocks(HQContext *c, AVFrame *pic,
                               int plane, int x, int y, int ilace,
@@ -192,18 +192,17 @@ static int hqa_decode_mb(HQContext *c, AVFrame *pic, int qgroup,
                          GetBitContext *gb, int x, int y)
 {
     int flag = 0;
-    int i, ret, cbp;
+    int i, ret;
 
     if (get_bits_left(gb) < 1)
         return AVERROR_INVALIDDATA;
 
-    cbp = get_vlc2(gb, hqa_cbp_vlc, 5, 1);
-
     for (i = 0; i < 12; i++)
         memset(c->block[i], 0, sizeof(*c->block));
     for (i = 0; i < 12; i++)
         c->block[i][0] = -128 * (1 << 6);
 
+    int cbp = get_vlc2(gb, ff_hq_cbp_vlc, HQ_CBP_VLC_BITS, 1);
     if (cbp) {
         flag = get_bits1(gb);
 
@@ -373,9 +372,6 @@ static int hq_hqa_decode_frame(AVCodecContext *avctx, AVFrame *pic,
 
 static av_cold void hq_init_vlcs(void)
 {
-    VLC_INIT_STATIC_TABLE(hqa_cbp_vlc, 5, FF_ARRAY_ELEMS(cbp_vlc_lens),
-                          cbp_vlc_lens, 1, 1, cbp_vlc_bits, 1, 1, 0);
-
     VLC_INIT_STATIC_TABLE(hq_ac_vlc, 9, NUM_HQ_AC_ENTRIES,
                           hq_ac_bits, 1, 1, hq_ac_codes, 2, 2, 0);
 }
diff --git a/libavcodec/hq_hqadata.h b/libavcodec/hq_hqadata.h
index 2faf47f003..d592ac0c21 100644
--- a/libavcodec/hq_hqadata.h
+++ b/libavcodec/hq_hqadata.h
@@ -36,15 +36,6 @@ typedef struct HQProfile {
 
 #define MAT_SIZE 64
 
-static const uint8_t cbp_vlc_bits[16] = {
-    0x04, 0x1C, 0x1D, 0x09, 0x1E, 0x0B, 0x1B, 0x08,
-    0x1F, 0x1A, 0x0C, 0x07, 0x0A, 0x06, 0x05, 0x00,
-};
-
-static const uint8_t cbp_vlc_lens[16] = {
-    4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2,
-};
-
 static const int32_t qmat00[MAT_SIZE] = {
     0x0040000, 0x000B18B, 0x00058C5, 0x000B1B1, 0x00082D3, 0x000B1B1,
     0x000A953, 0x000827B, 0x00104F7, 0x000A953, 0x0009000, 0x000EADD,
diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c
index 2e9698ee6c..0819575aa4 100644
--- a/libavcodec/hqx.c
+++ b/libavcodec/hqx.c
@@ -35,6 +35,7 @@
 
 #include "hqxdsp.h"
 #include "hqxvlc.h"
+#include "hq_common.h"
 
 /* HQX has four modes - 422, 444, 422alpha and 444alpha - all 12-bit */
 enum HQXFormat {
@@ -219,13 +220,12 @@ static int hqx_decode_422a(HQXContext *ctx, int slice_no, int x, int y)
     int flag = 0;
     int last_dc;
     int i, ret;
-    int cbp;
 
     memset(slice->block, 0, sizeof(*slice->block) * 12);
     for (i = 0; i < 12; i++)
         slice->block[i][0] = -0x800;
 
-    cbp = get_vlc2(gb, cbp_vlc, HQX_CBP_VLC_BITS, 1);
+    int cbp = get_vlc2(gb, ff_hq_cbp_vlc, HQ_CBP_VLC_BITS, 1);
     if (cbp) {
         const unsigned *quants;
 
@@ -305,13 +305,12 @@ static int hqx_decode_444a(HQXContext *ctx, int slice_no, int x, int y)
     int flag = 0;
     int last_dc;
     int i, ret;
-    int cbp;
 
     memset(slice->block, 0, sizeof(*slice->block) * 16);
     for (i = 0; i < 16; i++)
         slice->block[i][0] = -0x800;
 
-    cbp = get_vlc2(gb, cbp_vlc, HQX_CBP_VLC_BITS, 1);
+    int cbp = get_vlc2(gb, ff_hq_cbp_vlc, HQ_CBP_VLC_BITS, 1);
     if (cbp) {
         const unsigned *quants;
 
diff --git a/libavcodec/hqxvlc.h b/libavcodec/hqxvlc.h
index 28c55b20e0..abf81f60ad 100644
--- a/libavcodec/hqxvlc.h
+++ b/libavcodec/hqxvlc.h
@@ -28,7 +28,6 @@
 #include "libavutil/attributes.h"
 #include "libavutil/macros.h"
 
-#define HQX_CBP_VLC_BITS 5
 #define HQX_DC_VLC_BITS 9
 
 enum HQXACMode {
@@ -46,15 +45,6 @@ typedef struct HQXAC {
     const RL_VLC_ELEM *lut;
 } HQXAC;
 
-static const uint8_t cbp_vlc_bits[16] = {
-    0x04, 0x1C, 0x1D, 0x09, 0x1E, 0x0B, 0x1B, 0x08,
-    0x1F, 0x1A, 0x0C, 0x07, 0x0A, 0x06, 0x05, 0x00,
-};
-
-static const uint8_t cbp_vlc_lens[16] = {
-    4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2,
-};
-
 static const uint16_t dc9_vlc_bits[512] = {
     0x0010, 0x0008, 0x0022, 0x0024, 0x0026, 0x0028, 0x002A, 0x002C,
     0x002E, 0x0030, 0x0032, 0x0034, 0x0074, 0x0076, 0x0078, 0x007A,
@@ -1529,11 +1519,10 @@ static const uint8_t hqx_ac_lens[] = {
 
 static const uint16_t hqx_ac_nb_elems[] = { 815, 907, 512, 354, 257, 194 };
 
-static VLCElem cbp_vlc[(1 << HQX_CBP_VLC_BITS) + 896 /* dc9 */ + 1344 /* dc10 */
+static VLCElem cbp_vlc[896 /* dc9 */ + 1344 /* dc10 */
                        + 15630 /* RL_VLC_ELEMS for hqx_ac */];
 
 static const VLCElem *dc_vlc[2];
-
 #define INIT_DC_TABLE(idx, name)                                              \
     do {                                                                      \
          dc_vlc[idx] = ff_vlc_init_tables(&state, HQX_DC_VLC_BITS,            \
@@ -1548,9 +1537,6 @@ static av_cold av_unused void hqx_init_static(void)
     const uint8_t *lens = hqx_ac_lens;
     const int16_t *run_level = hqx_ac_run_level;
 
-    ff_vlc_init_tables(&state, HQX_CBP_VLC_BITS, FF_ARRAY_ELEMS(cbp_vlc_lens),
-                       cbp_vlc_lens, 1, 1, cbp_vlc_bits, 1, 1, 0);
-
     INIT_DC_TABLE(0, dc9);
     INIT_DC_TABLE(1, dc10);
 
-- 
2.45.2