Patches attached.

- Andreas
From 89a16c8e6efe441bf745ff1cf59296a2b97daf71 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Thu, 17 Apr 2025 15:43:31 +0200
Subject: [PATCH 01/13] avcodec/huffman: Switch to ff_vlc_init_from_lengths()

Avoids having to create the codes ourselves.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/huffman.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c
index d47fe10087..0de3097a82 100644
--- a/libavcodec/huffman.c
+++ b/libavcodec/huffman.c
@@ -115,40 +115,36 @@ end:
     return ret;
 }
 
-static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
-                           Node *nodes, int node,
-                           uint32_t pfx, int pl, int *pos, int no_zero_count)
+static void get_tree_codes(int8_t *lens, uint8_t *xlat,
+                           Node *nodes, int node, int pl, int *pos, int no_zero_count)
 {
     int s;
 
     s = nodes[node].sym;
     if (s != HNODE || (no_zero_count && !nodes[node].count)) {
-        bits[*pos] = pfx;
         lens[*pos] = pl;
         xlat[*pos] = s;
         (*pos)++;
     } else {
-        pfx <<= 1;
         pl++;
-        get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0, pfx, pl,
+        get_tree_codes(lens, xlat, nodes, nodes[node].n0, pl,
                        pos, no_zero_count);
-        pfx |= 1;
-        get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0 + 1, pfx, pl,
+        get_tree_codes(lens, xlat, nodes, nodes[node].n0 + 1, pl,
                        pos, no_zero_count);
     }
 }
 
-static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits)
+static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits, void *logctx)
 {
     int no_zero_count = !(flags & FF_HUFFMAN_FLAG_ZERO_COUNT);
-    uint32_t bits[256];
-    int16_t lens[256];
+    int8_t lens[256];
     uint8_t xlat[256];
     int pos = 0;
 
-    get_tree_codes(bits, lens, xlat, nodes, head, 0, 0,
+    get_tree_codes(lens, xlat, nodes, head, 0,
                    &pos, no_zero_count);
-    return ff_vlc_init_sparse(vlc, nb_bits, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0);
+    return ff_vlc_init_from_lengths(vlc, nb_bits, pos, lens, 1,
+                                    xlat, 1, 1, 0, 0, logctx);
 }
 
 
@@ -194,7 +190,7 @@ int ff_huff_build_tree(void *logctx, VLC *vlc, int nb_codes, int nb_bits,
         nodes[j].n0 = i;
         cur_node++;
     }
-    if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags, nb_bits) < 0) {
+    if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags, nb_bits, logctx) < 0) {
         av_log(logctx, AV_LOG_ERROR, "Error building tree\n");
         return -1;
     }
-- 
2.45.2

From be900261219c54b9d7e07a2382b096c2859592b5 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Thu, 17 Apr 2025 19:41:05 +0200
Subject: [PATCH 02/13] avcodec/vp6: Don't initialize unused VLC tables

There are only 2*3*4 VLC trees for decoding Huffman encoded
AC coefficients; see section 13.3.2 of the spec.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/vp56.h |  2 +-
 libavcodec/vp6.c  | 10 ++++------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h
index 87b7e06e0b..e922a13c5e 100644
--- a/libavcodec/vp56.h
+++ b/libavcodec/vp56.h
@@ -203,7 +203,7 @@ struct vp56_context {
     GetBitContext gb;
     VLC dccv_vlc[2];
     VLC runv_vlc[2];
-    VLC ract_vlc[2][3][6];
+    VLC ract_vlc[2][3][4];
     unsigned int nb_null[2][2];       /* number of consecutive NULL DC/AC */
 
     int have_undamaged_frame;
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 73d117c871..926694ae11 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -339,7 +339,7 @@ static int vp6_parse_coeff_models(VP56Context *s)
                                     vp6_huff_run_map, 9, &s->runv_vlc[pt]))
                 return -1;
             for (ct=0; ct<3; ct++)
-                for (cg = 0; cg < 6; cg++)
+                for (int cg = 0; cg < 4; cg++)
                     if (vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg],
                                             vp6_huff_coeff_map, 12,
                                             &s->ract_vlc[pt][ct][cg]))
@@ -704,15 +704,13 @@ static av_cold int vp6_decode_free(AVCodecContext *avctx)
 
 static av_cold void vp6_decode_free_context(VP56Context *s)
 {
-    int pt, ct, cg;
-
     ff_vp56_free_context(s);
 
-    for (pt=0; pt<2; pt++) {
+    for (int pt = 0; pt < 2; ++pt) {
         ff_vlc_free(&s->dccv_vlc[pt]);
         ff_vlc_free(&s->runv_vlc[pt]);
-        for (ct=0; ct<3; ct++)
-            for (cg=0; cg<6; cg++)
+        for (int ct = 0; ct < 3; ++ct)
+            for (int cg = 0; cg < 4; ++cg)
                 ff_vlc_free(&s->ract_vlc[pt][ct][cg]);
     }
 }
-- 
2.45.2

From fde92954b4c0778aa61d40342db9da91af1a60d4 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Thu, 17 Apr 2025 19:48:05 +0200
Subject: [PATCH 03/13] avcodec/vp6: Don't reload unnecessarily often in
 get_vlc2()

The VLC trees used here have very few different codes
and are therefore guaranteed to not be very deep: The AC/DC
VLCs have 12 elements and therefore a depth <= 11 whereas
the run VLCs have only nine elements and therefore a depth <= 8.
This allows to reduce the worst-case number of reloads for
reading a VLC code.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/vp6.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 926694ae11..de60ae93bb 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -415,7 +415,7 @@ static int vp6_parse_coeff_huffman(VP56Context *s)
     VP56Model *model = s->modelp;
     uint8_t *permute = s->idct_scantable;
     VLC *vlc_coeff;
-    int coeff, sign, coeff_idx;
+    int sign, coeff_idx;
     int b, cg, idx;
     int pt = 0;    /* plane type (0 for Y, 1 for U or V) */
 
@@ -433,11 +433,11 @@ static int vp6_parse_coeff_huffman(VP56Context *s)
             } else {
                 if (get_bits_left(&s->gb) <= 0)
                     return AVERROR_INVALIDDATA;
-                coeff = get_vlc2(&s->gb, vlc_coeff->table, FF_HUFFMAN_BITS, 3);
+                int coeff = get_vlc2(&s->gb, vlc_coeff->table, FF_HUFFMAN_BITS, 2);
                 if (coeff == 0) {
                     if (coeff_idx) {
                         int pt = (coeff_idx >= 6);
-                        run += get_vlc2(&s->gb, s->runv_vlc[pt].table, FF_HUFFMAN_BITS, 3);
+                        run += get_vlc2(&s->gb, s->runv_vlc[pt].table, FF_HUFFMAN_BITS, 1);
                         if (run >= 9)
                             run += get_bits(&s->gb, 6);
                     } else
-- 
2.45.2

From 10e53754d4bb14fd3188baab185494cdf387ad70 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Thu, 17 Apr 2025 20:13:56 +0200
Subject: [PATCH 04/13] avcodec/vp6: Use fewer number of bits in run VLCs

Given that these trees have only nine elements and are complete,
their depth is <= eight.

Also remove the now unused FF_HUFFMAN_BITS constant.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/huffman.h |  1 -
 libavcodec/vp6.c     | 18 ++++++++++++------
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/libavcodec/huffman.h b/libavcodec/huffman.h
index 1d5e140e81..dcf1f4ba78 100644
--- a/libavcodec/huffman.h
+++ b/libavcodec/huffman.h
@@ -38,7 +38,6 @@ typedef struct Node {
 
 #define FF_HUFFMAN_FLAG_HNODE_FIRST 0x01
 #define FF_HUFFMAN_FLAG_ZERO_COUNT  0x02
-#define FF_HUFFMAN_BITS 10
 
 typedef int (*HuffCmp)(const void *va, const void *vb);
 int ff_huff_build_tree(void *logctx, VLC *vlc, int nb_codes, int nb_bits,
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index de60ae93bb..69cfc5fa8b 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -41,6 +41,8 @@
 #include "vpx_rac.h"
 
 #define VP6_MAX_HUFF_SIZE 12
+#define AC_DC_HUFF_BITS   10
+#define RUN_HUFF_BITS      8
 
 static int vp6_parse_coeff(VP56Context *s);
 static int vp6_parse_coeff_huffman(VP56Context *s);
@@ -266,7 +268,8 @@ static int vp6_huff_cmp(const void *va, const void *vb)
 }
 
 static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
-                               const uint8_t *map, unsigned size, VLC *vlc)
+                               const uint8_t *map, unsigned size,
+                               int nb_bits, VLC *vlc)
 {
     Node nodes[2*VP6_MAX_HUFF_SIZE], *tmp = &nodes[size];
     int a, b, i;
@@ -282,7 +285,7 @@ static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
 
     ff_vlc_free(vlc);
     /* then build the huffman tree according to probabilities */
-    return ff_huff_build_tree(s->avctx, vlc, size, FF_HUFFMAN_BITS,
+    return ff_huff_build_tree(s->avctx, vlc, size, nb_bits,
                               nodes, vp6_huff_cmp,
                               FF_HUFFMAN_FLAG_HNODE_FIRST);
 }
@@ -333,15 +336,18 @@ static int vp6_parse_coeff_models(VP56Context *s)
     if (s->use_huffman) {
         for (pt=0; pt<2; pt++) {
             if (vp6_build_huff_tree(s, model->coeff_dccv[pt],
-                                    vp6_huff_coeff_map, 12, &s->dccv_vlc[pt]))
+                                    vp6_huff_coeff_map, 12, AC_DC_HUFF_BITS,
+                                    &s->dccv_vlc[pt]))
                 return -1;
             if (vp6_build_huff_tree(s, model->coeff_runv[pt],
-                                    vp6_huff_run_map, 9, &s->runv_vlc[pt]))
+                                    vp6_huff_run_map, 9, RUN_HUFF_BITS,
+                                    &s->runv_vlc[pt]))
                 return -1;
             for (ct=0; ct<3; ct++)
                 for (int cg = 0; cg < 4; cg++)
                     if (vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg],
                                             vp6_huff_coeff_map, 12,
+                                            AC_DC_HUFF_BITS,
                                             &s->ract_vlc[pt][ct][cg]))
                         return -1;
         }
@@ -433,11 +439,11 @@ static int vp6_parse_coeff_huffman(VP56Context *s)
             } else {
                 if (get_bits_left(&s->gb) <= 0)
                     return AVERROR_INVALIDDATA;
-                int coeff = get_vlc2(&s->gb, vlc_coeff->table, FF_HUFFMAN_BITS, 2);
+                int coeff = get_vlc2(&s->gb, vlc_coeff->table, AC_DC_HUFF_BITS, 2);
                 if (coeff == 0) {
                     if (coeff_idx) {
                         int pt = (coeff_idx >= 6);
-                        run += get_vlc2(&s->gb, s->runv_vlc[pt].table, FF_HUFFMAN_BITS, 1);
+                        run += get_vlc2(&s->gb, s->runv_vlc[pt].table, RUN_HUFF_BITS, 1);
                         if (run >= 9)
                             run += get_bits(&s->gb, 6);
                     } else
-- 
2.45.2

From faaa8ac870814de2d120849149f308ae8daaf751 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Thu, 17 Apr 2025 20:26:01 +0200
Subject: [PATCH 05/13] avcodec/vp6: Forward error codes

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/vp6.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 69cfc5fa8b..48ff9da818 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -298,6 +298,7 @@ static int vp6_parse_coeff_models(VP56Context *s)
     int node, cg, ctx, pos;
     int ct;    /* code type */
     int pt;    /* plane type (0 for Y, 1 for U or V) */
+    int ret;
 
     memset(def_prob, 0x80, sizeof(def_prob));
 
@@ -335,21 +336,25 @@ static int vp6_parse_coeff_models(VP56Context *s)
 
     if (s->use_huffman) {
         for (pt=0; pt<2; pt++) {
-            if (vp6_build_huff_tree(s, model->coeff_dccv[pt],
-                                    vp6_huff_coeff_map, 12, AC_DC_HUFF_BITS,
-                                    &s->dccv_vlc[pt]))
-                return -1;
-            if (vp6_build_huff_tree(s, model->coeff_runv[pt],
-                                    vp6_huff_run_map, 9, RUN_HUFF_BITS,
-                                    &s->runv_vlc[pt]))
-                return -1;
+            ret = vp6_build_huff_tree(s, model->coeff_dccv[pt],
+                                      vp6_huff_coeff_map, 12, AC_DC_HUFF_BITS,
+                                      &s->dccv_vlc[pt]);
+            if (ret < 0)
+                return ret;
+            ret = vp6_build_huff_tree(s, model->coeff_runv[pt],
+                                      vp6_huff_run_map, 9, RUN_HUFF_BITS,
+                                      &s->runv_vlc[pt]);
+            if (ret < 0)
+                return ret;
             for (ct=0; ct<3; ct++)
-                for (int cg = 0; cg < 4; cg++)
-                    if (vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg],
-                                            vp6_huff_coeff_map, 12,
-                                            AC_DC_HUFF_BITS,
-                                            &s->ract_vlc[pt][ct][cg]))
-                        return -1;
+                for (int cg = 0; cg < 4; cg++) {
+                    ret = vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg],
+                                              vp6_huff_coeff_map, 12,
+                                              AC_DC_HUFF_BITS,
+                                              &s->ract_vlc[pt][ct][cg]);
+                    if (ret < 0)
+                        return ret;
+                }
         }
         memset(s->nb_null, 0, sizeof(s->nb_null));
     } else {
-- 
2.45.2

From 709443e00fb342aaf2263c78e755dfde3c90f22d Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Fri, 18 Apr 2025 13:02:47 +0200
Subject: [PATCH 06/13] avcodec/cbs: Use put_bits63()

It is better when BUF_BITS == 64 (i.e. on x64), because
the underlying put_bits can then handle 0..63 bits naturally.
It does not worsen the code when BUF_BITS != 64, because
the compiler can optimize this to the same code as now
(due to the assert).

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/cbs.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index ba1034a72e..398d286a92 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -674,10 +674,7 @@ int CBS_FUNC(write_unsigned)(CodedBitstreamContext *ctx, PutBitContext *pbc,
     if (put_bits_left(pbc) < width)
         return AVERROR(ENOSPC);
 
-    if (width < 32)
-        put_bits(pbc, width, value);
-    else
-        put_bits32(pbc, value);
+    put_bits63(pbc, width, value);
 
     CBS_TRACE_WRITE_END();
 
@@ -746,10 +743,7 @@ int CBS_FUNC(write_signed)(CodedBitstreamContext *ctx, PutBitContext *pbc,
     if (put_bits_left(pbc) < width)
         return AVERROR(ENOSPC);
 
-    if (width < 32)
-        put_sbits(pbc, width, value);
-    else
-        put_bits32(pbc, value);
+    put_bits63(pbc, width, zero_extend(value, width));
 
     CBS_TRACE_WRITE_END();
 
-- 
2.45.2

From fd6140eba2ffd09fba80bd2ffc0232cc93197d12 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Fri, 18 Apr 2025 18:50:59 +0200
Subject: [PATCH 07/13] avcodec/webp: Check more directly for invalid codes

Don't rely on invalid codes leading to get_vlc2() returning
-1, which then gets converted to an uint8_t, i.e. to 255
and runs afoul of a length check later. After all, get_vlc2()
could be changed to return something else which may
be valid when cast to uint8_t.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/webp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 9f83b518ad..46b20a1ab6 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -278,7 +278,7 @@ static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_length
     for (sym = 0; sym < alphabet_size; sym++)
         max_code_length = FFMAX(max_code_length, code_lengths[sym]);
 
-    if (max_code_length == 0 || max_code_length > MAX_HUFFMAN_CODE_LENGTH)
+    if (max_code_length == 0)
         return AVERROR(EINVAL);
 
     codes = av_malloc_array(alphabet_size, sizeof(*codes));
@@ -375,7 +375,7 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
         if (!max_symbol--)
             break;
         code_len = huff_reader_get_symbol(&code_len_hc, &s->gb);
-        if (code_len < 16) {
+        if (code_len < 16U) {
             /* Code length code [0..15] indicates literal code lengths. */
             code_lengths[symbol++] = code_len;
             if (code_len)
@@ -383,6 +383,9 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
         } else {
             int repeat = 0, length = 0;
             switch (code_len) {
+            default:
+                ret = AVERROR_INVALIDDATA;
+                goto finish;
             case 16:
                 /* Code 16 repeats the previous non-zero value [3..6] times,
                  * i.e., 3 + ReadBits(2) times. If code 16 is used before a
-- 
2.45.2

From bb09b7d7d7f0136c352c4e2a760e2ed9b18e1042 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Fri, 18 Apr 2025 19:29:41 +0200
Subject: [PATCH 08/13] avcodec/webp: Switch to ff_vlc_init_from_lengths()

The earlier code would traverse over the code lengths
mutliple times (namely max_length + 1 times - once to get
the maximum length and once for each max_length to assign
codes) before calling ff_vlc_init_sparse() (which may traverse
them twice and sort them). The new code only traverses them once
(+ the one time in ff_vlc_init_from_lengths()).

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/webp.c | 108 +++++++++++++++++++++++-----------------------
 1 file changed, 55 insertions(+), 53 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 46b20a1ab6..2c918eac33 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -253,64 +253,58 @@ static int huff_reader_get_symbol(HuffReader *r, GetBitContext *gb)
 }
 
 static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_lengths,
-                                       int alphabet_size)
+                                       uint16_t len_counts[MAX_HUFFMAN_CODE_LENGTH + 1],
+                                       int alphabet_size, void *logctx)
 {
-    int len = 0, sym, code = 0, ret;
-    int max_code_length = 0;
-    uint16_t *codes;
-
-    /* special-case 1 symbol since the vlc reader cannot handle it */
-    for (sym = 0; sym < alphabet_size; sym++) {
-        if (code_lengths[sym] > 0) {
-            len++;
-            code = sym;
-            if (len > 1)
-                break;
-        }
+    uint16_t *syms;
+    uint8_t *lens;
+    unsigned nb_codes = 0;
+    int ret;
+
+    // Count the number of symbols of each length and transform len_counts
+    // into an array of offsets.
+    for (int len = 1; len <= MAX_HUFFMAN_CODE_LENGTH; ++len) {
+        unsigned cnt = len_counts[len];
+        len_counts[len] = nb_codes;
+        nb_codes += cnt;
     }
-    if (len == 1) {
-        r->nb_symbols = 1;
-        r->simple_symbols[0] = code;
-        r->simple = 1;
-        return 0;
+    if (nb_codes <= 1) {
+        if (nb_codes == 1) {
+            /* special-case 1 symbol since the vlc reader cannot handle it */
+            r->nb_symbols = 1;
+            r->simple = 1;
+            for (int sym = 0;; ++sym) {
+                av_assert1(sym < alphabet_size);
+                if (code_lengths[sym]) {
+                    r->simple_symbols[0] = sym;
+                    return 0;
+                }
+            }
+        }
+        // No symbols
+        return AVERROR_INVALIDDATA;
     }
 
-    for (sym = 0; sym < alphabet_size; sym++)
-        max_code_length = FFMAX(max_code_length, code_lengths[sym]);
-
-    if (max_code_length == 0)
-        return AVERROR(EINVAL);
-
-    codes = av_malloc_array(alphabet_size, sizeof(*codes));
-    if (!codes)
+    syms = av_malloc_array(nb_codes, sizeof(*syms) + sizeof(*lens));
+    if (!syms)
         return AVERROR(ENOMEM);
+    lens = (uint8_t*)(syms + nb_codes);
 
-    code = 0;
-    r->nb_symbols = 0;
-    for (len = 1; len <= max_code_length; len++) {
-        for (sym = 0; sym < alphabet_size; sym++) {
-            if (code_lengths[sym] != len)
-                continue;
-            codes[sym] = code++;
-            r->nb_symbols++;
+    for (int sym = 0; sym < alphabet_size; ++sym) {
+        if (code_lengths[sym]) {
+            unsigned idx = len_counts[code_lengths[sym]]++;
+            syms[idx] = sym;
+            lens[idx] = code_lengths[sym];
         }
-        code <<= 1;
-    }
-    if (!r->nb_symbols) {
-        av_free(codes);
-        return AVERROR_INVALIDDATA;
     }
 
-    ret = vlc_init(&r->vlc, 8, alphabet_size,
-                   code_lengths, sizeof(*code_lengths), sizeof(*code_lengths),
-                   codes, sizeof(*codes), sizeof(*codes), VLC_INIT_OUTPUT_LE);
-    if (ret < 0) {
-        av_free(codes);
+    ret = ff_vlc_init_from_lengths(&r->vlc, 8, nb_codes, lens, 1,
+                                   syms, 2, 2, 0, VLC_INIT_OUTPUT_LE, logctx);
+    av_free(syms);
+    if (ret < 0)
         return ret;
-    }
     r->simple = 0;
 
-    av_free(codes);
     return 0;
 }
 
@@ -335,20 +329,24 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
     HuffReader code_len_hc = { { 0 }, 0, 0, { 0 } };
     uint8_t *code_lengths;
     uint8_t code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
-    int i, symbol, max_symbol, prev_code_len, ret;
+    uint16_t len_counts[MAX_HUFFMAN_CODE_LENGTH + 1] = { 0 };
+    int symbol, max_symbol, prev_code_len, ret;
     int num_codes = 4 + get_bits(&s->gb, 4);
 
     av_assert1(num_codes <= NUM_CODE_LENGTH_CODES);
 
-    for (i = 0; i < num_codes; i++)
-        code_length_code_lengths[code_length_code_order[i]] = get_bits(&s->gb, 3);
+    for (int i = 0; i < num_codes; i++) {
+        unsigned len = get_bits(&s->gb, 3);
+        code_length_code_lengths[code_length_code_order[i]] = len;
+        len_counts[len]++;
+    }
 
-    ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths,
-                                      NUM_CODE_LENGTH_CODES);
+    ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths, len_counts,
+                                      NUM_CODE_LENGTH_CODES, s->avctx);
     if (ret < 0)
         return ret;
 
-    code_lengths = av_mallocz(alphabet_size);
+    code_lengths = av_malloc(alphabet_size);
     if (!code_lengths) {
         ret = AVERROR(ENOMEM);
         goto finish;
@@ -369,6 +367,7 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
 
     prev_code_len = 8;
     symbol        = 0;
+    memset(len_counts, 0, sizeof(len_counts));
     while (symbol < alphabet_size) {
         int code_len;
 
@@ -378,6 +377,7 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
         if (code_len < 16U) {
             /* Code length code [0..15] indicates literal code lengths. */
             code_lengths[symbol++] = code_len;
+            len_counts[code_len]++;
             if (code_len)
                 prev_code_len = code_len;
         } else {
@@ -392,6 +392,7 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
                  * non-zero value has been emitted, a value of 8 is repeated. */
                 repeat = 3 + get_bits(&s->gb, 2);
                 length = prev_code_len;
+                len_counts[length] += repeat;
                 break;
             case 17:
                 /* Code 17 emits a streak of zeros [3..10], i.e.,
@@ -416,7 +417,8 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
         }
     }
 
-    ret = huff_reader_build_canonical(hc, code_lengths, alphabet_size);
+    ret = huff_reader_build_canonical(hc, code_lengths, len_counts,
+                                      symbol, s->avctx);
 
 finish:
     ff_vlc_free(&code_len_hc.vlc);
-- 
2.45.2

From 6d81b0862963d5e527ea1b976a61829f086a1913 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Sun, 20 Apr 2025 20:32:20 +0200
Subject: [PATCH 09/13] avcodec/webp: Check before allocations

Avoids freeing lateron.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/webp.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 2c918eac33..2843b953bd 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -341,30 +341,29 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
         len_counts[len]++;
     }
 
-    ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths, len_counts,
-                                      NUM_CODE_LENGTH_CODES, s->avctx);
-    if (ret < 0)
-        return ret;
-
-    code_lengths = av_malloc(alphabet_size);
-    if (!code_lengths) {
-        ret = AVERROR(ENOMEM);
-        goto finish;
-    }
-
     if (get_bits1(&s->gb)) {
         int bits   = 2 + 2 * get_bits(&s->gb, 3);
         max_symbol = 2 + get_bits(&s->gb, bits);
         if (max_symbol > alphabet_size) {
             av_log(s->avctx, AV_LOG_ERROR, "max symbol %d > alphabet size %d\n",
                    max_symbol, alphabet_size);
-            ret = AVERROR_INVALIDDATA;
-            goto finish;
+            return AVERROR_INVALIDDATA;
         }
     } else {
         max_symbol = alphabet_size;
     }
 
+    ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths, len_counts,
+                                      NUM_CODE_LENGTH_CODES, s->avctx);
+    if (ret < 0)
+        return ret;
+
+    code_lengths = av_malloc(alphabet_size);
+    if (!code_lengths) {
+        ret = AVERROR(ENOMEM);
+        goto finish;
+    }
+
     prev_code_len = 8;
     symbol        = 0;
     memset(len_counts, 0, sizeof(len_counts));
-- 
2.45.2

From 765bbe86f0fe005ff187f24443d7c2fb04b4903a Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Sun, 20 Apr 2025 20:51:59 +0200
Subject: [PATCH 10/13] avcodec/webp: Combine allocations

Or avoid them altogether for the small stage-one VLC.

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/webp.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 2843b953bd..e26bf01c6a 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -254,10 +254,9 @@ static int huff_reader_get_symbol(HuffReader *r, GetBitContext *gb)
 
 static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_lengths,
                                        uint16_t len_counts[MAX_HUFFMAN_CODE_LENGTH + 1],
+                                       uint8_t lens[], uint16_t syms[],
                                        int alphabet_size, void *logctx)
 {
-    uint16_t *syms;
-    uint8_t *lens;
     unsigned nb_codes = 0;
     int ret;
 
@@ -285,11 +284,6 @@ static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_length
         return AVERROR_INVALIDDATA;
     }
 
-    syms = av_malloc_array(nb_codes, sizeof(*syms) + sizeof(*lens));
-    if (!syms)
-        return AVERROR(ENOMEM);
-    lens = (uint8_t*)(syms + nb_codes);
-
     for (int sym = 0; sym < alphabet_size; ++sym) {
         if (code_lengths[sym]) {
             unsigned idx = len_counts[code_lengths[sym]]++;
@@ -300,7 +294,6 @@ static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_length
 
     ret = ff_vlc_init_from_lengths(&r->vlc, 8, nb_codes, lens, 1,
                                    syms, 2, 2, 0, VLC_INIT_OUTPUT_LE, logctx);
-    av_free(syms);
     if (ret < 0)
         return ret;
     r->simple = 0;
@@ -329,6 +322,8 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
     HuffReader code_len_hc = { { 0 }, 0, 0, { 0 } };
     uint8_t *code_lengths;
     uint8_t code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
+    uint8_t reordered_code_length_code_lengths[NUM_CODE_LENGTH_CODES];
+    uint16_t reordered_code_length_syms[NUM_CODE_LENGTH_CODES];
     uint16_t len_counts[MAX_HUFFMAN_CODE_LENGTH + 1] = { 0 };
     int symbol, max_symbol, prev_code_len, ret;
     int num_codes = 4 + get_bits(&s->gb, 4);
@@ -354,11 +349,13 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
     }
 
     ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths, len_counts,
+                                      reordered_code_length_code_lengths,
+                                      reordered_code_length_syms,
                                       NUM_CODE_LENGTH_CODES, s->avctx);
     if (ret < 0)
         return ret;
 
-    code_lengths = av_malloc(alphabet_size);
+    code_lengths = av_malloc_array(alphabet_size, 2 * sizeof(uint8_t) + sizeof(uint16_t));
     if (!code_lengths) {
         ret = AVERROR(ENOMEM);
         goto finish;
@@ -417,6 +414,8 @@ static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
     }
 
     ret = huff_reader_build_canonical(hc, code_lengths, len_counts,
+                                      code_lengths + symbol,
+                                      (uint16_t*)(code_lengths + 2 * symbol),
                                       symbol, s->avctx);
 
 finish:
-- 
2.45.2

From e7c96c9061addc2c41ce76973f040a24e07be5d9 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Sun, 20 Apr 2025 21:29:47 +0200
Subject: [PATCH 11/13] avcodec/webp: Avoid loop

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/webp.c | 25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index e26bf01c6a..7d77d64524 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -267,31 +267,24 @@ static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_length
         len_counts[len] = nb_codes;
         nb_codes += cnt;
     }
+
+    for (int sym = 0; sym < alphabet_size; ++sym) {
+        if (code_lengths[sym]) {
+            unsigned idx = len_counts[code_lengths[sym]]++;
+            syms[idx] = sym;
+            lens[idx] = code_lengths[sym];
+        }
+    }
     if (nb_codes <= 1) {
         if (nb_codes == 1) {
             /* special-case 1 symbol since the vlc reader cannot handle it */
             r->nb_symbols = 1;
             r->simple = 1;
-            for (int sym = 0;; ++sym) {
-                av_assert1(sym < alphabet_size);
-                if (code_lengths[sym]) {
-                    r->simple_symbols[0] = sym;
-                    return 0;
-                }
-            }
+            r->simple_symbols[0] = syms[0];
         }
         // No symbols
         return AVERROR_INVALIDDATA;
     }
-
-    for (int sym = 0; sym < alphabet_size; ++sym) {
-        if (code_lengths[sym]) {
-            unsigned idx = len_counts[code_lengths[sym]]++;
-            syms[idx] = sym;
-            lens[idx] = code_lengths[sym];
-        }
-    }
-
     ret = ff_vlc_init_from_lengths(&r->vlc, 8, nb_codes, lens, 1,
                                    syms, 2, 2, 0, VLC_INIT_OUTPUT_LE, logctx);
     if (ret < 0)
-- 
2.45.2

From 3ff308b055ba3b8a6a501e7b1bf56a9a3ddef1a9 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Mon, 21 Apr 2025 12:20:01 +0200
Subject: [PATCH 12/13] avcodec/magicyuv: Set properties via AVPixFmtDescriptor

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/magicyuv.c | 43 ++++++-------------------------------------
 1 file changed, 6 insertions(+), 37 deletions(-)

diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c
index b85505c428..4a5c0be9e0 100644
--- a/libavcodec/magicyuv.c
+++ b/libavcodec/magicyuv.c
@@ -462,37 +462,22 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
         return AVERROR_PATCHWELCOME;
     }
 
-    s->hshift[1] =
-    s->vshift[1] =
-    s->hshift[2] =
-    s->vshift[2] = 0;
-    s->decorrelate = 0;
-    s->bps = 8;
-
     format = bytestream2_get_byteu(&gb);
     switch (format) {
     case 0x65:
         avctx->pix_fmt = AV_PIX_FMT_GBRP;
-        s->decorrelate = 1;
         break;
     case 0x66:
         avctx->pix_fmt = AV_PIX_FMT_GBRAP;
-        s->decorrelate = 1;
         break;
     case 0x67:
         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
         break;
     case 0x68:
         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
-        s->hshift[1] =
-        s->hshift[2] = 1;
         break;
     case 0x69:
         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-        s->hshift[1] =
-        s->vshift[1] =
-        s->hshift[2] =
-        s->vshift[2] = 1;
         break;
     case 0x6a:
         avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
@@ -502,60 +487,44 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
         break;
     case 0x6c:
         avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
-        s->hshift[1] =
-        s->hshift[2] = 1;
-        s->bps = 10;
         break;
     case 0x76:
         avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
-        s->bps = 10;
         break;
     case 0x6d:
         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
-        s->decorrelate = 1;
-        s->bps = 10;
         break;
     case 0x6e:
         avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
-        s->decorrelate = 1;
-        s->bps = 10;
         break;
     case 0x6f:
         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
-        s->decorrelate = 1;
-        s->bps = 12;
         break;
     case 0x70:
         avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
-        s->decorrelate = 1;
-        s->bps = 12;
         break;
     case 0x71:
         avctx->pix_fmt = AV_PIX_FMT_GBRP14;
-        s->decorrelate = 1;
-        s->bps = 14;
         break;
     case 0x72:
         avctx->pix_fmt = AV_PIX_FMT_GBRAP14;
-        s->decorrelate = 1;
-        s->bps = 14;
         break;
     case 0x73:
         avctx->pix_fmt = AV_PIX_FMT_GRAY10;
-        s->bps = 10;
         break;
     case 0x7b:
         avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
-        s->hshift[1] =
-        s->vshift[1] =
-        s->hshift[2] =
-        s->vshift[2] = 1;
-        s->bps = 10;
         break;
     default:
         avpriv_request_sample(avctx, "Format 0x%X", format);
         return AVERROR_PATCHWELCOME;
     }
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+    av_assert1(desc);
+    s->decorrelate = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
+    s->hshift[1] = s->hshift[2] = desc->log2_chroma_w;
+    s->vshift[1] = s->vshift[2] = desc->log2_chroma_h;
+    s->bps = desc->comp[0].depth;
     s->max = 1 << s->bps;
     s->magy_decode_slice = s->bps == 8 ? magy_decode_slice : magy_decode_slice10;
     s->planes = av_pix_fmt_count_planes(avctx->pix_fmt);
-- 
2.45.2

From 3071d662a403760b4d0ff210d76415f5c23647a6 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
Date: Mon, 21 Apr 2025 12:35:42 +0200
Subject: [PATCH 13/13] avcodec/magicyuv: Simplify check for RGB

Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com>
---
 libavcodec/magicyuv.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c
index 4a5c0be9e0..e106228757 100644
--- a/libavcodec/magicyuv.c
+++ b/libavcodec/magicyuv.c
@@ -521,7 +521,7 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
     }
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
     av_assert1(desc);
-    s->decorrelate = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
+    int is_rgb = s->decorrelate = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);
     s->hshift[1] = s->hshift[2] = desc->log2_chroma_w;
     s->vshift[1] = s->vshift[2] = desc->log2_chroma_h;
     s->bps = desc->comp[0].depth;
@@ -628,14 +628,7 @@ static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p,
     s->p = p;
     avctx->execute2(avctx, s->magy_decode_slice, NULL, NULL, s->nb_slices);
 
-    if (avctx->pix_fmt == AV_PIX_FMT_GBRP   ||
-        avctx->pix_fmt == AV_PIX_FMT_GBRAP  ||
-        avctx->pix_fmt == AV_PIX_FMT_GBRP10 ||
-        avctx->pix_fmt == AV_PIX_FMT_GBRAP10||
-        avctx->pix_fmt == AV_PIX_FMT_GBRAP12||
-        avctx->pix_fmt == AV_PIX_FMT_GBRAP14||
-        avctx->pix_fmt == AV_PIX_FMT_GBRP12||
-        avctx->pix_fmt == AV_PIX_FMT_GBRP14) {
+    if (is_rgb) {
         FFSWAP(uint8_t*, p->data[0], p->data[1]);
         FFSWAP(int, p->linesize[0], p->linesize[1]);
     } else {
-- 
2.45.2

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to