[FFmpeg-devel] [PATCH] libswresample/riscv:add RVV optimized for conv_flt_to_s16

daichengrong at iscas.ac.cn daichengrong at iscas.ac.cn
Thu Mar 20 11:30:01 EET 2025


From: daichengrong <daichengrong at iscas.ac.cn>

This patch introduces RVV optimized for conv_flt_to_s16.
On Banana PI F3, it gets an average improvement of 5% for 20000 SAMPLES.
---
 libswresample/audioconvert.c             |  2 +
 libswresample/riscv/Makefile             |  3 ++
 libswresample/riscv/audio_convert_init.c | 50 ++++++++++++++++++++++++
 libswresample/riscv/audio_convert_rvv.S  | 46 ++++++++++++++++++++++
 libswresample/swresample_internal.h      |  4 ++
 5 files changed, 105 insertions(+)
 create mode 100644 libswresample/riscv/Makefile
 create mode 100644 libswresample/riscv/audio_convert_init.c
 create mode 100644 libswresample/riscv/audio_convert_rvv.S

diff --git a/libswresample/audioconvert.c b/libswresample/audioconvert.c
index 04108fb966..49b56b6b5e 100644
--- a/libswresample/audioconvert.c
+++ b/libswresample/audioconvert.c
@@ -182,6 +182,8 @@ AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt,
     swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);
 #elif ARCH_AARCH64
     swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);
+#elif ARCH_RISCV
+    swri_audio_convert_init_riscv(ctx, out_fmt, in_fmt, channels);
 #endif
 
     return ctx;
diff --git a/libswresample/riscv/Makefile b/libswresample/riscv/Makefile
new file mode 100644
index 0000000000..01943cec64
--- /dev/null
+++ b/libswresample/riscv/Makefile
@@ -0,0 +1,3 @@
+OBJS                             += riscv/audio_convert_init.o 
+
+RVV-OBJS                        += riscv/audio_convert_rvv.o 
diff --git a/libswresample/riscv/audio_convert_init.c b/libswresample/riscv/audio_convert_init.c
new file mode 100644
index 0000000000..7bea7e6eb4
--- /dev/null
+++ b/libswresample/riscv/audio_convert_init.c
@@ -0,0 +1,50 @@
+/*
+ * This file is part of libswresample.
+ *
+ * libswresample 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.
+ *
+ * libswresample 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 libswresample; 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 "libavutil/samplefmt.h"
+#include "libswresample/swresample_internal.h"
+#include "libswresample/audioconvert.h"
+
+void swri_oldapi_conv_flt_to_s16_rvv(int16_t *dst, const float *src, int len);
+
+static void conv_flt_to_s16_rvv(uint8_t **dst, const uint8_t **src, int len){
+    swri_oldapi_conv_flt_to_s16_rvv((int16_t*)*dst, (const float*)*src, len);
+}
+
+av_cold void swri_audio_convert_init_riscv(struct AudioConvert *ac,
+                                       enum AVSampleFormat out_fmt,
+                                       enum AVSampleFormat in_fmt,
+                                       int channels)
+{
+    int flags = av_get_cpu_flags();
+
+    ac->simd_f= NULL;
+
+#if HAVE_RVV
+    if (flags & AV_CPU_FLAG_RVV_F32) {
+        if(out_fmt == AV_SAMPLE_FMT_S16 && in_fmt == AV_SAMPLE_FMT_FLT || out_fmt == AV_SAMPLE_FMT_S16P && in_fmt == AV_SAMPLE_FMT_FLTP)
+            ac->simd_f = conv_flt_to_s16_rvv;
+    }
+#endif
+}
diff --git a/libswresample/riscv/audio_convert_rvv.S b/libswresample/riscv/audio_convert_rvv.S
new file mode 100644
index 0000000000..d9d58d6d5e
--- /dev/null
+++ b/libswresample/riscv/audio_convert_rvv.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2025 daichengrong <daichengrong at iscas.ac.cn>
+ *
+ * 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 "config.h"
+#include "libavutil/riscv/asm.S"
+
+func swri_oldapi_conv_flt_to_s16_rvv, zve32f
+        mv      t1, a0
+        mv      t2, a1
+        #mv t3, a2
+1:      vsetvli a4,a2,e32,m8,ta,ma
+        vle32.v v8,(t2)
+        sub     a2, a2, a4
+        li      t0, (1<<15)
+        sext.w  t0,t0
+        fcvt.s.w        fa2, t0
+        vfmul.vf        v16, v8, fa2
+        vfcvt.x.f.v     v8, v16
+        vsetvli zero,zero,e16,m4,ta,ma
+        vnclip.wi       v16, v8, 0
+        vse16.v v16,(t1)
+        sll     a4,a4,0x1
+        add     t1, t1, a4
+        sll     a4, a4, 0x1
+        add     t2, t2, a4
+        bnez    a2, 1b
+        mv      a0, t1
+        ret
+endfunc
\ No newline at end of file
diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
index 7e46b16fb2..257f69f6dd 100644
--- a/libswresample/swresample_internal.h
+++ b/libswresample/swresample_internal.h
@@ -216,5 +216,9 @@ void swri_audio_convert_init_x86(struct AudioConvert *ac,
                                  enum AVSampleFormat out_fmt,
                                  enum AVSampleFormat in_fmt,
                                  int channels);
+void swri_audio_convert_init_riscv(struct AudioConvert *ac,
+                                 enum AVSampleFormat out_fmt,
+                                 enum AVSampleFormat in_fmt,
+                                 int channels);
 
 #endif
-- 
2.43.0



More information about the ffmpeg-devel mailing list