PR #24047 opened by AYOUB NABIL BOUBAGRAT (ayoubnabil) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24047 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24047.patch
i'm starting work on block switching for the AC-3 encoder as part of #23317. this first commit adds short MDCT support for both the float and fixed-point encoders. i'll add the remaining block switching support in follow-up commits. this only targets AC-3 for now. >From 79ba410f0e7b9363e60a3fb47eeb5a5d824cb6bd Mon Sep 17 00:00:00 2001 From: Ayoub Nabil Boubagrat <[email protected]> Date: Fri, 7 Aug 2026 23:00:00 +0200 Subject: [PATCH] avcodec/ac3enc: add short transform support Signed-off-by: Ayoub Nabil Boubagrat <[email protected]> --- libavcodec/ac3enc.c | 1 + libavcodec/ac3enc.h | 3 ++ libavcodec/ac3enc_fixed.c | 10 ++++-- libavcodec/ac3enc_float.c | 16 ++++++++-- libavcodec/ac3enc_template.c | 60 ++++++++++++++++++++++++++++++++++-- 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 0482d9ee58..9dcb173784 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -2184,6 +2184,7 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx) ff_af_queue_close(&s->afq); av_tx_uninit(&s->tx); + av_tx_uninit(&s->tx_short); return 0; } diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index 3e92af17f0..20d199b800 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -137,6 +137,7 @@ typedef struct AC3Block { uint16_t *qmant[AC3_MAX_CHANNELS]; ///< quantized mantissas uint8_t *cpl_coord_exp[AC3_MAX_CHANNELS]; ///< coupling coord exponents (cplcoexp) uint8_t *cpl_coord_mant[AC3_MAX_CHANNELS]; ///< coupling coord mantissas (cplcomant) + uint8_t block_switch[AC3_MAX_CHANNELS]; ///< block switch flags (blksw) uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block int num_rematrixing_bands; ///< number of rematrixing bands uint8_t rematrixing_flags[4]; ///< rematrixing flags @@ -170,6 +171,8 @@ typedef struct AC3EncodeContext { AC3DSPContext ac3dsp; ///< AC-3 optimized functions AVTXContext *tx; ///< FFT context for MDCT calculation av_tx_fn tx_fn; + AVTXContext *tx_short; ///< FFT context for short MDCT calculation + av_tx_fn tx_fn_short; AC3Block blocks[AC3_MAX_BLOCKS]; ///< per-block info diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index 876bb6bbc6..c2880f2c43 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -79,6 +79,7 @@ static av_cold int ac3_fixed_mdct_init(AVCodecContext *avctx, AC3EncodeContext * const float scale = -1.0f; int32_t *iwin = s->mdct_window_fixed; + int ret; ff_kbd_window_init(fwin, 5.0, AC3_BLOCK_SIZE); for (int i = 0; i < AC3_BLOCK_SIZE; i++) @@ -88,8 +89,13 @@ static av_cold int ac3_fixed_mdct_init(AVCodecContext *avctx, AC3EncodeContext * if (!s->fdsp) return AVERROR(ENOMEM); - return av_tx_init(&s->tx, &s->tx_fn, AV_TX_INT32_MDCT, 0, - AC3_BLOCK_SIZE, &scale, 0); + ret = av_tx_init(&s->tx, &s->tx_fn, AV_TX_INT32_MDCT, 0, + AC3_BLOCK_SIZE, &scale, 0); + if (ret < 0) + return ret; + + return av_tx_init(&s->tx_short, &s->tx_fn_short, AV_TX_INT32_MDCT, 0, + AC3_BLOCK_SIZE / 2, &scale, 0); } diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index 974c38ac25..990bfed878 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -85,12 +85,22 @@ static void sum_square_butterfly(AC3EncodeContext *s, float sum[4], */ static av_cold int ac3_float_mdct_init(AC3EncodeContext *s) { - const float scale = -2.0 / AC3_WINDOW_SIZE; + const float scale = -2.0 / AC3_WINDOW_SIZE; + /* A/52 uses -2/N with N=256 for each short transform. */ + const float short_scale = -4.0 / AC3_WINDOW_SIZE; + int ret; ff_kbd_window_init(s->mdct_window_float, 5.0, AC3_BLOCK_SIZE); - return av_tx_init(&s->tx, &s->tx_fn, AV_TX_FLOAT_MDCT, 0, - AC3_BLOCK_SIZE, &scale, 0); + ret = av_tx_init(&s->tx, &s->tx_fn, AV_TX_FLOAT_MDCT, 0, + AC3_BLOCK_SIZE, &scale, 0); + if (ret < 0) + return ret; + if (s->eac3) + return 0; + + return av_tx_init(&s->tx_short, &s->tx_fn_short, AV_TX_FLOAT_MDCT, 0, + AC3_BLOCK_SIZE / 2, &short_scale, 0); } diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c index 5331b45cb9..d7a0fc1055 100644 --- a/libavcodec/ac3enc_template.c +++ b/libavcodec/ac3enc_template.c @@ -44,6 +44,59 @@ #define RENAME(element) element ## _fixed #endif +/* + * Apply the two short MDCTs and interleave their coefficients. + */ +static void apply_short_mdct(AC3EncodeContext *s, CoefType *coef, + const SampleType *samples) +{ + const int quarter = AC3_BLOCK_SIZE / 4; + const int half = AC3_BLOCK_SIZE / 2; + const int three_quarters = 3 * AC3_BLOCK_SIZE / 4; + LOCAL_ALIGNED_32(SampleType, input, [AC3_BLOCK_SIZE]); + LOCAL_ALIGNED_32(CoefType, output, [AC3_MAX_COEFS]); + + /* AVTX implements the alpha=0 MDCT. The alpha=-1 transform in A/52 + * Section 8.2.3.2 is equivalent to [x[N/4..N-1], -x[0..N/4-1]], + * while the alpha=+1 transform starts at the last quarter of the + * 2N-sample window. */ +#if AC3ENC_FLOAT + memcpy(input, samples + quarter, three_quarters * sizeof(*input)); + for (int i = 0; i < quarter; i++) + input[three_quarters + i] = -samples[i]; +#else + /* The fixed MDCT scale cannot exceed one, so apply its factor of two to + * the input. FixedDSP scales the product of S32 input and the Q22 window + * by 2^-31, limiting the windowed samples to 2^22. Doubling them here + * therefore remains within 2^23. */ + for (int i = 0; i < three_quarters; i++) + input[i] = 2 * samples[quarter + i]; + for (int i = 0; i < quarter; i++) + input[three_quarters + i] = -2 * samples[i]; +#endif + + s->tx_fn_short(s->tx_short, output, input, sizeof(*input)); + +#if AC3ENC_FLOAT + for (int i = 0; i < quarter; i++) + input[i] = -samples[AC3_WINDOW_SIZE - quarter + i]; + memcpy(input + quarter, samples + AC3_BLOCK_SIZE, + three_quarters * sizeof(*input)); +#else + for (int i = 0; i < quarter; i++) + input[i] = -2 * samples[AC3_WINDOW_SIZE - quarter + i]; + for (int i = 0; i < three_quarters; i++) + input[quarter + i] = 2 * samples[AC3_BLOCK_SIZE + i]; +#endif + + s->tx_fn_short(s->tx_short, output + half, input, sizeof(*input)); + + for (int i = 0; i < half; i++) { + coef[2 * i ] = output[i]; + coef[2 * i + 1] = output[half + i]; + } +} + /* * Apply the MDCT to input samples to generate frequency coefficients. * This applies the KBD window and normalizes the input to reduce precision @@ -69,8 +122,11 @@ static void apply_mdct(AC3EncodeContext *s, uint8_t * const *samples) input_samples1, s->RENAME(mdct_window), AC3_BLOCK_SIZE); - s->tx_fn(s->tx, block->mdct_coef[ch+1], - windowed_samples, sizeof(*windowed_samples)); + if (block->block_switch[ch + 1]) + apply_short_mdct(s, block->mdct_coef[ch + 1], windowed_samples); + else + s->tx_fn(s->tx, block->mdct_coef[ch + 1], + windowed_samples, sizeof(*windowed_samples)); input_samples0 = input_samples1; input_samples1 += AC3_BLOCK_SIZE; } while (++blk < s->num_blocks); -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
