[PATCH 2/2] avcodec/x86/h264_intrapred: add AVX2 for 10-bit pred16x16 plane
ZaneHam via ffmpeg-devel <[email protected]> Tue, 28 Jul 2026 10:04:23 +1200
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <[email protected]> |
---
libavcodec/x86/h264_intrapred_10bit.asm | 97 +++++++++++++++++++++++++
libavcodec/x86/h264_intrapred_init.c | 2 +
2 files changed, 99 insertions(+)
diff --git a/libavcodec/x86/h264_intrapred_10bit.asm b/libavcodec/x86/h264_intrapred_10bit.asm
index 78e2f263bc..dc090f3888 100644
--- a/libavcodec/x86/h264_intrapred_10bit.asm
+++ b/libavcodec/x86/h264_intrapred_10bit.asm
@@ -40,6 +40,12 @@ pw_m32101234: dw -3, -2, -1, 0, 1, 2, 3, 4
pw_m3: times 8 dw -3
pd_17: times 4 dd 17
+; plane prediction: H gradient coefficients for top[-1..6] and top[8..15],
+; and the per-column ramp 0..15 (dwords, for the 32-bit accumulators)
+plane_coef_lo: dw -8, -7, -6, -5, -4, -3, -2, -1
+plane_coef_hi: dw 1, 2, 3, 4, 5, 6, 7, 8
+plane_ramp: dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+
SECTION .text
; dest, left, right, src
@@ -1302,4 +1308,95 @@ cglobal pred16x16_128_dc_10, 2, 4
jg .loop
RET
+;-----------------------------------------------------------------------------
+; void ff_pred16x16_plane_10_avx2(pixel *src, ptrdiff_t stride)
+; H.264 intra 16x16 plane prediction, 10-bit.
+; H, V = weighted gradients of the top row / left column
+; pred[x,y] = clip((a + y*V + x*H) >> 5, 0, 1023)
+; Values exceed 16-bit range at 10-bit, so the 16 columns live in two YMM
+; registers of 32-bit accumulators.
+;-----------------------------------------------------------------------------
+INIT_YMM avx2
+cglobal pred16x16_plane_10, 2, 9, 8
+ ; ---- H: gradient over the top row (row -1) ----
+ mov r2, r0
+ sub r2, r1 ; r2 = &top[0]
+ movu xm0, [r2-2] ; top[-1..6] (8 words)
+ movu xm1, [r2+16] ; top[8..15] (8 words)
+ pmaddwd xm0, [plane_coef_lo]
+ pmaddwd xm1, [plane_coef_hi]
+ paddd xm0, xm1 ; 4 dword partial sums
+ pshufd xm1, xm0, 0x0e
+ paddd xm0, xm1
+ pshufd xm1, xm0, 0x01
+ paddd xm0, xm1 ; H (raw) in the low dword
+ movd r3d, xm0
+ lea r3d, [r3d*5+32]
+ sar r3d, 6 ; r3d = H = (5*H+32)>>6
+ movzx r8d, word [r2+30] ; top[15], kept for a
+
+ ; ---- V: gradient over the left column (scalar; it is strided) ----
+ lea r4, [r0+r1*8]
+ sub r4, 2 ; &left[8]
+ lea r5, [r0+r1*4]
+ lea r5, [r5+r1*2]
+ sub r5, 2 ; &left[6]
+ movzx r6d, word [r4]
+ movzx r7d, word [r5]
+ sub r6d, r7d
+ mov r2d, r6d ; V acc, k=1 term
+%assign k 2
+%rep 7
+ add r4, r1
+ sub r5, r1
+ movzx r6d, word [r4]
+ movzx r7d, word [r5]
+ sub r6d, r7d
+ imul r6d, r6d, k
+ add r2d, r6d
+%assign k k+1
+%endrep
+ lea r2d, [r2d*5+32]
+ sar r2d, 6 ; r2d = V = (5*V+32)>>6
+
+ ; ---- a = 16*(left[15] + top[15] + 1) - 7*(H+V) ----
+ movzx r6d, word [r4] ; r4 == &left[15] after the loop
+ lea r6d, [r6+r8+1]
+ shl r6d, 4 ; 16*(left15 + top15 + 1)
+ mov r7d, r2d
+ add r7d, r3d ; H+V
+ mov r8d, r7d
+ shl r8d, 3
+ sub r8d, r7d ; 7*(H+V)
+ sub r6d, r8d ; r6d = a
+
+ ; ---- build the column ramps: acc = a + col*H (dwords) ----
+ movd xm3, r3d
+ vpbroadcastd m3, xm3 ; H
+ movd xm2, r6d
+ vpbroadcastd m2, xm2 ; a
+ movd xm4, r2d
+ vpbroadcastd m4, xm4 ; V
+ pmulld m0, m3, [plane_ramp]
+ pmulld m1, m3, [plane_ramp+32]
+ paddd m0, m2 ; a + {0..7}*H
+ paddd m1, m2 ; a + {8..15}*H
+ vpbroadcastw m7, [pw_pixel_max] ; 1023, for the high clamp
+
+ ; ---- fill 16 rows ----
+ mov r2d, 16
+.loop:
+ vpsrad m5, m0, 5
+ vpsrad m6, m1, 5
+ vpackusdw m5, m5, m6 ; dword->word, clamps low to 0; lanes scrambled
+ vpermq m5, m5, 0xd8 ; unscramble to columns 0..15
+ vpminuw m5, m5, m7 ; clamp high to 1023
+ movu [r0], m5
+ paddd m0, m4 ; next row: += V
+ paddd m1, m4
+ add r0, r1
+ dec r2d
+ jg .loop
+ RET
+
%endif ; HAVE_AVX2_EXTERNAL
diff --git a/libavcodec/x86/h264_intrapred_init.c b/libavcodec/x86/h264_intrapred_init.c
index 852c9ed7d6..d8dbcc1374 100644
--- a/libavcodec/x86/h264_intrapred_init.c
+++ b/libavcodec/x86/h264_intrapred_init.c
@@ -103,6 +103,7 @@ PRED16x16(128_dc, 10, avx2)
PRED16x16(left_dc, 10, avx2)
PRED16x16(vertical, 10, avx2)
PRED16x16(horizontal, 10, avx2)
+PRED16x16(plane, 10, avx2)
/* 8-bit versions */
PRED16x16(vertical, 8, sse)
@@ -321,6 +322,7 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id,
h->pred16x16[LEFT_DC_PRED8x8 ] = ff_pred16x16_left_dc_10_avx2;
h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_10_avx2;
h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_10_avx2;
+ h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_10_avx2;
}
}
}
--
2.51.0.windows.2
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]