[FFmpeg-devel] [PATCH v2 1/5] avcodec/hevcdsp: Add NEON optimization for qpel weighted mode
Shengbin Meng
shengbinmeng at gmail.com
Wed Nov 22 15:59:06 EET 2017
From: Meng Wang <wangmeng.kids at bytedance.com>
Signed-off-by: Meng Wang <wangmeng.kids at bytedance.com>
---
libavcodec/arm/hevcdsp_init_neon.c | 67 +++++
libavcodec/arm/hevcdsp_qpel_neon.S | 509 +++++++++++++++++++++++++++++++++++++
2 files changed, 576 insertions(+)
diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c
index a4628d2a93..183162803e 100644
--- a/libavcodec/arm/hevcdsp_init_neon.c
+++ b/libavcodec/arm/hevcdsp_init_neon.c
@@ -81,6 +81,8 @@ static void (*put_hevc_qpel_neon[4][4])(int16_t *dst, ptrdiff_t dststride, uint8
int height, int width);
static void (*put_hevc_qpel_uw_neon[4][4])(uint8_t *dst, ptrdiff_t dststride, uint8_t *_src, ptrdiff_t _srcstride,
int width, int height, int16_t* src2, ptrdiff_t src2stride);
+static void (*put_hevc_qpel_wt_neon[4][4])(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
+ int width, int height, int denom, int wx1, int ox1, int wx0, int ox0, int16_t* src2, ptrdiff_t src2stride);
void ff_hevc_put_qpel_neon_wrapper(int16_t *dst, uint8_t *src, ptrdiff_t srcstride,
int height, intptr_t mx, intptr_t my, int width);
void ff_hevc_put_qpel_uni_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride,
@@ -88,6 +90,15 @@ void ff_hevc_put_qpel_uni_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_
void ff_hevc_put_qpel_bi_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride,
int16_t *src2,
int height, intptr_t mx, intptr_t my, int width);
+void ff_hevc_put_qpel_uni_w_neon_wrapper(uint8_t *dst, ptrdiff_t dststride,
+ uint8_t *src, ptrdiff_t srcstride,
+ int height, int denom, int wx, int ox,
+ intptr_t mx, intptr_t my, int width);
+void ff_hevc_put_qpel_bi_w_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride,
+ int16_t *src2,
+ int height, int denom, int wx0, int wx1,
+ int ox0, int ox1, intptr_t mx, intptr_t my, int width);
+
#define QPEL_FUNC(name) \
void name(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, \
int height, int width)
@@ -142,6 +153,26 @@ QPEL_FUNC_UW(ff_hevc_put_qpel_uw_h3v2_neon_8);
QPEL_FUNC_UW(ff_hevc_put_qpel_uw_h3v3_neon_8);
#undef QPEL_FUNC_UW
+#define QPEL_FUNC_WT(name) \
+void name(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride, \
+ int width, int height, int denom, int wx1, int ox1, int wx0, int ox0, int16_t* src2, ptrdiff_t src2stride);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_v1_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_v2_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_v3_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h1_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h2_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h3_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h1v1_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h1v2_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h1v3_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h2v1_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h2v2_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h2v3_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h3v1_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h3v2_neon_8);
+QPEL_FUNC_WT(ff_hevc_put_qpel_wt_h3v3_neon_8);
+#undef QPEL_FUNC_WT
+
void ff_hevc_put_qpel_neon_wrapper(int16_t *dst, uint8_t *src, ptrdiff_t srcstride,
int height, intptr_t mx, intptr_t my, int width) {
@@ -160,6 +191,21 @@ void ff_hevc_put_qpel_bi_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t
put_hevc_qpel_uw_neon[my][mx](dst, dststride, src, srcstride, width, height, src2, MAX_PB_SIZE);
}
+void ff_hevc_put_qpel_uni_w_neon_wrapper(uint8_t *dst, ptrdiff_t dststride,
+ uint8_t *src, ptrdiff_t srcstride,
+ int height, int denom, int wx, int ox,
+ intptr_t mx, intptr_t my, int width) {
+ put_hevc_qpel_wt_neon[my][mx](dst, dststride, src, srcstride, width, height, denom, wx, ox, 0, 0, NULL, 0);
+}
+
+void ff_hevc_put_qpel_bi_w_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride,
+ int16_t *src2,
+ int height, int denom, int wx0, int wx1,
+ int ox0, int ox1, intptr_t mx, intptr_t my, int width) {
+ put_hevc_qpel_wt_neon[my][mx](dst, dststride, src, srcstride, width, height, denom, wx1, ox1, wx0, ox0, src2, MAX_PB_SIZE);
+}
+
+
av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth)
{
if (bit_depth == 8) {
@@ -211,6 +257,21 @@ av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth)
put_hevc_qpel_uw_neon[3][1] = ff_hevc_put_qpel_uw_h1v3_neon_8;
put_hevc_qpel_uw_neon[3][2] = ff_hevc_put_qpel_uw_h2v3_neon_8;
put_hevc_qpel_uw_neon[3][3] = ff_hevc_put_qpel_uw_h3v3_neon_8;
+ put_hevc_qpel_wt_neon[1][0] = ff_hevc_put_qpel_wt_v1_neon_8;
+ put_hevc_qpel_wt_neon[2][0] = ff_hevc_put_qpel_wt_v2_neon_8;
+ put_hevc_qpel_wt_neon[3][0] = ff_hevc_put_qpel_wt_v3_neon_8;
+ put_hevc_qpel_wt_neon[0][1] = ff_hevc_put_qpel_wt_h1_neon_8;
+ put_hevc_qpel_wt_neon[0][2] = ff_hevc_put_qpel_wt_h2_neon_8;
+ put_hevc_qpel_wt_neon[0][3] = ff_hevc_put_qpel_wt_h3_neon_8;
+ put_hevc_qpel_wt_neon[1][1] = ff_hevc_put_qpel_wt_h1v1_neon_8;
+ put_hevc_qpel_wt_neon[1][2] = ff_hevc_put_qpel_wt_h2v1_neon_8;
+ put_hevc_qpel_wt_neon[1][3] = ff_hevc_put_qpel_wt_h3v1_neon_8;
+ put_hevc_qpel_wt_neon[2][1] = ff_hevc_put_qpel_wt_h1v2_neon_8;
+ put_hevc_qpel_wt_neon[2][2] = ff_hevc_put_qpel_wt_h2v2_neon_8;
+ put_hevc_qpel_wt_neon[2][3] = ff_hevc_put_qpel_wt_h3v2_neon_8;
+ put_hevc_qpel_wt_neon[3][1] = ff_hevc_put_qpel_wt_h1v3_neon_8;
+ put_hevc_qpel_wt_neon[3][2] = ff_hevc_put_qpel_wt_h2v3_neon_8;
+ put_hevc_qpel_wt_neon[3][3] = ff_hevc_put_qpel_wt_h3v3_neon_8;
for (x = 0; x < 10; x++) {
c->put_hevc_qpel[x][1][0] = ff_hevc_put_qpel_neon_wrapper;
c->put_hevc_qpel[x][0][1] = ff_hevc_put_qpel_neon_wrapper;
@@ -221,6 +282,12 @@ av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth)
c->put_hevc_qpel_bi[x][1][0] = ff_hevc_put_qpel_bi_neon_wrapper;
c->put_hevc_qpel_bi[x][0][1] = ff_hevc_put_qpel_bi_neon_wrapper;
c->put_hevc_qpel_bi[x][1][1] = ff_hevc_put_qpel_bi_neon_wrapper;
+ c->put_hevc_qpel_uni_w[x][1][0] = ff_hevc_put_qpel_uni_w_neon_wrapper;
+ c->put_hevc_qpel_uni_w[x][0][1] = ff_hevc_put_qpel_uni_w_neon_wrapper;
+ c->put_hevc_qpel_uni_w[x][1][1] = ff_hevc_put_qpel_uni_w_neon_wrapper;
+ c->put_hevc_qpel_bi_w[x][1][0] = ff_hevc_put_qpel_bi_w_neon_wrapper;
+ c->put_hevc_qpel_bi_w[x][0][1] = ff_hevc_put_qpel_bi_w_neon_wrapper;
+ c->put_hevc_qpel_bi_w[x][1][1] = ff_hevc_put_qpel_bi_w_neon_wrapper;
}
c->put_hevc_qpel[0][0][0] = ff_hevc_put_pixels_w2_neon_8;
c->put_hevc_qpel[1][0][0] = ff_hevc_put_pixels_w4_neon_8;
diff --git a/libavcodec/arm/hevcdsp_qpel_neon.S b/libavcodec/arm/hevcdsp_qpel_neon.S
index 86f92cf75a..e188b215ba 100644
--- a/libavcodec/arm/hevcdsp_qpel_neon.S
+++ b/libavcodec/arm/hevcdsp_qpel_neon.S
@@ -333,6 +333,139 @@
bx lr
.endm
+.macro hevc_put_qpel_wt_vX_neon_8 filter
+ push {r4-r12}
+ ldr r5, [sp, #36] // width
+ ldr r4, [sp, #40] // height
+ ldr r8, [sp, #44] // denom
+ ldr r9, [sp, #48] // wx1
+ ldr r10,[sp, #52] // ox1
+ ldr r11,[sp, #64] // src2
+ vpush {d8-d15}
+ sub r2, r2, r3, lsl #1 // r2 - 3*stride
+ sub r2, r3
+ mov r12, r4
+ mov r6, r0
+ mov r7, r2
+ add r8, #6 // weight shift = denom + 6
+ vdup.32 q5, r8 // shift is a 32 bit action
+ vneg.s32 q4, q5 // q4 = -q5
+ vdup.32 q6, r9 // q6 wx
+ vdup.32 q5, r10 // q5 ox
+ cmp r11, #0 // if src2 != 0 goto bi mode
+ bne .Lbi\@
+0: loadin8
+ cmp r5, #4
+ beq 4f
+8: subs r4, #1
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmovl.s16 q13, d15
+ vmul.s32 q14, q12, q6 // src * wx
+ vmul.s32 q15, q13, q6 // src * wx
+ vqrshl.s32 q12, q14, q4 // src * wx >> shift
+ vqrshl.s32 q13, q15, q4 // src * wx >> shift
+ vadd.s32 q14, q12, q5 // src * wx >> shift + ox
+ vadd.s32 q15, q13, q5 // src * wx >> shift + ox
+ vqmovun.s32 d2, q14 // narrow signed 4x32bit to unsigned 4x16bit
+ vqmovun.s32 d3, q15 // narrow signed 4x32bit to unsigned 4x16bit
+ vqmovn.u16 d0, q1 // narrow unsigned 8x16bit to unsigned 8x8bit
+ vst1.8 d0, [r0], r1
+ regshuffle_d8
+ vld1.8 {d23}, [r2], r3
+ bne 8b
+ subs r5, #8
+ beq 99f
+ mov r4, r12
+ add r6, #8
+ mov r0, r6
+ add r7, #8
+ mov r2, r7
+ b 0b
+4: subs r4, #1
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmul.s32 q14, q12, q6
+ vqrshl.s32 q12, q14, q4
+ vadd.s32 q14, q12, q5
+ vqmovun.s32 d14, q14
+ vqmovn.u16 d0, q7
+ vst1.32 d0[0], [r0], r1
+ regshuffle_d8
+ vld1.32 {d23[0]}, [r2], r3
+ bne 4b
+ b 99f
+.Lbi\@: ldr r8, [sp, #120] // w0
+ vdup.32 q1, r8 // q1 wx0
+ ldr r8, [sp, #124] // ox0
+ vdup.32 q2, r8 // q2 ox0
+ vadd.s32 q2, q5 // q2 = ox0 +ox1
+ vmov.s32 q10, #1
+ vadd.s32 q2, q10 // q2 = ox0 +ox1 + 1
+ vneg.s32 q15, q4 // q15 = - q4, preperation for left shift
+ vqrshl.s32 q3, q2, q15 // q3 = (ox0 + ox1 + 1)<<shift
+ vsub.s32 q4, q10
+ ldr r9, [sp, #132] // src2stride
+ lsl r9, #1
+ mov r10, r11 // r10 store startpoint src2
+0: loadin8
+ cmp r5, #4
+ beq 4f
+8: subs r4, #1
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmovl.s16 q13, d15
+ vmul.s32 q14, q12, q6 // src * w1
+ vmul.s32 q15, q13, q6 // src * w1
+ vld1.16 {q0}, [r11], r9 // load 8x16 bit pixels from src2 to q0
+ vmovl.s16 q2, d0 // extend signed 4x16bit to 4x32 bit
+ vmovl.s16 q5, d1
+ vmul.s32 q2, q1 // src2 * w0
+ vmul.s32 q5, q1 // src2 * w0
+ vadd.s32 q14, q2 // src * w1 + src2 * w0
+ vadd.s32 q15, q5 // src * w1 + src2 * w0
+ vadd.s32 q14, q3 // (src* w1 + src2 * w0 +(ox0 + ox1 + 1))<<shift
+ vadd.s32 q15, q3
+ vqshl.s32 q12, q14, q4 // shift
+ vqshl.s32 q13, q15, q4 // shift
+ vqmovun.s32 d28, q12 // narrow
+ vqmovun.s32 d29, q13 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.8 d0, [r0], r1
+ regshuffle_d8
+ vld1.8 {d23}, [r2], r3
+ bne 8b
+ subs r5, #8
+ beq 99f
+ mov r4, r12
+ add r6, #8
+ mov r0, r6
+ add r10, #16
+ mov r11, r10
+ add r7, #8
+ mov r2, r7
+ b 0b
+4: subs r4, #1
+ \filter
+ vmovl.s16 q12, d14
+ vmul.s32 q14, q12, q6
+ vld1.16 d0, [r11], r9
+ vmovl.s16 q2, d0
+ vmul.s32 q2, q1
+ vadd.s32 q14, q2
+ vadd.s32 q14, q3
+ vqshl.s32 q12, q14, q4 // shift
+ vqmovun.s32 d28, q12 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.32 d0[0], [r0], r1
+ regshuffle_d8
+ vld1.32 {d23[0]}, [r2], r3
+ bne 4b
+99: vpop {d8-d15}
+ pop {r4-r12}
+ bx lr
+.endm
+
function ff_hevc_put_qpel_v1_neon_8, export=1
hevc_put_qpel_vX_neon_8 qpel_filter_1
endfunc
@@ -358,6 +491,19 @@ function ff_hevc_put_qpel_uw_v3_neon_8, export=1
hevc_put_qpel_uw_vX_neon_8 qpel_filter_3
endfunc
+function ff_hevc_put_qpel_wt_v1_neon_8, export=1
+ hevc_put_qpel_wt_vX_neon_8 qpel_filter_1
+endfunc
+
+function ff_hevc_put_qpel_wt_v2_neon_8, export=1
+ hevc_put_qpel_wt_vX_neon_8 qpel_filter_2
+endfunc
+
+function ff_hevc_put_qpel_wt_v3_neon_8, export=1
+ hevc_put_qpel_wt_vX_neon_8 qpel_filter_3
+endfunc
+
+
.macro hevc_put_qpel_hX_neon_8 filter
push {r4, r5, r6, r7}
ldr r4, [sp, #16] // height
@@ -469,6 +615,135 @@ endfunc
bx lr
.endm
+.macro hevc_put_qpel_wt_hX_neon_8 filter
+ push {r4-r12}
+ ldr r5, [sp, #36] // width
+ ldr r4, [sp, #40] // height
+ ldr r8, [sp, #44] // denom
+ ldr r9, [sp, #48] // wx1
+ ldr r10,[sp, #52] // ox1
+ ldr r11,[sp, #64] // src2
+ vpush {d8-d15}
+ sub r2, #4
+ mov r12, r4
+ mov r6, r0
+ mov r7, r2
+ add r8, #6 // weight shift = denom + 6
+ vdup.32 q5, r8 // dup shift to 32 bit
+ vneg.s32 q4, q5 // q4 = -q5 shift
+ vdup.32 q6, r9 // q6 wx
+ vdup.32 q5, r10 // q5 ox
+ cmp r11, #0 // if src2 != 0 goto bi mode
+ bne .Lbi\@
+ cmp r5, #4
+ beq 4f
+8: subs r4, #1
+ vextin8
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmovl.s16 q13, d15
+ vmul.s32 q14, q12, q6
+ vmul.s32 q15, q13, q6
+ vqrshl.s32 q12, q14, q4
+ vqrshl.s32 q13, q15, q4
+ vadd.s32 q14, q12, q5
+ vadd.s32 q15, q13, q5
+ vqmovun.s32 d2, q14 // narrow
+ vqmovun.s32 d3, q15 // narrow
+ vqmovn.u16 d0, q1
+ vst1.8 d0, [r0], r1
+ bne 8b
+ subs r5, #8
+ beq 99f
+ mov r4, r12
+ add r6, #8
+ mov r0, r6
+ add r7, #8
+ mov r2, r7
+ cmp r5, #4
+ bne 8b
+4: subs r4, #1
+ vextin8
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmul.s32 q14, q12, q6
+ vqrshl.s32 q12, q14, q4
+ vadd.s32 q14, q12, q5
+ vqmovun.s32 d14, q14
+ vqmovn.u16 d0, q7
+ vst1.32 d0[0], [r0], r1
+ bne 4b
+ b 99f
+.Lbi\@:
+ ldr r8, [sp, #120] // w0
+ vdup.32 q1, r8 // q1 wx0
+ ldr r8, [sp, #124] // ox0
+ vdup.32 q2, r8 // q2 ox0
+ vadd.s32 q2, q5 // q2 = ox0 +ox1
+ vmov.s32 q10, #1
+ vadd.s32 q2, q10 // q2 = ox0 +ox1 + 1
+ vneg.s32 q15, q4 // q15 = - q4, preperation for left shift
+ vqrshl.s32 q3, q2, q15 // q3 = (ox0 + ox1 + 1)<<shift
+ vsub.s32 q4, q10
+ ldr r9, [sp, #132] // src2stride
+ lsl r9, #1
+ cmp r5, #4
+ beq 4f
+ mov r10, r11
+8: subs r4, #1
+ vextin8
+ \filter
+ vmovl.s16 q12, d14 // extending signed 4x16bit data to 4x32 bit
+ vmovl.s16 q13, d15
+ vmul.s32 q14, q12, q6 // src * w1
+ vmul.s32 q15, q13, q6 // src * w1
+ vld1.16 {q0}, [r11], r9 // load 8x16 bit pixels from src2 to q0
+ vmovl.s16 q2, d0 // extend signed 4x16bit to 4x32 bit
+ vmovl.s16 q5, d1
+ vmul.s32 q2, q1 // src2 * w0
+ vmul.s32 q5, q1 // src2 * w0
+ vadd.s32 q14, q2 // src * w1 + src2 * w0
+ vadd.s32 q15, q5 // src * w1 + src2 * w0
+ vadd.s32 q14, q3 // (src* w1 + src2 * w0 +(ox0 + ox1 + 1))<<shift
+ vadd.s32 q15, q3
+ vqshl.s32 q12, q14, q4 // shift
+ vqshl.s32 q13, q15, q4 // shift
+ vqmovun.s32 d28, q12 // narrow
+ vqmovun.s32 d29, q13 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.8 d0, [r0], r1
+ bne 8b
+ subs r5, #8
+ beq 99f
+ mov r4, r12
+ add r6, #8
+ add r10, #16
+ mov r11, r10
+ mov r0, r6
+ add r7, #8
+ mov r2, r7
+ cmp r5, #4
+ bne 8b
+4: subs r4, #1
+ vextin8
+ \filter
+ vmovl.s16 q12, d14
+ vmul.s32 q14, q12, q6
+ vld1.16 d0, [r11], r9
+ vmovl.s16 q2, d0
+ vmul.s32 q2, q1
+ vadd.s32 q14, q2
+ vadd.s32 q14, q3
+ vqshl.s32 q12, q14, q4 // shift
+ vqmovun.s32 d28, q12 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.32 d0[0], [r0], r1
+ bne 4b
+99: vpop {d8-d15}
+ pop {r4-r12}
+ bx lr
+.endm
+
function ff_hevc_put_qpel_h1_neon_8, export=1
hevc_put_qpel_hX_neon_8 qpel_filter_1
endfunc
@@ -494,6 +769,18 @@ function ff_hevc_put_qpel_uw_h3_neon_8, export=1
hevc_put_qpel_uw_hX_neon_8 qpel_filter_3
endfunc
+function ff_hevc_put_qpel_wt_h1_neon_8, export=1
+ hevc_put_qpel_wt_hX_neon_8 qpel_filter_1
+endfunc
+
+function ff_hevc_put_qpel_wt_h2_neon_8, export=1
+ hevc_put_qpel_wt_hX_neon_8 qpel_filter_2
+endfunc
+
+function ff_hevc_put_qpel_wt_h3_neon_8, export=1
+ hevc_put_qpel_wt_hX_neon_8 qpel_filter_3
+endfunc
+
.macro hevc_put_qpel_hXvY_neon_8 filterh filterv
push {r4, r5, r6, r7}
ldr r4, [sp, #16] // height
@@ -665,6 +952,192 @@ endfunc
bx lr
.endm
+.macro hevc_put_qpel_wt_hXvY_neon_8 filterh filterv
+ push {r4-r12}
+ ldr r5, [sp, #36] // width
+ ldr r4, [sp, #40] // height
+ ldr r8, [sp, #44] // denom
+ ldr r9, [sp, #48] // wx
+ ldr r10,[sp, #52] // ox
+ ldr r11,[sp, #64] //src2
+ vpush {d8-d15}
+ sub r2, #4
+ sub r2, r2, r3, lsl #1
+ sub r2, r3 // extra_before 3
+ mov r12, r4
+ mov r6, r0
+ mov r7, r2
+ add r8, #6
+ vdup.32 q6, r8
+ vneg.s32 q5, q6 // q5 shift
+ vdup.32 q4, r9 // q4 wx
+ vdup.32 q6, r10 // q6 ox
+ vpush {q4-q6}
+ cmp r11, #0
+ bne .Lbi\@
+0: vextin8
+ \filterh q0
+ vextin8
+ \filterh q1
+ vextin8
+ \filterh q2
+ vextin8
+ \filterh q3
+ vextin8
+ \filterh q4
+ vextin8
+ \filterh q5
+ vextin8
+ \filterh q6
+ vextin8
+ \filterh q7
+ cmp r5, #4
+ beq 4f
+8: subs r4, #1
+ \filterv
+ vpop {q9-q11} // q9: wx q10: shift q11: ox
+ vmovl.s16 q12, d16
+ vmovl.s16 q13, d17
+ vmul.s32 q14, q12, q9
+ vmul.s32 q15, q13, q9
+ vqrshl.s32 q12, q14, q10
+ vqrshl.s32 q13, q15, q10
+ vadd.s32 q14, q12, q11
+ vadd.s32 q15, q13, q11
+ vqmovun.s32 d24, q14
+ vqmovun.s32 d25, q15
+ vqmovn.u16 d0, q12
+ vst1.8 d0, [r0], r1
+ vpush {q9-q11}
+ regshuffle_q8
+ vextin8
+ \filterh q7
+ bne 8b
+ subs r5, #8
+ beq 99f
+ mov r4, r12
+ add r6, #8
+ mov r0, r6
+ add r7, #8
+ mov r2, r7
+ b 0b
+4: subs r4, #1
+ \filterv
+ vpop {q9-q11} // q9: wx q10: shift q11: ox
+ vmovl.s16 q12, d16
+ vmul.s32 q14, q12, q9
+ vqrshl.s32 q12, q14, q10
+ vadd.s32 q14, q12, q11
+ vqmovun.s32 d24, q14
+ vqmovn.u16 d0, q12
+ vst1.32 d0[0], [r0], r1
+ vpush {q9-q11}
+ regshuffle_q8
+ vextin8
+ \filterh q7
+ bne 4b
+ b 99f
+.Lbi\@: ldr r8, [sp, #168] // w0
+ vdup.32 q1, r8 // q1 wx0
+ ldr r8, [sp, #172] // ox0
+ vdup.32 q3, r8 // dup ox0 to q3
+ ldr r9, [sp, #180] // src2stride
+ lsl r9, #1
+ vpop {q9-q11} // q9: wx q10: shift q11: ox
+ vadd.s32 q3, q11 // q3 = ox0 + ox1
+ vmov.s32 q4, #1
+ vadd.s32 q3, q4 // q3 = ox0 + ox1 + 1
+ vneg.s32 q15, q10 // q15 = -shift, prepare for left shift
+ vqrshl.s32 q2, q3, q15 // q2 = (ox0 + ox1 + 1)<<shift
+ vsub.s32 q10, q4 // q10 final shift = demon + #7
+ vmov.s32 q3, q10
+ vmov.s32 q4, q9
+ vpush {q1-q4} // q1: wx0, q2: final offset, q3: final shift, q4: wx1
+ mov r10, r11 // r10 store startpoint src2
+0: vextin8
+ \filterh q0
+ vextin8
+ \filterh q1
+ vextin8
+ \filterh q2
+ vextin8
+ \filterh q3
+ vextin8
+ \filterh q4
+ vextin8
+ \filterh q5
+ vextin8
+ \filterh q6
+ vextin8
+ \filterh q7
+ cmp r5, #4
+ beq 4f
+8: subs r4, #1
+ \filterv
+ vpop {q9-q12} // q9: wx0, q10: final offset, q11: final shift, q4: wx1
+ vmovl.s16 q13, d16 // move long filter result from q8 to q12
+ vmovl.s16 q14, d17 // move long filter result from q8 to q13
+ vmul.s32 q13, q12 // src * wx1
+ vmul.s32 q14, q12 // src * wx1
+ vld1.16 {q0}, [r11], r9
+ vmovl.s16 q8, d0
+ vmovl.s16 q15, d1
+ vmul.s32 q8, q9 // src2 * wx0
+ vmul.s32 q15, q9 // src2 * wx0
+ vadd.s32 q13, q8 // src * wx1 + src2 * wx0
+ vadd.s32 q14, q15 // src * wx1 + src2 * wx0
+ vadd.s32 q13, q10 // src * wx1 + src2 * wx0 + offset
+ vadd.s32 q14, q10 // src * wx1 + src2 * wx0 + offset
+ vqshl.s32 q8, q13, q11 // shift
+ vqshl.s32 q15, q14, q11 // shift
+ vqmovun.s32 d28, q8 // narrow
+ vqmovun.s32 d29, q15 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.8 d0, [r0], r1 // store
+ vpush {q9-q12} // push
+ regshuffle_q8
+ vextin8
+ \filterh q7
+ bne 8b
+ subs r5, #8
+ beq 98f
+ mov r4, r12
+ add r6, #8
+ mov r0, r6
+ add r10, #16
+ mov r11, r10
+ add r7, #8
+ mov r2, r7
+ b 0b
+4: subs r4, #1
+ \filterv
+ vpop {q9-q12} // q9: wx0, q10: final offset, q11: final shift, q4: wx1
+ vmovl.s16 q13, d16 // move long filter result from q8 to q12
+ vmul.s32 q13, q12 // src * wx1
+ vld1.16 d0, [r11], r9
+ vmovl.s16 q8, d0
+ vmul.s32 q8, q9 // src2 * wx0
+ vadd.s32 q13, q8 // src * wx1 + src2 * wx0
+ vadd.s32 q13, q10 // src * wx1 + src2 * wx0 + offset
+ vqshl.s32 q8, q13, q11 // shift
+ vqmovun.s32 d28, q8 // narrow
+ vqmovn.u16 d0, q14 // narrow
+ vst1.32 d0[0], [r0], r1
+ vpush {q9-q12} // push
+ regshuffle_q8
+ vextin8
+ \filterh q7
+ bne 4b
+98: vpop {q9-q12}
+ vpop {d8-d15}
+ pop {r4-r12}
+ bx lr
+99: vpop {q9-q11}
+ vpop {d8-d15}
+ pop {r4-r12}
+ bx lr
+.endm
+
function ff_hevc_put_qpel_h1v1_neon_8, export=1
hevc_put_qpel_hXvY_neon_8 qpel_filter_1 qpel_filter_1_32b
@@ -739,6 +1212,42 @@ function ff_hevc_put_qpel_uw_h3v3_neon_8, export=1
hevc_put_qpel_uw_hXvY_neon_8 qpel_filter_3 qpel_filter_3_32b
endfunc
+function ff_hevc_put_qpel_wt_h1v1_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_1 qpel_filter_1_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h2v1_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_2 qpel_filter_1_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h3v1_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_3 qpel_filter_1_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h1v2_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_1 qpel_filter_2_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h2v2_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_2 qpel_filter_2_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h3v2_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_3 qpel_filter_2_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h1v3_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_1 qpel_filter_3_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h2v3_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_2 qpel_filter_3_32b
+endfunc
+
+function ff_hevc_put_qpel_wt_h3v3_neon_8, export=1
+ hevc_put_qpel_wt_hXvY_neon_8 qpel_filter_3 qpel_filter_3_32b
+endfunc
+
.macro init_put_pixels
pld [r1]
pld [r1, r2]
--
2.13.6 (Apple Git-96)
More information about the ffmpeg-devel
mailing list