PR #24412 opened by Kyle Swanson (kylophone) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24412 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24412.patch
Speedup is around 34% on an AMD EPYC 9R14, single threaded 4K 422 HQ. Signed-off-by: Kyle Swanson <[email protected]> # Summary of changes `decode_dc_coeffs()`/`decode_ac_coeffs()` had been loading 32 bits from the bitstream for every codeword via UPDATE_CACHE_32. Since the mean codeword seems to be something like ~4 bits, using CACHED_BITSTREAM_READER means 64 bits are cached and refilled 32 bits at a time, so a dozen codewords come out of one refill instead of one. I wrote this whole thing from scratch before I realized CACHED_BITSTREAM_READER was a thing, and results were similar. Speedup is around 34% on an AMD EPYC 9R14, single threaded 4K 422 HQ. If you are interested, please test. >From ea302379b992250326a1847db2147df4c878cbf1 Mon Sep 17 00:00:00 2001 From: Kyle Swanson <[email protected]> Date: Mon, 31 Aug 2026 18:00:37 +0000 Subject: [PATCH] avcodec/proresdec: use the cached bitstream reader for coefficient parsing Speedup is around 34% on an AMD EPYC 9R14, single threaded 4K 422 HQ. Signed-off-by: Kyle Swanson <[email protected]> --- libavcodec/proresdec.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c index b971d17972..cfcc866885 100644 --- a/libavcodec/proresdec.c +++ b/libavcodec/proresdec.c @@ -35,6 +35,7 @@ #include "avcodec.h" #include "codec_internal.h" #include "decode.h" +#define CACHED_BITSTREAM_READER 1 #include "get_bits.h" #include "hwaccel_internal.h" #include "hwconfig.h" @@ -420,13 +421,12 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons return pic_data_size; } -#define DECODE_CODEWORD(val, codebook, SKIP) \ +#define DECODE_CODEWORD(val, codebook, gb) \ do { \ unsigned int rice_order, exp_order, switch_bits; \ unsigned int q, buf, bits; \ \ - UPDATE_CACHE_32(re, gb); /* We really need 32 bits */ \ - buf = GET_CACHE(re, gb); \ + buf = show_bits(gb, 32); /* We really need 32 bits */ \ \ /* number of bits to switch between rice and exp golomb */ \ switch_bits = codebook & 3; \ @@ -439,16 +439,17 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons bits = exp_order - switch_bits + (q<<1); \ if (bits > 31) \ return AVERROR_INVALIDDATA; \ - val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) + \ + val = (buf >> (32 - bits)) - (1 << exp_order) + \ ((switch_bits + 1) << rice_order); \ - SKIP(re, gb, bits); \ + skip_bits(gb, bits); \ } else if (rice_order) { \ - SKIP_BITS(re, gb, q+1); \ - val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order); \ - SKIP(re, gb, rice_order); \ + bits = q + 1 + rice_order; \ + val = (q << rice_order) + \ + ((buf >> (32 - bits)) & ((1u << rice_order) - 1)); \ + skip_bits(gb, bits); \ } else { \ val = q; \ - SKIP(re, gb, q+1); \ + skip_bits(gb, q + 1); \ } \ } while (0) @@ -464,9 +465,7 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, int16_t prev_dc; int code, i, sign; - OPEN_READER(re, gb); - - DECODE_CODEWORD(code, FIRST_DC_CB, LAST_SKIP_BITS); + DECODE_CODEWORD(code, FIRST_DC_CB, gb); prev_dc = TOSIGNED(code); out[0] = prev_dc; @@ -475,13 +474,12 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, code = 5; sign = 0; for (i = 1; i < blocks_per_slice; i++, out += 64) { - DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)], LAST_SKIP_BITS); + DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)], gb); if(code) sign ^= -(code & 1); else sign = 0; prev_dc += (((code + 1) >> 1) ^ sign) - sign; out[0] = prev_dc; } - CLOSE_READER(re, gb); return 0; } @@ -495,11 +493,9 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex const ProresContext *ctx = avctx->priv_data; int block_mask, sign; unsigned pos, run, level; - int max_coeffs, i, bits_left; + int max_coeffs, i, left_bits; int log2_block_count = av_log2(blocks_per_slice); - OPEN_READER(re, gb); - UPDATE_CACHE_32(re, gb); run = 4; level = 2; @@ -507,28 +503,26 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex block_mask = blocks_per_slice - 1; for (pos = block_mask;;) { - bits_left = gb->size_in_bits - re_index; - if (bits_left <= 0 || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left))) + left_bits = get_bits_left(gb); + if (left_bits <= 0 || (left_bits < 32 && !show_bits(gb, left_bits))) break; - DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)], LAST_SKIP_BITS); + DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)], gb); pos += run + 1; if (pos >= max_coeffs) { av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs); return AVERROR_INVALIDDATA; } - DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)], SKIP_BITS); + DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)], gb); level += 1; i = pos >> log2_block_count; - sign = SHOW_SBITS(re, gb, 1); - SKIP_BITS(re, gb, 1); + sign = -(int)get_bits1(gb); out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign); } - CLOSE_READER(re, gb); return 0; } -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
