This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 9347affa3d avcodec/x86/hevc: add SSE2 and AVX transform_4x4_luma
9347affa3d is described below
commit 9347affa3dc3aa35e90661a4a7564328f3db7972
Author: Marcos Ashton Iglesias <[email protected]>
AuthorDate: Sat Jul 11 17:07:55 2026 +0100
Commit: michaelni <[email protected]>
CommitDate: Thu Jul 23 17:58:45 2026 +0000
avcodec/x86/hevc: add SSE2 and AVX transform_4x4_luma
Implements the 4x4 luma DST-VII inverse transform for 8 and 10 bit,
using pmaddwd on (src0,src2)/(src1,src3) pairs, mirroring the
existing 4x4 IDCT structure.
checkasm --bench on a Core Ultra 7 155H:
hevc_transform_luma_4x4_8_c: 151.0
hevc_transform_luma_4x4_8_sse2: 35.9 ( 4.20x)
hevc_transform_luma_4x4_8_avx: 34.2 ( 4.42x)
hevc_transform_luma_4x4_10_c: 146.5
hevc_transform_luma_4x4_10_sse2: 35.0 ( 4.19x)
hevc_transform_luma_4x4_10_avx: 33.7 ( 4.35x)
Part of #23022.
---
libavcodec/x86/hevc/dsp_init.c | 10 ++++++
libavcodec/x86/hevc/idct.asm | 76 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/libavcodec/x86/hevc/dsp_init.c b/libavcodec/x86/hevc/dsp_init.c
index 85905e6959..c456ee9ed0 100644
--- a/libavcodec/x86/hevc/dsp_init.c
+++ b/libavcodec/x86/hevc/dsp_init.c
@@ -86,6 +86,12 @@ void ff_hevc_idct_32x32_10_ ## opt(int16_t *coeffs, int
col_limit);
IDCT_FUNCS(sse2)
IDCT_FUNCS(avx)
+#define TRANSFORM_LUMA_FUNCS(opt) \
+void ff_hevc_transform_4x4_luma_8_ ## opt(int16_t *coeffs); \
+void ff_hevc_transform_4x4_luma_10_ ## opt(int16_t *coeffs)
+
+TRANSFORM_LUMA_FUNCS(sse2);
+TRANSFORM_LUMA_FUNCS(avx);
#define ff_hevc_pel_filters ff_hevc_qpel_filters
#define DECL_HV_FILTER(f) \
@@ -837,6 +843,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int
bit_depth)
c->idct[0] = ff_hevc_idct_4x4_8_sse2;
c->idct[1] = ff_hevc_idct_8x8_8_sse2;
+ c->transform_4x4_luma = ff_hevc_transform_4x4_luma_8_sse2;
c->add_residual[1] = ff_hevc_add_residual_8_8_sse2;
c->add_residual[2] = ff_hevc_add_residual_16_8_sse2;
@@ -878,6 +885,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int
bit_depth)
c->idct[0] = ff_hevc_idct_4x4_8_avx;
c->idct[1] = ff_hevc_idct_8x8_8_avx;
+ c->transform_4x4_luma = ff_hevc_transform_4x4_luma_8_avx;
}
if (EXTERNAL_AVX2(cpu_flags)) {
c->sao_band_filter[0] = ff_hevc_sao_band_filter_8_8_avx2;
@@ -1017,6 +1025,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int
bit_depth)
c->idct[0] = ff_hevc_idct_4x4_10_sse2;
c->idct[1] = ff_hevc_idct_8x8_10_sse2;
+ c->transform_4x4_luma = ff_hevc_transform_4x4_luma_10_sse2;
c->add_residual[1] = ff_hevc_add_residual_8_10_sse2;
c->add_residual[2] = ff_hevc_add_residual_16_10_sse2;
@@ -1054,6 +1063,7 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int
bit_depth)
c->idct[0] = ff_hevc_idct_4x4_10_avx;
c->idct[1] = ff_hevc_idct_8x8_10_avx;
+ c->transform_4x4_luma = ff_hevc_transform_4x4_luma_10_avx;
SAO_BAND_INIT(10, avx);
}
diff --git a/libavcodec/x86/hevc/idct.asm b/libavcodec/x86/hevc/idct.asm
index 088144171d..cfa156c705 100644
--- a/libavcodec/x86/hevc/idct.asm
+++ b/libavcodec/x86/hevc/idct.asm
@@ -35,6 +35,16 @@ pw_64_m64: times 4 dw 64, -64
pw_83_36: times 4 dw 83, 36
pw_36_m83: times 4 dw 36, -83
+; 4x4 luma (DST-VII) transform coeffs, paired as (src0, src2) and (src1, src3)
+pw_29_84: times 4 dw 29, 84
+pw_74_55: times 4 dw 74, 55
+pw_55_m29: times 4 dw 55, -29
+pw_74_m84: times 4 dw 74, -84
+pw_74_m74: times 4 dw 74, -74
+pw_0_74: times 4 dw 0, 74
+pw_84_55: times 4 dw 84, 55
+pw_m74_m29: times 4 dw -74, -29
+
; 8x8 transform coeffs
pw_89_75: times 4 dw 89, 75
pw_50_18: times 4 dw 50, 18
@@ -366,6 +376,71 @@ cglobal hevc_idct_4x4_%1, 1, 1, 5, coeffs
RET
%endmacro
+; 4x4 luma inverse transform (DST-VII), one pass over 4 columns at once.
+; Unlike the DCT, DST-VII has no even/odd symmetry, so every output is a full
+; dot product of the 4 inputs; we pair them as (src0, src2) and (src1, src3)
+; and accumulate with pmaddwd, then scale, clip16 and transpose for the next
pass.
+; expects input rows in m0 (rows 0, 1) and m1 (rows 2, 3)
+; %1 - shift
+; %2 - rounding constant (label of a pd_* array)
+%macro TR_4x4_LUMA 2
+ ; m0: (s0, s2) per column m1: (s1, s3) per column
+ SBUTTERFLY wd, 0, 1, 2
+
+ pmaddwd m2, m0, [pw_29_84] ; dst0
+ pmaddwd m3, m1, [pw_74_55]
+ paddd m2, m3
+ pmaddwd m3, m0, [pw_55_m29] ; dst1
+ pmaddwd m4, m1, [pw_74_m84]
+ paddd m3, m4
+ pmaddwd m4, m0, [pw_74_m74] ; dst2
+ pmaddwd m5, m1, [pw_0_74]
+ paddd m4, m5
+ pmaddwd m5, m0, [pw_84_55] ; dst3
+ pmaddwd m0, m1, [pw_m74_m29]
+ paddd m5, m0
+
+ mova m0, [%2]
+ paddd m2, m0
+ paddd m3, m0
+ paddd m4, m0
+ paddd m5, m0
+
+ psrad m2, %1
+ psrad m3, %1
+ psrad m4, %1
+ psrad m5, %1
+
+ ; clip16
+ packssdw m2, m3 ; dst0 | dst1
+ packssdw m4, m5 ; dst2 | dst3
+
+ ; transpose the 4x4 block for the next pass
+ SBUTTERFLY wd, 2, 4, 0
+ SBUTTERFLY wd, 2, 4, 0
+ SWAP 0, 2
+ SWAP 1, 4
+%endmacro
+
+; void ff_hevc_transform_4x4_luma_{8,10}_<opt>(int16_t *coeffs)
+; %1 = bitdepth
+%macro TRANSFORM_4x4_LUMA 1
+cglobal hevc_transform_4x4_luma_%1, 1, 1, 6, coeffs
+ mova m0, [coeffsq]
+ mova m1, [coeffsq + 16]
+
+ TR_4x4_LUMA 7, pd_64
+%if %1 == 8
+ TR_4x4_LUMA 12, pd_2048
+%elif %1 == 10
+ TR_4x4_LUMA 10, pd_512
+%endif
+
+ mova [coeffsq], m0
+ mova [coeffsq + 16], m1
+ RET
+%endmacro
+
; scale, pack (clip16) and store the residuals 0 e8[0] + o8[0] --> + %1
; 4 at one time (4 columns) 1 e8[1] + o8[1]
; from %5: e8/16 + o8/16, with %1 offset ...
@@ -832,6 +907,7 @@ INIT_XMM %2
%endif
IDCT_8x8 %1
IDCT_4x4 %1
+TRANSFORM_4x4_LUMA %1
%endmacro
INIT_IDCT_DC 8
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]