History

avfilter/vf_convolution: add x86 SIMD for filter_3x3()

Tested using a simple command (apply edge enhance): ./ffmpeg_g -i ~/Downloads/bbb_sunflower_1080p_30fps_normal.mp4 \ -vf convolution="0 0 0 -1 1 0 0 0 0:0 0 0 -1 1 0 0 0 0:0 0 0 -1 1 0 0 0 0:0 0 0 -1 1 0 0 0 0:5:1:1:1:0:128:128:128" \ -an -vframes 1000 -f null /dev/null The fps increase from 151 to 270 on my local machine.

Ruiling Song committed 7 years ago

Commit 98e419c1 parent 6c67c8c5 files · +271 −38Browse files

Unified · Split

5 files
  1. libavfilter/convolution.h +64 −0
  2. libavfilter/vf_convolution.c +3 −38
  3. libavfilter/x86/Makefile +2 −0
  4. libavfilter/x86/vf_convolution.asm +156 −0
  5. libavfilter/x86/vf_convolution_init.c +46 −0
libavfilter/convolution.h+64−0
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (c) 2012-2013 Oka Motofumi (chikuzen.mo at gmail dot com)
3+ * Copyright (c) 2015 Paul B Mahol
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+#ifndef AVFILTER_CONVOLUTION_H
22+#define AVFILTER_CONVOLUTION_H
23+#include "avfilter.h"
24+
25+enum MatrixMode {
26+ MATRIX_SQUARE,
27+ MATRIX_ROW,
28+ MATRIX_COLUMN,
29+ MATRIX_NBMODES,
30+};
31+
32+typedef struct ConvolutionContext {
33+ const AVClass *class;
34+
35+ char *matrix_str[4];
36+ float rdiv[4];
37+ float bias[4];
38+ int mode[4];
39+ float scale;
40+ float delta;
41+ int planes;
42+
43+ int size[4];
44+ int depth;
45+ int max;
46+ int bpc;
47+ int nb_planes;
48+ int nb_threads;
49+ int planewidth[4];
50+ int planeheight[4];
51+ int matrix[4][49];
52+ int matrix_length[4];
53+ int copy[4];
54+
55+ void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride,
56+ int x, int width, int y, int height, int bpc);
57+ void (*filter[4])(uint8_t *dst, int width,
58+ float rdiv, float bias, const int *const matrix,
59+ const uint8_t *c[], int peak, int radius,
60+ int dstride, int stride);
61+} ConvolutionContext;
62+
63+void ff_convolution_init_x86(ConvolutionContext *s);
64+#endif
libavfilter/vf_convolution.c+3−38
@@ -25,48 +25,11 @@ · 24 unmodified lines
2525 #include "libavutil/opt.h"
2626 #include "libavutil/pixdesc.h"
2727 #include "avfilter.h"
28+#include "convolution.h"
2829 #include "formats.h"
2930 #include "internal.h"
3031 #include "video.h"
3132
32−enum MatrixMode {
33− MATRIX_SQUARE,
34− MATRIX_ROW,
35− MATRIX_COLUMN,
36− MATRIX_NBMODES,
37−};
38−
39−typedef struct ConvolutionContext {
40− const AVClass *class;
41−
42− char *matrix_str[4];
43− float rdiv[4];
44− float bias[4];
45− int mode[4];
46− float scale;
47− float delta;
48− int planes;
49−
50− int size[4];
51− int depth;
52− int max;
53− int bpc;
54− int nb_planes;
55− int nb_threads;
56− int planewidth[4];
57− int planeheight[4];
58− int matrix[4][49];
59− int matrix_length[4];
60− int copy[4];
61−
62− void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride,
63− int x, int width, int y, int height, int bpc);
64− void (*filter[4])(uint8_t *dst, int width,
65− float rdiv, float bias, const int *const matrix,
66− const uint8_t *c[], int peak, int radius,
67− int dstride, int stride);
68−} ConvolutionContext;
69−
7033 #define OFFSET(x) offsetof(ConvolutionContext, x)
7134 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
7235
@@ -625,6 +588,8 @@ static int config_input(AVFilterLink *inlink) · 552 unmodified lines
625588 s->filter[p] = filter16_7x7;
626589 }
627590 }
591+ if (ARCH_X86_64)
592+ ff_convolution_init_x86(s);
628593 } else if (!strcmp(ctx->filter->name, "prewitt")) {
629594 if (s->depth > 8)
630595 for (p = 0; p < s->nb_planes; p++)
libavfilter/x86/Makefile+2−0
@@ -5,6 +5,7 @@ OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn_init.o · 4 unmodified lines
55 OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend_init.o
66 OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif_init.o
77 OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o
8+OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution_init.o
89 OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o
910 OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o
1011 OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur_init.o
@@ -40,6 +41,7 @@ X86ASM-OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn.o · 29 unmodified lines
4041 X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o
4142 X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o
4243 X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o
44+X86ASM-OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution.o
4345 X86ASM-OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate.o
4446 X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o
4547 X86ASM-OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur.o
libavfilter/x86/vf_convolution.asm+156−0
@@ -0,0 +1,156 @@
1+;*****************************************************************************
2+;* x86-optimized functions for convolution filter
3+;*
4+;* This file is part of FFmpeg.
5+;*
6+;* FFmpeg is free software; you can redistribute it and/or
7+;* modify it under the terms of the GNU Lesser General Public
8+;* License as published by the Free Software Foundation; either
9+;* version 2.1 of the License, or (at your option) any later version.
10+;*
11+;* FFmpeg is distributed in the hope that it will be useful,
12+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+;* Lesser General Public License for more details.
15+;*
16+;* You should have received a copy of the GNU Lesser General Public
17+;* License along with FFmpeg; if not, write to the Free Software
18+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+;******************************************************************************
20+
21+%include "libavutil/x86/x86util.asm"
22+
23+SECTION_RODATA
24+half: dd 0.5
25+
26+SECTION .text
27+
28+; void filter_3x3_sse4(uint8_t *dst, int width,
29+; float rdiv, float bias, const int *const matrix,
30+; const uint8_t *c[], int peak, int radius,
31+; int dstride, int stride)
32+
33+
34+%macro PROCESS_V 1
35+ movss m2, [matrixq + 4 * %1]
36+ VBROADCASTSS m2, m2
37+ movss m3, [c%1q + xq]
38+ punpcklbw m3, m6
39+ punpcklwd m3, m6
40+ pmulld m2, m3
41+ paddd m4, m2
42+%endmacro
43+
44+%macro PROCESS_S 1
45+ movzx ptrd, byte [c%1q + xq]
46+ imul ptrd, [matrixq + 4 * %1]
47+ add rd, ptrd
48+%endmacro
49+
50+%macro FILTER_3X3 0
51+%if UNIX64
52+cglobal filter_3x3, 4, 15, 7, dst, width, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x
53+%else
54+cglobal filter_3x3, 4, 15, 7, dst, width, rdiv, bias, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x
55+%endif
56+
57+%if WIN64
58+ SWAP m0, m2
59+ SWAP m1, m3
60+ mov r2q, matrixmp
61+ mov r3q, ptrmp
62+ DEFINE_ARGS dst, width, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x
63+%endif
64+ movsxdifnidn widthq, widthd
65+ VBROADCASTSS m0, m0
66+ VBROADCASTSS m1, m1
67+ pxor m6, m6
68+ movss m5, [half]
69+ VBROADCASTSS m5, m5
70+ mov c0q, [ptrq + 0*gprsize]
71+ mov c1q, [ptrq + 1*gprsize]
72+ mov c2q, [ptrq + 2*gprsize]
73+ mov c3q, [ptrq + 3*gprsize]
74+ mov c4q, [ptrq + 4*gprsize]
75+ mov c5q, [ptrq + 5*gprsize]
76+ mov c6q, [ptrq + 6*gprsize]
77+ mov c7q, [ptrq + 7*gprsize]
78+ mov c8q, [ptrq + 8*gprsize]
79+
80+ xor xq, xq
81+ cmp widthq, mmsize/4
82+ jl .loop2
83+
84+ mov rq, widthq
85+ and rq, mmsize/4-1
86+ sub widthq, rq
87+
88+.loop1:
89+ pxor m4, m4 ; sum = 0;
90+
91+ PROCESS_V 0
92+ PROCESS_V 1
93+ PROCESS_V 2
94+ PROCESS_V 3
95+ PROCESS_V 4
96+ PROCESS_V 5
97+ PROCESS_V 6
98+ PROCESS_V 7
99+ PROCESS_V 8
100+
101+ cvtdq2ps m4, m4
102+ mulps m4, m0 ; sum *= rdiv
103+ addps m4, m1 ; sum += bias
104+ addps m4, m5 ; sum += 0.5
105+ cvttps2dq m4, m4
106+ packssdw m4, m4
107+ packuswb m4, m4
108+ movss [dstq + xq], m4
109+
110+ add xq, mmsize/4
111+ cmp xq, widthq
112+ jl .loop1
113+
114+ add widthq, rq
115+ cmp xq, widthq
116+ jge .end
117+
118+.loop2:
119+ ; reuse r to hold sum, init with zero
120+ xor rd, rd
121+
122+ PROCESS_S 0
123+ PROCESS_S 1
124+ PROCESS_S 2
125+ PROCESS_S 3
126+ PROCESS_S 4
127+ PROCESS_S 5
128+ PROCESS_S 6
129+ PROCESS_S 7
130+ PROCESS_S 8
131+
132+ pxor m4, m4
133+ cvtsi2ss m4, rd
134+ mulss m4, m0 ; sum *= rdiv
135+ addss m4, m1 ; sum += bias
136+ addss m4, m5 ; sum += 0.5
137+ ; we don't have simple scalar instructions to convert
138+ ; from 32bit to 8bit with saturation, so here
139+ ; just use packed version SSE instructions for simplicity.
140+ cvttps2dq m4, m4 ; trunc to integer
141+ packssdw m4, m4
142+ packuswb m4, m4
143+ movd rd, m4
144+ mov [dstq + xq], rb
145+
146+ add xq, 1
147+ cmp xq, widthq
148+ jl .loop2
149+.end:
150+ RET
151+%endmacro
152+
153+%if ARCH_X86_64
154+INIT_XMM sse4
155+FILTER_3X3
156+%endif
libavfilter/x86/vf_convolution_init.c+46−0
@@ -0,0 +1,46 @@
1+/*
2+ *
3+ * This file is part of FFmpeg.
4+ *
5+ * FFmpeg is free software; you can redistribute it and/or
6+ * modify it under the terms of the GNU Lesser General Public
7+ * License as published by the Free Software Foundation; either
8+ * version 2.1 of the License, or (at your option) any later version.
9+ *
10+ * FFmpeg is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+ * Lesser General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU Lesser General Public
16+ * License along with FFmpeg; if not, write to the Free Software
17+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+ */
19+
20+#include "config.h"
21+
22+#include "libavutil/attributes.h"
23+#include "libavutil/cpu.h"
24+#include "libavutil/x86/cpu.h"
25+#include "libavfilter/convolution.h"
26+
27+void ff_filter_3x3_sse4(uint8_t *dst, int width,
28+ float rdiv, float bias, const int *const matrix,
29+ const uint8_t *c[], int peak, int radius,
30+ int dstride, int stride);
31+
32+av_cold void ff_convolution_init_x86(ConvolutionContext *s)
33+{
34+#if ARCH_X86_64
35+ int i;
36+ int cpu_flags = av_get_cpu_flags();
37+ for (i = 0; i < 4; i++) {
38+ if (s->mode[i] == MATRIX_SQUARE) {
39+ if (s->matrix_length[i] == 9) {
40+ if (EXTERNAL_SSE4(cpu_flags))
41+ s->filter[i] = ff_filter_3x3_sse4;
42+ }
43+ }
44+ }
45+#endif
46+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t