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]

Reply via email to