FFmpeg  4.4.8
vf_convolve.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <float.h>
22 
23 #include "libavutil/imgutils.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/pixdesc.h"
26 #include "libavcodec/avfft.h"
27 
28 #include "avfilter.h"
29 #include "filters.h"
30 #include "formats.h"
31 #include "framesync.h"
32 #include "internal.h"
33 #include "video.h"
34 
35 #define MAX_THREADS 16
36 
37 typedef struct ConvolveContext {
38  const AVClass *class;
40 
43 
44  int fft_bits[4];
45  int fft_len[4];
46  int planewidth[4];
47  int planeheight[4];
48 
53 
54  int depth;
55  int planes;
56  int impulse;
57  float noise;
58  int nb_planes;
59  int got_impulse[4];
60 
61  int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
63 
64 #define OFFSET(x) offsetof(ConvolveContext, x)
65 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
66 
67 static const AVOption convolve_options[] = {
68  { "planes", "set planes to convolve", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
69  { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "impulse" },
70  { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "impulse" },
71  { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "impulse" },
72  { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS },
73  { NULL },
74 };
75 
77 {
78  static const enum AVPixelFormat pixel_fmts_fftfilt[] = {
97  };
98 
99  AVFilterFormats *fmts_list = ff_make_format_list(pixel_fmts_fftfilt);
100  if (!fmts_list)
101  return AVERROR(ENOMEM);
102  return ff_set_common_formats(ctx, fmts_list);
103 }
104 
105 static int config_input_main(AVFilterLink *inlink)
106 {
107  ConvolveContext *s = inlink->dst->priv;
109  int fft_bits, i;
110 
111  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
112  s->planewidth[0] = s->planewidth[3] = inlink->w;
113  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
114  s->planeheight[0] = s->planeheight[3] = inlink->h;
115 
116  s->nb_planes = desc->nb_components;
117  s->depth = desc->comp[0].depth;
118 
119  for (i = 0; i < s->nb_planes; i++) {
120  int w = s->planewidth[i];
121  int h = s->planeheight[i];
122  int n = FFMAX(w, h);
123 
124  for (fft_bits = 1; 1 << fft_bits < n; fft_bits++);
125 
126  s->fft_bits[i] = fft_bits;
127  s->fft_len[i] = 1 << s->fft_bits[i];
128 
129  if (!(s->fft_hdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex))))
130  return AVERROR(ENOMEM);
131 
132  if (!(s->fft_vdata[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex))))
133  return AVERROR(ENOMEM);
134 
135  if (!(s->fft_hdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex))))
136  return AVERROR(ENOMEM);
137 
138  if (!(s->fft_vdata_impulse[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(FFTComplex))))
139  return AVERROR(ENOMEM);
140  }
141 
142  return 0;
143 }
144 
146 {
147  AVFilterContext *ctx = inlink->dst;
148 
149  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
150  ctx->inputs[0]->h != ctx->inputs[1]->h) {
151  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
152  return AVERROR(EINVAL);
153  }
154  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
155  av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n");
156  return AVERROR(EINVAL);
157  }
158 
159  return 0;
160 }
161 
162 typedef struct ThreadData {
164  int plane, n;
165 } ThreadData;
166 
167 static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
168 {
169  ConvolveContext *s = ctx->priv;
170  ThreadData *td = arg;
171  FFTComplex *hdata = td->hdata;
172  const int plane = td->plane;
173  const int n = td->n;
174  int start = ff_slice_pos(n, jobnr, nb_jobs);
175  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
176  int y;
177 
178  for (y = start; y < end; y++) {
179  av_fft_permute(s->fft[plane][jobnr], hdata + y * n);
180  av_fft_calc(s->fft[plane][jobnr], hdata + y * n);
181  }
182 
183  return 0;
184 }
185 
186 static void get_input(ConvolveContext *s, FFTComplex *fft_hdata,
187  AVFrame *in, int w, int h, int n, int plane, float scale)
188 {
189  const int iw = (n - w) / 2, ih = (n - h) / 2;
190  int y, x;
191 
192  if (s->depth == 8) {
193  for (y = 0; y < h; y++) {
194  const uint8_t *src = in->data[plane] + in->linesize[plane] * y;
195 
196  for (x = 0; x < w; x++) {
197  fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale;
198  fft_hdata[(y + ih) * n + iw + x].im = 0;
199  }
200 
201  for (x = 0; x < iw; x++) {
202  fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re;
203  fft_hdata[(y + ih) * n + x].im = 0;
204  }
205 
206  for (x = n - iw; x < n; x++) {
207  fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re;
208  fft_hdata[(y + ih) * n + x].im = 0;
209  }
210  }
211 
212  for (y = 0; y < ih; y++) {
213  for (x = 0; x < n; x++) {
214  fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re;
215  fft_hdata[y * n + x].im = 0;
216  }
217  }
218 
219  for (y = n - ih; y < n; y++) {
220  for (x = 0; x < n; x++) {
221  fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re;
222  fft_hdata[y * n + x].im = 0;
223  }
224  }
225  } else {
226  for (y = 0; y < h; y++) {
227  const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y);
228 
229  for (x = 0; x < w; x++) {
230  fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale;
231  fft_hdata[(y + ih) * n + iw + x].im = 0;
232  }
233 
234  for (x = 0; x < iw; x++) {
235  fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re;
236  fft_hdata[(y + ih) * n + x].im = 0;
237  }
238 
239  for (x = n - iw; x < n; x++) {
240  fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re;
241  fft_hdata[(y + ih) * n + x].im = 0;
242  }
243  }
244 
245  for (y = 0; y < ih; y++) {
246  for (x = 0; x < n; x++) {
247  fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re;
248  fft_hdata[y * n + x].im = 0;
249  }
250  }
251 
252  for (y = n - ih; y < n; y++) {
253  for (x = 0; x < n; x++) {
254  fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re;
255  fft_hdata[y * n + x].im = 0;
256  }
257  }
258  }
259 }
260 
261 static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
262 {
263  ConvolveContext *s = ctx->priv;
264  ThreadData *td = arg;
265  FFTComplex *hdata = td->hdata;
266  FFTComplex *vdata = td->vdata;
267  const int plane = td->plane;
268  const int n = td->n;
269  int start = ff_slice_pos(n, jobnr, nb_jobs);
270  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
271  int y, x;
272 
273  for (y = start; y < end; y++) {
274  for (x = 0; x < n; x++) {
275  vdata[y * n + x].re = hdata[x * n + y].re;
276  vdata[y * n + x].im = hdata[x * n + y].im;
277  }
278 
279  av_fft_permute(s->fft[plane][jobnr], vdata + y * n);
280  av_fft_calc(s->fft[plane][jobnr], vdata + y * n);
281  }
282 
283  return 0;
284 }
285 
286 static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
287 {
288  ConvolveContext *s = ctx->priv;
289  ThreadData *td = arg;
290  FFTComplex *hdata = td->hdata;
291  FFTComplex *vdata = td->vdata;
292  const int plane = td->plane;
293  const int n = td->n;
294  int start = ff_slice_pos(n, jobnr, nb_jobs);
295  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
296  int y, x;
297 
298  for (y = start; y < end; y++) {
299  av_fft_permute(s->ifft[plane][jobnr], vdata + y * n);
300  av_fft_calc(s->ifft[plane][jobnr], vdata + y * n);
301 
302  for (x = 0; x < n; x++) {
303  hdata[x * n + y].re = vdata[y * n + x].re;
304  hdata[x * n + y].im = vdata[y * n + x].im;
305  }
306  }
307 
308  return 0;
309 }
310 
311 static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
312 {
313  ConvolveContext *s = ctx->priv;
314  ThreadData *td = arg;
315  FFTComplex *hdata = td->hdata;
316  const int plane = td->plane;
317  const int n = td->n;
318  int start = ff_slice_pos(n, jobnr, nb_jobs);
319  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
320  int y;
321 
322  for (y = start; y < end; y++) {
323  av_fft_permute(s->ifft[plane][jobnr], hdata + y * n);
324  av_fft_calc(s->ifft[plane][jobnr], hdata + y * n);
325  }
326 
327  return 0;
328 }
329 
331  int w, int h, int n, int plane, float scale)
332 {
333  const int max = (1 << s->depth) - 1;
334  const int hh = h / 2;
335  const int hw = w / 2;
336  int y, x;
337 
338  if (s->depth == 8) {
339  for (y = 0; y < hh; y++) {
340  uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane] + hw;
341  for (x = 0; x < hw; x++)
342  dst[x] = av_clip_uint8(input[y * n + x].re * scale);
343  }
344  for (y = 0; y < hh; y++) {
345  uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane];
346  for (x = 0; x < hw; x++)
347  dst[x] = av_clip_uint8(input[y * n + n - hw + x].re * scale);
348  }
349  for (y = 0; y < hh; y++) {
350  uint8_t *dst = out->data[plane] + y * out->linesize[plane] + hw;
351  for (x = 0; x < hw; x++)
352  dst[x] = av_clip_uint8(input[(n - hh + y) * n + x].re * scale);
353  }
354  for (y = 0; y < hh; y++) {
355  uint8_t *dst = out->data[plane] + y * out->linesize[plane];
356  for (x = 0; x < hw; x++)
357  dst[x] = av_clip_uint8(input[(n - hh + y) * n + n - hw + x].re * scale);
358  }
359  } else {
360  for (y = 0; y < hh; y++) {
361  uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane] + hw * 2);
362  for (x = 0; x < hw; x++)
363  dst[x] = av_clip(input[y * n + x].re * scale, 0, max);
364  }
365  for (y = 0; y < hh; y++) {
366  uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane]);
367  for (x = 0; x < hw; x++)
368  dst[x] = av_clip(input[y * n + n - hw + x].re * scale, 0, max);
369  }
370  for (y = 0; y < hh; y++) {
371  uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane] + hw * 2);
372  for (x = 0; x < hw; x++)
373  dst[x] = av_clip(input[(n - hh + y) * n + x].re * scale, 0, max);
374  }
375  for (y = 0; y < hh; y++) {
376  uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane]);
377  for (x = 0; x < hw; x++)
378  dst[x] = av_clip(input[(n - hh + y) * n + n - hw + x].re * scale, 0, max);
379  }
380  }
381 }
382 
383 static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
384 {
385  ConvolveContext *s = ctx->priv;
386  ThreadData *td = arg;
387  FFTComplex *input = td->hdata;
388  FFTComplex *filter = td->vdata;
389  const float noise = s->noise;
390  const int n = td->n;
391  int start = ff_slice_pos(n, jobnr, nb_jobs);
392  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
393  int y, x;
394 
395  for (y = start; y < end; y++) {
396  int yn = y * n;
397 
398  for (x = 0; x < n; x++) {
399  FFTSample re, im, ire, iim;
400 
401  re = input[yn + x].re;
402  im = input[yn + x].im;
403  ire = filter[yn + x].re + noise;
404  iim = filter[yn + x].im;
405 
406  input[yn + x].re = ire * re - iim * im;
407  input[yn + x].im = iim * re + ire * im;
408  }
409  }
410 
411  return 0;
412 }
413 
414 static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
415 {
416  ConvolveContext *s = ctx->priv;
417  ThreadData *td = arg;
418  FFTComplex *input = td->hdata;
419  FFTComplex *filter = td->vdata;
420  const float noise = s->noise;
421  const int n = td->n;
422  int start = ff_slice_pos(n, jobnr, nb_jobs);
423  int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
424  int y, x;
425 
426  for (y = start; y < end; y++) {
427  int yn = y * n;
428 
429  for (x = 0; x < n; x++) {
430  FFTSample re, im, ire, iim, div;
431 
432  re = input[yn + x].re;
433  im = input[yn + x].im;
434  ire = filter[yn + x].re;
435  iim = filter[yn + x].im;
436  div = ire * ire + iim * iim + noise;
437 
438  input[yn + x].re = (ire * re + iim * im) / div;
439  input[yn + x].im = (ire * im - iim * re) / div;
440  }
441  }
442 
443  return 0;
444 }
445 
447 {
448  AVFilterContext *ctx = fs->parent;
449  AVFilterLink *outlink = ctx->outputs[0];
450  ConvolveContext *s = ctx->priv;
451  AVFrame *mainpic = NULL, *impulsepic = NULL;
452  int ret, y, x, plane;
453 
454  ret = ff_framesync_dualinput_get(fs, &mainpic, &impulsepic);
455  if (ret < 0)
456  return ret;
457  if (!impulsepic)
458  return ff_filter_frame(outlink, mainpic);
459 
460  for (plane = 0; plane < s->nb_planes; plane++) {
461  FFTComplex *filter = s->fft_vdata_impulse[plane];
462  FFTComplex *input = s->fft_vdata[plane];
463  const int n = s->fft_len[plane];
464  const int w = s->planewidth[plane];
465  const int h = s->planeheight[plane];
466  float total = 0;
467  ThreadData td;
468 
469  if (!(s->planes & (1 << plane))) {
470  continue;
471  }
472 
473  td.plane = plane, td.n = n;
474  get_input(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f);
475 
476  td.hdata = s->fft_hdata[plane];
477  td.vdata = s->fft_vdata[plane];
478 
481 
482  if ((!s->impulse && !s->got_impulse[plane]) || s->impulse) {
483  if (s->depth == 8) {
484  for (y = 0; y < h; y++) {
485  const uint8_t *src = (const uint8_t *)(impulsepic->data[plane] + y * impulsepic->linesize[plane]) ;
486  for (x = 0; x < w; x++) {
487  total += src[x];
488  }
489  }
490  } else {
491  for (y = 0; y < h; y++) {
492  const uint16_t *src = (const uint16_t *)(impulsepic->data[plane] + y * impulsepic->linesize[plane]) ;
493  for (x = 0; x < w; x++) {
494  total += src[x];
495  }
496  }
497  }
498  total = FFMAX(1, total);
499 
500  get_input(s, s->fft_hdata_impulse[plane], impulsepic, w, h, n, plane, 1.f / total);
501 
502  td.hdata = s->fft_hdata_impulse[plane];
503  td.vdata = s->fft_vdata_impulse[plane];
504 
507 
508  s->got_impulse[plane] = 1;
509  }
510 
511  td.hdata = input;
512  td.vdata = filter;
513 
514  ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN3(MAX_THREADS, n, ff_filter_get_nb_threads(ctx)));
515 
516  td.hdata = s->fft_hdata[plane];
517  td.vdata = s->fft_vdata[plane];
518 
521 
522  get_output(s, s->fft_hdata[plane], mainpic, w, h, n, plane, 1.f / (n * n));
523  }
524 
525  return ff_filter_frame(outlink, mainpic);
526 }
527 
528 static int config_output(AVFilterLink *outlink)
529 {
530  AVFilterContext *ctx = outlink->src;
531  ConvolveContext *s = ctx->priv;
532  AVFilterLink *mainlink = ctx->inputs[0];
533  int ret, i, j;
534 
535  s->fs.on_event = do_convolve;
536  ret = ff_framesync_init_dualinput(&s->fs, ctx);
537  if (ret < 0)
538  return ret;
539  outlink->w = mainlink->w;
540  outlink->h = mainlink->h;
541  outlink->time_base = mainlink->time_base;
542  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
543  outlink->frame_rate = mainlink->frame_rate;
544 
545  if ((ret = ff_framesync_configure(&s->fs)) < 0)
546  return ret;
547 
548  for (i = 0; i < s->nb_planes; i++) {
549  for (j = 0; j < MAX_THREADS; j++) {
550  s->fft[i][j] = av_fft_init(s->fft_bits[i], 0);
551  s->ifft[i][j] = av_fft_init(s->fft_bits[i], 1);
552  if (!s->fft[i][j] || !s->ifft[i][j])
553  return AVERROR(ENOMEM);
554  }
555  }
556 
557  return 0;
558 }
559 
561 {
562  ConvolveContext *s = ctx->priv;
563  return ff_framesync_activate(&s->fs);
564 }
565 
567 {
568  ConvolveContext *s = ctx->priv;
569 
570  if (!strcmp(ctx->filter->name, "convolve")) {
571  s->filter = complex_multiply;
572  } else if (!strcmp(ctx->filter->name, "deconvolve")) {
573  s->filter = complex_divide;
574  } else {
575  return AVERROR_BUG;
576  }
577 
578  return 0;
579 }
580 
582 {
583  ConvolveContext *s = ctx->priv;
584  int i, j;
585 
586  for (i = 0; i < 4; i++) {
587  av_freep(&s->fft_hdata[i]);
588  av_freep(&s->fft_vdata[i]);
589  av_freep(&s->fft_hdata_impulse[i]);
590  av_freep(&s->fft_vdata_impulse[i]);
591 
592  for (j = 0; j < MAX_THREADS; j++) {
593  av_fft_end(s->fft[i][j]);
594  s->fft[i][j] = NULL;
595  av_fft_end(s->ifft[i][j]);
596  s->ifft[i][j] = NULL;
597  }
598  }
599 
600  ff_framesync_uninit(&s->fs);
601 }
602 
603 static const AVFilterPad convolve_inputs[] = {
604  {
605  .name = "main",
606  .type = AVMEDIA_TYPE_VIDEO,
607  .config_props = config_input_main,
608  },{
609  .name = "impulse",
610  .type = AVMEDIA_TYPE_VIDEO,
611  .config_props = config_input_impulse,
612  },
613  { NULL }
614 };
615 
616 static const AVFilterPad convolve_outputs[] = {
617  {
618  .name = "default",
619  .type = AVMEDIA_TYPE_VIDEO,
620  .config_props = config_output,
621  },
622  { NULL }
623 };
624 
625 #if CONFIG_CONVOLVE_FILTER
626 
628 
630  .name = "convolve",
631  .description = NULL_IF_CONFIG_SMALL("Convolve first video stream with second video stream."),
632  .preinit = convolve_framesync_preinit,
633  .init = init,
634  .uninit = uninit,
635  .query_formats = query_formats,
636  .activate = activate,
637  .priv_size = sizeof(ConvolveContext),
638  .priv_class = &convolve_class,
642 };
643 
644 #endif /* CONFIG_CONVOLVE_FILTER */
645 
646 #if CONFIG_DECONVOLVE_FILTER
647 
648 static const AVOption deconvolve_options[] = {
649  { "planes", "set planes to deconvolve", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
650  { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "impulse" },
651  { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "impulse" },
652  { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "impulse" },
653  { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS },
654  { NULL },
655 };
656 
658 
660  .name = "deconvolve",
661  .description = NULL_IF_CONFIG_SMALL("Deconvolve first video stream with second video stream."),
662  .preinit = deconvolve_framesync_preinit,
663  .init = init,
664  .uninit = uninit,
665  .query_formats = query_formats,
666  .activate = activate,
667  .priv_size = sizeof(ConvolveContext),
668  .priv_class = &deconvolve_class,
672 };
673 
674 #endif /* CONFIG_DECONVOLVE_FILTER */
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
AVFilter ff_vf_convolve
AVFilter ff_vf_deconvolve
#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
FFT functions.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
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 fs(width, name, subs,...)
Definition: cbs_vp9.c:259
static av_always_inline void filter(int16_t *output, ptrdiff_t out_stride, const int16_t *low, ptrdiff_t low_stride, const int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhddsp.c:27
#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 FFMIN3(a, b, c)
Definition: common.h:106
#define NULL
Definition: coverity.c:32
#define max(a, b)
Definition: cuda_runtime.h:33
int
float im
Definition: fft.c:82
float re
Definition: fft.c:82
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
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:124
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:376
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:341
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:358
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:290
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
Definition: framesync.h:302
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
@ AV_OPT_TYPE_INT
Definition: opt.h:225
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
float FFTSample
Definition: avfft.h:35
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition: avfilter.h:134
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
for(j=16;j >0;--j)
misc image utilities
int i
Definition: input.c:407
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
const char * desc
Definition: libsvtav1.c:79
uint8_t w
Definition: llviddspenc.c:39
static const struct @322 planes[]
static int noise(AVBSFContext *ctx, AVPacket *pkt)
Definition: noise_bsf.c:36
AVOptions.
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_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_YUV444P16
Definition: pixfmt.h:412
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:402
static void convolve(float *tgt, const float *src, int len, int n)
Definition: ra288.c:88
#define td
Definition: regdef.h:70
Describe the class of an AVClass context structure.
Definition: log.h:67
An instance of a filter.
Definition: avfilter.h:341
void * priv
private data for use by the filter
Definition: avfilter.h:356
A list of supported formats for one end of a filter link.
Definition: formats.h:65
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
FFFrameSync fs
Definition: vf_convolve.c:39
int got_impulse[4]
Definition: vf_convolve.c:59
int(* filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:61
int planeheight[4]
Definition: vf_convolve.c:47
FFTComplex * fft_vdata[4]
Definition: vf_convolve.c:50
FFTContext * fft[4][MAX_THREADS]
Definition: vf_convolve.c:41
int planewidth[4]
Definition: vf_convolve.c:46
FFTComplex * fft_vdata_impulse[4]
Definition: vf_convolve.c:52
FFTContext * ifft[4][MAX_THREADS]
Definition: vf_convolve.c:42
FFTComplex * fft_hdata_impulse[4]
Definition: vf_convolve.c:51
FFTComplex * fft_hdata[4]
Definition: vf_convolve.c:49
Frame sync structure.
Definition: framesync.h:146
FFTSample re
Definition: avfft.h:38
FFTSample im
Definition: avfft.h:38
Definition: fft.h:83
Used for passing data between threads.
Definition: dsddec.c:67
FFTComplex * vdata
Definition: vf_convolve.c:163
int plane
Definition: vf_blend.c:59
FFTComplex * hdata
Definition: vf_convolve.c:163
#define av_freep(p)
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
static const AVFilterPad convolve_outputs[]
Definition: vf_convolve.c:616
static const AVOption convolve_options[]
Definition: vf_convolve.c:67
static int do_convolve(FFFrameSync *fs)
Definition: vf_convolve.c:446
static int config_input_impulse(AVFilterLink *inlink)
Definition: vf_convolve.c:145
static int query_formats(AVFilterContext *ctx)
Definition: vf_convolve.c:76
static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:167
#define FLAGS
Definition: vf_convolve.c:65
static void get_output(ConvolveContext *s, FFTComplex *input, AVFrame *out, int w, int h, int n, int plane, float scale)
Definition: vf_convolve.c:330
static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:261
#define MAX_THREADS
Definition: vf_convolve.c:35
static const AVFilterPad convolve_inputs[]
Definition: vf_convolve.c:603
static int config_input_main(AVFilterLink *inlink)
Definition: vf_convolve.c:105
static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:383
static int activate(AVFilterContext *ctx)
Definition: vf_convolve.c:560
static av_cold int init(AVFilterContext *ctx)
Definition: vf_convolve.c:566
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_convolve.c:581
static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:286
static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:311
#define OFFSET(x)
Definition: vf_convolve.c:64
static int config_output(AVFilterLink *outlink)
Definition: vf_convolve.c:528
static void get_input(ConvolveContext *s, FFTComplex *fft_hdata, AVFrame *in, int w, int h, int n, int plane, float scale)
Definition: vf_convolve.c:186
static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_convolve.c:414