[FFmpeg-devel] [PATCH 3/3] avfilter/vf_convolution: add X86 SIMD for filter_column()

xujunzz at sjtu.edu.cn xujunzz at sjtu.edu.cn
Tue Dec 3 09:52:07 EET 2019


From: Xu Jun <xujunzz at sjtu.edu.cn>

Tested using this command:
./ffmpeg_g -s 1280*720 -pix_fmt yuv420p -i test.yuv -vf convolution="1 2 3 4 5 6 7 8 9:1 2 3 4 5 6 7 8 9:1 2 3 4 5 6 7 8 9:1 2 3 4 5 6 7 8 9:1/45:1/45:1/45:1/45:1:2:3:4:column:column:column:column" -an -vframes 5000 -f null /dev/null -benchmark

after patch:
frame= 4317 fps=464 q=-0.0 Lsize=N/A time=00:02:52.68 bitrate=N/A speed=18.6x
video:2260kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
bench: utime=30.556s stime=2.361s rtime=9.307s
bench: maxrss=15156kB

before patch:
frame= 4317 fps=271 q=-0.0 Lsize=N/A time=00:02:52.68 bitrate=N/A speed=10.8x
video:2260kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
bench: utime=76.097s stime=1.676s rtime=15.929s
bench: maxrss=15160kB

Signed-off-by: Xu Jun <xujunzz at sjtu.edu.cn>
---
 libavfilter/x86/vf_convolution.asm    | 129 ++++++++++++++++++++++++++
 libavfilter/x86/vf_convolution_init.c |   9 ++
 2 files changed, 138 insertions(+)

diff --git a/libavfilter/x86/vf_convolution.asm b/libavfilter/x86/vf_convolution.asm
index b71e9720fb..3dbfb26978 100755
--- a/libavfilter/x86/vf_convolution.asm
+++ b/libavfilter/x86/vf_convolution.asm
@@ -258,3 +258,132 @@ sub widthq, rq
 .end:
     RET
 %endif
+
+; void filter_column(uint8_t *dst, int height,
+;                         float rdiv, float bias, const int *const matrix,
+;                         const uint8_t *c[], int length, int radius,
+;                         int dstride, int stride);
+
+%if ARCH_X86_64
+INIT_XMM sse4
+%if UNIX64
+cglobal filter_column, 8, 15, 7, dst, height, matrix, ptr, width, rad, dstride, stride, i, ci, dst_off, off16, c_off, sum, r
+%else
+cglobal filter_column, 8, 15, 7, dst, height, rdiv, bias, matrix, ptr, width, rad, dstride, stride, i, ci, dst_off, off16, c_off, sum, r
+%endif
+
+%if WIN64
+    SWAP m0, m2
+    SWAP m1, m3
+    mov r2q, matrixmp
+    mov r3q, ptrmp
+    mov r4q, widthmp
+    mov r5q, radmp
+    mov r6q, dstridemp
+    mov r7q, stridemp
+    DEFINE_ARGS dst, height, matrix, ptr, width, rad, dstride, stride, i, ci, dst_off, off16, c_off, sum, r
+%endif
+
+movsxdifnidn widthq, widthd
+movsxdifnidn radq, radd
+movsxdifnidn dstrideq, dstrided
+movsxdifnidn strideq, strided
+sal radq, 1
+add radq, 1     ;2*radius+1
+movsxdifnidn heightq, heightd
+VBROADCASTSS m0, m0
+VBROADCASTSS m1, m1
+pxor m6, m6
+movss m5, [half]
+VBROADCASTSS m5, m5
+
+xor dst_offq, dst_offq
+xor c_offq, c_offq
+
+.loopy:
+    xor off16q, off16q
+    cmp widthq, mmsize/4
+    jl .loopr
+
+    mov rq, widthq
+    and rq, mmsize/4-1
+    sub widthq, rq
+
+    .loop16: ;parallel process 16 elements in a row
+        pxor m4, m4
+        xor iq, iq
+        .loopi:
+            movss m2, [matrixq + 4*iq]
+            VBROADCASTSS m2, m2
+            mov ciq, [ptrq + iq * gprsize]
+            movss m3, [ciq + c_offq] ;c[i][y*stride + off16]
+            punpcklbw m3, m6
+            punpcklwd m3, m6
+            pmulld m2, m3
+            paddd m4, m2
+
+            add iq, 1
+            cmp iq, radq
+            jl .loopi
+
+        cvtdq2ps m4, m4
+        mulps m4, m0     ; sum *= rdiv
+        addps m4, m1     ; sum += bias
+        addps m4, m5     ; sum += 0.5
+        cvttps2dq m4, m4
+        packssdw m4, m4
+        packuswb m4, m4
+        movss [dstq + dst_offq], m4
+        add c_offq, mmsize/4
+        add dst_offq, mmsize/4
+
+        add off16q, mmsize/4
+        cmp off16q, widthq
+        jl .loop16
+
+    add widthq, rq
+    cmp off16q, widthq
+    jge .paraend
+
+    .loopr:
+        xor sumd, sumd
+        xor iq, iq
+        .loopr_i:
+            mov ciq, [ptrq + iq * gprsize]
+            movzx rd, byte [ciq + c_offq]
+            imul rd, [matrixq + 4*iq]
+            add sumd, rd
+
+            add iq, 1
+            cmp iq, radq
+            jl .loopr_i
+
+        pxor m4, m4
+        cvtsi2ss m4, sumd
+        mulss m4, m0     ; sum *= rdiv
+        addss m4, m1     ; sum += bias
+        addss m4, m5     ; sum += 0.5
+        cvttps2dq m4, m4
+        packssdw m4, m4
+        packuswb m4, m4
+        movd sumd, m4
+        mov [dstq + dst_offq], sumb
+        add c_offq, 1
+        add dst_offq, 1
+        add off16q, 1
+        cmp off16q, widthq
+        jl .loopr
+
+    .paraend:
+    sub c_offq, widthq
+    sub dst_offq, widthq
+    add c_offq, strideq
+    add dst_offq, dstrideq
+
+    sub heightq, 1
+    cmp heightq, 0
+    jg .loopy
+
+.end:
+    RET
+%endif
diff --git a/libavfilter/x86/vf_convolution_init.c b/libavfilter/x86/vf_convolution_init.c
index 5eb3b3bee1..da39b8a400 100644
--- a/libavfilter/x86/vf_convolution_init.c
+++ b/libavfilter/x86/vf_convolution_init.c
@@ -34,6 +34,11 @@ void ff_filter_row_sse4(uint8_t *dst, int width,
                         const uint8_t *c[], int peak, int radius,
                         int dstride, int stride);
 
+void ff_filter_column_sse4(uint8_t *dst, int height,
+                        float rdiv, float bias, const int *const matrix,
+                        const uint8_t *c[], int length, int radius,
+                        int dstride, int stride);
+
 av_cold void ff_convolution_init_x86(ConvolutionContext *s)
 {
 #if ARCH_X86_64
@@ -50,6 +55,10 @@ av_cold void ff_convolution_init_x86(ConvolutionContext *s)
                 if (EXTERNAL_SSE4(cpu_flags))
                     s->filter[i] = ff_filter_row_sse4;
         }
+        if (s->mode[i] == MATRIX_COLUMN) {
+                if (EXTERNAL_SSE4(cpu_flags))
+                    s->filter[i] = ff_filter_column_sse4;
+        }
     }
 #endif
 }
-- 
2.17.1



More information about the ffmpeg-devel mailing list