PR #22616 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22616 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22616.patch
>From a0dd5e1a08c730acd4429a02c3d9135cad87126a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 23 Mar 2026 11:47:32 +0100 Subject: [PATCH 01/12] avcodec/sbcdec: Remove AVClass* from context This decoder has no private class. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbcdec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/sbcdec.c b/libavcodec/sbcdec.c index d999cefd22..e7ddef7699 100644 --- a/libavcodec/sbcdec.c +++ b/libavcodec/sbcdec.c @@ -45,7 +45,6 @@ struct sbc_decoder_state { }; typedef struct SBCDecContext { - AVClass *class; DECLARE_ALIGNED(SBC_ALIGN, struct sbc_frame, frame); DECLARE_ALIGNED(SBC_ALIGN, struct sbc_decoder_state, dsp); } SBCDecContext; -- 2.52.0 >From b0d5574195bacc81acfc460670cfadf80a462ce3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 23 Mar 2026 12:01:41 +0100 Subject: [PATCH 02/12] avcodec/sbc: Use union to save space One buffer is encoder-only, the other decoder-only. Also move crc_ctx before the buffers (into padding). Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbc.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavcodec/sbc.h b/libavcodec/sbc.h index 0a54f1fbbc..e0105f7338 100644 --- a/libavcodec/sbc.h +++ b/libavcodec/sbc.h @@ -102,16 +102,18 @@ struct sbc_frame { /* bit number x set means joint stereo has been used in subband x */ uint8_t joint; + const AVCRC *crc_ctx; + /* only the lower 4 bits of every element are to be used */ DECLARE_ALIGNED(SBC_ALIGN, uint32_t, scale_factor)[2][8]; - /* raw integer subband samples in the frame */ - DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample_f)[16][2][8]; + union { + /* raw integer subband samples in the frame - encoder only */ + DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample_f)[16][2][8]; - /* modified subband samples */ - DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample)[16][2][8]; - - const AVCRC *crc_ctx; + /* modified subband samples - decoder only */ + DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample)[16][2][8]; + }; }; uint8_t ff_sbc_crc8(const AVCRC *crc_ctx, const uint8_t *data, size_t len); -- 2.52.0 >From c7b016b365ab8dbadca824a10b33d5352b91834e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 23 Mar 2026 20:52:31 +0100 Subject: [PATCH 03/12] avcodec/x86/sbcdsp: Fix calculating four-subbands stereo scalefactors sbc_calc_scalefactors uses an int32_t [16/*max blocks*/][2/*max channels*/][8/*max subbands*/] array. The MMX version of this code treats the two inner arrays as one [2*8] array to process and it processes subbands*channels of them. But when subbands is < 8 and channels is two, the entries to process are not contiguous: One has to process 0..subbands-1 and 8..7+subbands, yet the code processed 0..2*subbands-1. This commit fixes this by processing entries 0..7+subbands if there are two channels. Before this commit, the following command line triggered an av_assert2() in put_bits(): ffmpeg_g -i tests/data/asynth-44100-2.wav -c sbc -b:a 200k \ -sbc_delay 0.003 -f null - Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/sbcdsp.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/x86/sbcdsp.asm b/libavcodec/x86/sbcdsp.asm index d68d3a9ae8..d46141b40c 100644 --- a/libavcodec/x86/sbcdsp.asm +++ b/libavcodec/x86/sbcdsp.asm @@ -126,7 +126,7 @@ cglobal sbc_calc_scalefactors, 5, 7, 4, sb_sample_f, scale_factor, blocks, chann shl subbandsd, 2 cmp channelsd, 2 jl .loop_1 - shl subbandsd, 1 + add subbandsd, 32 .loop_1: sub subbandsq, 8 -- 2.52.0 >From e963d620565e6d72f99f91e3f99185dd75b07c5a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 23 Mar 2026 14:36:55 +0100 Subject: [PATCH 04/12] tests/fate: Add SBC tests Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/Makefile | 1 + tests/fate/sbc.mak | 38 +++++++++++++++++++ tests/ref/fate/sbc-16000-1 | 4 ++ tests/ref/fate/sbc-44100-1 | 4 ++ tests/ref/fate/sbc-44100-2-joint-stereo | 4 ++ .../sbc-44100-2-joint-stereo-four-subbands | 4 ++ tests/ref/fate/sbc-44100-2-stereo | 4 ++ tests/ref/fate/sbc-44100-2-stereo-low-delay | 4 ++ tests/ref/fate/sbc-48000-1 | 4 ++ 9 files changed, 67 insertions(+) create mode 100644 tests/fate/sbc.mak create mode 100644 tests/ref/fate/sbc-16000-1 create mode 100644 tests/ref/fate/sbc-44100-1 create mode 100644 tests/ref/fate/sbc-44100-2-joint-stereo create mode 100644 tests/ref/fate/sbc-44100-2-joint-stereo-four-subbands create mode 100644 tests/ref/fate/sbc-44100-2-stereo create mode 100644 tests/ref/fate/sbc-44100-2-stereo-low-delay create mode 100644 tests/ref/fate/sbc-48000-1 diff --git a/tests/Makefile b/tests/Makefile index 4b3fa6a54a..3e119979d1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -240,6 +240,7 @@ include $(SRC_PATH)/tests/fate/qoa.mak include $(SRC_PATH)/tests/fate/qt.mak include $(SRC_PATH)/tests/fate/qtrle.mak include $(SRC_PATH)/tests/fate/real.mak +include $(SRC_PATH)/tests/fate/sbc.mak include $(SRC_PATH)/tests/fate/screen.mak include $(SRC_PATH)/tests/fate/segafilm.mak include $(SRC_PATH)/tests/fate/segment.mak diff --git a/tests/fate/sbc.mak b/tests/fate/sbc.mak new file mode 100644 index 0000000000..43d52140eb --- /dev/null +++ b/tests/fate/sbc.mak @@ -0,0 +1,38 @@ +FATE_SBC_TRANSCODE-$(call ENCDEC2, SBC, PCM_S16LE, SBC, SBC_PARSER ARESAMPLE_FILTER WAV_DEMUXER WAV_MUXER) += \ + $(addprefix fate-sbc-, 16000-1 44100-1 48000-1 44100-2-joint-stereo 44100-2-stereo-low-delay 44100-2-stereo 44100-2-joint-stereo-four-subbands) +fate-sbc-16000-1: tests/data/asynth-16000-1.wav +fate-sbc-16000-1: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-16000-1.wav \ + sbc "-c sbc -profile msbc" wav +fate-sbc-16000-1: CMP_SHIFT=-146 # 73 samples + +fate-sbc-48000-1: tests/data/asynth-48000-1.wav +fate-sbc-48000-1: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-48000-1.wav \ + sbc "-c sbc -sbc_delay 0.001 -b:a 500k" wav +fate-sbc-48000-1: CMP_SHIFT=-74 # 37 samples + +fate-sbc-44100-1: tests/data/asynth-44100-1.wav +fate-sbc-44100-1: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-44100-1.wav \ + sbc "-c sbc -b:a 250k" wav +fate-sbc-44100-1: CMP_SHIFT=-146 # 73 samples + +$(filter fate-sbc-44100-2%,$(FATE_SBC_TRANSCODE-yes)): tests/data/asynth-44100-2.wav +fate-sbc-44100-2-joint-stereo: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-44100-2.wav \ + sbc "-c sbc -b:a 50k" wav +fate-sbc-44100-2-joint-stereo: CMP_SHIFT=-292 # 73 samples + +fate-sbc-44100-2-joint-stereo-four-subbands: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-44100-2.wav \ + sbc "-c sbc -b:a 450k" wav +fate-sbc-44100-2-joint-stereo-four-subbands: CMP_SHIFT=-148 # 37 samples + +fate-sbc-44100-2-stereo-low-delay: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-44100-2.wav \ + sbc "-c sbc -b:a 200k -sbc_delay 0.003" wav +fate-sbc-44100-2-stereo-low-delay: CMP_SHIFT=-148 # 37 samples + +fate-sbc-44100-2-stereo: CMD = enc_dec wav $(TARGET_PATH)/tests/data/asynth-44100-2.wav \ + sbc "-c sbc -b:a 200k" wav +fate-sbc-44100-2-stereo: CMP_SHIFT=-292 # 73 samples + +FATE_SBC += $(FATE_SBC_TRANSCODE-yes) + +FATE_FFMPEG += $(FATE_SBC) +fate-sbc: $(FATE_SBC) diff --git a/tests/ref/fate/sbc-16000-1 b/tests/ref/fate/sbc-16000-1 new file mode 100644 index 0000000000..18d38c121a --- /dev/null +++ b/tests/ref/fate/sbc-16000-1 @@ -0,0 +1,4 @@ +831fd5ac5a06b75c7c28f7df8ae01843 *tests/data/fate/sbc-16000-1.sbc +96000 tests/data/fate/sbc-16000-1.sbc +572c6755da143f4e20ddf2036956fc7e *tests/data/fate/sbc-16000-1.out.wav +stddev: 60.09 PSNR: 60.75 MAXDIFF: 732 bytes: 192000/ 191854 diff --git a/tests/ref/fate/sbc-44100-1 b/tests/ref/fate/sbc-44100-1 new file mode 100644 index 0000000000..1f3baefa01 --- /dev/null +++ b/tests/ref/fate/sbc-44100-1 @@ -0,0 +1,4 @@ +c29a6bf35c30734bbbd21082a6eb6a3e *tests/data/fate/sbc-44100-1.sbc +186030 tests/data/fate/sbc-44100-1.sbc +d3bcdaa019b88acd49f6bc93c9acdbfd *tests/data/fate/sbc-44100-1.out.wav +stddev: 451.02 PSNR: 43.25 MAXDIFF: 5671 bytes: 529200/ 529006 diff --git a/tests/ref/fate/sbc-44100-2-joint-stereo b/tests/ref/fate/sbc-44100-2-joint-stereo new file mode 100644 index 0000000000..cb1add83f8 --- /dev/null +++ b/tests/ref/fate/sbc-44100-2-joint-stereo @@ -0,0 +1,4 @@ +a2b56cb77f3e750e64d04181e9efe5a4 *tests/data/fate/sbc-44100-2-joint-stereo.sbc +39273 tests/data/fate/sbc-44100-2-joint-stereo.sbc +2765842ff3325b58847bc7a6a709ff41 *tests/data/fate/sbc-44100-2-joint-stereo.out.wav +stddev: 5984.93 PSNR: 20.79 MAXDIFF:52173 bytes: 1058400/ 1058012 diff --git a/tests/ref/fate/sbc-44100-2-joint-stereo-four-subbands b/tests/ref/fate/sbc-44100-2-joint-stereo-four-subbands new file mode 100644 index 0000000000..21384a0c00 --- /dev/null +++ b/tests/ref/fate/sbc-44100-2-joint-stereo-four-subbands @@ -0,0 +1,4 @@ +908244c0a8d086e5f32b3d77ce58e4a4 *tests/data/fate/sbc-44100-2-joint-stereo-four-subbands.sbc +343122 tests/data/fate/sbc-44100-2-joint-stereo-four-subbands.sbc +9db2f8e52608851867d0e0cf77b1dff2 *tests/data/fate/sbc-44100-2-joint-stereo-four-subbands.out.wav +stddev: 76.69 PSNR: 58.63 MAXDIFF: 1609 bytes: 1058400/ 1058156 diff --git a/tests/ref/fate/sbc-44100-2-stereo b/tests/ref/fate/sbc-44100-2-stereo new file mode 100644 index 0000000000..805bdc9603 --- /dev/null +++ b/tests/ref/fate/sbc-44100-2-stereo @@ -0,0 +1,4 @@ +78ff642215025d3639f499664e2233b1 *tests/data/fate/sbc-44100-2-stereo.sbc +148824 tests/data/fate/sbc-44100-2-stereo.sbc +ad2855b10cd2b9f4a4c5dde459e7bb74 *tests/data/fate/sbc-44100-2-stereo.out.wav +stddev: 3515.64 PSNR: 25.41 MAXDIFF:49771 bytes: 1058400/ 1058012 diff --git a/tests/ref/fate/sbc-44100-2-stereo-low-delay b/tests/ref/fate/sbc-44100-2-stereo-low-delay new file mode 100644 index 0000000000..748bad98b8 --- /dev/null +++ b/tests/ref/fate/sbc-44100-2-stereo-low-delay @@ -0,0 +1,4 @@ +b2517da4b139e19f92c9a5791f0192e6 *tests/data/fate/sbc-44100-2-stereo-low-delay.sbc +148824 tests/data/fate/sbc-44100-2-stereo-low-delay.sbc +69348f4124256eb1bc47581aab5fa23c *tests/data/fate/sbc-44100-2-stereo-low-delay.out.wav +stddev: 3767.42 PSNR: 24.81 MAXDIFF:49898 bytes: 1058400/ 1058156 diff --git a/tests/ref/fate/sbc-48000-1 b/tests/ref/fate/sbc-48000-1 new file mode 100644 index 0000000000..ed2d7abb15 --- /dev/null +++ b/tests/ref/fate/sbc-48000-1 @@ -0,0 +1,4 @@ +fdfb37d00c4630f858b40524c2da7919 *tests/data/fate/sbc-48000-1.sbc +378000 tests/data/fate/sbc-48000-1.sbc +b729801f40be56c3c1b6d6130554079b *tests/data/fate/sbc-48000-1.out.wav +stddev: 48.83 PSNR: 62.56 MAXDIFF: 764 bytes: 576000/ 575926 -- 2.52.0 >From 209772a0860fb4e59cb39496a81090d50c354ae2 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 23 Mar 2026 19:14:34 +0100 Subject: [PATCH 05/12] avcodec/sbcdsp: Constify Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/arm/sbcdsp_init_arm.c | 2 +- libavcodec/sbcdsp.c | 16 ++++++++-------- libavcodec/sbcdsp.h | 6 +++--- libavcodec/x86/sbcdsp.asm | 2 +- libavcodec/x86/sbcdsp_init.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libavcodec/arm/sbcdsp_init_arm.c b/libavcodec/arm/sbcdsp_init_arm.c index b3a2c3d083..9463c75c2c 100644 --- a/libavcodec/arm/sbcdsp_init_arm.c +++ b/libavcodec/arm/sbcdsp_init_arm.c @@ -40,7 +40,7 @@ void ff_sbc_analyze_8_armv6(const int16_t *in, int32_t *out, const int16_t *cons void ff_sbc_analyze_4_neon(const int16_t *in, int32_t *out, const int16_t *consts); void ff_sbc_analyze_8_neon(const int16_t *in, int32_t *out, const int16_t *consts); -void ff_sbc_calc_scalefactors_neon(int32_t sb_sample_f[16][2][8], +void ff_sbc_calc_scalefactors_neon(const int32_t sb_sample_f[16][2][8], uint32_t scale_factor[2][8], int blocks, int channels, int subbands); int ff_sbc_calc_scalefactors_j_neon(int32_t sb_sample_f[16][2][8], diff --git a/libavcodec/sbcdsp.c b/libavcodec/sbcdsp.c index 5674bdc4a7..7c298c1d15 100644 --- a/libavcodec/sbcdsp.c +++ b/libavcodec/sbcdsp.c @@ -103,8 +103,8 @@ static void sbc_analyze_8_simd(const int16_t *in, int32_t *out, sbc_analyze_simd(in, out, consts, 8); } -static inline void sbc_analyze_4b_4s_simd(SBCDSPContext *s, - int16_t *x, int32_t *out, int out_stride) +static inline void sbc_analyze_4b_4s_simd(SBCDSPContext *s, const int16_t *x, + int32_t *out, int out_stride) { /* Analyze blocks */ s->sbc_analyze_4(x + 12, out, sbcdsp_analysis_consts_fixed4_simd_odd); @@ -116,8 +116,8 @@ static inline void sbc_analyze_4b_4s_simd(SBCDSPContext *s, s->sbc_analyze_4(x + 0, out, sbcdsp_analysis_consts_fixed4_simd_even); } -static inline void sbc_analyze_4b_8s_simd(SBCDSPContext *s, - int16_t *x, int32_t *out, int out_stride) +static inline void sbc_analyze_4b_8s_simd(SBCDSPContext *s, const int16_t *x, + int32_t *out, int out_stride) { /* Analyze blocks */ s->sbc_analyze_8(x + 24, out, sbcdsp_analysis_consts_fixed8_simd_odd); @@ -130,11 +130,11 @@ static inline void sbc_analyze_4b_8s_simd(SBCDSPContext *s, } static inline void sbc_analyze_1b_8s_simd_even(SBCDSPContext *s, - int16_t *x, int32_t *out, + const int16_t *x, int32_t *out, int out_stride); static inline void sbc_analyze_1b_8s_simd_odd(SBCDSPContext *s, - int16_t *x, int32_t *out, + const int16_t *x, int32_t *out, int out_stride) { s->sbc_analyze_8(x, out, sbcdsp_analysis_consts_fixed8_simd_odd); @@ -142,7 +142,7 @@ static inline void sbc_analyze_1b_8s_simd_odd(SBCDSPContext *s, } static inline void sbc_analyze_1b_8s_simd_even(SBCDSPContext *s, - int16_t *x, int32_t *out, + const int16_t *x, int32_t *out, int out_stride) { s->sbc_analyze_8(x, out, sbcdsp_analysis_consts_fixed8_simd_even); @@ -267,7 +267,7 @@ static int sbc_enc_process_input_8s(int position, const uint8_t *pcm, return position; } -static void sbc_calc_scalefactors(int32_t sb_sample_f[16][2][8], +static void sbc_calc_scalefactors(const int32_t sb_sample_f[16][2][8], uint32_t scale_factor[2][8], int blocks, int channels, int subbands) { diff --git a/libavcodec/sbcdsp.h b/libavcodec/sbcdsp.h index 20266bf25e..828ff852d1 100644 --- a/libavcodec/sbcdsp.h +++ b/libavcodec/sbcdsp.h @@ -53,11 +53,11 @@ struct sbc_dsp_context { /* Polyphase analysis filter for 4 subbands configuration, * it handles "increment" blocks at once */ void (*sbc_analyze_4s)(SBCDSPContext *s, - int16_t *x, int32_t *out, int out_stride); + const int16_t *x, int32_t *out, int out_stride); /* Polyphase analysis filter for 8 subbands configuration, * it handles "increment" blocks at once */ void (*sbc_analyze_8s)(SBCDSPContext *s, - int16_t *x, int32_t *out, int out_stride); + const int16_t *x, int32_t *out, int out_stride); /* Process input data (deinterleave, endian conversion, reordering), * depending on the number of subbands and input data byte order */ int (*sbc_enc_process_input_4s)(int position, const uint8_t *pcm, @@ -67,7 +67,7 @@ struct sbc_dsp_context { int16_t X[2][SBC_X_BUFFER_SIZE], int nsamples, int nchannels); /* Scale factors calculation */ - void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8], + void (*sbc_calc_scalefactors)(const int32_t sb_sample_f[16][2][8], uint32_t scale_factor[2][8], int blocks, int channels, int subbands); /* Scale factors calculation with joint stereo support */ diff --git a/libavcodec/x86/sbcdsp.asm b/libavcodec/x86/sbcdsp.asm index d46141b40c..ddc1237d8f 100644 --- a/libavcodec/x86/sbcdsp.asm +++ b/libavcodec/x86/sbcdsp.asm @@ -115,7 +115,7 @@ cglobal sbc_analyze_8, 3, 3, 4, in, out, consts ;******************************************************************* -;void ff_sbc_calc_scalefactors(int32_t sb_sample_f[16][2][8], +;void ff_sbc_calc_scalefactors(const int32_t sb_sample_f[16][2][8], ; uint32_t scale_factor[2][8], ; int blocks, int channels, int subbands) ;******************************************************************* diff --git a/libavcodec/x86/sbcdsp_init.c b/libavcodec/x86/sbcdsp_init.c index 7416a86ac6..d959f76f8c 100644 --- a/libavcodec/x86/sbcdsp_init.c +++ b/libavcodec/x86/sbcdsp_init.c @@ -36,7 +36,7 @@ void ff_sbc_analyze_4_mmx(const int16_t *in, int32_t *out, const int16_t *consts); void ff_sbc_analyze_8_mmx(const int16_t *in, int32_t *out, const int16_t *consts); -void ff_sbc_calc_scalefactors_mmx(int32_t sb_sample_f[16][2][8], +void ff_sbc_calc_scalefactors_mmx(const int32_t sb_sample_f[16][2][8], uint32_t scale_factor[2][8], int blocks, int channels, int subbands); -- 2.52.0 >From 7d969b3aab5a39a9184dc31103019948963242a8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 11:29:37 +0100 Subject: [PATCH 06/12] avcodec/sbcenc: Don't output uninitialized data Check in init whether the parameters are valid. This can be triggered with ffmpeg -i tests/data/asynth-44100-2.wav -c sbc -sbc_delay 0.001 \ -b:a 100k -f null - Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbcenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index fb810c4c52..8534dc83ce 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -128,10 +128,6 @@ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, avpkt->data[1] |= ((frame->subbands == 8) & 0x01) << 0; avpkt->data[2] = frame->bitpool; - - if (frame->bitpool > frame->subbands << (4 + (frame->mode == STEREO - || frame->mode == JOINT_STEREO))) - return -5; } /* Can't fill in crc yet */ @@ -259,6 +255,12 @@ static av_cold int sbc_encode_init(AVCodecContext *avctx) if (avctx->global_quality > 0) frame->bitpool = avctx->global_quality / FF_QP2LAMBDA; + if (frame->bitpool > frame->subbands << (4 + (frame->mode == STEREO + || frame->mode == JOINT_STEREO))) { + av_log(avctx, AV_LOG_ERROR, "Invalid parameter combination\n"); + return AVERROR_PATCHWELCOME; + } + avctx->frame_size = 4*((frame->subbands >> 3) + 1) * 4*(frame->blocks >> 2); } -- 2.52.0 >From cf0677337f2f8a21b8ba4b1b93e77d8f05cbccea Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 11:33:50 +0100 Subject: [PATCH 07/12] avcodec/sbcenc: Use correct size for PutBitContext Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbcenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index 8534dc83ce..6c59a8902c 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -135,7 +135,7 @@ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, crc_header[1] = avpkt->data[2]; crc_pos = 16; - init_put_bits(&pb, avpkt->data + 4, avpkt->size); + init_put_bits(&pb, avpkt->data + 4, avpkt->size - 4); if (frame->mode == JOINT_STEREO) { put_bits(&pb, frame->subbands, joint); -- 2.52.0 >From bb904fa672525d266b0f30b8e684dc0f43c98795 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 13:17:39 +0100 Subject: [PATCH 08/12] avcodec/sbcenc: Remove redundant memset() A codec's private context is zero-allocated. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbcenc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index 6c59a8902c..bc2f844789 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -272,7 +272,6 @@ static av_cold int sbc_encode_init(AVCodecContext *avctx) frame->codesize = frame->subbands * frame->blocks * avctx->ch_layout.nb_channels * 2; frame->crc_ctx = av_crc_get_table(AV_CRC_8_EBU); - memset(&sbc->dsp.X, 0, sizeof(sbc->dsp.X)); sbc->dsp.position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7; sbc->dsp.increment = sbc->msbc ? 1 : 4; ff_sbcdsp_init(&sbc->dsp); -- 2.52.0 >From 22f272f554771e210242258bf5a05deae234fa2d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 13:54:58 +0100 Subject: [PATCH 09/12] tests/checkasm: Add sbcdsp tests Only sbc_analyze_4 and sbc_analyze_8 for now. Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 ++ tests/checkasm/checkasm.h | 1 + tests/checkasm/sbcdsp.c | 79 +++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 85 insertions(+) create mode 100644 tests/checkasm/sbcdsp.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 6c525356aa..956f139090 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -48,6 +48,7 @@ AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_deblock.o hevc_de AVCODECOBJS-$(CONFIG_PNG_DECODER) += png.o AVCODECOBJS-$(CONFIG_RV34DSP) += rv34dsp.o AVCODECOBJS-$(CONFIG_RV40_DECODER) += rv40dsp.o +AVCODECOBJS-$(CONFIG_SBC_ENCODER) += sbcdsp.o AVCODECOBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o AVCODECOBJS-$(CONFIG_TAK_DECODER) += takdsp.o AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index b1504b14bb..b38e5926cb 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -249,6 +249,9 @@ static const struct { #if CONFIG_RV40_DECODER { "rv40dsp", checkasm_check_rv40dsp }, #endif + #if CONFIG_SBC_ENCODER + { "sbcdsp", checkasm_check_sbcdsp }, + #endif #if CONFIG_SVQ1_ENCODER { "svq1enc", checkasm_check_svq1enc }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index f653207363..cded57d3ea 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -135,6 +135,7 @@ void checkasm_check_pixblockdsp(void); void checkasm_check_pixelutils(void); void checkasm_check_png(void); void checkasm_check_qpeldsp(void); +void checkasm_check_sbcdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_rv34dsp(void); void checkasm_check_rv40dsp(void); diff --git a/tests/checkasm/sbcdsp.c b/tests/checkasm/sbcdsp.c new file mode 100644 index 0000000000..aefe066fe2 --- /dev/null +++ b/tests/checkasm/sbcdsp.c @@ -0,0 +1,79 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <stddef.h> +#include <stdint.h> + +#include "checkasm.h" +#include "libavcodec/sbcdsp.h" +#include "libavcodec/sbcdsp_data.h" +#include "libavutil/macros.h" +#include "libavutil/mem_internal.h" + +enum { + SBC_MAX_SUBBANDS = 8, +}; + +#define randomize_buffer(buf) \ +do { \ + for (size_t k = 0; k < FF_ARRAY_ELEMS(buf); ++k) \ + buf[k] = rnd(); \ +} while (0) + +static void check_sbc_analyze(SBCDSPContext *sbcdsp) +{ + DECLARE_ALIGNED(SBC_ALIGN, int16_t, in)[10 * SBC_MAX_SUBBANDS]; + DECLARE_ALIGNED(SBC_ALIGN, int32_t, out_ref)[SBC_MAX_SUBBANDS]; + DECLARE_ALIGNED(SBC_ALIGN, int32_t, out_new)[SBC_MAX_SUBBANDS]; + + declare_func_emms(AV_CPU_FLAG_MMX, void, const int16_t *in, int32_t *out, const int16_t *consts); + + for (int i = 0; i < 2; ++i) { + if (check_func(i ? sbcdsp->sbc_analyze_8 : sbcdsp->sbc_analyze_4, "sbc_analyze_%u", i ? 8 : 4)) { + randomize_buffer(in); + randomize_buffer(out_ref); + memcpy(out_new, out_ref, sizeof(out_new)); + + // the input is always 16-byte aligned for sbc_analyze_8 + // for sbc_analyze_4 it can be 0 or 8 mod 16. + const int16_t *const inp = i || rnd() & 1 ? in : in + 4; + // Use the proper const tables as random ones can cause overflow + #define CONST(SIZE, ODDEVEN) sbcdsp_analysis_consts_fixed ## SIZE ## _simd_ ## ODDEVEN + const int16_t *const consts = rnd() & 1 ? (i ? CONST(8, odd) : CONST(4, odd)) + : (i ? CONST(8, even) : CONST(4, even)); + + call_ref(inp, out_ref, consts); + call_new(inp, out_new, consts); + + if (memcmp(out_ref, out_new, sizeof(out_new))) + fail(); + + bench_new(inp, out_new, consts); + } + } + report("sbc_analyze"); +} + +void checkasm_check_sbcdsp(void) +{ + SBCDSPContext sbcdsp; + + ff_sbcdsp_init(&sbcdsp); + + check_sbc_analyze(&sbcdsp); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 8441bb3719..d75b885db1 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -53,6 +53,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp \ fate-checkasm-sbrdsp \ fate-checkasm-rv34dsp \ fate-checkasm-rv40dsp \ + fate-checkasm-sbcdsp \ fate-checkasm-scene_sad \ fate-checkasm-svq1enc \ fate-checkasm-synth_filter \ -- 2.52.0 >From 4835b3a900926e3078c3c2bd7fd2d2727f564d12 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 15:55:45 +0100 Subject: [PATCH 10/12] avcodec/x86/sbcdsp: Port ff_sbc_analyze_[48]_mmx to SSE2 Halfs the amount of pmaddwd and improves performance a lot: sbc_analyze_4_c: 55.7 ( 1.00x) sbc_analyze_4_mmx: 7.0 ( 7.94x) sbc_analyze_4_sse2: 4.3 (12.93x) sbc_analyze_8_c: 131.1 ( 1.00x) sbc_analyze_8_mmx: 22.4 ( 5.84x) sbc_analyze_8_sse2: 10.7 (12.25x) It also saves 224B of .text and allows to remove the emms_c() from sbcenc.c (notice that ff_sbc_calc_scalefactors_mmx() issues emms on its own, so it already abides by the ABI). Hint: A pshufd could be avoided per function if the constants were reordered. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/sbcenc.c | 2 - libavcodec/x86/sbcdsp.asm | 116 +++++++++++++++++++---------------- libavcodec/x86/sbcdsp_init.c | 12 ++-- tests/checkasm/sbcdsp.c | 2 +- 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index bc2f844789..7e047cd5ab 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -31,7 +31,6 @@ */ #include "libavutil/channel_layout.h" -#include "libavutil/emms.h" #include "libavutil/opt.h" #include "avcodec.h" #include "codec_internal.h" @@ -322,7 +321,6 @@ static int sbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, frame->blocks, frame->channels, frame->subbands); - emms_c(); sbc_pack_frame(avpkt, frame, j, sbc->msbc); *got_packet_ptr = 1; diff --git a/libavcodec/x86/sbcdsp.asm b/libavcodec/x86/sbcdsp.asm index ddc1237d8f..3351e2aadf 100644 --- a/libavcodec/x86/sbcdsp.asm +++ b/libavcodec/x86/sbcdsp.asm @@ -38,43 +38,44 @@ SECTION .text %endif %endmacro -%macro ANALYZE_MAC 9 ; out1, out2, in1, in2, tmp1, tmp2, add1, add2, offset - NIDN movq, %5, %3 - NIDN movq, %6, %4 - pmaddwd %5, [constsq+%9] - pmaddwd %6, [constsq+%9+8] - NIDN paddd, %1, %7 - NIDN paddd, %2, %8 -%endmacro - -%macro ANALYZE_MAC_IN 7 ; out1, out2, tmp1, tmp2, add1, add2, offset - ANALYZE_MAC %1, %2, [inq+%7], [inq+%7+8], %3, %4, %5, %6, %7 -%endmacro - -%macro ANALYZE_MAC_REG 7 ; out1, out2, in, tmp1, tmp2, offset, pack -%ifidn %7, pack - psrad %3, 16 ; SBC_PROTO_FIXED_SCALE - packssdw %3, %3 +%macro ANALYZE_MAC 6 ; out1, out2, tmp1, tmp2, offset, aligned + mov%6 %3, [inq+%5] + mov%6 %4, [inq+%5+mmsize] +%if %5 == 0 + pcmpeqd m0, m0 + psrld m0, 31 %endif - ANALYZE_MAC %1, %2, %3, %3, %4, %5, %4, %5, %6 + pmaddwd %3, [constsq+%5] + pmaddwd %4, [constsq+%5+mmsize] +%if %5 == 0 + pslld m0, 15 ; 1 << (SBC_PROTO_FIXED_SCALE - 1) as dword +%endif + NIDN paddd, %1, %3 + NIDN paddd, %2, %4 %endmacro ;******************************************************************* ;void ff_sbc_analyze_4(const int16_t *in, int32_t *out, const int16_t *consts); ;******************************************************************* -INIT_MMX mmx -cglobal sbc_analyze_4, 3, 3, 4, in, out, consts - ANALYZE_MAC_IN m0, m1, m0, m1, [scale_mask], [scale_mask], 0 - ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 16 - ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 32 - ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 48 - ANALYZE_MAC_IN m0, m1, m2, m3, m2, m3, 64 +INIT_XMM sse2 +cglobal sbc_analyze_4, 3, 3, 5, in, out, consts + ANALYZE_MAC m1, m2, m1, m2, 0, u + ANALYZE_MAC m1, m2, m3, m4, 32, u + movu m3, [inq+64] + paddd m1, m0 + pmaddwd m3, [constsq+64] + paddd m1, m2 + paddd m1, m3 - ANALYZE_MAC_REG m0, m2, m0, m0, m2, 80, pack - ANALYZE_MAC_REG m0, m2, m1, m1, m3, 96, pack + psrad m1, 16 + packssdw m1, m1 + pshufd m2, m1, q0000 + pmaddwd m2, [constsq+80] + pshufd m1, m1, q1111 + pmaddwd m1, [constsq+96] + paddd m1, m2 - movq [outq ], m0 - movq [outq+8], m2 + mova [outq], m1 RET @@ -82,34 +83,41 @@ cglobal sbc_analyze_4, 3, 3, 4, in, out, consts ;******************************************************************* ;void ff_sbc_analyze_8(const int16_t *in, int32_t *out, const int16_t *consts); ;******************************************************************* -INIT_MMX mmx -cglobal sbc_analyze_8, 3, 3, 4, in, out, consts - ANALYZE_MAC_IN m0, m1, m0, m1, [scale_mask], [scale_mask], 0 - ANALYZE_MAC_IN m2, m3, m2, m3, [scale_mask], [scale_mask], 16 - ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 32 - ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 48 - ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 64 - ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 80 - ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 96 - ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 112 - ANALYZE_MAC_IN m0, m1, m4, m5, m4, m5, 128 - ANALYZE_MAC_IN m2, m3, m6, m7, m6, m7, 144 +INIT_XMM sse2 +cglobal sbc_analyze_8, 3, 3, 6, in, out, consts + ANALYZE_MAC m1, m2, m1, m2, 0, a + ANALYZE_MAC m1, m2, m3, m4, 32, a + paddd m1, m0 + ANALYZE_MAC m1, m2, m3, m4, 64, a + ANALYZE_MAC m1, m2, m3, m4, 96, a + paddd m2, m0 + ANALYZE_MAC m1, m2, m3, m4, 128, a - ANALYZE_MAC_REG m4, m5, m0, m4, m5, 160, pack - ANALYZE_MAC_REG m4, m5, m1, m6, m7, 192, pack - ANALYZE_MAC_REG m4, m5, m2, m6, m7, 224, pack - ANALYZE_MAC_REG m4, m5, m3, m6, m7, 256, pack + psrad m1, 16 + psrad m2, 16 + packssdw m1, m2 - movq [outq ], m4 - movq [outq+8], m5 + pshufd m2, m1, q0000 + pmaddwd m0, m2, [constsq+160] + pshufd m3, m1, q1111 + pmaddwd m2, [constsq+176] + pmaddwd m4, m3, [constsq+192] + pshufd m5, m1, q2222 + pmaddwd m3, [constsq+208] + paddd m0, m4 + pmaddwd m4, m5, [constsq+224] + pshufd m1, m1, q3333 + pmaddwd m5, [constsq+240] + paddd m2, m3 + pmaddwd m3, m1, [constsq+256] + paddd m0, m4 + pmaddwd m1, [constsq+272] + paddd m0, m3 + paddd m2, m5 - ANALYZE_MAC_REG m0, m5, m0, m0, m5, 176, no - ANALYZE_MAC_REG m0, m5, m1, m1, m7, 208, no - ANALYZE_MAC_REG m0, m5, m2, m2, m7, 240, no - ANALYZE_MAC_REG m0, m5, m3, m3, m7, 272, no - - movq [outq+16], m0 - movq [outq+24], m5 + mova [outq], m0 + paddd m2, m1 + mova [outq+16], m2 RET diff --git a/libavcodec/x86/sbcdsp_init.c b/libavcodec/x86/sbcdsp_init.c index d959f76f8c..acca0bbdc9 100644 --- a/libavcodec/x86/sbcdsp_init.c +++ b/libavcodec/x86/sbcdsp_init.c @@ -26,7 +26,7 @@ /** * @file - * SBC MMX optimization for some basic "building bricks" + * SBC DSP optimization for some basic "building bricks" */ #include "libavutil/attributes.h" @@ -34,8 +34,8 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/sbcdsp.h" -void ff_sbc_analyze_4_mmx(const int16_t *in, int32_t *out, const int16_t *consts); -void ff_sbc_analyze_8_mmx(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_analyze_4_sse2(const int16_t *in, int32_t *out, const int16_t *consts); +void ff_sbc_analyze_8_sse2(const int16_t *in, int32_t *out, const int16_t *consts); void ff_sbc_calc_scalefactors_mmx(const int32_t sb_sample_f[16][2][8], uint32_t scale_factor[2][8], int blocks, int channels, int subbands); @@ -45,8 +45,10 @@ av_cold void ff_sbcdsp_init_x86(SBCDSPContext *s) int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { - s->sbc_analyze_4 = ff_sbc_analyze_4_mmx; - s->sbc_analyze_8 = ff_sbc_analyze_8_mmx; s->sbc_calc_scalefactors = ff_sbc_calc_scalefactors_mmx; } + if (EXTERNAL_SSE2(cpu_flags)) { + s->sbc_analyze_4 = ff_sbc_analyze_4_sse2; + s->sbc_analyze_8 = ff_sbc_analyze_8_sse2; + } } diff --git a/tests/checkasm/sbcdsp.c b/tests/checkasm/sbcdsp.c index aefe066fe2..3bef11a5e7 100644 --- a/tests/checkasm/sbcdsp.c +++ b/tests/checkasm/sbcdsp.c @@ -41,7 +41,7 @@ static void check_sbc_analyze(SBCDSPContext *sbcdsp) DECLARE_ALIGNED(SBC_ALIGN, int32_t, out_ref)[SBC_MAX_SUBBANDS]; DECLARE_ALIGNED(SBC_ALIGN, int32_t, out_new)[SBC_MAX_SUBBANDS]; - declare_func_emms(AV_CPU_FLAG_MMX, void, const int16_t *in, int32_t *out, const int16_t *consts); + declare_func(void, const int16_t *in, int32_t *out, const int16_t *consts); for (int i = 0; i < 2; ++i) { if (check_func(i ? sbcdsp->sbc_analyze_8 : sbcdsp->sbc_analyze_4, "sbc_analyze_%u", i ? 8 : 4)) { -- 2.52.0 >From 08476c00321a2650ee937e7748c68feb28909ec7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 17:33:35 +0100 Subject: [PATCH 11/12] tests/checkasm/sbcdsp: Add test for calc_scalefactors Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/sbcdsp.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/checkasm/sbcdsp.c b/tests/checkasm/sbcdsp.c index 3bef11a5e7..802eb430ed 100644 --- a/tests/checkasm/sbcdsp.c +++ b/tests/checkasm/sbcdsp.c @@ -69,6 +69,45 @@ static void check_sbc_analyze(SBCDSPContext *sbcdsp) report("sbc_analyze"); } +static void check_sbc_calc_scalefactors(const SBCDSPContext *const sbcdsp) +{ + DECLARE_ALIGNED(SBC_ALIGN, int32_t, sb_sample_f)[16][2][8]; + DECLARE_ALIGNED(SBC_ALIGN, uint32_t, scale_factor_ref)[2][8]; + DECLARE_ALIGNED(SBC_ALIGN, uint32_t, scale_factor_new)[2][8]; + + declare_func(void, const int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands); + + static int blocks = 0; + if (!blocks) + blocks = ((const int[]){4, 8, 12, 15, 16})[rnd() % 5]; + int inited = 0; + + for (int ch = 1; ch <= 2; ++ch) { + for (int subbands = 4; subbands <= 8; subbands += 4) { + if (!check_func(sbcdsp->sbc_calc_scalefactors, "calc_scalefactors_%dch_%dsubbands", ch, subbands)) + return; + + if (!inited) { + for (size_t i = 0; i < FF_ARRAY_ELEMS(sb_sample_f); ++i) + for (size_t j = 0; j < FF_ARRAY_ELEMS(sb_sample_f[0]); ++j) + for (size_t k = 0; k < FF_ARRAY_ELEMS(sb_sample_f[0][0]); ++k) + sb_sample_f[i][j][k] = rnd(); + } + + call_ref(sb_sample_f, scale_factor_ref, blocks, ch, subbands); + call_new(sb_sample_f, scale_factor_new, blocks, ch, subbands); + for (int i = 0; i < ch; ++i) + for (int j = 0; j < subbands; ++j) + if (scale_factor_ref[i][j] != scale_factor_new[i][j]) + fail(); + + bench_new(sb_sample_f, scale_factor_new, blocks, ch, subbands); + } + } +} + void checkasm_check_sbcdsp(void) { SBCDSPContext sbcdsp; @@ -76,4 +115,7 @@ void checkasm_check_sbcdsp(void) ff_sbcdsp_init(&sbcdsp); check_sbc_analyze(&sbcdsp); + + check_sbc_calc_scalefactors(&sbcdsp); + report("calc_scalefactors"); } -- 2.52.0 >From 50b8ea90b083b97f361fbdd6aa4e56c10bbea9a1 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 24 Mar 2026 23:06:05 +0100 Subject: [PATCH 12/12] avcodec/x86/sbcdsp: Port MMX sbc_calc_scalefactors to SSE4 Besides giving a nice speedup over the MMX version, it also avoids processing unnecessarily much input and touching unnecessarily much output in the 2ch-4subbands case. calc_scalefactors_1ch_4subbands_c: 106.9 ( 1.00x) calc_scalefactors_1ch_4subbands_mmx: 46.7 ( 2.29x) calc_scalefactors_1ch_4subbands_sse4: 11.8 ( 9.05x) calc_scalefactors_1ch_8subbands_c: 220.5 ( 1.00x) calc_scalefactors_1ch_8subbands_mmx: 92.3 ( 2.39x) calc_scalefactors_1ch_8subbands_sse4: 23.8 ( 9.28x) calc_scalefactors_2ch_4subbands_c: 222.5 ( 1.00x) calc_scalefactors_2ch_4subbands_mmx: 139.3 ( 1.60x) calc_scalefactors_2ch_4subbands_sse4: 23.6 ( 9.41x) calc_scalefactors_2ch_8subbands_c: 440.3 ( 1.00x) calc_scalefactors_2ch_8subbands_mmx: 196.8 ( 2.24x) calc_scalefactors_2ch_8subbands_sse4: 46.5 ( 9.48x) The MMX version has been removed. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/sbcdsp.asm | 75 ++++++++++++++++-------------------- libavcodec/x86/sbcdsp_init.c | 12 +++--- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/libavcodec/x86/sbcdsp.asm b/libavcodec/x86/sbcdsp.asm index 3351e2aadf..7742d6d316 100644 --- a/libavcodec/x86/sbcdsp.asm +++ b/libavcodec/x86/sbcdsp.asm @@ -26,10 +26,6 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA - -scale_mask: times 2 dd 0x8000 ; 1 << (SBC_PROTO_FIXED_SCALE - 1) - SECTION .text %macro NIDN 3 @@ -127,50 +123,45 @@ cglobal sbc_analyze_8, 3, 3, 6, in, out, consts ; uint32_t scale_factor[2][8], ; int blocks, int channels, int subbands) ;******************************************************************* -INIT_MMX mmx -cglobal sbc_calc_scalefactors, 5, 7, 4, sb_sample_f, scale_factor, blocks, channels, subbands, ptr, blk - ; subbands = 4 * subbands * channels - movq m3, [scale_mask] - shl subbandsd, 2 - cmp channelsd, 2 - jl .loop_1 - add subbandsd, 32 +INIT_XMM sse4 +cglobal sbc_calc_scalefactors, 5, 6, 5, sb_sample_f, scale_factor, blocks, channels, subbands, step + shl blocksd, 6 + pcmpeqd m3, m3 + shl subbandsd, 2 + mov stepd, 48 + add sb_sample_fq, blocksq + psrld m4, m3, 25 ; pd_127 + neg blocksq + shl channelsd, 5 + sub stepd, subbandsd ; step = subbands == 4 ? 32 : 16 + pxor m2, m2 .loop_1: - sub subbandsq, 8 - lea ptrq, [sb_sample_fq + subbandsq] + lea subbandsq, [blocksq+64] - ; blk = (blocks - 1) * 64; - lea blkq, [blocksq - 1] - shl blkd, 6 - - movq m0, m3 + pabsd m0, [sb_sample_fq+blocksq] .loop_2: - movq m1, [ptrq+blkq] - pxor m2, m2 - pcmpgtd m1, m2 - paddd m1, [ptrq+blkq] - pcmpgtd m2, m1 - pxor m1, m2 + pabsd m1, [sb_sample_fq+subbandsq] + pmaxud m0, m1 + add subbandsq, 64 + js .loop_2 - por m0, m1 + paddd m0, m3 ; max - 1, representable as signed value + pmaxsd m0, m2 - sub blkq, 64 - jns .loop_2 + ; We have to calculate log2(x|(1<<15))-15. This equals log2(x>>15) for x >= 2^15 + ; and x>>15 is exactly representable as a float, so one can get the log2 + ; by converting to float and subtracting 127 from the exponent. + ; For x < 2^15 the result is correct when using saturated subtraction. + psrld m0, 15 + cvtdq2ps m0, m0 + add sb_sample_fq, stepq + psrld m0, 23 ; exponent + psubusw m0, m4 ; same as saturated dword subtraction + mova [scale_factorq], m0 - movd blkd, m0 - psrlq m0, 32 - bsr blkd, blkd - sub blkd, 15 ; SCALE_OUT_BITS - mov [scale_factorq + subbandsq], blkd + add scale_factorq, stepq + sub channelsd, stepd + jg .loop_1 - movd blkd, m0 - bsr blkd, blkd - sub blkd, 15 ; SCALE_OUT_BITS - mov [scale_factorq + subbandsq + 4], blkd - - cmp subbandsq, 0 - jg .loop_1 - - emms RET diff --git a/libavcodec/x86/sbcdsp_init.c b/libavcodec/x86/sbcdsp_init.c index acca0bbdc9..b92f348942 100644 --- a/libavcodec/x86/sbcdsp_init.c +++ b/libavcodec/x86/sbcdsp_init.c @@ -36,19 +36,19 @@ void ff_sbc_analyze_4_sse2(const int16_t *in, int32_t *out, const int16_t *consts); void ff_sbc_analyze_8_sse2(const int16_t *in, int32_t *out, const int16_t *consts); -void ff_sbc_calc_scalefactors_mmx(const int32_t sb_sample_f[16][2][8], - uint32_t scale_factor[2][8], - int blocks, int channels, int subbands); +void ff_sbc_calc_scalefactors_sse4(const int32_t sb_sample_f[16][2][8], + uint32_t scale_factor[2][8], + int blocks, int channels, int subbands); av_cold void ff_sbcdsp_init_x86(SBCDSPContext *s) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - s->sbc_calc_scalefactors = ff_sbc_calc_scalefactors_mmx; - } if (EXTERNAL_SSE2(cpu_flags)) { s->sbc_analyze_4 = ff_sbc_analyze_4_sse2; s->sbc_analyze_8 = ff_sbc_analyze_8_sse2; } + if (EXTERNAL_SSE4(cpu_flags)) { + s->sbc_calc_scalefactors = ff_sbc_calc_scalefactors_sse4; + } } -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
