PR #23795 opened by Jia.Yuan
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23795
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23795.patch

Tested on SG2044 (T-Head CPU) with the following benchmark results:

[yuanjia@sg2044sr FFmpeg]$ ./tests/checkasm/checkasm --test=fdctdsp --bench 
--repeat=12
checkasm:
 - CPU: T-Head, vendor arch 0x90C0D00, imp 0x2047000
 - CPU: VLEN = 128 bits
 - Timing source: gettime
 - Bench duration: 1000 µs per function (1000000 nsecs)
 - Random seed: 367382480

Benchmark results:
  name             nsecs (vs ref)
  fdct_c:          245.4
  fdct_rvv_i32:     74.6 ( 3.29x)

(Test #2 and subsequent tests show consistent ~3.29x speedup)

All checkasm tests passed.

# 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 4609745ca93193733b2485898cd6db2d472d20bc Mon Sep 17 00:00:00 2001
From: yuanjia <[email protected]>
Date: Mon, 13 Jul 2026 18:13:57 +0800
Subject: [PATCH] RISC-V: optimize fdct
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Tested on SG2044 (T-Head CPU) with the following benchmark results:

[yuanjia@sg2044sr FFmpeg]$ ./tests/checkasm/checkasm --test=fdctdsp --bench 
--repeat=12
checkasm:
 - CPU: T-Head, vendor arch 0x90C0D00, imp 0x2047000
 - CPU: VLEN = 128 bits
 - Timing source: gettime
 - Bench duration: 1000 µs per function (1000000 nsecs)
 - Random seed: 367382480

Benchmark results:
  name             nsecs (vs ref)
  fdct_c:          245.4
  fdct_rvv_i32:     74.6 ( 3.29x)

(Test #2 and subsequent tests show consistent ~3.29x speedup)

All checkasm tests passed.
---
 libavcodec/avcodec.h            |   2 +
 libavcodec/fdctdsp.c            |   2 +
 libavcodec/fdctdsp.h            |   3 +-
 libavcodec/options_table.h      |   1 +
 libavcodec/riscv/Makefile       |   2 +
 libavcodec/riscv/fdct.h         |  26 ++++
 libavcodec/riscv/fdctdsp_init.c |  45 ++++++
 libavcodec/riscv/fdctdsp_rvv.S  | 254 ++++++++++++++++++++++++++++++++
 libavcodec/riscv/rvv.S          |  85 +++++++++++
 libavcodec/tests/riscv/dct.c    |  30 ++++
 10 files changed, 449 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/riscv/fdct.h
 create mode 100644 libavcodec/riscv/fdctdsp_init.c
 create mode 100644 libavcodec/riscv/fdctdsp_rvv.S
 create mode 100644 libavcodec/riscv/rvv.S
 create mode 100644 libavcodec/tests/riscv/dct.c

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 11ee76efd9..b64daaca47 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1535,6 +1535,8 @@ typedef struct AVCodecContext {
 #define FF_DCT_ALTIVEC 5
 #define FF_DCT_FAAN    6
 #define FF_DCT_NEON    7
+#define FF_DCT_RVV     8
+
 
     /**
      * IDCT algorithm, see FF_IDCT_* below.
diff --git a/libavcodec/fdctdsp.c b/libavcodec/fdctdsp.c
index d20558ce88..2d217ae664 100644
--- a/libavcodec/fdctdsp.c
+++ b/libavcodec/fdctdsp.c
@@ -48,5 +48,7 @@ av_cold void ff_fdctdsp_init(FDCTDSPContext *c, 
AVCodecContext *avctx)
     ff_fdctdsp_init_ppc(c, avctx, high_bit_depth);
 #elif ARCH_X86
     ff_fdctdsp_init_x86(c, avctx, high_bit_depth);
+#elif ARCH_RISCV
+    ff_fdctdsp_init_riscv(c, avctx, high_bit_depth);
 #endif
 }
diff --git a/libavcodec/fdctdsp.h b/libavcodec/fdctdsp.h
index cad99ed7ca..fb72941332 100644
--- a/libavcodec/fdctdsp.h
+++ b/libavcodec/fdctdsp.h
@@ -38,7 +38,8 @@ void ff_fdctdsp_init_ppc(FDCTDSPContext *c, struct 
AVCodecContext *avctx,
                          unsigned high_bit_depth);
 void ff_fdctdsp_init_x86(FDCTDSPContext *c, struct AVCodecContext *avctx,
                          unsigned high_bit_depth);
-
+void ff_fdctdsp_init_riscv(FDCTDSPContext *c, struct AVCodecContext *avctx,
+                         unsigned high_bit_depth);
 void ff_fdct_ifast(int16_t *data);
 void ff_fdct_ifast248(int16_t *data);
 void ff_jpeg_fdct_islow_8(int16_t *data);
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index a16fc84df4..c4d0f82983 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -158,6 +158,7 @@ static const AVOption avcodec_options[] = {
 {"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_ALTIVEC }, INT_MIN, 
INT_MAX, V|E, .unit = "dct"},
 {"faan", "floating point AAN DCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FAAN 
}, INT_MIN, INT_MAX, V|E, .unit = "dct"},
 {"neon", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_NEON }, INT_MIN, INT_MAX, 
V|E, .unit = "dct"},
+{"rvv", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_DCT_RVV }, INT_MIN, INT_MAX, 
V|E, .unit = "dct" },
 {"lumi_mask", "compresses bright areas stronger than medium ones", 
OFFSET(lumi_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
 {"tcplx_mask", "temporal complexity masking", OFFSET(temporal_cplx_masking), 
AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
 {"scplx_mask", "spatial complexity masking", OFFSET(spatial_cplx_masking), 
AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
diff --git a/libavcodec/riscv/Makefile b/libavcodec/riscv/Makefile
index 28d745cfe3..0fad15d841 100644
--- a/libavcodec/riscv/Makefile
+++ b/libavcodec/riscv/Makefile
@@ -5,6 +5,8 @@ RVV-OBJS-$(CONFIG_AAC_ENCODER) += riscv/aacencdsp_rvv.o
 OBJS-$(CONFIG_AC3DSP) += riscv/ac3dsp_init.o
 RV-OBJS-$(CONFIG_AC3DSP) += riscv/ac3dsp_rvb.o
 RVV-OBJS-$(CONFIG_AC3DSP) += riscv/ac3dsp_rvv.o
+OBJS-$(CONFIG_FDCTDSP) += riscv/fdctdsp_init.o
+RVV-OBJS-$(CONFIG_FDCTDSP) += riscv/fdctdsp_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
diff --git a/libavcodec/riscv/fdct.h b/libavcodec/riscv/fdct.h
new file mode 100644
index 0000000000..ab88634b73
--- /dev/null
+++ b/libavcodec/riscv/fdct.h
@@ -0,0 +1,26 @@
+/*
+ * 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
+ */
+
+#ifndef AVCODEC_RVV_FDCT_H
+#define AVCODEC_RVV_FDCT_H
+
+#include <stdint.h>
+
+void ff_fdct_rvv(int16_t *block);
+
+#endif /* AVCODEC_RVV_FDCT_H */
diff --git a/libavcodec/riscv/fdctdsp_init.c b/libavcodec/riscv/fdctdsp_init.c
new file mode 100644
index 0000000000..0429b8d04d
--- /dev/null
+++ b/libavcodec/riscv/fdctdsp_init.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2026 Jia Yuan <[email protected]>
+ *
+ * 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/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/riscv/cpu.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/fdctdsp.h"
+#include "fdct.h"
+
+av_cold void ff_fdctdsp_init_riscv(FDCTDSPContext *c, AVCodecContext *avctx,
+                                     unsigned high_bit_depth)
+{
+#if HAVE_RVV
+    int cpu_flags = av_get_cpu_flags();
+    if (!(cpu_flags & AV_CPU_FLAG_RVV_I32) || !ff_rv_vlen_least(128)) {
+        return;
+    }
+
+    const int dct_algo = avctx->dct_algo;
+
+    if (!high_bit_depth) {
+        if (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_RVV) {
+            c->fdct = ff_fdct_rvv;
+        }
+    }
+#endif
+}
diff --git a/libavcodec/riscv/fdctdsp_rvv.S b/libavcodec/riscv/fdctdsp_rvv.S
new file mode 100644
index 0000000000..9906c2c5d2
--- /dev/null
+++ b/libavcodec/riscv/fdctdsp_rvv.S
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2026 Jia Yuan <[email protected]>
+ *
+ * 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"
+#include "rvv.S"
+
+/* Constants for FDCT */
+#define CONST_BITS  13
+#ifndef EIGHT_BIT_SAMPLES
+#  define PASS1_BITS  1
+#else
+#  define PASS1_BITS  2
+#endif
+#define DESCALE_P1  (CONST_BITS - PASS1_BITS)   /* 12 or 11 */
+#define DESCALE_P2  (CONST_BITS + PASS1_BITS)   /* 14 or 15 */
+
+/* FIX(x) = (int)( (x) * (1 << CONST_BITS) + 0.5 ) */
+#define F_0_298   2446
+#define F_0_390   3196
+#define F_0_541   4433
+#define F_0_765   6270
+#define F_0_899   7373
+#define F_1_175   9633
+#define F_1_501  12299
+#define F_1_847  15137
+#define F_1_961  16069
+#define F_2_053  16819
+#define F_2_562  20995
+#define F_3_072  25172
+
+/* RVV constant table (aligned on 4 bytes) */
+    .balign 4
+fdct_consts:
+    .hword  F_0_298, -F_0_390, F_0_541, F_0_765
+    .hword -F_0_899, F_1_175, F_1_501, -F_1_847
+    .hword -F_1_961, F_2_053, -F_2_562, F_3_072
+    .hword  0, 0, 0, 0          /* padding */
+
+/* ------------------------------------------------------- */
+/* One‑dimensional FDCT (8 elements in, 8 elements out)    */
+/*   pass: 0 = first pass (shift DESCALE_P1, shl out0/out4)*/
+/*         1 = second pass (shift DESCALE_P2, srshr out0/4)*/
+/* ------------------------------------------------------- */
+.macro fdct_1d pass, r0, r1, r2, r3, r4, r5, r6, r7
+    /* Input  : r0..r7 (int16, m1)                         */
+    /* During 32‑bit arithmetic we switch to e32, m2       */
+    /* Output : v16..v23 (int16, m1)                       */
+
+    /* ---- Butterfly sums/differences (16‑bit) ---- */
+    vadd.vv   v24, \r0, \r7    /* tmp0 = S0 + S7 */
+    vsub.vv   v31, \r0, \r7    /* tmp7 = S0 - S7 */
+    vadd.vv   v25, \r1, \r6    /* tmp1 = S1 + S6 */
+    vsub.vv   v30, \r1, \r6    /* tmp6 = S1 - S6 */
+    vadd.vv   v26, \r2, \r5    /* tmp2 = S2 + S5 */
+    vsub.vv   v29, \r2, \r5    /* tmp5 = S2 - S5 */
+    vadd.vv   v27, \r3, \r4    /* tmp3 = S3 + S4 */
+    vsub.vv   v28, \r3, \r4    /* tmp4 = S3 - S4 */
+
+    /* ---- Even part ---- */
+    vadd.vv   v4,  v24, v27    /* tmp10 = tmp0 + tmp3 */
+    vsub.vv   v5,  v24, v27    /* tmp13 = tmp0 - tmp3 */
+    vadd.vv   v6,  v25, v26    /* tmp11 = tmp1 + tmp2 */
+    vsub.vv   v7,  v25, v26    /* tmp12 = tmp1 - tmp2 */
+
+    vadd.vv   v16, v4, v6      /* out0 = tmp10 + tmp11 */
+    vsub.vv   v20, v4, v6      /* out4 = tmp10 - tmp11 */
+    vadd.vv   v12, v7, v5      /* (tmp12 + tmp13) for z1 */
+
+    /* For the first pass: left shift out0 and out4 */
+.if \pass == 0
+    vsll.vi   v16, v16, PASS1_BITS
+    vsll.vi   v20, v20, PASS1_BITS
+.else
+    /* Second pass: rounding right shift out0 and out4 */
+    vsetivli  zero, 8, e32, m2, ta, ma
+    vsext.vf2 v8, v16
+    vsext.vf2 v10, v20
+    vsetivli  zero, 8, e16, m1, ta, ma
+    vnclip.wi v16, v8, PASS1_BITS
+    vnclip.wi v20, v10, PASS1_BITS
+.endif
+
+    li        t2, F_0_541
+    li        t3, F_0_765
+    li        t4, -(F_1_847)
+
+    /* z1 = (tmp12+tmp13) * F_0_541 */
+    vwmul.vx  v18, v12, t2
+    vsetivli  zero, 8, e32, m2, ta, ma
+    vmv.v.v   v22, v18         /* copy for out6 */
+
+    /* out2 = z1 + tmp13 * F_0_765 */
+    vsetivli  zero, 8, e16, m1, ta, ma
+    vwmacc.vx v18, t3, v5
+
+    /* out6 = z1 + tmp12 * (-F_1_847) */
+    vwmacc.vx v22, t4, v7
+
+    /* Narrow & shift (DESCALE_P1 or DESCALE_P2) */
+    vsetivli  zero, 8, e16, m1, ta, ma
+.if \pass == 0
+    vnclip.wi v18, v18, DESCALE_P1
+    vnclip.wi v22, v22, DESCALE_P1
+.else
+    vnclip.wi v18, v18, DESCALE_P2
+    vnclip.wi v22, v22, DESCALE_P2
+.endif
+
+    /* ---- Odd part  ---- */
+    vadd.vv   v2, v28, v31      /* z1 */
+    vadd.vv   v3, v29, v30      /* z2 */
+    vadd.vv   v6, v28, v30      /* z3 */
+    vadd.vv   v7, v29, v31      /* z4 */
+
+    /* z5 = (z3 + z4) * F_1_175 */
+    li        t2, F_1_175
+    vwmul.vx  v4, v6, t2   /* z5 = z3 * F_1_175 */
+    vwmacc.vx v4, t2, v7   /* z5 += z4 * F_1_175 */
+
+    /* tmp4 = S4 * F_0_298, tmp5 = S5 * F_2_053,
+       tmp6 = S6 * F_3_072, tmp7 = S7 * F_1_501 */
+    li        t3, F_0_298
+    li        t4, F_2_053
+    li        t5, F_3_072
+    li        t6, F_1_501 
+    vwmul.vx  v8, v28, t3
+    vwmul.vx  v10, v29, t4
+    vwmul.vx  v12, v30, t5
+    vwmul.vx  v14, v31, t6
+
+    /* z1..z4 with negative coefficients */
+    li        t1, -(F_0_899)
+    li        t2, -(F_2_562)
+    li        t3, -(F_1_961)
+    li        t4, -(F_0_390)
+    vwmul.vx  v24, v2, t1
+    vwmul.vx  v26, v3, t2
+    vwmul.vx  v28, v6, t3
+    vwmul.vx  v30, v7, t4
+
+    vsetivli  zero, 8, e32, m2, ta, ma
+    /* z3 += z5, z4 += z5 */
+    vadd.vv   v28, v28, v4
+    vadd.vv   v30, v30, v4
+
+    /* tmp4 += z1 ; tmp5 += z2 ; tmp6 += z3 ; tmp7 += z4 */
+    vadd.vv    v8,  v8,  v24          /* tmp4 += z1 */
+    vadd.vv    v10, v10, v26          /* tmp5 += z2 */
+    vadd.vv    v12, v12, v28          /* tmp6 += z3 */
+    vadd.vv    v14, v14, v30          /* tmp7 += z4 */
+
+    /* tmp4 += z3 ; tmp5 += z4 ; tmp6 += z2 ; tmp7 += z1 */
+    vadd.vv    v8,  v8,  v28          /* tmp4 += z3 */
+    vadd.vv    v10, v10, v30          /* tmp5 += z4 */
+    vadd.vv    v12, v12, v26          /* tmp6 += z2 */
+    vadd.vv    v14, v14, v24          /* tmp7 += z1 */
+
+    /* ---- Restore 16‑bit mode ---- */
+    vsetivli   zero, 8, e16, m1, ta, ma
+.if \pass == 0
+    vnclip.wi v23, v8, DESCALE_P1
+    vnclip.wi v21, v10, DESCALE_P1
+    vnclip.wi v19, v12, DESCALE_P1
+    vnclip.wi v17, v14, DESCALE_P1
+.else
+    vnclip.wi v23, v8, DESCALE_P2
+    vnclip.wi v21, v10, DESCALE_P2
+    vnclip.wi v19, v12, DESCALE_P2
+    vnclip.wi v17, v14, DESCALE_P2
+.endif
+
+.endm
+
+/* ------------------------------------------------------- */
+/* 8×8 FDCT entry point                                    */
+/*   void ff_fdct_rvv(int16_t *data)                       */
+/* ------------------------------------------------------- */
+func ff_fdct_rvv, zve32x
+    lpad 0
+
+    li        t1, 0x55
+    vsetivli  zero, 8, e16, m1, ta, ma
+    vmv.v.x   v0, t1
+    csrwi     vxrm, 0
+
+    /* Load 8×8 block (rows) */
+    mv        t0, a0
+    vle16.v   v16, (t0)
+    addi      t0, t0, 16
+    vle16.v   v17, (t0)
+    addi      t0, t0, 16
+    vle16.v   v18, (t0)
+    addi      t0, t0, 16
+    vle16.v   v19, (t0)
+    addi      t0, t0, 16
+    vle16.v   v20, (t0)
+    addi      t0, t0, 16
+    vle16.v   v21, (t0)
+    addi      t0, t0, 16
+    vle16.v   v22, (t0)
+    addi      t0, t0, 16
+    vle16.v   v23, (t0)
+
+    /* First transpose: rows → columns */
+    TRANSPOSE_8x8 16, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, 
v19, v20, v21, v22, v23
+
+    /* First 1‑D FDCT (columns) */
+    vsetivli   zero, 8, e16, m1, ta, ma
+    fdct_1d 0, v8, v9, v10, v11, v12, v13, v14, v15
+
+    /* Transpose again: columns → rows */
+    TRANSPOSE_8x8 16, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, 
v19, v20, v21, v22, v23
+
+    /* Second 1‑D FDCT (rows) */
+    vsetivli   zero, 8, e16, m1, ta, ma
+    fdct_1d 1, v8, v9, v10, v11, v12, v13, v14, v15
+
+    /* Store the final 8×8 block back to memory */
+    mv        t0, a0
+    vse16.v   v16, (t0)
+    addi      t0, t0, 16
+    vse16.v   v17, (t0)
+    addi      t0, t0, 16
+    vse16.v   v18, (t0)
+    addi      t0, t0, 16
+    vse16.v   v19, (t0)
+    addi      t0, t0, 16
+    vse16.v   v20, (t0)
+    addi      t0, t0, 16
+    vse16.v   v21, (t0)
+    addi      t0, t0, 16
+    vse16.v   v22, (t0)
+    addi      t0, t0, 16
+    vse16.v   v23, (t0)
+
+    ret
+endfunc
\ No newline at end of file
diff --git a/libavcodec/riscv/rvv.S b/libavcodec/riscv/rvv.S
new file mode 100644
index 0000000000..338929b76c
--- /dev/null
+++ b/libavcodec/riscv/rvv.S
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2026 Jia Yuan <[email protected]>
+ *
+ * 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
+ */
+
+// v0 must be 0x55 as mask
+.macro TRANSPOSE_8x8 es, d0, d1, d2, d3, d4, d5, d6, d7, r0, r1, r2, r3, r4, 
r5, r6, r7
+    vslideup.vi     \d0, \r1, 1
+    vslidedown.vi   \d1, \r0, 1
+    vslideup.vi     \d2, \r3, 1
+    vslidedown.vi   \d3, \r2, 1
+    vslideup.vi     \d4, \r5, 1
+    vslidedown.vi   \d5, \r4, 1
+    vslideup.vi     \d6, \r7, 1
+    vslidedown.vi   \d7, \r6, 1
+    vmerge.vvm      \d0, \d0, \r0, v0
+    vmerge.vvm      \d1, \r1, \d1, v0
+    vmerge.vvm      \d2, \d2, \r2, v0
+    vmerge.vvm      \d3, \r3, \d3, v0
+    vmerge.vvm      \d4, \d4, \r4, v0
+    vmerge.vvm      \d5, \r5, \d5, v0
+    vmerge.vvm      \d6, \d6, \r6, v0
+    vmerge.vvm      \d7, \r7, \d7, v0
+
+.if \es == 16
+    vsetivli        zero, 4, e32, m1, ta, ma
+.elseif \es == 8
+    vsetivli        zero, 4, e16, m1, ta, ma
+.endif
+
+    vslideup.vi     \r0, \d2, 1
+    vslidedown.vi   \r1, \d0, 1
+    vslideup.vi     \r2, \d3, 1
+    vslidedown.vi   \r3, \d1, 1
+    vslideup.vi     \r4, \d6, 1
+    vslidedown.vi   \r5, \d4, 1
+    vslideup.vi     \r6, \d7, 1
+    vslidedown.vi   \r7, \d5, 1
+    vmerge.vvm      \r0, \r0, \d0, v0
+    vmerge.vvm      \r1, \d2, \r1, v0
+    vmerge.vvm      \r2, \r2, \d1, v0
+    vmerge.vvm      \r3, \d3, \r3, v0
+    vmerge.vvm      \r4, \r4, \d4, v0
+    vmerge.vvm      \r5, \d6, \r5, v0
+    vmerge.vvm      \r6, \r6, \d5, v0
+    vmerge.vvm      \r7, \d7, \r7, v0
+
+.if \es == 16
+    vsetivli        zero, 2, e64, m1, ta, ma
+.elseif \es == 8
+    vsetivli        zero, 2, e32, m1, ta, ma
+.endif
+
+    vslideup.vi     \d0, \r4, 1
+    vslidedown.vi   \d4, \r0, 1
+    vslideup.vi     \d1, \r6, 1
+    vslidedown.vi   \d5, \r2, 1
+    vslideup.vi     \d2, \r5, 1
+    vslidedown.vi   \d6, \r1, 1
+    vslideup.vi     \d3, \r7, 1
+    vslidedown.vi   \d7, \r3, 1
+    vmerge.vvm      \d0, \d0, \r0, v0
+    vmerge.vvm      \d4, \r4, \d4, v0
+    vmerge.vvm      \d1, \d1, \r2, v0
+    vmerge.vvm      \d5, \r6, \d5, v0
+    vmerge.vvm      \d2, \d2, \r1, v0
+    vmerge.vvm      \d6, \r5, \d6, v0
+    vmerge.vvm      \d3, \d3, \r3, v0
+    vmerge.vvm      \d7, \r7, \d7, v0
+.endm
\ No newline at end of file
diff --git a/libavcodec/tests/riscv/dct.c b/libavcodec/tests/riscv/dct.c
new file mode 100644
index 0000000000..f440c9c326
--- /dev/null
+++ b/libavcodec/tests/riscv/dct.c
@@ -0,0 +1,30 @@
+/*
+ * 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/cpu.h"
+#include "libavcodec/riscv/fdct.h"
+
+static const struct algo fdct_tab_arch[] = {
+#if HAVE_RVV
+    { "rvv", ff_fdct_rvv, FF_IDCT_PERM_NONE, AV_CPU_FLAG_RVV },
+#endif
+    { 0 }
+};
+
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to