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
25enum MatrixMode {
26 MATRIX_SQUARE,
27 MATRIX_ROW,
28 MATRIX_COLUMN,
29 MATRIX_NBMODES,
30};
31
32typedef 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
63void ff_convolution_init_x86(ConvolutionContext *s);
64#endif
libavfilter/vf_convolution.c+3−38
@@ -25,48 +25,11 @@ · 24 unmodified lines
25#include "libavutil/opt.h"25#include "libavutil/opt.h"
26#include "libavutil/pixdesc.h"26#include "libavutil/pixdesc.h"
27#include "avfilter.h"27#include "avfilter.h"
28#include "convolution.h"
28#include "formats.h"29#include "formats.h"
29#include "internal.h"30#include "internal.h"
30#include "video.h"31#include "video.h"
31 32
32enum MatrixMode {
33 MATRIX_SQUARE,
34 MATRIX_ROW,
35 MATRIX_COLUMN,
36 MATRIX_NBMODES,
37};
38
39typedef 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
70#define OFFSET(x) offsetof(ConvolutionContext, x)33#define OFFSET(x) offsetof(ConvolutionContext, x)
71#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM34#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
72 35
@@ -625,6 +588,8 @@ static int config_input(AVFilterLink *inlink) · 552 unmodified lines
625 s->filter[p] = filter16_7x7;588 s->filter[p] = filter16_7x7;
626 }589 }
627 }590 }
591 if (ARCH_X86_64)
592 ff_convolution_init_x86(s);
628 } else if (!strcmp(ctx->filter->name, "prewitt")) {593 } else if (!strcmp(ctx->filter->name, "prewitt")) {
629 if (s->depth > 8)594 if (s->depth > 8)
630 for (p = 0; p < s->nb_planes; p++)595 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
5OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend_init.o5OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend_init.o
6OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif_init.o6OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif_init.o
7OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o7OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o
8OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution_init.o
8OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o9OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o
9OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o10OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o
10OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur_init.o11OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur_init.o
@@ -40,6 +41,7 @@ X86ASM-OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn.o · 29 unmodified lines
40X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o41X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o
41X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o42X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o
42X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o43X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o
44X86ASM-OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution.o
43X86ASM-OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate.o45X86ASM-OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate.o
44X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o46X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o
45X86ASM-OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur.o47X86ASM-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
23SECTION_RODATA
24half: dd 0.5
25
26SECTION .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
52cglobal filter_3x3, 4, 15, 7, dst, width, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x
53%else
54cglobal 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
154INIT_XMM sse4
155FILTER_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
27void 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
32av_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