[FFmpeg-devel] [PATCH v4 13/13] avfilter/x86/f_ebur128: implement AVX true peak calculation
Niklas Haas
ffmpeg at haasn.xyz
Tue Jun 17 16:48:40 EEST 2025
On Tue, 17 Jun 2025 14:06:06 +0200 Niklas Haas <ffmpeg at haasn.xyz> wrote:
> From: Niklas Haas <git at haasn.dev>
>
> Stereo only, for simplicity. Slightly faster than the C code.
I will drop this and the prior commit and resubmit them in a refactored form
that also speeds up the sample peak calculation.
In the meantime, I would appreciate a review of the rest.
> ---
> libavfilter/f_ebur128.c | 8 +++-----
> libavfilter/f_ebur128.h | 2 +-
> libavfilter/x86/f_ebur128.asm | 25 +++++++++++++++++++++++++
> libavfilter/x86/f_ebur128_init.c | 9 +++++++--
> 4 files changed, 36 insertions(+), 8 deletions(-)
>
> diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
> index 0adc89c823..c64f6ed032 100644
> --- a/libavfilter/f_ebur128.c
> +++ b/libavfilter/f_ebur128.c
> @@ -502,6 +502,9 @@ static int config_audio_output(AVFilterLink *outlink)
> return AVERROR(ENOMEM);
> }
>
> +#if ARCH_X86
> + ff_ebur128_init_x86(&ebur128->dsp, nb_channels);
> +#endif
> return 0;
> }
>
> @@ -581,11 +584,6 @@ static av_cold int init(AVFilterContext *ctx)
>
> ebur128->dsp.filter_channels = ff_ebur128_filter_channels_c;
> ebur128->dsp.true_peak = ff_ebur128_true_peak_c;
> -
> -#if ARCH_X86
> - ff_ebur128_init_x86(&ebur128->dsp);
> -#endif
> -
> return 0;
> }
>
> diff --git a/libavfilter/f_ebur128.h b/libavfilter/f_ebur128.h
> index 8aab7838a0..5fb9d4a8d5 100644
> --- a/libavfilter/f_ebur128.h
> +++ b/libavfilter/f_ebur128.h
> @@ -53,7 +53,7 @@ static_assert(offsetof(EBUR128DSPContext, pre) == 0, "struct l
> static_assert(offsetof(EBUR128DSPContext, rlb) == 5 * sizeof(double), "struct layout mismatch");
> static_assert(offsetof(EBUR128DSPContext, y) == 10 * sizeof(double), "struct layout mismatch");
>
> -void ff_ebur128_init_x86(EBUR128DSPContext *dsp);
> +void ff_ebur128_init_x86(EBUR128DSPContext *dsp, int nb_channels);
>
> void ff_ebur128_filter_channels_c(const EBUR128DSPContext *, const double *,
> double *, double *, double *, double *, int);
> diff --git a/libavfilter/x86/f_ebur128.asm b/libavfilter/x86/f_ebur128.asm
> index d9cc8d9361..53dd3f858d 100644
> --- a/libavfilter/x86/f_ebur128.asm
> +++ b/libavfilter/x86/f_ebur128.asm
> @@ -39,6 +39,10 @@ struc DSP
> .z resq 1
> endstruc
>
> +SECTION_RODATA
> +
> +abs_mask: dq 0x7FFFFFFFFFFFFFFF
> +
> SECTION .text
>
> %macro MOVNQ 3 ; num, dst, src
> @@ -139,3 +143,24 @@ cglobal ebur128_filter_channels, 7, 9, 14, dsp, samples, cache400, cache3000, su
> test channelsd, channelsd
> jnz .loop
> RET
> +
> +cglobal ebur128_true_peak_stereo, 5, 6, 4, tp, tppf, channels, samples, nb_samples
> + vpbroadcastq m4, [abs_mask]
> + pxor m0, m0 ; maxpeak
> + movupd m1, [tpq] ; tp
> + pxor m2, m2 ; tppf
> +.inner:
> + movupd m3, [samplesq]
> + add samplesq, 16
> + pand m3, m4
> + maxpd m1, m3
> + maxpd m2, m3
> + dec nb_samplesd
> + jg .inner
> + movupd [tpq], m1
> + movupd [tppfq], m2
> + maxpd m0, m1
> + shufpd m1, m0, m0, 1
> + maxpd m0, m1
> + movq rax, m0
> + RET
> diff --git a/libavfilter/x86/f_ebur128_init.c b/libavfilter/x86/f_ebur128_init.c
> index 8f38aee967..527e5e4dbc 100644
> --- a/libavfilter/x86/f_ebur128_init.c
> +++ b/libavfilter/x86/f_ebur128_init.c
> @@ -26,10 +26,15 @@
> void ff_ebur128_filter_channels_avx(const EBUR128DSPContext *, const double *,
> double *, double *, double *, double *, int);
>
> -av_cold void ff_ebur128_init_x86(EBUR128DSPContext *dsp)
> +double ff_ebur128_true_peak_stereo_avx(double *, double *, int, const double *, int);
> +
> +av_cold void ff_ebur128_init_x86(EBUR128DSPContext *dsp, int nb_channels)
> {
> int cpu_flags = av_get_cpu_flags();
>
> - if (ARCH_X86_64 && EXTERNAL_AVX(cpu_flags))
> + if (ARCH_X86_64 && EXTERNAL_AVX(cpu_flags)) {
> dsp->filter_channels = ff_ebur128_filter_channels_avx;
> + if (nb_channels == 2)
> + dsp->true_peak = ff_ebur128_true_peak_stereo_avx;
> + }
> }
> --
> 2.49.0
>
More information about the ffmpeg-devel
mailing list