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 
81 {
82  static const enum AVPixelFormat pix_fmts[] = {
102  };
103 
105 }
106 
107 typedef struct ThreadData {
108  AVFrame *in, *out;
109 } ThreadData;
110 
111 static void filter16_prewitt(uint8_t *dstp, int width,
112  float scale, float delta, const int *const matrix,
113  const uint8_t *c[], int peak, int radius,
114  int dstride, int stride, int size)
115 {
116  uint16_t *dst = (uint16_t *)dstp;
117  int x;
118 
119  for (x = 0; x < width; x++) {
120  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * -1 +
121  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 1 + AV_RN16A(&c[8][2 * x]) * 1;
122  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1 +
123  AV_RN16A(&c[5][2 * x]) * 1 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
124 
125  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
126  }
127 }
128 
129 static void filter16_roberts(uint8_t *dstp, int width,
130  float scale, float delta, const int *const matrix,
131  const uint8_t *c[], int peak, int radius,
132  int dstride, int stride, int size)
133 {
134  uint16_t *dst = (uint16_t *)dstp;
135  int x;
136 
137  for (x = 0; x < width; x++) {
138  float suma = AV_RN16A(&c[0][2 * x]) * 1 + AV_RN16A(&c[1][2 * x]) * -1;
139  float sumb = AV_RN16A(&c[4][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1;
140 
141  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
142  }
143 }
144 
145 static void filter16_sobel(uint8_t *dstp, int width,
146  float scale, float delta, const int *const matrix,
147  const uint8_t *c[], int peak, int radius,
148  int dstride, int stride, int size)
149 {
150  uint16_t *dst = (uint16_t *)dstp;
151  int x;
152 
153  for (x = 0; x < width; x++) {
154  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -2 + AV_RN16A(&c[2][2 * x]) * -1 +
155  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 2 + AV_RN16A(&c[8][2 * x]) * 1;
156  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -2 +
157  AV_RN16A(&c[5][2 * x]) * 2 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
158 
159  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
160  }
161 }
162 
163 static void filter16_scharr(uint8_t *dstp, int width,
164  float scale, float delta, const int *const matrix,
165  const uint8_t *c[], int peak, int radius,
166  int dstride, int stride, int size)
167 {
168  uint16_t *dst = (uint16_t *)dstp;
169  int x;
170 
171  for (x = 0; x < width; x++) {
172  float suma = AV_RN16A(&c[0][2 * x]) * -47 + AV_RN16A(&c[1][2 * x]) * -162 + AV_RN16A(&c[2][2 * x]) * -47 +
173  AV_RN16A(&c[6][2 * x]) * 47 + AV_RN16A(&c[7][2 * x]) * 162 + AV_RN16A(&c[8][2 * x]) * 47;
174  float sumb = AV_RN16A(&c[0][2 * x]) * -47 + AV_RN16A(&c[2][2 * x]) * 47 + AV_RN16A(&c[3][2 * x]) * -162 +
175  AV_RN16A(&c[5][2 * x]) * 162 + AV_RN16A(&c[6][2 * x]) * -47 + AV_RN16A(&c[8][2 * x]) * 47;
176 
177  suma /= 256.f;
178  sumb /= 256.f;
179  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
180  }
181 }
182 
183 static void filter16_kirsch(uint8_t *dstp, int width,
184  float scale, float delta, const int *const matrix,
185  const uint8_t *c[], int peak, int radius,
186  int dstride, int stride, int size)
187 {
188  uint16_t *dst = (uint16_t *)dstp;
189  const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2];
190  const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5];
191  const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8];
192  int x;
193 
194  for (x = 0; x < width; x++) {
195  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
196  c3[x] * -3 + c5[x] * -3 +
197  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
198  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
199  c3[x] * 5 + c5[x] * -3 +
200  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
201  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
202  c3[x] * 5 + c5[x] * 5 +
203  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
204  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
205  c3[x] * 5 + c5[x] * 5 +
206  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
207  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
208  c3[x] * -3 + c5[x] * 5 +
209  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
210  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
211  c3[x] * -3 + c5[x] * -3 +
212  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
213  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
214  c3[x] * -3 + c5[x] * -3 +
215  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
216  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
217  c3[x] * -3 + c5[x] * -3 +
218  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
219 
220  sum0 = FFMAX(sum0, sum1);
221  sum2 = FFMAX(sum2, sum3);
222  sum4 = FFMAX(sum4, sum5);
223  sum6 = FFMAX(sum6, sum7);
224  sum0 = FFMAX(sum0, sum2);
225  sum4 = FFMAX(sum4, sum6);
226  sum0 = FFMAX(sum0, sum4);
227 
228  dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak);
229  }
230 }
231 
232 static void filter_prewitt(uint8_t *dst, int width,
233  float scale, float delta, const int *const matrix,
234  const uint8_t *c[], int peak, int radius,
235  int dstride, int stride, int size)
236 {
237  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
238  const uint8_t *c3 = c[3], *c5 = c[5];
239  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
240  int x;
241 
242  for (x = 0; x < width; x++) {
243  float suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 +
244  c6[x] * 1 + c7[x] * 1 + c8[x] * 1;
245  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 +
246  c5[x] * 1 + c6[x] * -1 + c8[x] * 1;
247 
248  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
249  }
250 }
251 
252 static void filter_roberts(uint8_t *dst, int width,
253  float scale, float delta, const int *const matrix,
254  const uint8_t *c[], int peak, int radius,
255  int dstride, int stride, int size)
256 {
257  int x;
258 
259  for (x = 0; x < width; x++) {
260  float suma = c[0][x] * 1 + c[1][x] * -1;
261  float sumb = c[4][x] * 1 + c[3][x] * -1;
262 
263  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
264  }
265 }
266 
267 static void filter_sobel(uint8_t *dst, int width,
268  float scale, float delta, const int *const matrix,
269  const uint8_t *c[], int peak, int radius,
270  int dstride, int stride, int size)
271 {
272  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
273  const uint8_t *c3 = c[3], *c5 = c[5];
274  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
275  int x;
276 
277  for (x = 0; x < width; x++) {
278  float suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 +
279  c6[x] * 1 + c7[x] * 2 + c8[x] * 1;
280  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 +
281  c5[x] * 2 + c6[x] * -1 + c8[x] * 1;
282 
283  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
284  }
285 }
286 
287 static void filter_scharr(uint8_t *dst, int width,
288  float scale, float delta, const int *const matrix,
289  const uint8_t *c[], int peak, int radius,
290  int dstride, int stride, int size)
291 {
292  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
293  const uint8_t *c3 = c[3], *c5 = c[5];
294  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
295  int x;
296 
297  for (x = 0; x < width; x++) {
298  float suma = c0[x] * -47 + c1[x] * -162 + c2[x] * -47 +
299  c6[x] * 47 + c7[x] * 162 + c8[x] * 47;
300  float sumb = c0[x] * -47 + c2[x] * 47 + c3[x] * -162 +
301  c5[x] * 162 + c6[x] * -47 + c8[x] * 47;
302 
303  suma /= 256.f;
304  sumb /= 256.f;
305  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
306  }
307 }
308 
309 static void filter_kirsch(uint8_t *dst, int width,
310  float scale, float delta, const int *const matrix,
311  const uint8_t *c[], int peak, int radius,
312  int dstride, int stride, int size)
313 {
314  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
315  const uint8_t *c3 = c[3], *c5 = c[5];
316  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
317  int x;
318 
319  for (x = 0; x < width; x++) {
320  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
321  c3[x] * -3 + c5[x] * -3 +
322  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
323  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
324  c3[x] * 5 + c5[x] * -3 +
325  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
326  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
327  c3[x] * 5 + c5[x] * 5 +
328  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
329  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
330  c3[x] * 5 + c5[x] * 5 +
331  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
332  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
333  c3[x] * -3 + c5[x] * 5 +
334  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
335  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
336  c3[x] * -3 + c5[x] * -3 +
337  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
338  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
339  c3[x] * -3 + c5[x] * -3 +
340  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
341  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
342  c3[x] * -3 + c5[x] * -3 +
343  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
344 
345  sum0 = FFMAX(sum0, sum1);
346  sum2 = FFMAX(sum2, sum3);
347  sum4 = FFMAX(sum4, sum5);
348  sum6 = FFMAX(sum6, sum7);
349  sum0 = FFMAX(sum0, sum2);
350  sum4 = FFMAX(sum4, sum6);
351  sum0 = FFMAX(sum0, sum4);
352 
353  dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta);
354  }
355 }
356 
357 static void filter16_3x3(uint8_t *dstp, int width,
358  float rdiv, float bias, const int *const matrix,
359  const uint8_t *c[], int peak, int radius,
360  int dstride, int stride, int size)
361 {
362  uint16_t *dst = (uint16_t *)dstp;
363  int x;
364 
365  for (x = 0; x < width; x++) {
366  int sum = AV_RN16A(&c[0][2 * x]) * matrix[0] +
367  AV_RN16A(&c[1][2 * x]) * matrix[1] +
368  AV_RN16A(&c[2][2 * x]) * matrix[2] +
369  AV_RN16A(&c[3][2 * x]) * matrix[3] +
370  AV_RN16A(&c[4][2 * x]) * matrix[4] +
371  AV_RN16A(&c[5][2 * x]) * matrix[5] +
372  AV_RN16A(&c[6][2 * x]) * matrix[6] +
373  AV_RN16A(&c[7][2 * x]) * matrix[7] +
374  AV_RN16A(&c[8][2 * x]) * matrix[8];
375  sum = (int)(sum * rdiv + bias + 0.5f);
376  dst[x] = av_clip(sum, 0, peak);
377  }
378 }
379 
380 static void filter16_5x5(uint8_t *dstp, int width,
381  float rdiv, float bias, const int *const matrix,
382  const uint8_t *c[], int peak, int radius,
383  int dstride, int stride, int size)
384 {
385  uint16_t *dst = (uint16_t *)dstp;
386  int x;
387 
388  for (x = 0; x < width; x++) {
389  int i, sum = 0;
390 
391  for (i = 0; i < 25; i++)
392  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
393 
394  sum = (int)(sum * rdiv + bias + 0.5f);
395  dst[x] = av_clip(sum, 0, peak);
396  }
397 }
398 
399 static void filter16_7x7(uint8_t *dstp, int width,
400  float rdiv, float bias, const int *const matrix,
401  const uint8_t *c[], int peak, int radius,
402  int dstride, int stride, int size)
403 {
404  uint16_t *dst = (uint16_t *)dstp;
405  int x;
406 
407  for (x = 0; x < width; x++) {
408  int i, sum = 0;
409 
410  for (i = 0; i < 49; i++)
411  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
412 
413  sum = (int)(sum * rdiv + bias + 0.5f);
414  dst[x] = av_clip(sum, 0, peak);
415  }
416 }
417 
418 static void filter16_row(uint8_t *dstp, int width,
419  float rdiv, float bias, const int *const matrix,
420  const uint8_t *c[], int peak, int radius,
421  int dstride, int stride, int size)
422 {
423  uint16_t *dst = (uint16_t *)dstp;
424  int x;
425 
426  for (x = 0; x < width; x++) {
427  int i, sum = 0;
428 
429  for (i = 0; i < 2 * radius + 1; i++)
430  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
431 
432  sum = (int)(sum * rdiv + bias + 0.5f);
433  dst[x] = av_clip(sum, 0, peak);
434  }
435 }
436 
437 static void filter16_column(uint8_t *dstp, int height,
438  float rdiv, float bias, const int *const matrix,
439  const uint8_t *c[], int peak, int radius,
440  int dstride, int stride, int size)
441 {
442  DECLARE_ALIGNED(64, int, sum)[16];
443  uint16_t *dst = (uint16_t *)dstp;
444  const int width = FFMIN(16, size);
445 
446  for (int y = 0; y < height; y++) {
447 
448  memset(sum, 0, sizeof(sum));
449  for (int i = 0; i < 2 * radius + 1; i++) {
450  for (int off16 = 0; off16 < width; off16++)
451  sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i];
452  }
453 
454  for (int off16 = 0; off16 < width; off16++) {
455  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
456  dst[off16] = av_clip(sum[off16], 0, peak);
457  }
458  dst += dstride / 2;
459  }
460 }
461 
462 static void filter_7x7(uint8_t *dst, int width,
463  float rdiv, float bias, const int *const matrix,
464  const uint8_t *c[], int peak, int radius,
465  int dstride, int stride, int size)
466 {
467  int x;
468 
469  for (x = 0; x < width; x++) {
470  int i, sum = 0;
471 
472  for (i = 0; i < 49; i++)
473  sum += c[i][x] * matrix[i];
474 
475  sum = (int)(sum * rdiv + bias + 0.5f);
476  dst[x] = av_clip_uint8(sum);
477  }
478 }
479 
480 static void filter_5x5(uint8_t *dst, int width,
481  float rdiv, float bias, const int *const matrix,
482  const uint8_t *c[], int peak, int radius,
483  int dstride, int stride, int size)
484 {
485  int x;
486 
487  for (x = 0; x < width; x++) {
488  int i, sum = 0;
489 
490  for (i = 0; i < 25; i++)
491  sum += c[i][x] * matrix[i];
492 
493  sum = (int)(sum * rdiv + bias + 0.5f);
494  dst[x] = av_clip_uint8(sum);
495  }
496 }
497 
498 static void filter_3x3(uint8_t *dst, int width,
499  float rdiv, float bias, const int *const matrix,
500  const uint8_t *c[], int peak, int radius,
501  int dstride, int stride, int size)
502 {
503  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
504  const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];
505  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
506  int x;
507 
508  for (x = 0; x < width; x++) {
509  int sum = c0[x] * matrix[0] + c1[x] * matrix[1] + c2[x] * matrix[2] +
510  c3[x] * matrix[3] + c4[x] * matrix[4] + c5[x] * matrix[5] +
511  c6[x] * matrix[6] + c7[x] * matrix[7] + c8[x] * matrix[8];
512  sum = (int)(sum * rdiv + bias + 0.5f);
513  dst[x] = av_clip_uint8(sum);
514  }
515 }
516 
517 static void filter_row(uint8_t *dst, int width,
518  float rdiv, float bias, const int *const matrix,
519  const uint8_t *c[], int peak, int radius,
520  int dstride, int stride, int size)
521 {
522  int x;
523 
524  for (x = 0; x < width; x++) {
525  int i, sum = 0;
526 
527  for (i = 0; i < 2 * radius + 1; i++)
528  sum += c[i][x] * matrix[i];
529 
530  sum = (int)(sum * rdiv + bias + 0.5f);
531  dst[x] = av_clip_uint8(sum);
532  }
533 }
534 
535 static void filter_column(uint8_t *dst, int height,
536  float rdiv, float bias, const int *const matrix,
537  const uint8_t *c[], int peak, int radius,
538  int dstride, int stride, int size)
539 {
540  DECLARE_ALIGNED(64, int, sum)[16];
541 
542  for (int y = 0; y < height; y++) {
543  memset(sum, 0, sizeof(sum));
544 
545  for (int i = 0; i < 2 * radius + 1; i++) {
546  for (int off16 = 0; off16 < 16; off16++)
547  sum[off16] += c[i][0 + y * stride + off16] * matrix[i];
548  }
549 
550  for (int off16 = 0; off16 < 16; off16++) {
551  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
552  dst[off16] = av_clip_uint8(sum[off16]);
553  }
554  dst += dstride;
555  }
556 }
557 
558 static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,
559  int x, int w, int y, int h, int bpc)
560 {
561  int i;
562 
563  for (i = 0; i < 9; i++) {
564  int xoff = FFABS(x + ((i % 3) - 1));
565  int yoff = FFABS(y + (i / 3) - 1);
566 
567  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
568  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
569 
570  c[i] = src + xoff * bpc + yoff * stride;
571  }
572 }
573 
574 static void setup_5x5(int radius, const uint8_t *c[], const uint8_t *src, int stride,
575  int x, int w, int y, int h, int bpc)
576 {
577  int i;
578 
579  for (i = 0; i < 25; i++) {
580  int xoff = FFABS(x + ((i % 5) - 2));
581  int yoff = FFABS(y + (i / 5) - 2);
582 
583  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
584  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
585 
586  c[i] = src + xoff * bpc + yoff * stride;
587  }
588 }
589 
590 static void setup_7x7(int radius, const uint8_t *c[], const uint8_t *src, int stride,
591  int x, int w, int y, int h, int bpc)
592 {
593  int i;
594 
595  for (i = 0; i < 49; i++) {
596  int xoff = FFABS(x + ((i % 7) - 3));
597  int yoff = FFABS(y + (i / 7) - 3);
598 
599  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
600  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
601 
602  c[i] = src + xoff * bpc + yoff * stride;
603  }
604 }
605 
606 static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int stride,
607  int x, int w, int y, int h, int bpc)
608 {
609  int i;
610 
611  for (i = 0; i < radius * 2 + 1; i++) {
612  int xoff = FFABS(x + i - radius);
613 
614  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
615 
616  c[i] = src + xoff * bpc + y * stride;
617  }
618 }
619 
620 static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride,
621  int x, int w, int y, int h, int bpc)
622 {
623  int i;
624 
625  for (i = 0; i < radius * 2 + 1; i++) {
626  int xoff = FFABS(x + i - radius);
627 
628  xoff = xoff >= h ? 2 * h - 1 - xoff : xoff;
629 
630  c[i] = src + y * bpc + xoff * stride;
631  }
632 }
633 
634 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
635 {
636  ConvolutionContext *s = ctx->priv;
637  ThreadData *td = arg;
638  AVFrame *in = td->in;
639  AVFrame *out = td->out;
640  int plane;
641 
642  for (plane = 0; plane < s->nb_planes; plane++) {
643  const int mode = s->mode[plane];
644  const int bpc = s->bpc;
645  const int radius = s->size[plane] / 2;
646  const int height = s->planeheight[plane];
647  const int width = s->planewidth[plane];
648  const int stride = in->linesize[plane];
649  const int dstride = out->linesize[plane];
650  const int sizeh = mode == MATRIX_COLUMN ? width : height;
651  const int sizew = mode == MATRIX_COLUMN ? height : width;
652  const int slice_start = (sizeh * jobnr) / nb_jobs;
653  const int slice_end = (sizeh * (jobnr+1)) / nb_jobs;
654  const float rdiv = s->rdiv[plane];
655  const float bias = s->bias[plane];
656  const uint8_t *src = in->data[plane];
657  const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : dstride);
658  uint8_t *dst = out->data[plane] + dst_pos;
659  const int *matrix = s->matrix[plane];
660  const int step = mode == MATRIX_COLUMN ? 16 : 1;
661  const uint8_t *c[49];
662  int y, x;
663 
664  if (s->copy[plane]) {
665  if (mode == MATRIX_COLUMN)
666  av_image_copy_plane(dst, dstride, src + slice_start * bpc, stride,
667  (slice_end - slice_start) * bpc, height);
668  else
669  av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,
670  width * bpc, slice_end - slice_start);
671  continue;
672  }
673  for (y = slice_start; y < slice_end; y += step) {
674  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
675  const int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0;
676 
677  for (x = 0; x < radius; x++) {
678  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
679  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
680 
681  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
682  s->filter[plane](dst + yoff + xoff, 1, rdiv,
683  bias, matrix, c, s->max, radius,
684  dstride, stride, slice_end - step);
685  }
686  s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc);
687  s->filter[plane](dst + yoff + xoff, sizew - 2 * radius,
688  rdiv, bias, matrix, c, s->max, radius,
689  dstride, stride, slice_end - step);
690  for (x = sizew - radius; x < sizew; x++) {
691  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
692  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
693 
694  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
695  s->filter[plane](dst + yoff + xoff, 1, rdiv,
696  bias, matrix, c, s->max, radius,
697  dstride, stride, slice_end - step);
698  }
699  if (mode != MATRIX_COLUMN)
700  dst += dstride;
701  }
702  }
703 
704  return 0;
705 }
706 
708 {
709  AVFilterContext *ctx = inlink->dst;
710  ConvolutionContext *s = ctx->priv;
712  int p;
713 
714  s->depth = desc->comp[0].depth;
715  s->max = (1 << s->depth) - 1;
716 
717  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
718  s->planewidth[0] = s->planewidth[3] = inlink->w;
719  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
720  s->planeheight[0] = s->planeheight[3] = inlink->h;
721 
722  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
723  s->nb_threads = ff_filter_get_nb_threads(ctx);
724  s->bpc = (s->depth + 7) / 8;
725 
726  if (!strcmp(ctx->filter->name, "convolution")) {
727  if (s->depth > 8) {
728  for (p = 0; p < s->nb_planes; p++) {
729  if (s->mode[p] == MATRIX_ROW)
730  s->filter[p] = filter16_row;
731  else if (s->mode[p] == MATRIX_COLUMN)
732  s->filter[p] = filter16_column;
733  else if (s->size[p] == 3)
734  s->filter[p] = filter16_3x3;
735  else if (s->size[p] == 5)
736  s->filter[p] = filter16_5x5;
737  else if (s->size[p] == 7)
738  s->filter[p] = filter16_7x7;
739  }
740  }
741 #if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64
743 #endif
744  } else if (!strcmp(ctx->filter->name, "prewitt")) {
745  if (s->depth > 8)
746  for (p = 0; p < s->nb_planes; p++)
747  s->filter[p] = filter16_prewitt;
748  } else if (!strcmp(ctx->filter->name, "roberts")) {
749  if (s->depth > 8)
750  for (p = 0; p < s->nb_planes; p++)
751  s->filter[p] = filter16_roberts;
752  } else if (!strcmp(ctx->filter->name, "sobel")) {
753  if (s->depth > 8)
754  for (p = 0; p < s->nb_planes; p++)
755  s->filter[p] = filter16_sobel;
756  } else if (!strcmp(ctx->filter->name, "kirsch")) {
757  if (s->depth > 8)
758  for (p = 0; p < s->nb_planes; p++)
759  s->filter[p] = filter16_kirsch;
760  } else if (!strcmp(ctx->filter->name, "scharr")) {
761  if (s->depth > 8)
762  for (p = 0; p < s->nb_planes; p++)
763  s->filter[p] = filter16_scharr;
764  }
765 
766  return 0;
767 }
768 
770 {
771  AVFilterContext *ctx = inlink->dst;
772  ConvolutionContext *s = ctx->priv;
773  AVFilterLink *outlink = ctx->outputs[0];
774  AVFrame *out;
775  ThreadData td;
776 
777  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
778  if (!out) {
779  av_frame_free(&in);
780  return AVERROR(ENOMEM);
781  }
783 
784  td.in = in;
785  td.out = out;
787  FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads));
788 
789  av_frame_free(&in);
790  return ff_filter_frame(outlink, out);
791 }
792 
794 {
795  ConvolutionContext *s = ctx->priv;
796  int i;
797 
798  if (!strcmp(ctx->filter->name, "convolution")) {
799  for (i = 0; i < 4; i++) {
800  int *matrix = (int *)s->matrix[i];
801  char *p, *arg, *saveptr = NULL;
802  float sum = 0;
803 
804  p = s->matrix_str[i];
805  if (p) {
806  s->matrix_length[i] = 0;
807 
808  while (s->matrix_length[i] < 49) {
809  if (!(arg = av_strtok(p, " |", &saveptr)))
810  break;
811 
812  p = NULL;
813  sscanf(arg, "%d", &matrix[s->matrix_length[i]]);
814  sum += matrix[s->matrix_length[i]];
815  s->matrix_length[i]++;
816  }
817 
818  if (!(s->matrix_length[i] & 1)) {
819  av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n");
820  return AVERROR(EINVAL);
821  }
822  }
823 
824  if (s->mode[i] == MATRIX_ROW) {
825  s->filter[i] = filter_row;
826  s->setup[i] = setup_row;
827  s->size[i] = s->matrix_length[i];
828  } else if (s->mode[i] == MATRIX_COLUMN) {
829  s->filter[i] = filter_column;
830  s->setup[i] = setup_column;
831  s->size[i] = s->matrix_length[i];
832  } else if (s->matrix_length[i] == 9) {
833  s->size[i] = 3;
834 
835  if (!memcmp(matrix, same3x3, sizeof(same3x3))) {
836  s->copy[i] = 1;
837  } else {
838  s->filter[i] = filter_3x3;
839  s->copy[i] = 0;
840  }
841  s->setup[i] = setup_3x3;
842  } else if (s->matrix_length[i] == 25) {
843  s->size[i] = 5;
844  if (!memcmp(matrix, same5x5, sizeof(same5x5))) {
845  s->copy[i] = 1;
846  } else {
847  s->filter[i] = filter_5x5;
848  s->copy[i] = 0;
849  }
850  s->setup[i] = setup_5x5;
851  } else if (s->matrix_length[i] == 49) {
852  s->size[i] = 7;
853  if (!memcmp(matrix, same7x7, sizeof(same7x7))) {
854  s->copy[i] = 1;
855  } else {
856  s->filter[i] = filter_7x7;
857  s->copy[i] = 0;
858  }
859  s->setup[i] = setup_7x7;
860  } else {
861  return AVERROR(EINVAL);
862  }
863 
864  if (sum == 0)
865  sum = 1;
866  if (s->rdiv[i] == 0)
867  s->rdiv[i] = 1. / sum;
868 
869  if (s->copy[i] && (s->rdiv[i] != 1. || s->bias[i] != 0.))
870  s->copy[i] = 0;
871  }
872  } else if (!strcmp(ctx->filter->name, "prewitt")) {
873  for (i = 0; i < 4; i++) {
874  if ((1 << i) & s->planes)
875  s->filter[i] = filter_prewitt;
876  else
877  s->copy[i] = 1;
878  s->size[i] = 3;
879  s->setup[i] = setup_3x3;
880  s->rdiv[i] = s->scale;
881  s->bias[i] = s->delta;
882  }
883  } else if (!strcmp(ctx->filter->name, "roberts")) {
884  for (i = 0; i < 4; i++) {
885  if ((1 << i) & s->planes)
886  s->filter[i] = filter_roberts;
887  else
888  s->copy[i] = 1;
889  s->size[i] = 3;
890  s->setup[i] = setup_3x3;
891  s->rdiv[i] = s->scale;
892  s->bias[i] = s->delta;
893  }
894  } else if (!strcmp(ctx->filter->name, "sobel")) {
895  for (i = 0; i < 4; i++) {
896  if ((1 << i) & s->planes)
897  s->filter[i] = filter_sobel;
898  else
899  s->copy[i] = 1;
900  s->size[i] = 3;
901  s->setup[i] = setup_3x3;
902  s->rdiv[i] = s->scale;
903  s->bias[i] = s->delta;
904  }
905  } else if (!strcmp(ctx->filter->name, "kirsch")) {
906  for (i = 0; i < 4; i++) {
907  if ((1 << i) & s->planes)
908  s->filter[i] = filter_kirsch;
909  else
910  s->copy[i] = 1;
911  s->size[i] = 3;
912  s->setup[i] = setup_3x3;
913  s->rdiv[i] = s->scale;
914  s->bias[i] = s->delta;
915  }
916  } else if (!strcmp(ctx->filter->name, "scharr")) {
917  for (i = 0; i < 4; i++) {
918  if ((1 << i) & s->planes)
919  s->filter[i] = filter_scharr;
920  else
921  s->copy[i] = 1;
922  s->size[i] = 3;
923  s->setup[i] = setup_3x3;
924  s->rdiv[i] = s->scale;
925  s->bias[i] = s->delta;
926  }
927  }
928 
929  return 0;
930 }
931 
932 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
933  char *res, int res_len, int flags)
934 {
935  int ret;
936 
937  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
938  if (ret < 0)
939  return ret;
940 
941  return init(ctx);
942 }
943 
944 static const AVFilterPad convolution_inputs[] = {
945  {
946  .name = "default",
947  .type = AVMEDIA_TYPE_VIDEO,
948  .config_props = config_input,
949  .filter_frame = filter_frame,
950  },
951 };
952 
954  {
955  .name = "default",
956  .type = AVMEDIA_TYPE_VIDEO,
957  },
958 };
959 
960 #if CONFIG_CONVOLUTION_FILTER
961 
962 const AVFilter ff_vf_convolution = {
963  .name = "convolution",
964  .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."),
965  .priv_size = sizeof(ConvolutionContext),
966  .priv_class = &convolution_class,
967  .init = init,
972  .process_command = process_command,
973 };
974 
975 #endif /* CONFIG_CONVOLUTION_FILTER */
976 
977 static const AVOption common_options[] = {
978  { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS},
979  { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS},
980  { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS},
981  { NULL }
982 };
983 
984 AVFILTER_DEFINE_CLASS_EXT(common, "kirsch/prewitt/roberts/scharr/sobel",
986 
987 #if CONFIG_PREWITT_FILTER
988 
989 const AVFilter ff_vf_prewitt = {
990  .name = "prewitt",
991  .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."),
992  .priv_size = sizeof(ConvolutionContext),
993  .priv_class = &common_class,
994  .init = init,
999  .process_command = process_command,
1000 };
1001 
1002 #endif /* CONFIG_PREWITT_FILTER */
1003 
1004 #if CONFIG_SOBEL_FILTER
1005 
1006 const AVFilter ff_vf_sobel = {
1007  .name = "sobel",
1008  .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."),
1009  .priv_size = sizeof(ConvolutionContext),
1010  .priv_class = &common_class,
1011  .init = init,
1016  .process_command = process_command,
1017 };
1018 
1019 #endif /* CONFIG_SOBEL_FILTER */
1020 
1021 #if CONFIG_ROBERTS_FILTER
1022 
1023 const AVFilter ff_vf_roberts = {
1024  .name = "roberts",
1025  .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."),
1026  .priv_size = sizeof(ConvolutionContext),
1027  .priv_class = &common_class,
1028  .init = init,
1033  .process_command = process_command,
1034 };
1035 
1036 #endif /* CONFIG_ROBERTS_FILTER */
1037 
1038 #if CONFIG_KIRSCH_FILTER
1039 
1040 const AVFilter ff_vf_kirsch = {
1041  .name = "kirsch",
1042  .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."),
1043  .priv_size = sizeof(ConvolutionContext),
1044  .priv_class = &common_class,
1045  .init = init,
1050  .process_command = process_command,
1051 };
1052 
1053 #endif /* CONFIG_KIRSCH_FILTER */
1054 
1055 #if CONFIG_SCHARR_FILTER
1056 
1057 const AVFilter ff_vf_scharr = {
1058  .name = "scharr",
1059  .description = NULL_IF_CONFIG_SMALL("Apply scharr operator."),
1060  .priv_size = sizeof(ConvolutionContext),
1061  .priv_class = &common_class,
1062  .init = init,
1067  .process_command = process_command,
1068 };
1069 
1070 #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:432
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:411
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:977
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:418
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:574
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:399
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:498
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:129
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:1019
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2540
ff_vf_scharr
const AVFilter ff_vf_scharr
convolution_inputs
static const AVFilterPad convolution_inputs[]
Definition: vf_convolution.c:944
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
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_convolution.c:80
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:424
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:431
w
uint8_t w
Definition: llviddspenc.c:38
AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:426
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:111
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:389
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:492
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:535
convolution.h
video.h
AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:427
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:267
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:606
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:369
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
formats.h
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2580
AV_PIX_FMT_YUVA420P9
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:423
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:407
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:287
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:405
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:433
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:620
AV_PIX_FMT_YUV422P9
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:387
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_convolution.c:769
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:373
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:357
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:392
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
planes
static const struct @318 planes[]
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:932
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:401
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:409
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:437
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:410
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:402
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:232
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2037
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
ff_set_common_formats_from_list
int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts)
Equivalent to ff_set_common_formats(ctx, ff_make_format_list(fmts))
Definition: formats.c:703
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(convolution)
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:290
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:430
AV_PIX_FMT_YUV420P9
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:386
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:380
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:400
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:372
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:152
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:370
if
if(ret)
Definition: filter_design.txt:179
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_convolution.c:793
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:408
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:390
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:404
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:480
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:252
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:394
size
int size
Definition: twinvq_data.h:10344
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:396
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:883
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:428
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
i
int i
Definition: input.c:406
filter_slice
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolution.c:634
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:590
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:406
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:804
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:462
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:558
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:388
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:425
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:393
AV_PIX_FMT_YUV422P14
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:398
convolution_outputs
static const AVFilterPad convolution_outputs[]
Definition: vf_convolution.c:953
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:429
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:309
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:346
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
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:171
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:517
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:183
same3x3
static const int same3x3[9]
Definition: vf_convolution.c:62
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_convolution.c:707
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:145
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:153
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:395
h
h
Definition: vp9dsp_template.c:2038
AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:399
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:371
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:163
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:397