FFmpeg  4.4.8
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 "filters.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_kirsch(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  const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2];
170  const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5];
171  const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8];
172  int x;
173 
174  for (x = 0; x < width; x++) {
175  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
176  c3[x] * -3 + c5[x] * -3 +
177  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
178  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
179  c3[x] * 5 + c5[x] * -3 +
180  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
181  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
182  c3[x] * 5 + c5[x] * 5 +
183  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
184  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
185  c3[x] * 5 + c5[x] * 5 +
186  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
187  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
188  c3[x] * -3 + c5[x] * 5 +
189  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
190  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
191  c3[x] * -3 + c5[x] * -3 +
192  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
193  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
194  c3[x] * -3 + c5[x] * -3 +
195  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
196  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
197  c3[x] * -3 + c5[x] * -3 +
198  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
199 
200  sum0 = FFMAX(sum0, sum1);
201  sum2 = FFMAX(sum2, sum3);
202  sum4 = FFMAX(sum4, sum5);
203  sum6 = FFMAX(sum6, sum7);
204  sum0 = FFMAX(sum0, sum2);
205  sum4 = FFMAX(sum4, sum6);
206  sum0 = FFMAX(sum0, sum4);
207 
208  dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak);
209  }
210 }
211 
212 static void filter_prewitt(uint8_t *dst, int width,
213  float scale, float delta, const int *const matrix,
214  const uint8_t *c[], int peak, int radius,
215  int dstride, int stride, int size)
216 {
217  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
218  const uint8_t *c3 = c[3], *c5 = c[5];
219  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
220  int x;
221 
222  for (x = 0; x < width; x++) {
223  float suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 +
224  c6[x] * 1 + c7[x] * 1 + c8[x] * 1;
225  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 +
226  c5[x] * 1 + c6[x] * -1 + c8[x] * 1;
227 
228  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
229  }
230 }
231 
232 static void filter_roberts(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  int x;
238 
239  for (x = 0; x < width; x++) {
240  float suma = c[0][x] * 1 + c[1][x] * -1;
241  float sumb = c[4][x] * 1 + c[3][x] * -1;
242 
243  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
244  }
245 }
246 
247 static void filter_sobel(uint8_t *dst, int width,
248  float scale, float delta, const int *const matrix,
249  const uint8_t *c[], int peak, int radius,
250  int dstride, int stride, int size)
251 {
252  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
253  const uint8_t *c3 = c[3], *c5 = c[5];
254  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
255  int x;
256 
257  for (x = 0; x < width; x++) {
258  float suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 +
259  c6[x] * 1 + c7[x] * 2 + c8[x] * 1;
260  float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 +
261  c5[x] * 2 + c6[x] * -1 + c8[x] * 1;
262 
263  dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta);
264  }
265 }
266 
267 static void filter_kirsch(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  int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 +
279  c3[x] * -3 + c5[x] * -3 +
280  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
281  int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 +
282  c3[x] * 5 + c5[x] * -3 +
283  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
284  int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 +
285  c3[x] * 5 + c5[x] * 5 +
286  c6[x] * -3 + c7[x] * -3 + c8[x] * -3;
287  int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
288  c3[x] * 5 + c5[x] * 5 +
289  c6[x] * 5 + c7[x] * -3 + c8[x] * -3;
290  int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
291  c3[x] * -3 + c5[x] * 5 +
292  c6[x] * 5 + c7[x] * 5 + c8[x] * -3;
293  int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 +
294  c3[x] * -3 + c5[x] * -3 +
295  c6[x] * 5 + c7[x] * 5 + c8[x] * 5;
296  int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 +
297  c3[x] * -3 + c5[x] * -3 +
298  c6[x] * -3 + c7[x] * 5 + c8[x] * 5;
299  int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 +
300  c3[x] * -3 + c5[x] * -3 +
301  c6[x] * -3 + c7[x] * -3 + c8[x] * 5;
302 
303  sum0 = FFMAX(sum0, sum1);
304  sum2 = FFMAX(sum2, sum3);
305  sum4 = FFMAX(sum4, sum5);
306  sum6 = FFMAX(sum6, sum7);
307  sum0 = FFMAX(sum0, sum2);
308  sum4 = FFMAX(sum4, sum6);
309  sum0 = FFMAX(sum0, sum4);
310 
311  dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta);
312  }
313 }
314 
315 static void filter16_3x3(uint8_t *dstp, int width,
316  float rdiv, float bias, const int *const matrix,
317  const uint8_t *c[], int peak, int radius,
318  int dstride, int stride, int size)
319 {
320  uint16_t *dst = (uint16_t *)dstp;
321  int x;
322 
323  for (x = 0; x < width; x++) {
324  unsigned sum = (unsigned)AV_RN16A(&c[0][2 * x]) * matrix[0] +
325  (unsigned)AV_RN16A(&c[1][2 * x]) * matrix[1] +
326  (unsigned)AV_RN16A(&c[2][2 * x]) * matrix[2] +
327  (unsigned)AV_RN16A(&c[3][2 * x]) * matrix[3] +
328  (unsigned)AV_RN16A(&c[4][2 * x]) * matrix[4] +
329  (unsigned)AV_RN16A(&c[5][2 * x]) * matrix[5] +
330  (unsigned)AV_RN16A(&c[6][2 * x]) * matrix[6] +
331  (unsigned)AV_RN16A(&c[7][2 * x]) * matrix[7] +
332  (unsigned)AV_RN16A(&c[8][2 * x]) * matrix[8];
333  dst[x] = av_clip((int)sum * rdiv + bias + 0.5f, 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;
347  unsigned sum = 0;
348 
349  for (i = 0; i < 25; i++)
350  sum += (unsigned)AV_RN16A(&c[i][2 * x]) * matrix[i];
351 
352  dst[x] = av_clip((int)sum * rdiv + bias + 0.5f, 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;
366  unsigned sum = 0;
367 
368  for (i = 0; i < 49; i++)
369  sum += (unsigned)AV_RN16A(&c[i][2 * x]) * matrix[i];
370 
371  dst[x] = av_clip((int)sum * rdiv + bias + 0.5f, 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;
385  unsigned sum = 0;
386 
387  for (i = 0; i < 2 * radius + 1; i++)
388  sum += (unsigned)AV_RN16A(&c[i][2 * x]) * matrix[i];
389 
390  dst[x] = av_clip((int)sum * rdiv + bias + 0.5f, 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, unsigned, 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] += (unsigned)AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i];
409  }
410 
411  for (int off16 = 0; off16 < width; off16++) {
412  dst[off16] = av_clip((int)sum[off16] * rdiv + bias + 0.5f, 0, peak);
413  }
414  dst += dstride / 2;
415  }
416 }
417 
418 static void filter_7x7(uint8_t *dst, 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  int x;
424 
425  for (x = 0; x < width; x++) {
426  int i;
427  unsigned sum = 0;
428 
429  for (i = 0; i < 49; i++)
430  sum += (unsigned)c[i][x] * matrix[i];
431 
432  dst[x] = av_clip_uint8((int)sum * rdiv + bias + 0.5f);
433  }
434 }
435 
436 static void filter_5x5(uint8_t *dst, int width,
437  float rdiv, float bias, const int *const matrix,
438  const uint8_t *c[], int peak, int radius,
439  int dstride, int stride, int size)
440 {
441  int x;
442 
443  for (x = 0; x < width; x++) {
444  int i;
445  unsigned sum = 0;
446 
447  for (i = 0; i < 25; i++)
448  sum += (unsigned)c[i][x] * matrix[i];
449 
450  dst[x] = av_clip_uint8((int)sum * rdiv + bias + 0.5f);
451  }
452 }
453 
454 static void filter_3x3(uint8_t *dst, int width,
455  float rdiv, float bias, const int *const matrix,
456  const uint8_t *c[], int peak, int radius,
457  int dstride, int stride, int size)
458 {
459  const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
460  const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];
461  const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8];
462  int x;
463 
464  for (x = 0; x < width; x++) {
465  unsigned sum = (unsigned)c0[x] * matrix[0] + (unsigned)c1[x] * matrix[1] + (unsigned)c2[x] * matrix[2] +
466  (unsigned)c3[x] * matrix[3] + (unsigned)c4[x] * matrix[4] + (unsigned)c5[x] * matrix[5] +
467  (unsigned)c6[x] * matrix[6] + (unsigned)c7[x] * matrix[7] + (unsigned)c8[x] * matrix[8];
468  dst[x] = av_clip_uint8((int)sum * rdiv + bias + 0.5f);
469  }
470 }
471 
472 static void filter_row(uint8_t *dst, int width,
473  float rdiv, float bias, const int *const matrix,
474  const uint8_t *c[], int peak, int radius,
475  int dstride, int stride, int size)
476 {
477  int x;
478 
479  for (x = 0; x < width; x++) {
480  int i;
481  unsigned sum = 0;
482 
483  for (i = 0; i < 2 * radius + 1; i++)
484  sum += (unsigned)c[i][x] * matrix[i];
485 
486  dst[x] = av_clip_uint8((int)sum * rdiv + bias + 0.5f);
487  }
488 }
489 
490 static void filter_column(uint8_t *dst, int height,
491  float rdiv, float bias, const int *const matrix,
492  const uint8_t *c[], int peak, int radius,
493  int dstride, int stride, int size)
494 {
495  DECLARE_ALIGNED(64, unsigned, sum)[16];
496 
497  for (int y = 0; y < height; y++) {
498  memset(sum, 0, sizeof(sum));
499 
500  for (int i = 0; i < 2 * radius + 1; i++) {
501  for (int off16 = 0; off16 < 16; off16++)
502  sum[off16] += (unsigned)c[i][0 + y * stride + off16] * matrix[i];
503  }
504 
505  for (int off16 = 0; off16 < 16; off16++) {
506  dst[off16] = av_clip_uint8((int)sum[off16] * rdiv + bias + 0.5f);
507  }
508  dst += dstride;
509  }
510 }
511 
512 static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,
513  int x, int w, int y, int h, int bpc)
514 {
515  int i;
516 
517  for (i = 0; i < 9; i++) {
518  int xoff = FFABS(x + ((i % 3) - 1));
519  int yoff = FFABS(y + (i / 3) - 1);
520 
521  xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
522  yoff = yoff >= h ? 2 * h - 1 - yoff : yoff;
523 
524  c[i] = src + xoff * bpc + yoff * stride;
525  }
526 }
527 
528 static void setup_5x5(int radius, const uint8_t *c[], const uint8_t *src, int stride,
529  int x, int w, int y, int h, int bpc)
530 {
531  int i;
532 
533  for (i = 0; i < 25; i++) {
534  int xoff = avpriv_mirror(x + (i % 5) - 2, w - 1);
535  int yoff = avpriv_mirror(y + (i / 5) - 2, h - 1);
536 
537  c[i] = src + xoff * bpc + yoff * stride;
538  }
539 }
540 
541 static void setup_7x7(int radius, const uint8_t *c[], const uint8_t *src, int stride,
542  int x, int w, int y, int h, int bpc)
543 {
544  int i;
545 
546  for (i = 0; i < 49; i++) {
547  int xoff = avpriv_mirror(x + (i % 7) - 3, w - 1);
548  int yoff = avpriv_mirror(y + (i / 7) - 3, h - 1);
549 
550  c[i] = src + xoff * bpc + yoff * stride;
551  }
552 }
553 
554 static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int stride,
555  int x, int w, int y, int h, int bpc)
556 {
557  int i;
558 
559  for (i = 0; i < radius * 2 + 1; i++) {
560  int xoff = avpriv_mirror(x + i - radius, w - 1);
561 
562  c[i] = src + xoff * bpc + y * stride;
563  }
564 }
565 
566 static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride,
567  int x, int w, int y, int h, int bpc)
568 {
569  int i;
570 
571  for (i = 0; i < radius * 2 + 1; i++) {
572  int xoff = avpriv_mirror(x + i - radius, h - 1);
573 
574  c[i] = src + y * bpc + xoff * stride;
575  }
576 }
577 
578 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
579 {
580  ConvolutionContext *s = ctx->priv;
581  ThreadData *td = arg;
582  AVFrame *in = td->in;
583  AVFrame *out = td->out;
584  int plane;
585 
586  for (plane = 0; plane < s->nb_planes; plane++) {
587  const int mode = s->mode[plane];
588  const int bpc = s->bpc;
589  const int radius = s->size[plane] / 2;
590  const int height = s->planeheight[plane];
591  const int width = s->planewidth[plane];
592  const int stride = in->linesize[plane];
593  const int dstride = out->linesize[plane];
594  const int sizeh = mode == MATRIX_COLUMN ? width : height;
595  const int sizew = mode == MATRIX_COLUMN ? height : width;
596  const int slice_start = ff_slice_pos(sizeh, jobnr, nb_jobs);
597  const int slice_end = ff_slice_pos(sizeh, jobnr + 1, nb_jobs);
598  const float rdiv = s->rdiv[plane];
599  const float bias = s->bias[plane];
600  const uint8_t *src = in->data[plane];
601  const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : dstride);
602  uint8_t *dst = out->data[plane] + dst_pos;
603  const int *matrix = s->matrix[plane];
604  const int step = mode == MATRIX_COLUMN ? 16 : 1;
605  const uint8_t *c[49];
606  int y, x;
607 
608  if (s->copy[plane]) {
609  if (mode == MATRIX_COLUMN)
610  av_image_copy_plane(dst, dstride, src + slice_start * bpc, stride,
611  (slice_end - slice_start) * bpc, height);
612  else
613  av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,
614  width * bpc, slice_end - slice_start);
615  continue;
616  }
617  for (y = slice_start; y < slice_end; y += step) {
618  const int left = FFMIN(radius, sizew);
619  const int right = FFMAX(left, sizew - radius);
620  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : left * bpc;
621  const int yoff = mode == MATRIX_COLUMN ? left * dstride : 0;
622 
623  for (x = 0; x < left; x++) {
624  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
625  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
626 
627  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
628  s->filter[plane](dst + yoff + xoff, 1, rdiv,
629  bias, matrix, c, s->max, radius,
630  dstride, stride, slice_end - step);
631  }
632  s->setup[plane](radius, c, src, stride, left, width, y, height, bpc);
633  s->filter[plane](dst + yoff + xoff, right - left,
634  rdiv, bias, matrix, c, s->max, radius,
635  dstride, stride, slice_end - step);
636  for (x = right; x < sizew; x++) {
637  const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
638  const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
639 
640  s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
641  s->filter[plane](dst + yoff + xoff, 1, rdiv,
642  bias, matrix, c, s->max, radius,
643  dstride, stride, slice_end - step);
644  }
645  if (mode != MATRIX_COLUMN)
646  dst += dstride;
647  }
648  }
649 
650  return 0;
651 }
652 
653 static int config_input(AVFilterLink *inlink)
654 {
655  AVFilterContext *ctx = inlink->dst;
656  ConvolutionContext *s = ctx->priv;
658  int p;
659 
660  s->depth = desc->comp[0].depth;
661  s->max = (1 << s->depth) - 1;
662 
663  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
664  s->planewidth[0] = s->planewidth[3] = inlink->w;
665  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
666  s->planeheight[0] = s->planeheight[3] = inlink->h;
667 
668  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
669  s->nb_threads = ff_filter_get_nb_threads(ctx);
670  s->bpc = (s->depth + 7) / 8;
671 
672  if (!strcmp(ctx->filter->name, "convolution")) {
673  if (s->depth > 8) {
674  for (p = 0; p < s->nb_planes; p++) {
675  if (s->mode[p] == MATRIX_ROW)
676  s->filter[p] = filter16_row;
677  else if (s->mode[p] == MATRIX_COLUMN)
678  s->filter[p] = filter16_column;
679  else if (s->size[p] == 3)
680  s->filter[p] = filter16_3x3;
681  else if (s->size[p] == 5)
682  s->filter[p] = filter16_5x5;
683  else if (s->size[p] == 7)
684  s->filter[p] = filter16_7x7;
685  }
686  }
687 #if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64
689 #endif
690  } else if (!strcmp(ctx->filter->name, "prewitt")) {
691  if (s->depth > 8)
692  for (p = 0; p < s->nb_planes; p++)
693  s->filter[p] = filter16_prewitt;
694  } else if (!strcmp(ctx->filter->name, "roberts")) {
695  if (s->depth > 8)
696  for (p = 0; p < s->nb_planes; p++)
697  s->filter[p] = filter16_roberts;
698  } else if (!strcmp(ctx->filter->name, "sobel")) {
699  if (s->depth > 8)
700  for (p = 0; p < s->nb_planes; p++)
701  s->filter[p] = filter16_sobel;
702  } else if (!strcmp(ctx->filter->name, "kirsch")) {
703  if (s->depth > 8)
704  for (p = 0; p < s->nb_planes; p++)
705  s->filter[p] = filter16_kirsch;
706  }
707 
708  return 0;
709 }
710 
711 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
712 {
713  AVFilterContext *ctx = inlink->dst;
714  ConvolutionContext *s = ctx->priv;
715  AVFilterLink *outlink = ctx->outputs[0];
716  AVFrame *out;
717  ThreadData td;
718 
719  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
720  if (!out) {
721  av_frame_free(&in);
722  return AVERROR(ENOMEM);
723  }
725 
726  td.in = in;
727  td.out = out;
728  ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads));
729 
730  av_frame_free(&in);
731  return ff_filter_frame(outlink, out);
732 }
733 
735 {
736  ConvolutionContext *s = ctx->priv;
737  int i;
738 
739  if (!strcmp(ctx->filter->name, "convolution")) {
740  for (i = 0; i < 4; i++) {
741  int *matrix = (int *)s->matrix[i];
742  char *p, *arg, *saveptr = NULL;
743  float sum = 0;
744 
745  p = s->matrix_str[i];
746  if (p) {
747  s->matrix_length[i] = 0;
748 
749  while (s->matrix_length[i] < 49) {
750  if (!(arg = av_strtok(p, " |", &saveptr)))
751  break;
752 
753  p = NULL;
754  sscanf(arg, "%d", &matrix[s->matrix_length[i]]);
755  sum += matrix[s->matrix_length[i]];
756  s->matrix_length[i]++;
757  }
758 
759  if (!(s->matrix_length[i] & 1)) {
760  av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n");
761  return AVERROR(EINVAL);
762  }
763  }
764 
765  if (s->mode[i] == MATRIX_ROW) {
766  s->filter[i] = filter_row;
767  s->setup[i] = setup_row;
768  s->size[i] = s->matrix_length[i];
769  } else if (s->mode[i] == MATRIX_COLUMN) {
770  s->filter[i] = filter_column;
771  s->setup[i] = setup_column;
772  s->size[i] = s->matrix_length[i];
773  } else if (s->matrix_length[i] == 9) {
774  s->size[i] = 3;
775 
776  if (!memcmp(matrix, same3x3, sizeof(same3x3))) {
777  s->copy[i] = 1;
778  } else {
779  s->filter[i] = filter_3x3;
780  s->copy[i] = 0;
781  }
782  s->setup[i] = setup_3x3;
783  } else if (s->matrix_length[i] == 25) {
784  s->size[i] = 5;
785  if (!memcmp(matrix, same5x5, sizeof(same5x5))) {
786  s->copy[i] = 1;
787  } else {
788  s->filter[i] = filter_5x5;
789  s->copy[i] = 0;
790  }
791  s->setup[i] = setup_5x5;
792  } else if (s->matrix_length[i] == 49) {
793  s->size[i] = 7;
794  if (!memcmp(matrix, same7x7, sizeof(same7x7))) {
795  s->copy[i] = 1;
796  } else {
797  s->filter[i] = filter_7x7;
798  s->copy[i] = 0;
799  }
800  s->setup[i] = setup_7x7;
801  } else {
802  return AVERROR(EINVAL);
803  }
804 
805  if (sum == 0)
806  sum = 1;
807  if (s->rdiv[i] == 0)
808  s->rdiv[i] = 1. / sum;
809 
810  if (s->copy[i] && (s->rdiv[i] != 1. || s->bias[i] != 0.))
811  s->copy[i] = 0;
812  }
813  } else if (!strcmp(ctx->filter->name, "prewitt")) {
814  for (i = 0; i < 4; i++) {
815  if ((1 << i) & s->planes)
816  s->filter[i] = filter_prewitt;
817  else
818  s->copy[i] = 1;
819  s->size[i] = 3;
820  s->setup[i] = setup_3x3;
821  s->rdiv[i] = s->scale;
822  s->bias[i] = s->delta;
823  }
824  } else if (!strcmp(ctx->filter->name, "roberts")) {
825  for (i = 0; i < 4; i++) {
826  if ((1 << i) & s->planes)
827  s->filter[i] = filter_roberts;
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, "sobel")) {
836  for (i = 0; i < 4; i++) {
837  if ((1 << i) & s->planes)
838  s->filter[i] = filter_sobel;
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, "kirsch")) {
847  for (i = 0; i < 4; i++) {
848  if ((1 << i) & s->planes)
849  s->filter[i] = filter_kirsch;
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  }
858 
859  return 0;
860 }
861 
862 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
863  char *res, int res_len, int flags)
864 {
865  int ret;
866 
867  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
868  if (ret < 0)
869  return ret;
870 
871  return init(ctx);
872 }
873 
874 static const AVFilterPad convolution_inputs[] = {
875  {
876  .name = "default",
877  .type = AVMEDIA_TYPE_VIDEO,
878  .config_props = config_input,
879  .filter_frame = filter_frame,
880  },
881  { NULL }
882 };
883 
885  {
886  .name = "default",
887  .type = AVMEDIA_TYPE_VIDEO,
888  },
889  { NULL }
890 };
891 
892 #if CONFIG_CONVOLUTION_FILTER
893 
895  .name = "convolution",
896  .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."),
897  .priv_size = sizeof(ConvolutionContext),
898  .priv_class = &convolution_class,
899  .init = init,
905 };
906 
907 #endif /* CONFIG_CONVOLUTION_FILTER */
908 
909 #if CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER
910 
911 static const AVOption prewitt_roberts_sobel_options[] = {
912  { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS},
913  { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS},
914  { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS},
915  { NULL }
916 };
917 
918 #if CONFIG_PREWITT_FILTER
919 
920 #define prewitt_options prewitt_roberts_sobel_options
921 AVFILTER_DEFINE_CLASS(prewitt);
922 
924  .name = "prewitt",
925  .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."),
926  .priv_size = sizeof(ConvolutionContext),
927  .priv_class = &prewitt_class,
928  .init = init,
934 };
935 
936 #endif /* CONFIG_PREWITT_FILTER */
937 
938 #if CONFIG_SOBEL_FILTER
939 
940 #define sobel_options prewitt_roberts_sobel_options
942 
944  .name = "sobel",
945  .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."),
946  .priv_size = sizeof(ConvolutionContext),
947  .priv_class = &sobel_class,
948  .init = init,
954 };
955 
956 #endif /* CONFIG_SOBEL_FILTER */
957 
958 #if CONFIG_ROBERTS_FILTER
959 
960 #define roberts_options prewitt_roberts_sobel_options
961 AVFILTER_DEFINE_CLASS(roberts);
962 
964  .name = "roberts",
965  .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."),
966  .priv_size = sizeof(ConvolutionContext),
967  .priv_class = &roberts_class,
968  .init = init,
974 };
975 
976 #endif /* CONFIG_ROBERTS_FILTER */
977 
978 #if CONFIG_KIRSCH_FILTER
979 
980 #define kirsch_options prewitt_roberts_sobel_options
981 AVFILTER_DEFINE_CLASS(kirsch);
982 
984  .name = "kirsch",
985  .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."),
986  .priv_size = sizeof(ConvolutionContext),
987  .priv_class = &kirsch_class,
988  .init = init,
994 };
995 
996 #endif /* CONFIG_KIRSCH_FILTER */
997 
998 #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:1096
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:572
#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:27
@ MATRIX_COLUMN
Definition: convolution.h:29
@ MATRIX_ROW
Definition: convolution.h:28
@ MATRIX_NBMODES
Definition: convolution.h:30
#define NULL
Definition: coverity.c:32
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
Definition: filters.h:271
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 av_always_inline av_const int avpriv_mirror(int x, int w)
Definition: internal.h:269
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
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:104
float delta
static double c[64]