PR #23712 opened by ixgbe URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23712 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23712.patch
Add a RISC-V Vector implementation of the float synthesis filter used by the DCA decoder. The wrapper keeps the existing IMDCT path in C and dispatches the RVV inner loop only when single-precision vectors, RVB, and VLEN >= 128 are available. checkasm --test=synth_filter passes. Benchmarked on Sophon SG2044 with native FFmpeg timers: name nsecs (vs ref) synth_filter_float_c: 667.6 synth_filter_float_rvv_f32: 266.5 (2.50x) Signed-off-by: YuanSheng <[email protected]> Co-authored-by: Wang Yang <[email protected]> # Summary of changes Briefly describe what this PR does and why. <!-- If this PR requires new FATE test samples, attach them to the PR and list their target paths below (relative to the fate-suite root). Attached filenames must match the sample's filename: ```fate-samples # e.g. vorbis/new-sample.ogg ``` --> >From 6d13eb41165de0409fd8b00a432bbc7f7790cb64 Mon Sep 17 00:00:00 2001 From: ixgbe <[email protected]> Date: Mon, 6 Jul 2026 09:20:50 +0800 Subject: [PATCH] libavcodec/riscv: add RVV optimized synth_filter_float Add a RISC-V Vector implementation of the float synthesis filter used by the DCA decoder. The wrapper keeps the existing IMDCT path in C and dispatches the RVV inner loop only when single-precision vectors, RVB, and VLEN >= 128 are available. checkasm --test=synth_filter passes. Benchmarked on Sophon SG2044 with native FFmpeg timers: name nsecs (vs ref) synth_filter_float_c: 667.6 synth_filter_float_rvv_f32: 266.5 (2.50x) Signed-off-by: YuanSheng <[email protected]> Co-authored-by: Wang Yang <[email protected]> --- libavcodec/riscv/Makefile | 2 + libavcodec/riscv/synth_filter_init.c | 62 ++++++++++++++++++++ libavcodec/riscv/synth_filter_rvv.S | 84 ++++++++++++++++++++++++++++ libavcodec/synth_filter.c | 2 + libavcodec/synth_filter.h | 1 + 5 files changed, 151 insertions(+) create mode 100644 libavcodec/riscv/synth_filter_init.c create mode 100644 libavcodec/riscv/synth_filter_rvv.S diff --git a/libavcodec/riscv/Makefile b/libavcodec/riscv/Makefile index ff063afc35..9f5bb5d10b 100644 --- a/libavcodec/riscv/Makefile +++ b/libavcodec/riscv/Makefile @@ -8,6 +8,8 @@ RVV-OBJS-$(CONFIG_AC3DSP) += riscv/ac3dsp_rvv.o RVVB-OBJS-$(CONFIG_AC3DSP) += riscv/ac3dsp_rvvb.o OBJS-$(CONFIG_ALAC_DECODER) += riscv/alacdsp_init.o RVV-OBJS-$(CONFIG_ALAC_DECODER) += riscv/alacdsp_rvv.o +OBJS-$(CONFIG_DCA_DECODER) += riscv/synth_filter_init.o +RVV-OBJS-$(CONFIG_DCA_DECODER) += riscv/synth_filter_rvv.o OBJS-$(CONFIG_AUDIODSP) += riscv/audiodsp_init.o RVV-OBJS-$(CONFIG_AUDIODSP) += riscv/audiodsp_rvv.o OBJS-$(CONFIG_BLOCKDSP) += riscv/blockdsp_init.o diff --git a/libavcodec/riscv/synth_filter_init.c b/libavcodec/riscv/synth_filter_init.c new file mode 100644 index 0000000000..7cadcefc1a --- /dev/null +++ b/libavcodec/riscv/synth_filter_init.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2026 Institute of Software Chinese Academy of Sciences (ISCAS). + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <stdint.h> + +#include "config.h" + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/riscv/cpu.h" +#include "libavcodec/synth_filter.h" + +void ff_synth_filter_inner_rvv(float *synth_buf_ptr, float synth_buf2[32], + const float window[512], float out[32], + intptr_t offset, float scale); + +static void synth_filter_rvv(AVTXContext *imdct, + float *synth_buf_ptr, int *synth_buf_offset, + float synth_buf2[32], const float window[512], + float out[32], float in[32], float scale, + av_tx_fn imdct_fn) +{ + float *synth_buf = synth_buf_ptr + *synth_buf_offset; + + imdct_fn(imdct, synth_buf, in, sizeof(float)); + + ff_synth_filter_inner_rvv(synth_buf, synth_buf2, window, out, + *synth_buf_offset, scale); + + *synth_buf_offset = (*synth_buf_offset - 32) & 511; +} + +av_cold void ff_synth_filter_init_riscv(SynthFilterContext *s) +{ +#if HAVE_RVV + int flags = av_get_cpu_flags(); + + /* Needs single-precision RVV (Zve32f), Zbb (clz, for the run-time minimal + * LMUL select via vtype_ivli), and 16 e32 elements per vector, i.e. + * VLEN >= 128 (vlenb >= 16). AV_CPU_FLAG_RVB implies Zba+Zbb+Zbs. */ + if ((flags & AV_CPU_FLAG_RVV_F32) && (flags & AV_CPU_FLAG_RVB) && + ff_get_rv_vlenb() >= 16) + s->synth_filter_float = synth_filter_rvv; +#endif +} diff --git a/libavcodec/riscv/synth_filter_rvv.S b/libavcodec/riscv/synth_filter_rvv.S new file mode 100644 index 0000000000..458bf84b91 --- /dev/null +++ b/libavcodec/riscv/synth_filter_rvv.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2026 Institute of Software Chinese Academy of Sciences (ISCAS). + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "libavutil/riscv/asm.S" + +.macro synth_block + vle32.v v16, (t3) + vrgather.vv v20, v16, v28 + addi t5, a2, 16 * 4 + vle32.v v24, (t5) + vfmacc.vv v4, v24, v16 + vle32.v v24, (a2) + vfnmsac.vv v0, v24, v20 + addi t4, t3, 16 * 4 + vle32.v v16, (t4) + vrgather.vv v20, v16, v28 + addi t5, a2, 32 * 4 + vle32.v v24, (t5) + vfmacc.vv v8, v24, v16 + addi t5, a2, 48 * 4 + vle32.v v24, (t5) + vfmacc.vv v12, v24, v20 + addi t3, t3, 64 * 4 + addi a2, a2, 64 * 4 + addi t1, t1, 64 * 4 +.endm + +func ff_synth_filter_inner_rvv, zve32f, zbb + lpad 0 +NOHWF fmv.w.x fa0, a5 + li t2, 16 + vtype_ivli t0, 16, e32, ta, ma + vsetvl zero, t2, t0 + vid.v v28 + li t5, 15 + vrsub.vx v28, v28, t5 + vle32.v v0, (a1) + addi t4, a1, 16 * 4 + vle32.v v4, (t4) + vmv.v.i v8, 0 + vmv.v.i v12, 0 + li t0, 512 + sub t0, t0, a4 + slli t0, t0, 2 + li t1, 0 + mv t3, a0 +1: + synth_block + blt t1, t0, 1b + li t4, 512 * 4 + sub t3, t3, t4 + li t6, 512 * 4 + bge t1, t6, 3f +2: + synth_block + blt t1, t6, 2b +3: + vfmul.vf v0, v0, fa0 + vfmul.vf v4, v4, fa0 + vse32.v v0, (a3) + addi t4, a3, 16 * 4 + vse32.v v4, (t4) + vse32.v v8, (a1) + addi t4, a1, 16 * 4 + vse32.v v12, (t4) + ret +endfunc diff --git a/libavcodec/synth_filter.c b/libavcodec/synth_filter.c index 82a2f812b8..2943ca9568 100644 --- a/libavcodec/synth_filter.c +++ b/libavcodec/synth_filter.c @@ -180,6 +180,8 @@ av_cold void ff_synth_filter_init(SynthFilterContext *c) ff_synth_filter_init_aarch64(c); #elif ARCH_ARM ff_synth_filter_init_arm(c); +#elif ARCH_RISCV + ff_synth_filter_init_riscv(c); #elif ARCH_X86 && HAVE_X86ASM ff_synth_filter_init_x86(c); #endif diff --git a/libavcodec/synth_filter.h b/libavcodec/synth_filter.h index cf6f2678b7..d781cc3fbf 100644 --- a/libavcodec/synth_filter.h +++ b/libavcodec/synth_filter.h @@ -48,6 +48,7 @@ typedef struct SynthFilterContext { void ff_synth_filter_init(SynthFilterContext *c); void ff_synth_filter_init_aarch64(SynthFilterContext *c); void ff_synth_filter_init_arm(SynthFilterContext *c); +void ff_synth_filter_init_riscv(SynthFilterContext *c); void ff_synth_filter_init_x86(SynthFilterContext *c); #endif /* AVCODEC_SYNTH_FILTER_H */ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
