FFmpeg
vf_convolution.c
Go to the documentation of this file.
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 
22 #include "libavutil/avstring.h"
23 #include "libavutil/imgutils.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem_internal.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/pixdesc.h"
28 #include "avfilter.h"
29 #include "convolution.h"
30 #include "formats.h"
31 #include "internal.h"
32 #include "video.h"
33 
34 #define OFFSET(x) offsetof(ConvolutionContext, x)
35 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
36 
37 static const AVOption convolution_options[] = {
38  { "0m", "set matrix for 1st plane", OFFSET(matrix_str[0]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS },
39  { "1m", "set matrix for 2nd plane", OFFSET(matrix_str[1]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS },
40  { "2m", "set matrix for 3rd plane", OFFSET(matrix_str[2]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS },
41  { "3m", "set matrix for 4th plane", OFFSET(matrix_str[3]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS },
42  { "0rdiv", "set rdiv for 1st plane", OFFSET(rdiv[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
43  { "1rdiv", "set rdiv for 2nd plane", OFFSET(rdiv[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
44  { "2rdiv", "set rdiv for 3rd plane", OFFSET(rdiv[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
45  { "3rdiv", "set rdiv for 4th plane", OFFSET(rdiv[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
46  { "0bias", "set bias for 1st plane", OFFSET(bias[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
47  { "1bias", "set bias for 2nd plane", OFFSET(bias[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
48  { "2bias", "set bias for 3rd plane", OFFSET(bias[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
49  { "3bias", "set bias for 4th plane", OFFSET(bias[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
50  { "0mode", "set matrix mode for 1st plane", OFFSET(mode[0]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
51  { "1mode", "set matrix mode for 2nd plane", OFFSET(mode[1]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
52  { "2mode", "set matrix mode for 3rd plane", OFFSET(mode[2]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
53  { "3mode", "set matrix mode for 4th plane", OFFSET(mode[3]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
54  { "square", "square matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_SQUARE}, 0, 0, FLAGS, "mode" },
55  { "row", "single row matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_ROW} , 0, 0, FLAGS, "mode" },
56  { "column", "single column matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_COLUMN}, 0, 0, FLAGS, "mode" },
57  { NULL }
58 };
59 
60 AVFILTER_DEFINE_CLASS(convolution);
61 
62 static const int same3x3[9] = {0, 0, 0,
63  0, 1, 0,
64  0, 0, 0};
65 
66 static const int same5x5[25] = {0, 0, 0, 0, 0,
67  0, 0, 0, 0, 0,
68  0, 0, 1, 0, 0,
69  0, 0, 0, 0, 0,
70  0, 0, 0, 0, 0};
71 
72 static const int same7x7[49] = {0, 0, 0, 0, 0, 0, 0,
73  0, 0, 0, 0, 0, 0, 0,
74  0, 0, 0, 0, 0, 0, 0,
75  0, 0, 0, 1, 0, 0, 0,
76  0, 0, 0, 0, 0, 0, 0,
77  0, 0, 0, 0, 0, 0, 0,
78  0, 0, 0, 0, 0, 0, 0};
79 
80 static const enum AVPixelFormat pix_fmts[] = {
100 };
101 
102 typedef struct ThreadData {
103  AVFrame *in, *out;
104 } ThreadData;
105 
106 static void filter16_prewitt(uint8_t *dstp, int width,
107  float scale, float delta, const int *const matrix,
108  const uint8_t *c[], int peak, int radius,
109  int dstride, int stride, int size)
110 {
111  uint16_t *dst = (uint16_t *)dstp;
112  int x;
113 
114  for (x = 0; x < width; x++) {
115  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * -1 +
116  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 1 + AV_RN16A(&c[8][2 * x]) * 1;
117  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1 +
118  AV_RN16A(&c[5][2 * x]) * 1 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
119 
120  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
121  }
122 }
123 
124 static void filter16_roberts(uint8_t *dstp, int width,
125  float scale, float delta, const int *const matrix,
126  const uint8_t *c[], int peak, int radius,
127  int dstride, int stride, int size)
128 {
129  uint16_t *dst = (uint16_t *)dstp;
130  int x;
131 
132  for (x = 0; x < width; x++) {
133  float suma = AV_RN16A(&c[0][2 * x]) * 1 + AV_RN16A(&c[1][2 * x]) * -1;
134  float sumb = AV_RN16A(&c[4][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1;
135 
136  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
137  }
138 }
139 
140 static void filter16_sobel(uint8_t *dstp, int width,
141  float scale, float delta, const int *const matrix,
142  const uint8_t *c[], int peak, int radius,
143  int dstride, int stride, int size)
144 {
145  uint16_t *dst = (uint16_t *)dstp;
146  int x;
147 
148  for (x = 0; x < width; x++) {
149  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -2 + AV_RN16A(&c[2][2 * x]) * -1 +
150  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 2 + AV_RN16A(&c[8][2 * x]) * 1;
151  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -2 +
152  AV_RN16A(&c[5][2 * x]) * 2 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
153 
154  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
155  }
156 }
157 
158 static void filter16_scharr(uint8_t *dstp, int width,
159  float scale, float delta, const int *const matrix,
160  const uint8_t *c[], int peak, int radius,
161  int dstride, int stride, int size)
162 {
163  uint16_t *dst = (uint16_t *)dstp;
164  int x;
165 
166  for (x = 0; x < width; x++) {
167  float suma = AV_RN16A(&c[0][2 * x]) * -47 + AV_RN16A(&c[1][2 * x]) * -162 + AV_RN16A(&c[2][2 * x]) * -47 +
168  AV_RN16A(&c[6][2 * x]) * 47 + AV_RN16A(&c[7][2 * x]) * 162 + AV_RN16A(&c[8][2 * x]) * 47;
169  float sumb = AV_RN16A(&c[0][2 * x]) * -47 + AV_RN16A(&c[2][2 * x]) * 47 + AV_RN16A(&c[3][2 * x]) * -162 +
170  AV_RN16A(&c[5][2 * x]) * 162 + AV_RN16A(&c[6][2 * x]) * -47 + AV_RN16A(&c[8][2 * x]) * 47;
171 
172  suma /= 256.f;
173  sumb /= 256.f;
174  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
175  }
176 }
177 
178 static void filter16_kirsch(uint8_t *dstp, int width,
179  float scale, float delta, const int *const matrix,
180  const uint8_t *c[], int peak, int radius,
181  int dstride, int stride, int size)
182 {
183  uint16_t *dst = (uint16_t *)dstp;
184  const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2];
185  const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5];
186  const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8];
187  int x;
188 
189  for (x = 0; x < width; x++) {
190  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
191  c3[x] * -3 + c5[x] * -3 +
192  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
193  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
194  c3[x] * 5 + c5[x] * -3 +
195  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
196  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
197  c3[x] * 5 + c5[x] * 5 +
198  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
199  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
200  c3[x] * 5 + c5[x] * 5 +
201  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
202  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
203  c3[x] * -3 + c5[x] * 5 +
204  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
205  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
206  c3[x] * -3 + c5[x] * -3 +
207  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
208  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
209  c3[x] * -3 + c5[x] * -3 +
210  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
211  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
212  c3[x] * -3 + c5[x] * -3 +
213  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
214 
215  sum0 = FFMAX(sum0, sum1);
216  sum2 = FFMAX(sum2, sum3);
217  sum4 = FFMAX(sum4, sum5);
218  sum6 = FFMAX(sum6, sum7);
219  sum0 = FFMAX(sum0, sum2);
220  sum4 = FFMAX(sum4, sum6);
221  sum0 = FFMAX(sum0, sum4);
222 
223  dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak);
224  }
225 }
226 
227 static void filter_prewitt(uint8_t *dst, int width,
228  float scale, float delta, const int *const matrix,
229  const uint8_t *c[], int peak, int radius,
230  int dstride, int stride, int size)
231 {
232  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
233  const uint8_t *c3 = c[3], *c5 = c[5];
234  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
235  int x;
236 
237  for (x = 0; x < width; x++) {
238  float suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 +
239  c6[x] * 1 + c7[x] * 1 + c8[x] * 1;
240  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 +
241  c5[x] * 1 + c6[x] * -1 + c8[x] * 1;
242 
243  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
244  }
245 }
246 
247 static void filter_roberts(uint8_t *dst, int width,
248  float scale, float delta, const int *const matrix,
249  const uint8_t *c[], int peak, int radius,
250  int dstride, int stride, int size)
251 {
252  int x;
253 
254  for (x = 0; x < width; x++) {
255  float suma = c[0][x] * 1 + c[1][x] * -1;
256  float sumb = c[4][x] * 1 + c[3][x] * -1;
257 
258  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
259  }
260 }
261 
262 static void filter_sobel(uint8_t *dst, int width,
263  float scale, float delta, const int *const matrix,
264  const uint8_t *c[], int peak, int radius,
265  int dstride, int stride, int size)
266 {
267  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
268  const uint8_t *c3 = c[3], *c5 = c[5];
269  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
270  int x;
271 
272  for (x = 0; x < width; x++) {
273  float suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 +
274  c6[x] * 1 + c7[x] * 2 + c8[x] * 1;
275  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 +
276  c5[x] * 2 + c6[x] * -1 + c8[x] * 1;
277 
278  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
279  }
280 }
281 
282 static void filter_scharr(uint8_t *dst, int width,
283  float scale, float delta, const int *const matrix,
284  const uint8_t *c[], int peak, int radius,
285  int dstride, int stride, int size)
286 {
287  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
288  const uint8_t *c3 = c[3], *c5 = c[5];
289  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
290  int x;
291 
292  for (x = 0; x < width; x++) {
293  float suma = c0[x] * -47 + c1[x] * -162 + c2[x] * -47 +
294  c6[x] * 47 + c7[x] * 162 + c8[x] * 47;
295  float sumb = c0[x] * -47 + c2[x] * 47 + c3[x] * -162 +
296  c5[x] * 162 + c6[x] * -47 + c8[x] * 47;
297 
298  suma /= 256.f;
299  sumb /= 256.f;
300  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
301  }
302 }
303 
304 static void filter_kirsch(uint8_t *dst, int width,
305  float scale, float delta, const int *const matrix,
306  const uint8_t *c[], int peak, int radius,
307  int dstride, int stride, int size)
308 {
309  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
310  const uint8_t *c3 = c[3], *c5 = c[5];
311  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
312  int x;
313 
314  for (x = 0; x < width; x++) {
315  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
316  c3[x] * -3 + c5[x] * -3 +
317  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
318  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
319  c3[x] * 5 + c5[x] * -3 +
320  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
321  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
322  c3[x] * 5 + c5[x] * 5 +
323  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
324  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
325  c3[x] * 5 + c5[x] * 5 +
326  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
327  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
328  c3[x] * -3 + c5[x] * 5 +
329  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
330  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
331  c3[x] * -3 + c5[x] * -3 +
332  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
333  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
334  c3[x] * -3 + c5[x] * -3 +
335  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
336  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
337  c3[x] * -3 + c5[x] * -3 +
338  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
339 
340  sum0 = FFMAX(sum0, sum1);
341  sum2 = FFMAX(sum2, sum3);
342  sum4 = FFMAX(sum4, sum5);
343  sum6 = FFMAX(sum6, sum7);
344  sum0 = FFMAX(sum0, sum2);
345  sum4 = FFMAX(sum4, sum6);
346  sum0 = FFMAX(sum0, sum4);
347 
348  dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta);
349  }
350 }
351 
352 static void filter16_3x3(uint8_t *dstp, int width,
353  float rdiv, float bias, const int *const matrix,
354  const uint8_t *c[], int peak, int radius,
355  int dstride, int stride, int size)
356 {
357  uint16_t *dst = (uint16_t *)dstp;
358  int x;
359 
360  for (x = 0; x < width; x++) {
361  int sum = AV_RN16A(&c[0][2 * x]) * matrix[0] +
362  AV_RN16A(&c[1][2 * x]) * matrix[1] +
363  AV_RN16A(&c[2][2 * x]) * matrix[2] +
364  AV_RN16A(&c[3][2 * x]) * matrix[3] +
365  AV_RN16A(&c[4][2 * x]) * matrix[4] +
366  AV_RN16A(&c[5][2 * x]) * matrix[5] +
367  AV_RN16A(&c[6][2 * x]) * matrix[6] +
368  AV_RN16A(&c[7][2 * x]) * matrix[7] +
369  AV_RN16A(&c[8][2 * x]) * matrix[8];
370  sum = (int)(sum * rdiv + bias + 0.5f);
371  dst[x] = av_clip(sum, 0, peak);
372  }
373 }
374 
375 static void filter16_5x5(uint8_t *dstp, int width,
376  float rdiv, float bias, const int *const matrix,
377  const uint8_t *c[], int peak, int radius,
378  int dstride, int stride, int size)
379 {
380  uint16_t *dst = (uint16_t *)dstp;
381  int x;
382 
383  for (x = 0; x < width; x++) {
384  int i, sum = 0;
385 
386  for (i = 0; i < 25; i++)
387  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
388 
389  sum = (int)(sum * rdiv + bias + 0.5f);
390  dst[x] = av_clip(sum, 0, peak);
391  }
392 }
393 
394 static void filter16_7x7(uint8_t *dstp, int width,
395  float rdiv, float bias, const int *const matrix,
396  const uint8_t *c[], int peak, int radius,
397  int dstride, int stride, int size)
398 {
399  uint16_t *dst = (uint16_t *)dstp;
400  int x;
401 
402  for (x = 0; x < width; x++) {
403  int i, sum = 0;
404 
405  for (i = 0; i < 49; i++)
406  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
407 
408  sum = (int)(sum * rdiv + bias + 0.5f);
409  dst[x] = av_clip(sum, 0, peak);
410  }
411 }
412 
413 static void filter16_row(uint8_t *dstp, int width,
414  float rdiv, float bias, const int *const matrix,
415  const uint8_t *c[], int peak, int radius,
416  int dstride, int stride, int size)
417 {
418  uint16_t *dst = (uint16_t *)dstp;
419  int x;
420 
421  for (x = 0; x < width; x++) {
422  int i, sum = 0;
423 
424  for (i = 0; i < 2 * radius + 1; i++)
425  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
426 
427  sum = (int)(sum * rdiv + bias + 0.5f);
428  dst[x] = av_clip(sum, 0, peak);
429  }
430 }
431 
432 static void filter16_column(uint8_t *dstp, int height,
433  float rdiv, float bias, const int *const matrix,
434  const uint8_t *c[], int peak, int radius,
435  int dstride, int stride, int size)
436 {
437  DECLARE_ALIGNED(64, int, sum)[16];
438  uint16_t *dst = (uint16_t *)dstp;
439  const int width = FFMIN(16, size);
440 
441  for (int y = 0; y < height; y++) {
442 
443  memset(sum, 0, sizeof(sum));
444  for (int i = 0; i < 2 * radius + 1; i++) {
445  for (int off16 = 0; off16 < width; off16++)
446  sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i];
447  }
448 
449  for (int off16 = 0; off16 < width; off16++) {
450  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
451  dst[off16] = av_clip(sum[off16], 0, peak);
452  }
453  dst += dstride / 2;
454  }
455 }
456 
457 static void filter_7x7(uint8_t *dst, int width,
458  float rdiv, float bias, const int *const matrix,
459  const uint8_t *c[], int peak, int radius,
460  int dstride, int stride, int size)
461 {
462  int x;
463 
464  for (x = 0; x < width; x++) {
465  int i, sum = 0;
466 
467  for (i = 0; i < 49; i++)
468  sum += c[i][x] * matrix[i];
469 
470  sum = (int)(sum * rdiv + bias + 0.5f);
471  dst[x] = av_clip_uint8(sum);
472  }
473 }
474 
475 static void filter_5x5(uint8_t *dst, int width,
476  float rdiv, float bias, const int *const matrix,
477  const uint8_t *c[], int peak, int radius,
478  int dstride, int stride, int size)
479 {
480  int x;
481 
482  for (x = 0; x < width; x++) {
483  int i, sum = 0;
484 
485  for (i = 0; i < 25; i++)
486  sum += c[i][x] * matrix[i];
487 
488  sum = (int)(sum * rdiv + bias + 0.5f);
489  dst[x] = av_clip_uint8(sum);
490  }
491 }
492 
493 static void filter_3x3(uint8_t *dst, int width,
494  float rdiv, float bias, const int *const matrix,
495  const uint8_t *c[], int peak, int radius,
496  int dstride, int stride, int size)
497 {
498  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
499  const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];
500  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
501  int x;
502 
503  for (x = 0; x < width; x++) {
504  int sum = c0[x] * matrix[0] + c1[x] * matrix[1] + c2[x] * matrix[2] +
505  c3[x] * matrix[3] + c4[x] * matrix[4] + c5[x] * matrix[5] +
506  c6[x] * matrix[6] + c7[x] * matrix[7] + c8[x] * matrix[8];
507  sum = (int)(sum * rdiv + bias + 0.5f);
508  dst[x] = av_clip_uint8(sum);
509  }
510 }
511 
512 static void filter_row(uint8_t *dst, int width,
513  float rdiv, float bias, const int *const matrix,
514  const uint8_t *c[], int peak, int radius,
515  int dstride, int stride, int size)
516 {
517  int x;
518 
519  for (x = 0; x < width; x++) {
520  int i, sum = 0;
521 
522  for (i = 0; i < 2 * radius + 1; i++)
523  sum += c[i][x] * matrix[i];
524 
525  sum = (int)(sum * rdiv + bias + 0.5f);
526  dst[x] = av_clip_uint8(sum);
527  }
528 }
529 
530 static void filter_column(uint8_t *dst, int height,
531  float rdiv, float bias, const int *const matrix,
532  const uint8_t *c[], int peak, int radius,
533  int dstride, int stride, int size)
534 {
535  DECLARE_ALIGNED(64, int, sum)[16];
536 
537  for (int y = 0; y < height; y++) {
538  memset(sum, 0, sizeof(sum));
539 
540  for (int i = 0; i < 2 * radius + 1; i++) {
541  for (int off16 = 0; off16 < 16; off16++)
542  sum[off16] += c[i][0 + y * stride + off16] * matrix[i];
543  }
544 
545  for (int off16 = 0; off16 < 16; off16++) {
546  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
547  dst[off16] = av_clip_uint8(sum[off16]);
548  }
549  dst += dstride;
550  }
551 }
552 
553 static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,
554  int x, int w, int y, int h, int bpc)
555 {
556  int i;
557 
558  for (i = 0; i < 9; i++) {
559  int xoff = FFABS(x + ((i % 3) - 1));
560  int yoff = FFABS(y + (i / 3) - 1);
561 
562  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
563  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
564 
565  c[i] = src + xoff * bpc + yoff * stride;
566  }
567 }
568 
569 static void setup_5x5(int radius, const uint8_t *c[], const uint8_t *src, int stride,
570  int x, int w, int y, int h, int bpc)
571 {
572  int i;
573 
574  for (i = 0; i < 25; i++) {
575  int xoff = FFABS(x + ((i % 5) - 2));
576  int yoff = FFABS(y + (i / 5) - 2);
577 
578  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
579  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
580 
581  c[i] = src + xoff * bpc + yoff * stride;
582  }
583 }
584 
585 static void setup_7x7(int radius, const uint8_t *c[], const uint8_t *src, int stride,
586  int x, int w, int y, int h, int bpc)
587 {
588  int i;
589 
590  for (i = 0; i < 49; i++) {
591  int xoff = FFABS(x + ((i % 7) - 3));
592  int yoff = FFABS(y + (i / 7) - 3);
593 
594  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
595  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
596 
597  c[i] = src + xoff * bpc + yoff * stride;
598  }
599 }
600 
601 static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int stride,
602  int x, int w, int y, int h, int bpc)
603 {
604  int i;
605 
606  for (i = 0; i < radius * 2 + 1; i++) {
607  int xoff = FFABS(x + i - radius);
608 
609  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
610 
611  c[i] = src + xoff * bpc + y * stride;
612  }
613 }
614 
615 static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride,
616  int x, int w, int y, int h, int bpc)
617 {
618  int i;
619 
620  for (i = 0; i < radius * 2 + 1; i++) {
621  int xoff = FFABS(x + i - radius);
622 
623  xoff = xoff >= h ? 2 * h - 1 - xoff : xoff;
624 
625  c[i] = src + y * bpc + xoff * stride;
626  }
627 }
628 
629 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
630 {
631  ConvolutionContext *s = ctx->priv;
632  ThreadData *td = arg;
633  AVFrame *in = td->in;
634  AVFrame *out = td->out;
635  int plane;
636 
637  for (plane = 0; plane < s->nb_planes; plane++) {
638  const int mode = s->mode[plane];
639  const int bpc = s->bpc;
640  const int radius = s->size[plane] / 2;
641  const int height = s->planeheight[plane];
642  const int width = s->planewidth[plane];
643  const int stride = in->linesize[plane];
644  const int dstride = out->linesize[plane];
645  const int sizeh = mode == MATRIX_COLUMN ? width : height;
646  const int sizew = mode == MATRIX_COLUMN ? height : width;
647  const int slice_start = (sizeh * jobnr) / nb_jobs;
648  const int slice_end = (sizeh * (jobnr+1)) / nb_jobs;
649  const float rdiv = s->rdiv[plane];
650  const float bias = s->bias[plane];
651  const uint8_t *src = in->data[plane];
652  const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : dstride);
653  uint8_t *dst = out->data[plane] + dst_pos;
654  const int *matrix = s->matrix[plane];
655  const int step = mode == MATRIX_COLUMN ? 16 : 1;
656  const uint8_t *c[49];
657  int y, x;
658 
659  if (s->copy[plane]) {
660  if (mode == MATRIX_COLUMN)
661  av_image_copy_plane(dst, dstride, src + slice_start * bpc, stride,
662  (slice_end - slice_start) * bpc, height);
663  else
664  av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,
665  width * bpc, slice_end - slice_start);
666  continue;
667  }
668  for (y = slice_start; y < slice_end; y += step) {
669  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
670  const int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0;
671 
672  for (x = 0; x < radius; x++) {
673  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
674  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
675 
676  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
677  s->filter[plane](dst + yoff + xoff, 1, rdiv,
678  bias, matrix, c, s->max, radius,
679  dstride, stride, slice_end - step);
680  }
681  s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc);
682  s->filter[plane](dst + yoff + xoff, sizew - 2 * radius,
683  rdiv, bias, matrix, c, s->max, radius,
684  dstride, stride, slice_end - step);
685  for (x = sizew - radius; x < sizew; x++) {
686  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
687  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
688 
689  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
690  s->filter[plane](dst + yoff + xoff, 1, rdiv,
691  bias, matrix, c, s->max, radius,
692  dstride, stride, slice_end - step);
693  }
694  if (mode != MATRIX_COLUMN)
695  dst += dstride;
696  }
697  }
698 
699  return 0;
700 }
701 
703 {
704  ConvolutionContext *s = ctx->priv;
705  AVFilterLink *inlink = ctx->inputs[0];
707  int p, i;
708 
709  if (!strcmp(ctx->filter->name, "convolution")) {
710  for (i = 0; i < 4; i++) {
711  int *matrix = (int *)s->matrix[i];
712  char *orig, *p, *arg, *saveptr = NULL;
713  float sum = 1.f;
714 
715  p = orig = av_strdup(s->matrix_str[i]);
716  if (p) {
717  s->matrix_length[i] = 0;
718  s->rdiv[i] = 0.f;
719  sum = 0.f;
720 
721  while (s->matrix_length[i] < 49) {
722  if (!(arg = av_strtok(p, " |", &saveptr)))
723  break;
724 
725  p = NULL;
726  sscanf(arg, "%d", &matrix[s->matrix_length[i]]);
727  sum += matrix[s->matrix_length[i]];
728  s->matrix_length[i]++;
729  }
730 
731  av_freep(&orig);
732  if (!(s->matrix_length[i] & 1)) {
733  av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n");
734  return AVERROR(EINVAL);
735  }
736  }
737 
738  if (s->mode[i] == MATRIX_ROW) {
739  s->filter[i] = filter_row;
740  s->setup[i] = setup_row;
741  s->size[i] = s->matrix_length[i];
742  } else if (s->mode[i] == MATRIX_COLUMN) {
743  s->filter[i] = filter_column;
744  s->setup[i] = setup_column;
745  s->size[i] = s->matrix_length[i];
746  } else if (s->matrix_length[i] == 9) {
747  s->size[i] = 3;
748 
749  if (!memcmp(matrix, same3x3, sizeof(same3x3))) {
750  s->copy[i] = 1;
751  } else {
752  s->filter[i] = filter_3x3;
753  s->copy[i] = 0;
754  }
755  s->setup[i] = setup_3x3;
756  } else if (s->matrix_length[i] == 25) {
757  s->size[i] = 5;
758  if (!memcmp(matrix, same5x5, sizeof(same5x5))) {
759  s->copy[i] = 1;
760  } else {
761  s->filter[i] = filter_5x5;
762  s->copy[i] = 0;
763  }
764  s->setup[i] = setup_5x5;
765  } else if (s->matrix_length[i] == 49) {
766  s->size[i] = 7;
767  if (!memcmp(matrix, same7x7, sizeof(same7x7))) {
768  s->copy[i] = 1;
769  } else {
770  s->filter[i] = filter_7x7;
771  s->copy[i] = 0;
772  }
773  s->setup[i] = setup_7x7;
774  } else {
775  return AVERROR(EINVAL);
776  }
777 
778  if (sum == 0)
779  sum = 1;
780  if (s->rdiv[i] == 0)
781  s->rdiv[i] = 1. / sum;
782 
783  if (s->copy[i] && (s->rdiv[i] != 1. || s->bias[i] != 0.))
784  s->copy[i] = 0;
785  }
786  } else if (!strcmp(ctx->filter->name, "prewitt")) {
787  for (i = 0; i < 4; i++) {
788  s->filter[i] = filter_prewitt;
789  s->copy[i] = !((1 << i) & s->planes);
790  s->size[i] = 3;
791  s->setup[i] = setup_3x3;
792  s->rdiv[i] = s->scale;
793  s->bias[i] = s->delta;
794  }
795  } else if (!strcmp(ctx->filter->name, "roberts")) {
796  for (i = 0; i < 4; i++) {
797  s->filter[i] = filter_roberts;
798  s->copy[i] = !((1 << i) & s->planes);
799  s->size[i] = 3;
800  s->setup[i] = setup_3x3;
801  s->rdiv[i] = s->scale;
802  s->bias[i] = s->delta;
803  }
804  } else if (!strcmp(ctx->filter->name, "sobel")) {
805  for (i = 0; i < 4; i++) {
806  s->filter[i] = filter_sobel;
807  s->copy[i] = !((1 << i) & s->planes);
808  s->size[i] = 3;
809  s->setup[i] = setup_3x3;
810  s->rdiv[i] = s->scale;
811  s->bias[i] = s->delta;
812  }
813  } else if (!strcmp(ctx->filter->name, "kirsch")) {
814  for (i = 0; i < 4; i++) {
815  s->filter[i] = filter_kirsch;
816  s->copy[i] = !((1 << i) & s->planes);
817  s->size[i] = 3;
818  s->setup[i] = setup_3x3;
819  s->rdiv[i] = s->scale;
820  s->bias[i] = s->delta;
821  }
822  } else if (!strcmp(ctx->filter->name, "scharr")) {
823  for (i = 0; i < 4; i++) {
824  s->filter[i] = filter_scharr;
825  s->copy[i] = !((1 << i) & s->planes);
826  s->size[i] = 3;
827  s->setup[i] = setup_3x3;
828  s->rdiv[i] = s->scale;
829  s->bias[i] = s->delta;
830  }
831  }
832 
833  s->depth = desc->comp[0].depth;
834  s->max = (1 << s->depth) - 1;
835 
836  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
837  s->planewidth[0] = s->planewidth[3] = inlink->w;
838  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
839  s->planeheight[0] = s->planeheight[3] = inlink->h;
840 
841  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
842  s->nb_threads = ff_filter_get_nb_threads(ctx);
843  s->bpc = (s->depth + 7) / 8;
844 
845  if (!strcmp(ctx->filter->name, "convolution")) {
846  if (s->depth > 8) {
847  for (p = 0; p < s->nb_planes; p++) {
848  if (s->mode[p] == MATRIX_ROW)
849  s->filter[p] = filter16_row;
850  else if (s->mode[p] == MATRIX_COLUMN)
851  s->filter[p] = filter16_column;
852  else if (s->size[p] == 3)
853  s->filter[p] = filter16_3x3;
854  else if (s->size[p] == 5)
855  s->filter[p] = filter16_5x5;
856  else if (s->size[p] == 7)
857  s->filter[p] = filter16_7x7;
858  }
859  }
860 #if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64
862 #endif
863  } else if (!strcmp(ctx->filter->name, "prewitt")) {
864  if (s->depth > 8)
865  for (p = 0; p < s->nb_planes; p++)
866  s->filter[p] = filter16_prewitt;
867  } else if (!strcmp(ctx->filter->name, "roberts")) {
868  if (s->depth > 8)
869  for (p = 0; p < s->nb_planes; p++)
870  s->filter[p] = filter16_roberts;
871  } else if (!strcmp(ctx->filter->name, "sobel")) {
872  if (s->depth > 8)
873  for (p = 0; p < s->nb_planes; p++)
874  s->filter[p] = filter16_sobel;
875  } else if (!strcmp(ctx->filter->name, "kirsch")) {
876  if (s->depth > 8)
877  for (p = 0; p < s->nb_planes; p++)
878  s->filter[p] = filter16_kirsch;
879  } else if (!strcmp(ctx->filter->name, "scharr")) {
880  if (s->depth > 8)
881  for (p = 0; p < s->nb_planes; p++)
882  s->filter[p] = filter16_scharr;
883  }
884 
885  return 0;
886 }
887 
889 {
890  AVFilterContext *ctx = inlink->dst;
891  return param_init(ctx);
892 }
893 
895 {
896  AVFilterContext *ctx = inlink->dst;
897  ConvolutionContext *s = ctx->priv;
898  AVFilterLink *outlink = ctx->outputs[0];
899  AVFrame *out;
900  ThreadData td;
901 
902  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
903  if (!out) {
904  av_frame_free(&in);
905  return AVERROR(ENOMEM);
906  }
908 
909  td.in = in;
910  td.out = out;
912  FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads));
913 
914  av_frame_free(&in);
915  return ff_filter_frame(outlink, out);
916 }
917 
918 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
919  char *res, int res_len, int flags)
920 {
921  int ret;
922 
923  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
924  if (ret < 0)
925  return ret;
926 
927  return param_init(ctx);
928 }
929 
930 static const AVFilterPad convolution_inputs[] = {
931  {
932  .name = "default",
933  .type = AVMEDIA_TYPE_VIDEO,
934  .config_props = config_input,
935  .filter_frame = filter_frame,
936  },
937 };
938 
940  {
941  .name = "default",
942  .type = AVMEDIA_TYPE_VIDEO,
943  },
944 };
945 
946 #if CONFIG_CONVOLUTION_FILTER
947 
948 const AVFilter ff_vf_convolution = {
949  .name = "convolution",
950  .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."),
951  .priv_size = sizeof(ConvolutionContext),
952  .priv_class = &convolution_class,
957  .process_command = process_command,
958 };
959 
960 #endif /* CONFIG_CONVOLUTION_FILTER */
961 
962 static const AVOption common_options[] = {
963  { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS},
964  { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS},
965  { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS},
966  { NULL }
967 };
968 
969 AVFILTER_DEFINE_CLASS_EXT(common, "kirsch/prewitt/roberts/scharr/sobel",
971 
972 #if CONFIG_PREWITT_FILTER
973 
974 const AVFilter ff_vf_prewitt = {
975  .name = "prewitt",
976  .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."),
977  .priv_size = sizeof(ConvolutionContext),
978  .priv_class = &common_class,
983  .process_command = process_command,
984 };
985 
986 #endif /* CONFIG_PREWITT_FILTER */
987 
988 #if CONFIG_SOBEL_FILTER
989 
990 const AVFilter ff_vf_sobel = {
991  .name = "sobel",
992  .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."),
993  .priv_size = sizeof(ConvolutionContext),
994  .priv_class = &common_class,
999  .process_command = process_command,
1000 };
1001 
1002 #endif /* CONFIG_SOBEL_FILTER */
1003 
1004 #if CONFIG_ROBERTS_FILTER
1005 
1006 const AVFilter ff_vf_roberts = {
1007  .name = "roberts",
1008  .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."),
1009  .priv_size = sizeof(ConvolutionContext),
1010  .priv_class = &common_class,
1015  .process_command = process_command,
1016 };
1017 
1018 #endif /* CONFIG_ROBERTS_FILTER */
1019 
1020 #if CONFIG_KIRSCH_FILTER
1021 
1022 const AVFilter ff_vf_kirsch = {
1023  .name = "kirsch",
1024  .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."),
1025  .priv_size = sizeof(ConvolutionContext),
1026  .priv_class = &common_class,
1031  .process_command = process_command,
1032 };
1033 
1034 #endif /* CONFIG_KIRSCH_FILTER */
1035 
1036 #if CONFIG_SCHARR_FILTER
1037 
1038 const AVFilter ff_vf_scharr = {
1039  .name = "scharr",
1040  .description = NULL_IF_CONFIG_SMALL("Apply scharr operator."),
1041  .priv_size = sizeof(ConvolutionContext),
1042  .priv_class = &common_class,
1047  .process_command = process_command,
1048 };
1049 
1050 #endif /* CONFIG_SCHARR_FILTER */
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:98
AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:434
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:413
stride
int stride
Definition: mace.c:144
td
#define td
Definition: regdef.h:70
common_options
static const AVOption common_options[]
Definition: vf_convolution.c:962
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
filter16_row
static void filter16_row(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:413
setup_5x5
static void setup_5x5(int radius, const uint8_t *c[], const uint8_t *src, int stride, int x, int w, int y, int h, int bpc)
Definition: vf_convolution.c:569
av_clip
#define av_clip
Definition: common.h:96
same5x5
static const int same5x5[25]
Definition: vf_convolution.c:66
filter16_7x7
static void filter16_7x7(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:394
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
mem_internal.h
filter_3x3
static void filter_3x3(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:493
filter16_roberts
static void filter16_roberts(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:124
out
FILE * out
Definition: movenc.c:54
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2564
ff_vf_scharr
const AVFilter ff_vf_scharr
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: internal.h:171
convolution_inputs
static const AVFilterPad convolution_inputs[]
Definition: vf_convolution.c:930
ff_vf_roberts
const AVFilter ff_vf_roberts
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
OFFSET
#define OFFSET(x)
Definition: vf_convolution.c:34
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
AV_PIX_FMT_YUVA422P9
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:426
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
pixdesc.h
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:433
w
uint8_t w
Definition: llviddspenc.c:38
AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:428
ff_vf_kirsch
const AVFilter ff_vf_kirsch
AVOption
AVOption.
Definition: opt.h:247
filter16_prewitt
static void filter16_prewitt(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:106
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:391
ff_vf_prewitt
const AVFilter ff_vf_prewitt
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:153
c1
static const uint64_t c1
Definition: murmur3.c:51
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:473
filter_column
static void filter_column(uint8_t *dst, int height, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:530
convolution.h
video.h
AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:429
filter_sobel
static void filter_sobel(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:262
setup_row
static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int stride, int x, int w, int y, int h, int bpc)
Definition: vf_convolution.c:601
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:371
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
planes
static const struct @320 planes[]
formats.h
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2604
AV_PIX_FMT_YUVA420P9
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:425
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:409
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
filter_scharr
static void filter_scharr(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:282
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:407
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:435
setup_column
static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride, int x, int w, int y, int h, int bpc)
Definition: vf_convolution.c:615
AV_PIX_FMT_YUV422P9
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:389
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_convolution.c:894
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1377
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:375
filter16_3x3
static void filter16_3x3(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:352
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:50
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:394
AV_PIX_FMT_YUVJ411P
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:248
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_convolution.c:918
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:403
MATRIX_NBMODES
@ MATRIX_NBMODES
Definition: convolution.h:29
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:411
filter16_column
static void filter16_column(uint8_t *dstp, int height, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:432
width
#define width
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
MATRIX_SQUARE
@ MATRIX_SQUARE
Definition: convolution.h:26
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:412
AV_PIX_FMT_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:404
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:51
filter_prewitt
static void filter_prewitt(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:227
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2041
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:186
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(convolution)
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:432
AV_PIX_FMT_YUV420P9
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:388
filter16_5x5
static void filter16_5x5(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:375
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:402
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:374
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
f
#define f(width, name)
Definition: cbs_vp9.c:255
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:191
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
arg
const char * arg
Definition: jacosubdec.c:67
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:65
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:372
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:410
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:537
MATRIX_ROW
@ MATRIX_ROW
Definition: convolution.h:27
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
src
#define src
Definition: vp8dsp.c:255
ConvolutionContext
Definition: convolution.h:32
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:392
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:406
param_init
static int param_init(AVFilterContext *ctx)
Definition: vf_convolution.c:702
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ff_vf_convolution
const AVFilter ff_vf_convolution
filter_5x5
static void filter_5x5(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:475
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
filter_roberts
static void filter_roberts(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:247
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: vf_convolution.c:80
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:396
size
int size
Definition: twinvq_data.h:10344
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:398
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:882
height
#define height
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:167
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:430
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:130
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:227
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem.h:116
filter_slice
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolution.c:629
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
FFMIN3
#define FFMIN3(a, b, c)
Definition: macros.h:50
setup_7x7
static void setup_7x7(int radius, const uint8_t *c[], const uint8_t *src, int stride, int x, int w, int y, int h, int bpc)
Definition: vf_convolution.c:585
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:408
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:803
delta
float delta
Definition: vorbis_enc_data.h:430
ThreadData
Used for passing data between threads.
Definition: dsddec.c:67
filter_7x7
static void filter_7x7(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:457
setup_3x3
static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride, int x, int w, int y, int h, int bpc)
Definition: vf_convolution.c:553
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:56
AV_PIX_FMT_YUV444P9
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:390
convolution_options
static const AVOption convolution_options[]
Definition: vf_convolution.c:37
AVFilter
Filter definition.
Definition: avfilter.h:149
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:427
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:395
AV_PIX_FMT_YUV422P14
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:400
convolution_outputs
static const AVFilterPad convolution_outputs[]
Definition: vf_convolution.c:939
c2
static const uint64_t c2
Definition: murmur3.c:52
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:431
filter_kirsch
static void filter_kirsch(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:304
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
avfilter.h
AV_RN16A
#define AV_RN16A(p)
Definition: intreadwrite.h:522
AVFILTER_DEFINE_CLASS_EXT
AVFILTER_DEFINE_CLASS_EXT(common, "kirsch/prewitt/roberts/scharr/sobel", common_options)
av_clip_uint8
#define av_clip_uint8
Definition: common.h:102
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:386
MATRIX_COLUMN
@ MATRIX_COLUMN
Definition: convolution.h:28
ff_vf_sobel
const AVFilter ff_vf_sobel
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:121
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:279
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
ThreadData::in
AVFrame * in
Definition: af_adecorrelate.c:154
filter_row
static void filter_row(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:512
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
ff_convolution_init_x86
void ff_convolution_init_x86(ConvolutionContext *s)
Definition: vf_convolution_init.c:32
filter16_kirsch
static void filter16_kirsch(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:178
same3x3
static const int same3x3[9]
Definition: vf_convolution.c:62
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_convolution.c:888
filter16_sobel
static void filter16_sobel(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:140
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:192
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
imgutils.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:334
AV_PIX_FMT_YUV410P
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
same7x7
static const int same7x7[49]
Definition: vf_convolution.c:72
AV_PIX_FMT_YUV440P12
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:397
h
h
Definition: vp9dsp_template.c:2038
AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:401
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:373
FLAGS
#define FLAGS
Definition: vf_convolution.c:35
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:143
int
int
Definition: ffmpeg_filter.c:156
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
filter16_scharr
static void filter16_scharr(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, int dstride, int stride, int size)
Definition: vf_convolution.c:158
AV_PIX_FMT_YUVA422P
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:166
AV_PIX_FMT_YUV420P14
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:399