From 1d2322ea36ae7480c8e3e2fce3d8f9969f0691e5 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 13 Mar 2025 22:17:03 +0100
Subject: [PATCH 08/17] avcodec/hqx: Cache pointer to used dc table

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hqx.c    | 32 ++++++++++++++++----------------
 libavcodec/hqxvlc.h |  2 +-
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c
index e73a023c29..aab28a2156 100644
--- a/libavcodec/hqx.c
+++ b/libavcodec/hqx.c
@@ -68,7 +68,9 @@ typedef struct HQXContext {
     unsigned int data_size;
     uint32_t slice_off[17];
 
-    VLC dc_vlc[3];
+    const VLCElem *dc_vlc;
+
+    VLC dc_vlcs[3];
 } HQXContext;
 
 #define HQX_HEADER_SIZE 59
@@ -140,7 +142,7 @@ static inline void hqx_get_ac(GetBitContext *gb, const HQXAC *ac,
     *lev  = level;
 }
 
-static int decode_block(GetBitContext *gb, VLC *vlc,
+static int decode_block(GetBitContext *gb, const VLCElem vlc[],
                         const int *quants, int dcb,
                         int16_t block[64], int *last_dc)
 {
@@ -149,7 +151,7 @@ static int decode_block(GetBitContext *gb, VLC *vlc,
     int run, lev, pos = 0;
 
     memset(block, 0, 64 * sizeof(*block));
-    dc = get_vlc2(gb, vlc->table, HQX_DC_VLC_BITS, 2);
+    dc = get_vlc2(gb, vlc, HQX_DC_VLC_BITS, 2);
     *last_dc += dc;
 
     block[0] = sign_extend(*last_dc << (12 - dcb), 12);
@@ -196,10 +198,9 @@ static int hqx_decode_422(HQXContext *ctx, int slice_no, int x, int y)
     quants = hqx_quants[get_bits(gb, 4)];
 
     for (i = 0; i < 8; i++) {
-        int vlc_index = ctx->dcb - 9;
         if (i == 0 || i == 4 || i == 6)
             last_dc = 0;
-        ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants,
+        ret = decode_block(gb, ctx->dc_vlc, quants,
                            ctx->dcb, slice->block[i], &last_dc);
         if (ret < 0)
             return ret;
@@ -244,8 +245,7 @@ static int hqx_decode_422a(HQXContext *ctx, int slice_no, int x, int y)
             if (i == 0 || i == 4 || i == 8 || i == 10)
                 last_dc = 0;
             if (cbp & (1 << i)) {
-                int vlc_index = ctx->dcb - 9;
-                ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants,
+                ret = decode_block(gb, ctx->dc_vlc, quants,
                                    ctx->dcb, slice->block[i], &last_dc);
                 if (ret < 0)
                     return ret;
@@ -280,10 +280,9 @@ static int hqx_decode_444(HQXContext *ctx, int slice_no, int x, int y)
     quants = hqx_quants[get_bits(gb, 4)];
 
     for (i = 0; i < 12; i++) {
-        int vlc_index = ctx->dcb - 9;
         if (i == 0 || i == 4 || i == 8)
             last_dc = 0;
-        ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants,
+        ret = decode_block(gb, ctx->dc_vlc, quants,
                            ctx->dcb, slice->block[i], &last_dc);
         if (ret < 0)
             return ret;
@@ -327,8 +326,7 @@ static int hqx_decode_444a(HQXContext *ctx, int slice_no, int x, int y)
             if (i == 0 || i == 4 || i == 8 || i == 12)
                 last_dc = 0;
             if (cbp & (1 << i)) {
-                int vlc_index = ctx->dcb - 9;
-                ret = decode_block(gb, &ctx->dc_vlc[vlc_index], quants,
+                ret = decode_block(gb, ctx->dc_vlc, quants,
                                    ctx->dcb, slice->block[i], &last_dc);
                 if (ret < 0)
                     return ret;
@@ -434,7 +432,7 @@ static int hqx_decode_frame(AVCodecContext *avctx, AVFrame *frame,
     HQXContext *ctx = avctx->priv_data;
     const uint8_t *src = avpkt->data;
     uint32_t info_tag;
-    int data_start;
+    int data_start, dcb_code;
     int i, ret;
 
     if (avpkt->size < 4 + 4) {
@@ -473,16 +471,18 @@ static int hqx_decode_frame(AVCodecContext *avctx, AVFrame *frame,
     }
     ctx->interlaced = !(src[2] & 0x80);
     ctx->format     = src[2] & 7;
-    ctx->dcb        = (src[3] & 3) + 8;
+    dcb_code        = src[3] & 3;
     ctx->width      = AV_RB16(src + 4);
     ctx->height     = AV_RB16(src + 6);
     for (i = 0; i < 17; i++)
         ctx->slice_off[i] = AV_RB24(src + 8 + i * 3);
 
-    if (ctx->dcb == 8) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid DC precision %d.\n", ctx->dcb);
+    if (dcb_code == 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid DC precision 8.\n");
         return AVERROR_INVALIDDATA;
     }
+    ctx->dc_vlc = ctx->dc_vlcs[dcb_code - 1].table;
+    ctx->dcb    = dcb_code + 8;
     ret = av_image_check_size(ctx->width, ctx->height, 0, avctx);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Invalid stored dimensions %dx%d.\n",
@@ -543,7 +543,7 @@ static av_cold int hqx_decode_close(AVCodecContext *avctx)
     HQXContext *ctx = avctx->priv_data;
 
     for (i = 0; i < 3; i++) {
-        ff_vlc_free(&ctx->dc_vlc[i]);
+        ff_vlc_free(&ctx->dc_vlcs[i]);
     }
 
     return 0;
diff --git a/libavcodec/hqxvlc.h b/libavcodec/hqxvlc.h
index aa7fbcdc59..4bdc3cd191 100644
--- a/libavcodec/hqxvlc.h
+++ b/libavcodec/hqxvlc.h
@@ -1533,7 +1533,7 @@ static VLCElem cbp_vlc[(1 << HQX_CBP_VLC_BITS) + 15630 /* RL_VLC_ELEMS for hqx_a
 
 #define INIT_DC_TABLE(idx, name)                                              \
     do {                                                                      \
-        ret = vlc_init(&ctx->dc_vlc[idx], HQX_DC_VLC_BITS,                    \
+        ret = vlc_init(&ctx->dc_vlcs[idx], HQX_DC_VLC_BITS,                   \
                        FF_ARRAY_ELEMS(name ## _vlc_lens),                     \
                        name ## _vlc_lens, 1, 1,                               \
                        name ## _vlc_bits, 2, 2, 0);                           \
-- 
2.45.2