FFmpeg  4.4
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/opt.h"
26 #include "libavutil/pixdesc.h"
27 #include "avfilter.h"
28 #include "convolution.h"
29 #include "formats.h"
30 #include "internal.h"
31 #include "video.h"
32 
33 #define OFFSET(x) offsetof(ConvolutionContext, x)
34 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
35 
36 static const AVOption convolution_options[] = {
37  { "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 },
38  { "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 },
39  { "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 },
40  { "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 },
41  { "0rdiv", "set rdiv for 1st plane", OFFSET(rdiv[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
42  { "1rdiv", "set rdiv for 2nd plane", OFFSET(rdiv[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
43  { "2rdiv", "set rdiv for 3rd plane", OFFSET(rdiv[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
44  { "3rdiv", "set rdiv for 4th plane", OFFSET(rdiv[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
45  { "0bias", "set bias for 1st plane", OFFSET(bias[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
46  { "1bias", "set bias for 2nd plane", OFFSET(bias[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
47  { "2bias", "set bias for 3rd plane", OFFSET(bias[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
48  { "3bias", "set bias for 4th plane", OFFSET(bias[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, INT_MAX, FLAGS},
49  { "0mode", "set matrix mode for 1st plane", OFFSET(mode[0]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
50  { "1mode", "set matrix mode for 2nd plane", OFFSET(mode[1]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
51  { "2mode", "set matrix mode for 3rd plane", OFFSET(mode[2]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
52  { "3mode", "set matrix mode for 4th plane", OFFSET(mode[3]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
53  { "square", "square matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_SQUARE}, 0, 0, FLAGS, "mode" },
54  { "row", "single row matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_ROW} , 0, 0, FLAGS, "mode" },
55  { "column", "single column matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_COLUMN}, 0, 0, FLAGS, "mode" },
56  { NULL }
57 };
58 
59 AVFILTER_DEFINE_CLASS(convolution);
60 
61 static const int same3x3[9] = {0, 0, 0,
62  0, 1, 0,
63  0, 0, 0};
64 
65 static const int same5x5[25] = {0, 0, 0, 0, 0,
66  0, 0, 0, 0, 0,
67  0, 0, 1, 0, 0,
68  0, 0, 0, 0, 0,
69  0, 0, 0, 0, 0};
70 
71 static const int same7x7[49] = {0, 0, 0, 0, 0, 0, 0,
72  0, 0, 0, 0, 0, 0, 0,
73  0, 0, 0, 0, 0, 0, 0,
74  0, 0, 0, 1, 0, 0, 0,
75  0, 0, 0, 0, 0, 0, 0,
76  0, 0, 0, 0, 0, 0, 0,
77  0, 0, 0, 0, 0, 0, 0};
78 
80 {
81  static const enum AVPixelFormat pix_fmts[] = {
101  };
102 
104 }
105 
106 typedef struct ThreadData {
107  AVFrame *in, *out;
108 } ThreadData;
109 
110 static void filter16_prewitt(uint8_t *dstp, int width,
111  float scale, float delta, const int *const matrix,
112  const uint8_t *c[], int peak, int radius,
113  int dstride, int stride, int size)
114 {
115  uint16_t *dst = (uint16_t *)dstp;
116  int x;
117 
118  for (x = 0; x < width; x++) {
119  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * -1 +
120  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 1 + AV_RN16A(&c[8][2 * x]) * 1;
121  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1 +
122  AV_RN16A(&c[5][2 * x]) * 1 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
123 
124  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
125  }
126 }
127 
128 static void filter16_roberts(uint8_t *dstp, int width,
129  float scale, float delta, const int *const matrix,
130  const uint8_t *c[], int peak, int radius,
131  int dstride, int stride, int size)
132 {
133  uint16_t *dst = (uint16_t *)dstp;
134  int x;
135 
136  for (x = 0; x < width; x++) {
137  float suma = AV_RN16A(&c[0][2 * x]) * 1 + AV_RN16A(&c[1][2 * x]) * -1;
138  float sumb = AV_RN16A(&c[4][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1;
139 
140  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
141  }
142 }
143 
144 static void filter16_sobel(uint8_t *dstp, int width,
145  float scale, float delta, const int *const matrix,
146  const uint8_t *c[], int peak, int radius,
147  int dstride, int stride, int size)
148 {
149  uint16_t *dst = (uint16_t *)dstp;
150  int x;
151 
152  for (x = 0; x < width; x++) {
153  float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -2 + AV_RN16A(&c[2][2 * x]) * -1 +
154  AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 2 + AV_RN16A(&c[8][2 * x]) * 1;
155  float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -2 +
156  AV_RN16A(&c[5][2 * x]) * 2 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1;
157 
158  dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak);
159  }
160 }
161 
162 static void filter16_kirsch(uint8_t *dstp, int width,
163  float scale, float delta, const int *const matrix,
164  const uint8_t *c[], int peak, int radius,
165  int dstride, int stride, int size)
166 {
167  uint16_t *dst = (uint16_t *)dstp;
168  const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2];
169  const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5];
170  const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8];
171  int x;
172 
173  for (x = 0; x < width; x++) {
174  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
175  c3[x] * -3 + c5[x] * -3 +
176  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
177  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
178  c3[x] * 5 + c5[x] * -3 +
179  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
180  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
181  c3[x] * 5 + c5[x] * 5 +
182  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
183  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
184  c3[x] * 5 + c5[x] * 5 +
185  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
186  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
187  c3[x] * -3 + c5[x] * 5 +
188  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
189  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
190  c3[x] * -3 + c5[x] * -3 +
191  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
192  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
193  c3[x] * -3 + c5[x] * -3 +
194  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
195  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
196  c3[x] * -3 + c5[x] * -3 +
197  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
198 
199  sum0 = FFMAX(sum0, sum1);
200  sum2 = FFMAX(sum2, sum3);
201  sum4 = FFMAX(sum4, sum5);
202  sum6 = FFMAX(sum6, sum7);
203  sum0 = FFMAX(sum0, sum2);
204  sum4 = FFMAX(sum4, sum6);
205  sum0 = FFMAX(sum0, sum4);
206 
207  dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak);
208  }
209 }
210 
211 static void filter_prewitt(uint8_t *dst, int width,
212  float scale, float delta, const int *const matrix,
213  const uint8_t *c[], int peak, int radius,
214  int dstride, int stride, int size)
215 {
216  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
217  const uint8_t *c3 = c[3], *c5 = c[5];
218  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
219  int x;
220 
221  for (x = 0; x < width; x++) {
222  float suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 +
223  c6[x] * 1 + c7[x] * 1 + c8[x] * 1;
224  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 +
225  c5[x] * 1 + c6[x] * -1 + c8[x] * 1;
226 
227  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
228  }
229 }
230 
231 static void filter_roberts(uint8_t *dst, int width,
232  float scale, float delta, const int *const matrix,
233  const uint8_t *c[], int peak, int radius,
234  int dstride, int stride, int size)
235 {
236  int x;
237 
238  for (x = 0; x < width; x++) {
239  float suma = c[0][x] * 1 + c[1][x] * -1;
240  float sumb = c[4][x] * 1 + c[3][x] * -1;
241 
242  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
243  }
244 }
245 
246 static void filter_sobel(uint8_t *dst, int width,
247  float scale, float delta, const int *const matrix,
248  const uint8_t *c[], int peak, int radius,
249  int dstride, int stride, int size)
250 {
251  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
252  const uint8_t *c3 = c[3], *c5 = c[5];
253  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
254  int x;
255 
256  for (x = 0; x < width; x++) {
257  float suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 +
258  c6[x] * 1 + c7[x] * 2 + c8[x] * 1;
259  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 +
260  c5[x] * 2 + c6[x] * -1 + c8[x] * 1;
261 
262  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
263  }
264 }
265 
266 static void filter_kirsch(uint8_t *dst, int width,
267  float scale, float delta, const int *const matrix,
268  const uint8_t *c[], int peak, int radius,
269  int dstride, int stride, int size)
270 {
271  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
272  const uint8_t *c3 = c[3], *c5 = c[5];
273  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
274  int x;
275 
276  for (x = 0; x < width; x++) {
277  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
278  c3[x] * -3 + c5[x] * -3 +
279  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
280  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
281  c3[x] * 5 + c5[x] * -3 +
282  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
283  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
284  c3[x] * 5 + c5[x] * 5 +
285  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
286  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
287  c3[x] * 5 + c5[x] * 5 +
288  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
289  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
290  c3[x] * -3 + c5[x] * 5 +
291  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
292  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
293  c3[x] * -3 + c5[x] * -3 +
294  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
295  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
296  c3[x] * -3 + c5[x] * -3 +
297  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
298  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
299  c3[x] * -3 + c5[x] * -3 +
300  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
301 
302  sum0 = FFMAX(sum0, sum1);
303  sum2 = FFMAX(sum2, sum3);
304  sum4 = FFMAX(sum4, sum5);
305  sum6 = FFMAX(sum6, sum7);
306  sum0 = FFMAX(sum0, sum2);
307  sum4 = FFMAX(sum4, sum6);
308  sum0 = FFMAX(sum0, sum4);
309 
310  dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta);
311  }
312 }
313 
314 static void filter16_3x3(uint8_t *dstp, int width,
315  float rdiv, float bias, const int *const matrix,
316  const uint8_t *c[], int peak, int radius,
317  int dstride, int stride, int size)
318 {
319  uint16_t *dst = (uint16_t *)dstp;
320  int x;
321 
322  for (x = 0; x < width; x++) {
323  int sum = AV_RN16A(&c[0][2 * x]) * matrix[0] +
324  AV_RN16A(&c[1][2 * x]) * matrix[1] +
325  AV_RN16A(&c[2][2 * x]) * matrix[2] +
326  AV_RN16A(&c[3][2 * x]) * matrix[3] +
327  AV_RN16A(&c[4][2 * x]) * matrix[4] +
328  AV_RN16A(&c[5][2 * x]) * matrix[5] +
329  AV_RN16A(&c[6][2 * x]) * matrix[6] +
330  AV_RN16A(&c[7][2 * x]) * matrix[7] +
331  AV_RN16A(&c[8][2 * x]) * matrix[8];
332  sum = (int)(sum * rdiv + bias + 0.5f);
333  dst[x] = av_clip(sum, 0, peak);
334  }
335 }
336 
337 static void filter16_5x5(uint8_t *dstp, int width,
338  float rdiv, float bias, const int *const matrix,
339  const uint8_t *c[], int peak, int radius,
340  int dstride, int stride, int size)
341 {
342  uint16_t *dst = (uint16_t *)dstp;
343  int x;
344 
345  for (x = 0; x < width; x++) {
346  int i, sum = 0;
347 
348  for (i = 0; i < 25; i++)
349  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
350 
351  sum = (int)(sum * rdiv + bias + 0.5f);
352  dst[x] = av_clip(sum, 0, peak);
353  }
354 }
355 
356 static void filter16_7x7(uint8_t *dstp, int width,
357  float rdiv, float bias, const int *const matrix,
358  const uint8_t *c[], int peak, int radius,
359  int dstride, int stride, int size)
360 {
361  uint16_t *dst = (uint16_t *)dstp;
362  int x;
363 
364  for (x = 0; x < width; x++) {
365  int i, sum = 0;
366 
367  for (i = 0; i < 49; i++)
368  sum += AV_RN16A(&c[i][2 * x]) * matrix[i];
369 
370  sum = (int)(sum * rdiv + bias + 0.5f);
371  dst[x] = av_clip(sum, 0, peak);
372  }
373 }
374 
375 static void filter16_row(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 < 2 * radius + 1; 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_column(uint8_t *dstp, int height,
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  DECLARE_ALIGNED(64, int, sum)[16];
400  uint16_t *dst = (uint16_t *)dstp;
401  const int width = FFMIN(16, size);
402 
403  for (int y = 0; y < height; y++) {
404 
405  memset(sum, 0, sizeof(sum));
406  for (int i = 0; i < 2 * radius + 1; i++) {
407  for (int off16 = 0; off16 < width; off16++)
408  sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i];
409  }
410 
411  for (int off16 = 0; off16 < width; off16++) {
412  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
413  dst[off16] = av_clip(sum[off16], 0, peak);
414  }
415  dst += dstride / 2;
416  }
417 }
418 
419 static void filter_7x7(uint8_t *dst, int width,
420  float rdiv, float bias, const int *const matrix,
421  const uint8_t *c[], int peak, int radius,
422  int dstride, int stride, int size)
423 {
424  int x;
425 
426  for (x = 0; x < width; x++) {
427  int i, sum = 0;
428 
429  for (i = 0; i < 49; i++)
430  sum += c[i][x] * matrix[i];
431 
432  sum = (int)(sum * rdiv + bias + 0.5f);
433  dst[x] = av_clip_uint8(sum);
434  }
435 }
436 
437 static void filter_5x5(uint8_t *dst, int width,
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  int x;
443 
444  for (x = 0; x < width; x++) {
445  int i, sum = 0;
446 
447  for (i = 0; i < 25; i++)
448  sum += c[i][x] * matrix[i];
449 
450  sum = (int)(sum * rdiv + bias + 0.5f);
451  dst[x] = av_clip_uint8(sum);
452  }
453 }
454 
455 static void filter_3x3(uint8_t *dst, int width,
456  float rdiv, float bias, const int *const matrix,
457  const uint8_t *c[], int peak, int radius,
458  int dstride, int stride, int size)
459 {
460  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
461  const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];
462  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
463  int x;
464 
465  for (x = 0; x < width; x++) {
466  int sum = c0[x] * matrix[0] + c1[x] * matrix[1] + c2[x] * matrix[2] +
467  c3[x] * matrix[3] + c4[x] * matrix[4] + c5[x] * matrix[5] +
468  c6[x] * matrix[6] + c7[x] * matrix[7] + c8[x] * matrix[8];
469  sum = (int)(sum * rdiv + bias + 0.5f);
470  dst[x] = av_clip_uint8(sum);
471  }
472 }
473 
474 static void filter_row(uint8_t *dst, int width,
475  float rdiv, float bias, const int *const matrix,
476  const uint8_t *c[], int peak, int radius,
477  int dstride, int stride, int size)
478 {
479  int x;
480 
481  for (x = 0; x < width; x++) {
482  int i, sum = 0;
483 
484  for (i = 0; i < 2 * radius + 1; i++)
485  sum += c[i][x] * matrix[i];
486 
487  sum = (int)(sum * rdiv + bias + 0.5f);
488  dst[x] = av_clip_uint8(sum);
489  }
490 }
491 
492 static void filter_column(uint8_t *dst, int height,
493  float rdiv, float bias, const int *const matrix,
494  const uint8_t *c[], int peak, int radius,
495  int dstride, int stride, int size)
496 {
497  DECLARE_ALIGNED(64, int, sum)[16];
498 
499  for (int y = 0; y < height; y++) {
500  memset(sum, 0, sizeof(sum));
501 
502  for (int i = 0; i < 2 * radius + 1; i++) {
503  for (int off16 = 0; off16 < 16; off16++)
504  sum[off16] += c[i][0 + y * stride + off16] * matrix[i];
505  }
506 
507  for (int off16 = 0; off16 < 16; off16++) {
508  sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
509  dst[off16] = av_clip_uint8(sum[off16]);
510  }
511  dst += dstride;
512  }
513 }
514 
515 static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,
516  int x, int w, int y, int h, int bpc)
517 {
518  int i;
519 
520  for (i = 0; i < 9; i++) {
521  int xoff = FFABS(x + ((i % 3) - 1));
522  int yoff = FFABS(y + (i / 3) - 1);
523 
524  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
525  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
526 
527  c[i] = src + xoff * bpc + yoff * stride;
528  }
529 }
530 
531 static void setup_5x5(int radius, const uint8_t *c[], const uint8_t *src, int stride,
532  int x, int w, int y, int h, int bpc)
533 {
534  int i;
535 
536  for (i = 0; i < 25; i++) {
537  int xoff = FFABS(x + ((i % 5) - 2));
538  int yoff = FFABS(y + (i / 5) - 2);
539 
540  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
541  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
542 
543  c[i] = src + xoff * bpc + yoff * stride;
544  }
545 }
546 
547 static void setup_7x7(int radius, const uint8_t *c[], const uint8_t *src, int stride,
548  int x, int w, int y, int h, int bpc)
549 {
550  int i;
551 
552  for (i = 0; i < 49; i++) {
553  int xoff = FFABS(x + ((i % 7) - 3));
554  int yoff = FFABS(y + (i / 7) - 3);
555 
556  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
557  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
558 
559  c[i] = src + xoff * bpc + yoff * stride;
560  }
561 }
562 
563 static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int stride,
564  int x, int w, int y, int h, int bpc)
565 {
566  int i;
567 
568  for (i = 0; i < radius * 2 + 1; i++) {
569  int xoff = FFABS(x + i - radius);
570 
571  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
572 
573  c[i] = src + xoff * bpc + y * stride;
574  }
575 }
576 
577 static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride,
578  int x, int w, int y, int h, int bpc)
579 {
580  int i;
581 
582  for (i = 0; i < radius * 2 + 1; i++) {
583  int xoff = FFABS(x + i - radius);
584 
585  xoff = xoff >= h ? 2 * h - 1 - xoff : xoff;
586 
587  c[i] = src + y * bpc + xoff * stride;
588  }
589 }
590 
591 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
592 {
593  ConvolutionContext *s = ctx->priv;
594  ThreadData *td = arg;
595  AVFrame *in = td->in;
596  AVFrame *out = td->out;
597  int plane;
598 
599  for (plane = 0; plane < s->nb_planes; plane++) {
600  const int mode = s->mode[plane];
601  const int bpc = s->bpc;
602  const int radius = s->size[plane] / 2;
603  const int height = s->planeheight[plane];
604  const int width = s->planewidth[plane];
605  const int stride = in->linesize[plane];
606  const int dstride = out->linesize[plane];
607  const int sizeh = mode == MATRIX_COLUMN ? width : height;
608  const int sizew = mode == MATRIX_COLUMN ? height : width;
609  const int slice_start = (sizeh * jobnr) / nb_jobs;
610  const int slice_end = (sizeh * (jobnr+1)) / nb_jobs;
611  const float rdiv = s->rdiv[plane];
612  const float bias = s->bias[plane];
613  const uint8_t *src = in->data[plane];
614  const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : dstride);
615  uint8_t *dst = out->data[plane] + dst_pos;
616  const int *matrix = s->matrix[plane];
617  const int step = mode == MATRIX_COLUMN ? 16 : 1;
618  const uint8_t *c[49];
619  int y, x;
620 
621  if (s->copy[plane]) {
622  if (mode == MATRIX_COLUMN)
623  av_image_copy_plane(dst, dstride, src + slice_start * bpc, stride,
624  (slice_end - slice_start) * bpc, height);
625  else
626  av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,
627  width * bpc, slice_end - slice_start);
628  continue;
629  }
630  for (y = slice_start; y < slice_end; y += step) {
631  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
632  const int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0;
633 
634  for (x = 0; x < radius; x++) {
635  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
636  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
637 
638  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
639  s->filter[plane](dst + yoff + xoff, 1, rdiv,
640  bias, matrix, c, s->max, radius,
641  dstride, stride, slice_end - step);
642  }
643  s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc);
644  s->filter[plane](dst + yoff + xoff, sizew - 2 * radius,
645  rdiv, bias, matrix, c, s->max, radius,
646  dstride, stride, slice_end - step);
647  for (x = sizew - radius; x < sizew; x++) {
648  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
649  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
650 
651  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
652  s->filter[plane](dst + yoff + xoff, 1, rdiv,
653  bias, matrix, c, s->max, radius,
654  dstride, stride, slice_end - step);
655  }
656  if (mode != MATRIX_COLUMN)
657  dst += dstride;
658  }
659  }
660 
661  return 0;
662 }
663 
664 static int config_input(AVFilterLink *inlink)
665 {
666  AVFilterContext *ctx = inlink->dst;
667  ConvolutionContext *s = ctx->priv;
669  int p;
670 
671  s->depth = desc->comp[0].depth;
672  s->max = (1 << s->depth) - 1;
673 
674  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
675  s->planewidth[0] = s->planewidth[3] = inlink->w;
676  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
677  s->planeheight[0] = s->planeheight[3] = inlink->h;
678 
679  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
680  s->nb_threads = ff_filter_get_nb_threads(ctx);
681  s->bpc = (s->depth + 7) / 8;
682 
683  if (!strcmp(ctx->filter->name, "convolution")) {
684  if (s->depth > 8) {
685  for (p = 0; p < s->nb_planes; p++) {
686  if (s->mode[p] == MATRIX_ROW)
687  s->filter[p] = filter16_row;
688  else if (s->mode[p] == MATRIX_COLUMN)
689  s->filter[p] = filter16_column;
690  else if (s->size[p] == 3)
691  s->filter[p] = filter16_3x3;
692  else if (s->size[p] == 5)
693  s->filter[p] = filter16_5x5;
694  else if (s->size[p] == 7)
695  s->filter[p] = filter16_7x7;
696  }
697  }
698 #if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64
700 #endif
701  } else if (!strcmp(ctx->filter->name, "prewitt")) {
702  if (s->depth > 8)
703  for (p = 0; p < s->nb_planes; p++)
704  s->filter[p] = filter16_prewitt;
705  } else if (!strcmp(ctx->filter->name, "roberts")) {
706  if (s->depth > 8)
707  for (p = 0; p < s->nb_planes; p++)
708  s->filter[p] = filter16_roberts;
709  } else if (!strcmp(ctx->filter->name, "sobel")) {
710  if (s->depth > 8)
711  for (p = 0; p < s->nb_planes; p++)
712  s->filter[p] = filter16_sobel;
713  } else if (!strcmp(ctx->filter->name, "kirsch")) {
714  if (s->depth > 8)
715  for (p = 0; p < s->nb_planes; p++)
716  s->filter[p] = filter16_kirsch;
717  }
718 
719  return 0;
720 }
721 
722 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
723 {
724  AVFilterContext *ctx = inlink->dst;
725  ConvolutionContext *s = ctx->priv;
726  AVFilterLink *outlink = ctx->outputs[0];
727  AVFrame *out;
728  ThreadData td;
729 
730  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
731  if (!out) {
732  av_frame_free(&in);
733  return AVERROR(ENOMEM);
734  }
736 
737  td.in = in;
738  td.out = out;
739  ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads));
740 
741  av_frame_free(&in);
742  return ff_filter_frame(outlink, out);
743 }
744 
746 {
747  ConvolutionContext *s = ctx->priv;
748  int i;
749 
750  if (!strcmp(ctx->filter->name, "convolution")) {
751  for (i = 0; i < 4; i++) {
752  int *matrix = (int *)s->matrix[i];
753  char *p, *arg, *saveptr = NULL;
754  float sum = 0;
755 
756  p = s->matrix_str[i];
757  if (p) {
758  s->matrix_length[i] = 0;
759 
760  while (s->matrix_length[i] < 49) {
761  if (!(arg = av_strtok(p, " |", &saveptr)))
762  break;
763 
764  p = NULL;
765  sscanf(arg, "%d", &matrix[s->matrix_length[i]]);
766  sum += matrix[s->matrix_length[i]];
767  s->matrix_length[i]++;
768  }
769 
770  if (!(s->matrix_length[i] & 1)) {
771  av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n");
772  return AVERROR(EINVAL);
773  }
774  }
775 
776  if (s->mode[i] == MATRIX_ROW) {
777  s->filter[i] = filter_row;
778  s->setup[i] = setup_row;
779  s->size[i] = s->matrix_length[i];
780  } else if (s->mode[i] == MATRIX_COLUMN) {
781  s->filter[i] = filter_column;
782  s->setup[i] = setup_column;
783  s->size[i] = s->matrix_length[i];
784  } else if (s->matrix_length[i] == 9) {
785  s->size[i] = 3;
786 
787  if (!memcmp(matrix, same3x3, sizeof(same3x3))) {
788  s->copy[i] = 1;
789  } else {
790  s->filter[i] = filter_3x3;
791  s->copy[i] = 0;
792  }
793  s->setup[i] = setup_3x3;
794  } else if (s->matrix_length[i] == 25) {
795  s->size[i] = 5;
796  if (!memcmp(matrix, same5x5, sizeof(same5x5))) {
797  s->copy[i] = 1;
798  } else {
799  s->filter[i] = filter_5x5;
800  s->copy[i] = 0;
801  }
802  s->setup[i] = setup_5x5;
803  } else if (s->matrix_length[i] == 49) {
804  s->size[i] = 7;
805  if (!memcmp(matrix, same7x7, sizeof(same7x7))) {
806  s->copy[i] = 1;
807  } else {
808  s->filter[i] = filter_7x7;
809  s->copy[i] = 0;
810  }
811  s->setup[i] = setup_7x7;
812  } else {
813  return AVERROR(EINVAL);
814  }
815 
816  if (sum == 0)
817  sum = 1;
818  if (s->rdiv[i] == 0)
819  s->rdiv[i] = 1. / sum;
820 
821  if (s->copy[i] && (s->rdiv[i] != 1. || s->bias[i] != 0.))
822  s->copy[i] = 0;
823  }
824  } else if (!strcmp(ctx->filter->name, "prewitt")) {
825  for (i = 0; i < 4; i++) {
826  if ((1 << i) & s->planes)
827  s->filter[i] = filter_prewitt;
828  else
829  s->copy[i] = 1;
830  s->size[i] = 3;
831  s->setup[i] = setup_3x3;
832  s->rdiv[i] = s->scale;
833  s->bias[i] = s->delta;
834  }
835  } else if (!strcmp(ctx->filter->name, "roberts")) {
836  for (i = 0; i < 4; i++) {
837  if ((1 << i) & s->planes)
838  s->filter[i] = filter_roberts;
839  else
840  s->copy[i] = 1;
841  s->size[i] = 3;
842  s->setup[i] = setup_3x3;
843  s->rdiv[i] = s->scale;
844  s->bias[i] = s->delta;
845  }
846  } else if (!strcmp(ctx->filter->name, "sobel")) {
847  for (i = 0; i < 4; i++) {
848  if ((1 << i) & s->planes)
849  s->filter[i] = filter_sobel;
850  else
851  s->copy[i] = 1;
852  s->size[i] = 3;
853  s->setup[i] = setup_3x3;
854  s->rdiv[i] = s->scale;
855  s->bias[i] = s->delta;
856  }
857  } else if (!strcmp(ctx->filter->name, "kirsch")) {
858  for (i = 0; i < 4; i++) {
859  if ((1 << i) & s->planes)
860  s->filter[i] = filter_kirsch;
861  else
862  s->copy[i] = 1;
863  s->size[i] = 3;
864  s->setup[i] = setup_3x3;
865  s->rdiv[i] = s->scale;
866  s->bias[i] = s->delta;
867  }
868  }
869 
870  return 0;
871 }
872 
873 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
874  char *res, int res_len, int flags)
875 {
876  int ret;
877 
878  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
879  if (ret < 0)
880  return ret;
881 
882  return init(ctx);
883 }
884 
885 static const AVFilterPad convolution_inputs[] = {
886  {
887  .name = "default",
888  .type = AVMEDIA_TYPE_VIDEO,
889  .config_props = config_input,
890  .filter_frame = filter_frame,
891  },
892  { NULL }
893 };
894 
896  {
897  .name = "default",
898  .type = AVMEDIA_TYPE_VIDEO,
899  },
900  { NULL }
901 };
902 
903 #if CONFIG_CONVOLUTION_FILTER
904 
906  .name = "convolution",
907  .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."),
908  .priv_size = sizeof(ConvolutionContext),
909  .priv_class = &convolution_class,
910  .init = init,
916 };
917 
918 #endif /* CONFIG_CONVOLUTION_FILTER */
919 
920 #if CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER
921 
922 static const AVOption prewitt_roberts_sobel_options[] = {
923  { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS},
924  { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS},
925  { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS},
926  { NULL }
927 };
928 
929 #if CONFIG_PREWITT_FILTER
930 
931 #define prewitt_options prewitt_roberts_sobel_options
932 AVFILTER_DEFINE_CLASS(prewitt);
933 
935  .name = "prewitt",
936  .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."),
937  .priv_size = sizeof(ConvolutionContext),
938  .priv_class = &prewitt_class,
939  .init = init,
945 };
946 
947 #endif /* CONFIG_PREWITT_FILTER */
948 
949 #if CONFIG_SOBEL_FILTER
950 
951 #define sobel_options prewitt_roberts_sobel_options
953 
955  .name = "sobel",
956  .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."),
957  .priv_size = sizeof(ConvolutionContext),
958  .priv_class = &sobel_class,
959  .init = init,
965 };
966 
967 #endif /* CONFIG_SOBEL_FILTER */
968 
969 #if CONFIG_ROBERTS_FILTER
970 
971 #define roberts_options prewitt_roberts_sobel_options
972 AVFILTER_DEFINE_CLASS(roberts);
973 
975  .name = "roberts",
976  .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."),
977  .priv_size = sizeof(ConvolutionContext),
978  .priv_class = &roberts_class,
979  .init = init,
985 };
986 
987 #endif /* CONFIG_ROBERTS_FILTER */
988 
989 #if CONFIG_KIRSCH_FILTER
990 
991 #define kirsch_options prewitt_roberts_sobel_options
992 AVFILTER_DEFINE_CLASS(kirsch);
993 
995  .name = "kirsch",
996  .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."),
997  .priv_size = sizeof(ConvolutionContext),
998  .priv_class = &kirsch_class,
999  .init = init,
1005 };
1006 
1007 #endif /* CONFIG_KIRSCH_FILTER */
1008 
1009 #endif /* CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER */
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
AVFilter ff_vf_convolution
AVFilter ff_vf_prewitt
AVFilter ff_vf_kirsch
AVFilter ff_vf_roberts
AVFilter ff_vf_sobel
#define av_cold
Definition: attributes.h:88
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
uint8_t
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1094
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
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
Main libavfilter public API header.
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFMIN(a, b)
Definition: common.h:105
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
#define av_clip
Definition: common.h:122
#define FFMAX(a, b)
Definition: common.h:103
#define av_clip_uint8
Definition: common.h:128
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define FFMIN3(a, b, c)
Definition: common.h:106
void ff_convolution_init_x86(ConvolutionContext *s)
@ MATRIX_SQUARE
Definition: convolution.h:26
@ MATRIX_COLUMN
Definition: convolution.h:28
@ MATRIX_ROW
Definition: convolution.h:27
@ MATRIX_NBMODES
Definition: convolution.h:29
#define NULL
Definition: coverity.c:32
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
int
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:587
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
@ AV_OPT_TYPE_INT
Definition: opt.h:225
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
#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:126
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
#define DECLARE_ALIGNED(n, t, v)
Declare a variable that is aligned in memory.
Definition: mem.h:117
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
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:373
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
misc image utilities
int i
Definition: input.c:407
#define AV_RN16A(p)
Definition: intreadwrite.h:522
const char * arg
Definition: jacosubdec.c:66
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:303
const char * desc
Definition: libsvtav1.c:79
uint8_t w
Definition: llviddspenc.c:39
static const struct @322 planes[]
int stride
Definition: mace.c:144
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
static const uint64_t c2
Definition: murmur3.c:52
static const uint64_t c1
Definition: murmur3.c:51
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2613
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:410
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:406
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:398
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:399
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:405
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:379
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:421
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:397
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:438
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:441
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:403
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:436
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:434
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:404
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:400
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:381
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:396
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:433
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:437
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:407
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
@ 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_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
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
@ 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:258
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
@ 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_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
@ 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
@ 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
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:439
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:408
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:380
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:382
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:411
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:443
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:442
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:418
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:409
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:435
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:417
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:440
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:412
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:402
#define td
Definition: regdef.h:70
An instance of a filter.
Definition: avfilter.h:341
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1699
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
AVOption.
Definition: opt.h:248
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
Used for passing data between threads.
Definition: dsddec.c:67
AVFrame * out
Definition: af_adeclick.c:502
AVFrame * in
Definition: af_adenorm.c:223
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
#define height
#define width
int size
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)
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)
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)
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)
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)
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVOption convolution_options[]
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)
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)
static const int same5x5[25]
static int query_formats(AVFilterContext *ctx)
static const int same7x7[49]
static const AVFilterPad convolution_outputs[]
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)
static int config_input(AVFilterLink *inlink)
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)
#define FLAGS
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)
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)
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)
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
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)
static const AVFilterPad convolution_inputs[]
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)
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)
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)
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static av_cold int init(AVFilterContext *ctx)
AVFILTER_DEFINE_CLASS(convolution)
static const int same3x3[9]
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)
#define OFFSET(x)
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)
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)
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)
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)
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)
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)
static void sobel(int w, int h, uint16_t *dst, int dst_linesize, int8_t *dir, int dir_linesize, const uint8_t *src, int src_linesize)
if(ret< 0)
Definition: vf_mcdeint.c:282
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
float delta
static double c[64]