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".