[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