PR #24578 opened by ww8191201-coder
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24578
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24578.patch

# lavc/riscv: add RVV high-bit-depth H.264 chroma MC for 8xH blocks

RISC-V currently uses the C chroma motion-compensation functions for H.264 bit 
depths above 8. On a SpacemiT X100, the 8xH functions take a measurable share 
of High 10 decoding time.

The RVV put and avg functions handle zero offsets as copies, use two weighted 
sources for horizontal or vertical interpolation, and reuse the middle source 
row when processing two bilinear rows. A single-row tail handles odd heights. 
Dispatch is limited to bit depths 9–16 with RVV_I32 and VLEN of at least 128 
bits. The 4xH and 2xH functions retain the existing C implementation.

## Verification

Built from FFmpeg master with GCC 15.2.0 on riscv64. The following passed:

- make fate-checkasm-h264chroma
- checkasm --test=h264chroma: 10/10 tests
- 27,648 independent cases covering 9, 10, 12 and 16 bit samples; 2/4/8 widths; 
heights 1, 2, 3, 4, 8 and 16; put/avg; all x/y offsets from 0 to 7; and random 
and extreme inputs
- Frame CRC comparison against the unmodified baseline for a 900-frame, 640×360 
yuv420p10le High 10 stream: identical output

## Performance

Measurements used CPU 0 of a SpacemiT X100 (VLEN=256), pinned at 2.2 GHz. The 
same configure options and GCC 15.2.0 were used for baseline and patched 
builds. Per-function figures are means of nine runs with 500,000 calls per case 
after warm-up; no runs were discarded.

| 10-bit 8×8 case | C ns/call | RVV ns/call | Throughput gain |
| --------------- | --------: | ----------: | --------------: |
| put, x/y=0/0    |     54.32 |       28.35 |           91.6% |
| put, x/y=3/0    |     88.60 |       52.58 |           68.5% |
| put, x/y=0/3    |     91.00 |       51.88 |           75.4% |
| put, x/y=3/5    |    170.94 |       78.90 |          116.7% |
| avg, x/y=0/0    |    100.90 |       36.11 |          179.4% |
| avg, x/y=3/0    |    126.33 |       61.65 |          104.9% |
| avg, x/y=0/3    |    125.25 |       60.64 |          106.6% |
| avg, x/y=3/5    |    209.84 |       87.53 |          139.7% |

Each listed case was faster in all nine runs. The geometric-mean throughput 
gain across the eight cases was 107.8% at 10 bit and 108.9% at 16 bit.

For a 30-second, 900-frame High 10 stream encoded with libx264 (preset medium, 
CRF 20, three B-frames, three references), single-threaded decoding to the null 
muxer took 2.2019 ± 0.0228 s on master and 2.0931 ± 0.0144 s with the RVV 
functions (mean ± sample standard deviation, seven runs). That is 5.19% higher 
throughput; the patched build was faster in all seven paired runs.




From edb925f07daf3c0d2e786073ece74dfbf39ed048 Mon Sep 17 00:00:00 2001
From: Hongyan Wang <[email protected]>
Date: Sun, 20 Sep 2026 12:40:49 +0800
Subject: [PATCH] lavc/riscv: add RVV high-bit-depth H.264 chroma MC for 8xH
 blocks

Add 16-bit sample interpolation for put and avg on 8xH chroma blocks.
Handle zero, one-dimensional and bilinear offsets separately, and
process two rows at a time with a single-row tail for odd heights.

Signed-off-by: Hongyan Wang <[email protected]>
Co-authored-by: YuanSheng <[email protected]>
Co-authored-by: Fei Zhang <[email protected]>
---
 libavcodec/riscv/h264_chroma_init_riscv.c |   7 +
 libavcodec/riscv/h264_mc_chroma.S         | 213 ++++++++++++++++++++++
 2 files changed, 220 insertions(+)

diff --git a/libavcodec/riscv/h264_chroma_init_riscv.c 
b/libavcodec/riscv/h264_chroma_init_riscv.c
index b6bde42c0a..f0f4b5f20f 100644
--- a/libavcodec/riscv/h264_chroma_init_riscv.c
+++ b/libavcodec/riscv/h264_chroma_init_riscv.c
@@ -32,6 +32,9 @@ void h264_avg_chroma_mc4_rvv(uint8_t *p_dst, const uint8_t 
*p_src, ptrdiff_t str
 void h264_put_chroma_mc2_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t 
stride, int h, int x, int y);
 void h264_avg_chroma_mc2_rvv(uint8_t *p_dst, const uint8_t *p_src, ptrdiff_t 
stride, int h, int x, int y);
 
+void ff_put_h264_chroma_mc8_16_rvv(uint8_t *p_dst, const uint8_t *p_src, 
ptrdiff_t stride, int h, int x, int y);
+void ff_avg_h264_chroma_mc8_16_rvv(uint8_t *p_dst, const uint8_t *p_src, 
ptrdiff_t stride, int h, int x, int y);
+
 av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, int bit_depth)
 {
 #if HAVE_RVV
@@ -45,6 +48,10 @@ av_cold void ff_h264chroma_init_riscv(H264ChromaContext *c, 
int bit_depth)
         c->avg_h264_chroma_pixels_tab[1] = h264_avg_chroma_mc4_rvv;
         c->put_h264_chroma_pixels_tab[2] = h264_put_chroma_mc2_rvv;
         c->avg_h264_chroma_pixels_tab[2] = h264_avg_chroma_mc2_rvv;
+    } else if (bit_depth > 8 && bit_depth <= 16 &&
+               (flags & AV_CPU_FLAG_RVV_I32) && ff_rv_vlen_least(128)) {
+        c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_16_rvv;
+        c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_16_rvv;
     }
 #endif
 }
diff --git a/libavcodec/riscv/h264_mc_chroma.S 
b/libavcodec/riscv/h264_mc_chroma.S
index 79394b987d..18e9e5fdfc 100644
--- a/libavcodec/riscv/h264_mc_chroma.S
+++ b/libavcodec/riscv/h264_mc_chroma.S
@@ -380,3 +380,216 @@ func h264_avg_chroma_mc2_rvv, zve32x
         li      t6, 2
         j       21b
 endfunc
+
+.macro h264_chroma_mc16 op
+func ff_\op\()_h264_chroma_mc8_16_rvv, zve32x
+        lpad    0
+        blez    a3, 9f
+        csrwi   vxrm, 0
+        vsetivli zero, 8, e16, m1, ta, ma
+        or      t0, a4, a5
+        beqz    t0, 7f
+        beqz    a5, 3f
+        beqz    a4, 5f
+
+        li      t0, 8
+        sub     t1, t0, a4
+        sub     t2, t0, a5
+        mul     t3, t1, t2
+        mul     t4, a4, t2
+        mul     t5, t1, a5
+        mul     t6, a4, a5
+        slli    a4, a2, 1
+1:
+        addi    a6, a3, -2
+        bltz    a6, 2f
+        vle16.v v0, (a1)
+        addi    a6, a1, 2
+        vle16.v v1, (a6)
+        add     a6, a1, a2
+        vle16.v v2, (a6)
+        addi    a7, a6, 2
+        vle16.v v3, (a7)
+        vwmulu.vx v8, v0, t3
+        vwmaccu.vx v8, t4, v1
+        vwmaccu.vx v8, t5, v2
+        vwmaccu.vx v8, t6, v3
+        vnclipu.wi v12, v8, 6
+        add     a6, a6, a2
+        vle16.v v4, (a6)
+        addi    a7, a6, 2
+        vle16.v v5, (a7)
+        vwmulu.vx v10, v2, t3
+        vwmaccu.vx v10, t4, v3
+        vwmaccu.vx v10, t5, v4
+        vwmaccu.vx v10, t6, v5
+        vnclipu.wi v13, v10, 6
+.ifc \op, avg
+        vle16.v v6, (a0)
+        vaaddu.vv v12, v12, v6
+        add     a7, a0, a2
+        vle16.v v7, (a7)
+        vaaddu.vv v13, v13, v7
+.endif
+        vse16.v v12, (a0)
+        add     a7, a0, a2
+        vse16.v v13, (a7)
+        add     a1, a1, a4
+        add     a0, a0, a4
+        addi    a3, a3, -2
+        bgtz    a3, 1b
+        ret
+2:
+        vle16.v v0, (a1)
+        addi    a6, a1, 2
+        vle16.v v1, (a6)
+        add     a6, a1, a2
+        vle16.v v2, (a6)
+        addi    a7, a6, 2
+        vle16.v v3, (a7)
+        vwmulu.vx v8, v0, t3
+        vwmaccu.vx v8, t4, v1
+        vwmaccu.vx v8, t5, v2
+        vwmaccu.vx v8, t6, v3
+        vnclipu.wi v12, v8, 6
+.ifc \op, avg
+        vle16.v v6, (a0)
+        vaaddu.vv v12, v12, v6
+.endif
+        vse16.v v12, (a0)
+        ret
+
+3:
+        li      t0, 8
+        sub     t1, t0, a4
+        mv      t2, a4
+        slli    a4, a2, 1
+4:
+        addi    a6, a3, -2
+        bltz    a6, 41f
+        vle16.v v0, (a1)
+        addi    a6, a1, 2
+        vle16.v v1, (a6)
+        add     a6, a1, a2
+        vle16.v v2, (a6)
+        addi    a7, a6, 2
+        vle16.v v3, (a7)
+        vwmulu.vx v8, v0, t1
+        vwmaccu.vx v8, t2, v1
+        vwmulu.vx v10, v2, t1
+        vwmaccu.vx v10, t2, v3
+        vnclipu.wi v12, v8, 3
+        vnclipu.wi v13, v10, 3
+.ifc \op, avg
+        vle16.v v4, (a0)
+        vaaddu.vv v12, v12, v4
+        add     a7, a0, a2
+        vle16.v v5, (a7)
+        vaaddu.vv v13, v13, v5
+.endif
+        vse16.v v12, (a0)
+        add     a7, a0, a2
+        vse16.v v13, (a7)
+        add     a1, a1, a4
+        add     a0, a0, a4
+        addi    a3, a3, -2
+        bgtz    a3, 4b
+        ret
+41:
+        vle16.v v0, (a1)
+        addi    a6, a1, 2
+        vle16.v v1, (a6)
+        vwmulu.vx v8, v0, t1
+        vwmaccu.vx v8, t2, v1
+        vnclipu.wi v12, v8, 3
+.ifc \op, avg
+        vle16.v v4, (a0)
+        vaaddu.vv v12, v12, v4
+.endif
+        vse16.v v12, (a0)
+        ret
+
+5:
+        li      t0, 8
+        sub     t1, t0, a5
+        mv      t2, a5
+        slli    a4, a2, 1
+6:
+        addi    a6, a3, -2
+        bltz    a6, 61f
+        vle16.v v0, (a1)
+        add     a6, a1, a2
+        vle16.v v1, (a6)
+        add     a7, a6, a2
+        vle16.v v2, (a7)
+        vwmulu.vx v8, v0, t1
+        vwmaccu.vx v8, t2, v1
+        vwmulu.vx v10, v1, t1
+        vwmaccu.vx v10, t2, v2
+        vnclipu.wi v12, v8, 3
+        vnclipu.wi v13, v10, 3
+.ifc \op, avg
+        vle16.v v3, (a0)
+        vaaddu.vv v12, v12, v3
+        add     a7, a0, a2
+        vle16.v v4, (a7)
+        vaaddu.vv v13, v13, v4
+.endif
+        vse16.v v12, (a0)
+        add     a7, a0, a2
+        vse16.v v13, (a7)
+        add     a1, a1, a4
+        add     a0, a0, a4
+        addi    a3, a3, -2
+        bgtz    a3, 6b
+        ret
+61:
+        vle16.v v0, (a1)
+        add     a6, a1, a2
+        vle16.v v1, (a6)
+        vwmulu.vx v8, v0, t1
+        vwmaccu.vx v8, t2, v1
+        vnclipu.wi v12, v8, 3
+.ifc \op, avg
+        vle16.v v3, (a0)
+        vaaddu.vv v12, v12, v3
+.endif
+        vse16.v v12, (a0)
+        ret
+
+7:
+        slli    a4, a2, 1
+        addi    a6, a3, -2
+        bltz    a6, 8f
+        vle16.v v0, (a1)
+        add     a6, a1, a2
+        vle16.v v1, (a6)
+.ifc \op, avg
+        vle16.v v2, (a0)
+        vaaddu.vv v0, v0, v2
+        add     a7, a0, a2
+        vle16.v v3, (a7)
+        vaaddu.vv v1, v1, v3
+.endif
+        vse16.v v0, (a0)
+        add     a7, a0, a2
+        vse16.v v1, (a7)
+        add     a1, a1, a4
+        add     a0, a0, a4
+        addi    a3, a3, -2
+        bgtz    a3, 7b
+        ret
+8:
+        vle16.v v0, (a1)
+.ifc \op, avg
+        vle16.v v2, (a0)
+        vaaddu.vv v0, v0, v2
+.endif
+        vse16.v v0, (a0)
+9:
+        ret
+endfunc
+.endm
+
+        h264_chroma_mc16 put
+        h264_chroma_mc16 avg
-- 
2.52.0

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

Reply via email to