FFmpeg
Loading...
Searching...
No Matches
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 "config_components.h"
22
23#include <float.h>
24
25#include "libavutil/mem.h"
26#include "libavutil/opt.h"
27#include "libavutil/pixdesc.h"
28#include "libavutil/tx.h"
29
30#include "avfilter.h"
31#include "filters.h"
32#include "framesync.h"
33
34#define MAX_THREADS 16
35
81
82#define OFFSET(x) offsetof(ConvolveContext, x)
83#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
84
85static const AVOption convolve_options[] = {
86 { "planes", "set planes to convolve", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
87 { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "impulse" },
88 { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "impulse" },
89 { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "impulse" },
90 { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS },
91 { NULL },
92};
93
114
115static int config_input(AVFilterLink *inlink)
116{
117 ConvolveContext *s = inlink->dst->priv;
119 const int w = inlink->w;
120 const int h = inlink->h;
121
122 s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(w, desc->log2_chroma_w);
123 s->planewidth[0] = s->planewidth[3] = w;
124 s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(h, desc->log2_chroma_h);
125 s->planeheight[0] = s->planeheight[3] = h;
126
127 s->nb_planes = desc->nb_components;
128 s->depth = desc->comp[0].depth;
129
130 for (int i = 0; i < s->nb_planes; i++) {
131 int w = s->planewidth[i];
132 int h = s->planeheight[i];
133 int n = FFMAX(w, h);
134
135 s->fft_len[i] = 1 << (av_log2(2 * n - 1));
136
137 if (!(s->fft_hdata_in[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
138 return AVERROR(ENOMEM);
139
140 if (!(s->fft_hdata_out[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
141 return AVERROR(ENOMEM);
142
143 if (!(s->fft_vdata_in[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
144 return AVERROR(ENOMEM);
145
146 if (!(s->fft_vdata_out[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
147 return AVERROR(ENOMEM);
148
149 if (!(s->fft_hdata_impulse_in[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
150 return AVERROR(ENOMEM);
151
152 if (!(s->fft_vdata_impulse_in[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
153 return AVERROR(ENOMEM);
154
155 if (!(s->fft_hdata_impulse_out[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
156 return AVERROR(ENOMEM);
157
158 if (!(s->fft_vdata_impulse_out[i] = av_calloc(s->fft_len[i], s->fft_len[i] * sizeof(AVComplexFloat))))
159 return AVERROR(ENOMEM);
160 }
161
162 return 0;
163}
164
166{
167 AVFilterContext *ctx = inlink->dst;
168
169 if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
170 ctx->inputs[0]->h != ctx->inputs[1]->h) {
171 av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
172 return AVERROR(EINVAL);
173 }
174
175 return 0;
176}
177
178typedef struct ThreadData {
181 int plane, n;
182} ThreadData;
183
184static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
185{
186 ConvolveContext *s = ctx->priv;
187 ThreadData *td = arg;
188 AVComplexFloat *hdata_in = td->hdata_in;
189 AVComplexFloat *hdata_out = td->hdata_out;
190 const int plane = td->plane;
191 const int n = td->n;
192 int start = ff_slice_pos(n, jobnr, nb_jobs);
193 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
194 int y;
195
196 for (y = start; y < end; y++) {
197 s->tx_fn[plane](s->fft[plane][jobnr], hdata_out + y * n, hdata_in + y * n, sizeof(AVComplexFloat));
198 }
199
200 return 0;
201}
202
203#define SQR(x) ((x) * (x))
204
206 AVComplexFloat *fft_hdata,
207 AVFrame *in, int w, int h,
208 int n, int plane, float scale)
209{
210 float sum = 0.f;
211 float mean, dev;
212 int y, x;
213
214 if (s->depth == 8) {
215 for (y = 0; y < h; y++) {
216 const uint8_t *src = in->data[plane] + in->linesize[plane] * y;
217
218 for (x = 0; x < w; x++)
219 sum += src[x];
220 }
221
222 mean = sum / (w * h);
223 sum = 0.f;
224 for (y = 0; y < h; y++) {
225 const uint8_t *src = in->data[plane] + in->linesize[plane] * y;
226
227 for (x = 0; x < w; x++)
228 sum += SQR(src[x] - mean);
229 }
230
231 dev = sqrtf(sum / (w * h));
232 scale /= dev;
233 for (y = 0; y < h; y++) {
234 const uint8_t *src = in->data[plane] + in->linesize[plane] * y;
235
236 for (x = 0; x < w; x++) {
237 fft_hdata[y * n + x].re = (src[x] - mean) * scale;
238 fft_hdata[y * n + x].im = 0;
239 }
240
241 for (x = w; x < n; x++) {
242 fft_hdata[y * n + x].re = 0;
243 fft_hdata[y * n + x].im = 0;
244 }
245 }
246
247 for (y = h; y < n; y++) {
248 for (x = 0; x < n; x++) {
249 fft_hdata[y * n + x].re = 0;
250 fft_hdata[y * n + x].im = 0;
251 }
252 }
253 } else {
254 for (y = 0; y < h; y++) {
255 const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y);
256
257 for (x = 0; x < w; x++)
258 sum += src[x];
259 }
260
261 mean = sum / (w * h);
262 sum = 0.f;
263 for (y = 0; y < h; y++) {
264 const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y);
265
266 for (x = 0; x < w; x++)
267 sum += SQR(src[x] - mean);
268 }
269
270 dev = sqrtf(sum / (w * h));
271 scale /= dev;
272 for (y = 0; y < h; y++) {
273 const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y);
274
275 for (x = 0; x < w; x++) {
276 fft_hdata[y * n + x].re = (src[x] - mean) * scale;
277 fft_hdata[y * n + x].im = 0;
278 }
279
280 for (x = w; x < n; x++) {
281 fft_hdata[y * n + x].re = 0;
282 fft_hdata[y * n + x].im = 0;
283 }
284 }
285
286 for (y = h; y < n; y++) {
287 for (x = 0; x < n; x++) {
288 fft_hdata[y * n + x].re = 0;
289 fft_hdata[y * n + x].im = 0;
290 }
291 }
292 }
293}
294
295static void get_input(ConvolveContext *s, AVComplexFloat *fft_hdata,
296 AVFrame *in, int w, int h, int n, int plane, float scale)
297{
298 const int iw = (n - w) / 2, ih = (n - h) / 2;
299 int y, x;
300
301 if (s->depth == 8) {
302 for (y = 0; y < h; y++) {
303 const uint8_t *src = in->data[plane] + in->linesize[plane] * y;
304
305 for (x = 0; x < w; x++) {
306 fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale;
307 fft_hdata[(y + ih) * n + iw + x].im = 0;
308 }
309
310 for (x = 0; x < iw; x++) {
311 fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re;
312 fft_hdata[(y + ih) * n + x].im = 0;
313 }
314
315 for (x = n - iw; x < n; x++) {
316 fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re;
317 fft_hdata[(y + ih) * n + x].im = 0;
318 }
319 }
320
321 for (y = 0; y < ih; y++) {
322 for (x = 0; x < n; x++) {
323 fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re;
324 fft_hdata[y * n + x].im = 0;
325 }
326 }
327
328 for (y = n - ih; y < n; y++) {
329 for (x = 0; x < n; x++) {
330 fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re;
331 fft_hdata[y * n + x].im = 0;
332 }
333 }
334 } else {
335 for (y = 0; y < h; y++) {
336 const uint16_t *src = (const uint16_t *)(in->data[plane] + in->linesize[plane] * y);
337
338 for (x = 0; x < w; x++) {
339 fft_hdata[(y + ih) * n + iw + x].re = src[x] * scale;
340 fft_hdata[(y + ih) * n + iw + x].im = 0;
341 }
342
343 for (x = 0; x < iw; x++) {
344 fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + iw].re;
345 fft_hdata[(y + ih) * n + x].im = 0;
346 }
347
348 for (x = n - iw; x < n; x++) {
349 fft_hdata[(y + ih) * n + x].re = fft_hdata[(y + ih) * n + n - iw - 1].re;
350 fft_hdata[(y + ih) * n + x].im = 0;
351 }
352 }
353
354 for (y = 0; y < ih; y++) {
355 for (x = 0; x < n; x++) {
356 fft_hdata[y * n + x].re = fft_hdata[ih * n + x].re;
357 fft_hdata[y * n + x].im = 0;
358 }
359 }
360
361 for (y = n - ih; y < n; y++) {
362 for (x = 0; x < n; x++) {
363 fft_hdata[y * n + x].re = fft_hdata[(n - ih - 1) * n + x].re;
364 fft_hdata[y * n + x].im = 0;
365 }
366 }
367 }
368}
369
370static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
371{
372 ConvolveContext *s = ctx->priv;
373 ThreadData *td = arg;
374 AVComplexFloat *hdata = td->hdata_out;
375 AVComplexFloat *vdata_in = td->vdata_in;
376 AVComplexFloat *vdata_out = td->vdata_out;
377 const int plane = td->plane;
378 const int n = td->n;
379 int start = ff_slice_pos(n, jobnr, nb_jobs);
380 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
381 int y, x;
382
383 for (y = start; y < end; y++) {
384 for (x = 0; x < n; x++) {
385 vdata_in[y * n + x].re = hdata[x * n + y].re;
386 vdata_in[y * n + x].im = hdata[x * n + y].im;
387 }
388
389 s->tx_fn[plane](s->fft[plane][jobnr], vdata_out + y * n, vdata_in + y * n, sizeof(AVComplexFloat));
390 }
391
392 return 0;
393}
394
395static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
396{
397 ConvolveContext *s = ctx->priv;
398 ThreadData *td = arg;
399 AVComplexFloat *hdata = td->hdata_out;
400 AVComplexFloat *vdata_out = td->vdata_out;
401 AVComplexFloat *vdata_in = td->vdata_in;
402 const int plane = td->plane;
403 const int n = td->n;
404 int start = ff_slice_pos(n, jobnr, nb_jobs);
405 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
406 int y, x;
407
408 for (y = start; y < end; y++) {
409 s->itx_fn[plane](s->ifft[plane][jobnr], vdata_out + y * n, vdata_in + y * n, sizeof(AVComplexFloat));
410
411 for (x = 0; x < n; x++) {
412 hdata[x * n + y].re = vdata_out[y * n + x].re;
413 hdata[x * n + y].im = vdata_out[y * n + x].im;
414 }
415 }
416
417 return 0;
418}
419
420static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
421{
422 ConvolveContext *s = ctx->priv;
423 ThreadData *td = arg;
424 AVComplexFloat *hdata_out = td->hdata_out;
425 AVComplexFloat *hdata_in = td->hdata_in;
426 const int plane = td->plane;
427 const int n = td->n;
428 int start = ff_slice_pos(n, jobnr, nb_jobs);
429 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
430 int y;
431
432 for (y = start; y < end; y++) {
433 s->itx_fn[plane](s->ifft[plane][jobnr], hdata_out + y * n, hdata_in + y * n, sizeof(AVComplexFloat));
434 }
435
436 return 0;
437}
438
440 int w, int h, int n, int plane, float scale)
441{
442 const int imax = (1 << s->depth) - 1;
443
444 scale *= imax * 16;
445 if (s->depth == 8) {
446 for (int y = 0; y < h; y++) {
447 uint8_t *dst = out->data[plane] + y * out->linesize[plane];
448 for (int x = 0; x < w; x++)
449 dst[x] = av_clip_uint8(input[y * n + x].re * scale);
450 }
451 } else {
452 for (int y = 0; y < h; y++) {
453 uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane]);
454 for (int x = 0; x < w; x++)
455 dst[x] = av_clip(input[y * n + x].re * scale, 0, imax);
456 }
457 }
458}
459
461 int w, int h, int n, int plane, float scale)
462{
463 const int max = (1 << s->depth) - 1;
464 const int hh = h / 2;
465 const int hw = w / 2;
466 int y, x;
467
468 if (s->depth == 8) {
469 for (y = 0; y < hh; y++) {
470 uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane] + hw;
471 for (x = 0; x < hw; x++)
472 dst[x] = av_clip_uint8(input[y * n + x].re * scale);
473 }
474 for (y = 0; y < hh; y++) {
475 uint8_t *dst = out->data[plane] + (y + hh) * out->linesize[plane];
476 for (x = 0; x < hw; x++)
477 dst[x] = av_clip_uint8(input[y * n + n - hw + x].re * scale);
478 }
479 for (y = 0; y < hh; y++) {
480 uint8_t *dst = out->data[plane] + y * out->linesize[plane] + hw;
481 for (x = 0; x < hw; x++)
482 dst[x] = av_clip_uint8(input[(n - hh + y) * n + x].re * scale);
483 }
484 for (y = 0; y < hh; y++) {
485 uint8_t *dst = out->data[plane] + y * out->linesize[plane];
486 for (x = 0; x < hw; x++)
487 dst[x] = av_clip_uint8(input[(n - hh + y) * n + n - hw + x].re * scale);
488 }
489 } else {
490 for (y = 0; y < hh; y++) {
491 uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane] + hw * 2);
492 for (x = 0; x < hw; x++)
493 dst[x] = av_clip(input[y * n + x].re * scale, 0, max);
494 }
495 for (y = 0; y < hh; y++) {
496 uint16_t *dst = (uint16_t *)(out->data[plane] + (y + hh) * out->linesize[plane]);
497 for (x = 0; x < hw; x++)
498 dst[x] = av_clip(input[y * n + n - hw + x].re * scale, 0, max);
499 }
500 for (y = 0; y < hh; y++) {
501 uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane] + hw * 2);
502 for (x = 0; x < hw; x++)
503 dst[x] = av_clip(input[(n - hh + y) * n + x].re * scale, 0, max);
504 }
505 for (y = 0; y < hh; y++) {
506 uint16_t *dst = (uint16_t *)(out->data[plane] + y * out->linesize[plane]);
507 for (x = 0; x < hw; x++)
508 dst[x] = av_clip(input[(n - hh + y) * n + n - hw + x].re * scale, 0, max);
509 }
510 }
511}
512
513static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
514{
515 ConvolveContext *s = ctx->priv;
516 ThreadData *td = arg;
517 AVComplexFloat *input = td->hdata_in;
519 const float noise = s->noise;
520 const int n = td->n;
521 int start = ff_slice_pos(n, jobnr, nb_jobs);
522 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
523 int y, x;
524
525 for (y = start; y < end; y++) {
526 int yn = y * n;
527
528 for (x = 0; x < n; x++) {
529 float re, im, ire, iim;
530
531 re = input[yn + x].re;
532 im = input[yn + x].im;
533 ire = filter[yn + x].re + noise;
534 iim = filter[yn + x].im;
535
536 input[yn + x].re = ire * re - iim * im;
537 input[yn + x].im = iim * re + ire * im;
538 }
539 }
540
541 return 0;
542}
543
544static int complex_xcorrelate(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
545{
546 ThreadData *td = arg;
547 AVComplexFloat *input = td->hdata_in;
549 const int n = td->n;
550 const float scale = 1.f / (n * n);
551 int start = ff_slice_pos(n, jobnr, nb_jobs);
552 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
553
554 for (int y = start; y < end; y++) {
555 int yn = y * n;
556
557 for (int x = 0; x < n; x++) {
558 float re, im, ire, iim;
559
560 re = input[yn + x].re;
561 im = input[yn + x].im;
562 ire = filter[yn + x].re * scale;
563 iim = -filter[yn + x].im * scale;
564
565 input[yn + x].re = ire * re - iim * im;
566 input[yn + x].im = iim * re + ire * im;
567 }
568 }
569
570 return 0;
571}
572
573static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
574{
575 ConvolveContext *s = ctx->priv;
576 ThreadData *td = arg;
577 AVComplexFloat *input = td->hdata_in;
579 const float noise = s->noise;
580 const int n = td->n;
581 int start = ff_slice_pos(n, jobnr, nb_jobs);
582 int end = ff_slice_pos(n, jobnr + 1, nb_jobs);
583 int y, x;
584
585 for (y = start; y < end; y++) {
586 int yn = y * n;
587
588 for (x = 0; x < n; x++) {
589 float re, im, ire, iim, div;
590
591 re = input[yn + x].re;
592 im = input[yn + x].im;
593 ire = filter[yn + x].re;
594 iim = filter[yn + x].im;
595 div = ire * ire + iim * iim + noise;
596
597 input[yn + x].re = (ire * re + iim * im) / div;
598 input[yn + x].im = (ire * im - iim * re) / div;
599 }
600 }
601
602 return 0;
603}
604
605static void prepare_impulse(AVFilterContext *ctx, AVFrame *impulsepic, int plane)
606{
607 ConvolveContext *s = ctx->priv;
608 const int n = s->fft_len[plane];
609 const int w = s->secondarywidth[plane];
610 const int h = s->secondaryheight[plane];
611 ThreadData td;
612 float total = 0;
613
614 if (s->depth == 8) {
615 for (int y = 0; y < h; y++) {
616 const uint8_t *src = (const uint8_t *)(impulsepic->data[plane] + y * impulsepic->linesize[plane]) ;
617 for (int x = 0; x < w; x++) {
618 total += src[x];
619 }
620 }
621 } else {
622 for (int y = 0; y < h; y++) {
623 const uint16_t *src = (const uint16_t *)(impulsepic->data[plane] + y * impulsepic->linesize[plane]) ;
624 for (int x = 0; x < w; x++) {
625 total += src[x];
626 }
627 }
628 }
629 total = FFMAX(1, total);
630
631 s->get_input(s, s->fft_hdata_impulse_in[plane], impulsepic, w, h, n, plane, 1.f / total);
632
633 td.n = n;
634 td.plane = plane;
635 td.hdata_in = s->fft_hdata_impulse_in[plane];
636 td.vdata_in = s->fft_vdata_impulse_in[plane];
637 td.hdata_out = s->fft_hdata_impulse_out[plane];
638 td.vdata_out = s->fft_vdata_impulse_out[plane];
639
644
645 s->got_impulse[plane] = 1;
646}
647
648static void prepare_secondary(AVFilterContext *ctx, AVFrame *secondary, int plane)
649{
650 ConvolveContext *s = ctx->priv;
651 const int n = s->fft_len[plane];
652 ThreadData td;
653
654 s->get_input(s, s->fft_hdata_impulse_in[plane], secondary,
655 s->secondarywidth[plane],
656 s->secondaryheight[plane],
657 n, plane, 1.f);
658
659 td.n = n;
660 td.plane = plane;
661 td.hdata_in = s->fft_hdata_impulse_in[plane];
662 td.vdata_in = s->fft_vdata_impulse_in[plane];
663 td.hdata_out = s->fft_hdata_impulse_out[plane];
664 td.vdata_out = s->fft_vdata_impulse_out[plane];
665
670
671 s->got_impulse[plane] = 1;
672}
673
675{
676 AVFilterContext *ctx = fs->parent;
677 AVFilterLink *outlink = ctx->outputs[0];
678 ConvolveContext *s = ctx->priv;
679 AVFrame *mainpic = NULL, *impulsepic = NULL;
680 int ret, plane;
681
682 ret = ff_framesync_dualinput_get(fs, &mainpic, &impulsepic);
683 if (ret < 0)
684 return ret;
685 if (!impulsepic)
686 return ff_filter_frame(outlink, mainpic);
687
688 for (plane = 0; plane < s->nb_planes; plane++) {
689 AVComplexFloat *filter = s->fft_vdata_impulse_out[plane];
690 AVComplexFloat *input = s->fft_vdata_out[plane];
691 const int n = s->fft_len[plane];
692 const int w = s->primarywidth[plane];
693 const int h = s->primaryheight[plane];
694 const int ow = s->planewidth[plane];
695 const int oh = s->planeheight[plane];
696 ThreadData td;
697
698 if (!(s->planes & (1 << plane))) {
699 continue;
700 }
701
702 td.plane = plane, td.n = n;
703 s->get_input(s, s->fft_hdata_in[plane], mainpic, w, h, n, plane, 1.f);
704
705 td.hdata_in = s->fft_hdata_in[plane];
706 td.vdata_in = s->fft_vdata_in[plane];
707 td.hdata_out = s->fft_hdata_out[plane];
708 td.vdata_out = s->fft_vdata_out[plane];
709
714
715 if ((!s->impulse && !s->got_impulse[plane]) || s->impulse) {
716 s->prepare_impulse(ctx, impulsepic, plane);
717 }
718
719 td.hdata_in = input;
720 td.vdata_in = filter;
721
722 ff_filter_execute(ctx, s->filter, &td, NULL,
724
725 td.hdata_in = s->fft_hdata_out[plane];
726 td.vdata_in = s->fft_vdata_out[plane];
727 td.hdata_out = s->fft_hdata_in[plane];
728 td.vdata_out = s->fft_vdata_in[plane];
729
732
733 td.hdata_out = s->fft_hdata_out[plane];
734 td.hdata_in = s->fft_hdata_in[plane];
735
738
739 s->get_output(s, s->fft_hdata_out[plane], mainpic, ow, oh, n, plane, 1.f / (n * n));
740 }
741
742 return ff_filter_frame(outlink, mainpic);
743}
744
745static int config_output(AVFilterLink *outlink)
746{
747 FilterLink *outl = ff_filter_link(outlink);
749 AVFilterContext *ctx = outlink->src;
750 ConvolveContext *s = ctx->priv;
751 AVFilterLink *mainlink = ctx->inputs[0];
752 FilterLink *ml = ff_filter_link(mainlink);
753 AVFilterLink *secondlink = ctx->inputs[1];
754 int ret, i, j;
755
756 s->primarywidth[1] = s->primarywidth[2] = AV_CEIL_RSHIFT(mainlink->w, desc->log2_chroma_w);
757 s->primarywidth[0] = s->primarywidth[3] = mainlink->w;
758 s->primaryheight[1] = s->primaryheight[2] = AV_CEIL_RSHIFT(mainlink->h, desc->log2_chroma_h);
759 s->primaryheight[0] = s->primaryheight[3] = mainlink->h;
760
761 s->secondarywidth[1] = s->secondarywidth[2] = AV_CEIL_RSHIFT(secondlink->w, desc->log2_chroma_w);
762 s->secondarywidth[0] = s->secondarywidth[3] = secondlink->w;
763 s->secondaryheight[1] = s->secondaryheight[2] = AV_CEIL_RSHIFT(secondlink->h, desc->log2_chroma_h);
764 s->secondaryheight[0] = s->secondaryheight[3] = secondlink->h;
765
766 s->fs.on_event = do_convolve;
767 ret = ff_framesync_init_dualinput(&s->fs, ctx);
768 if (ret < 0)
769 return ret;
770 outlink->w = mainlink->w;
771 outlink->h = mainlink->h;
772 outlink->time_base = mainlink->time_base;
773 outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
774 outl->frame_rate = ml->frame_rate;
775
776 if ((ret = ff_framesync_configure(&s->fs)) < 0)
777 return ret;
778
779 for (i = 0; i < s->nb_planes; i++) {
780 for (j = 0; j < MAX_THREADS; j++) {
781 float scale = 1.f;
782
783 ret = av_tx_init(&s->fft[i][j], &s->tx_fn[i], AV_TX_FLOAT_FFT, 0, s->fft_len[i], &scale, 0);
784 if (ret < 0)
785 return ret;
786 ret = av_tx_init(&s->ifft[i][j], &s->itx_fn[i], AV_TX_FLOAT_FFT, 1, s->fft_len[i], &scale, 0);
787 if (ret < 0)
788 return ret;
789 }
790 }
791
792 return 0;
793}
794
796{
797 ConvolveContext *s = ctx->priv;
798 return ff_framesync_activate(&s->fs);
799}
800
802{
803 ConvolveContext *s = ctx->priv;
804
805 if (!strcmp(ctx->filter->name, "convolve")) {
806 s->filter = complex_multiply;
807 s->prepare_impulse = prepare_impulse;
808 s->get_input = get_input;
809 s->get_output = get_output;
810 } else if (!strcmp(ctx->filter->name, "xcorrelate")) {
811 s->filter = complex_xcorrelate;
812 s->prepare_impulse = prepare_secondary;
813 s->get_input = get_zeropadded_input;
814 s->get_output = get_xoutput;
815 } else if (!strcmp(ctx->filter->name, "deconvolve")) {
816 s->filter = complex_divide;
817 s->prepare_impulse = prepare_impulse;
818 s->get_input = get_input;
819 s->get_output = get_output;
820 } else {
821 return AVERROR_BUG;
822 }
823
824 return 0;
825}
826
828{
829 ConvolveContext *s = ctx->priv;
830 int i, j;
831
832 for (i = 0; i < 4; i++) {
833 av_freep(&s->fft_hdata_in[i]);
834 av_freep(&s->fft_vdata_in[i]);
835 av_freep(&s->fft_hdata_out[i]);
836 av_freep(&s->fft_vdata_out[i]);
837 av_freep(&s->fft_hdata_impulse_in[i]);
838 av_freep(&s->fft_vdata_impulse_in[i]);
839 av_freep(&s->fft_hdata_impulse_out[i]);
840 av_freep(&s->fft_vdata_impulse_out[i]);
841
842 for (j = 0; j < MAX_THREADS; j++) {
843 av_tx_uninit(&s->fft[i][j]);
844 av_tx_uninit(&s->ifft[i][j]);
845 }
846 }
847
849}
850
851static const AVFilterPad convolve_inputs[] = {
852 {
853 .name = "main",
854 .type = AVMEDIA_TYPE_VIDEO,
855 .config_props = config_input,
856 },{
857 .name = "impulse",
858 .type = AVMEDIA_TYPE_VIDEO,
859 .config_props = config_input_impulse,
860 },
861};
862
864 {
865 .name = "default",
866 .type = AVMEDIA_TYPE_VIDEO,
867 .config_props = config_output,
868 },
869};
870
872
873#if CONFIG_CONVOLVE_FILTER
874
876
877const FFFilter ff_vf_convolve = {
878 .p.name = "convolve",
879 .p.description = NULL_IF_CONFIG_SMALL("Convolve first video stream with second video stream."),
880 .p.priv_class = &convolve_class,
882 .preinit = convolve_framesync_preinit,
883 .init = init,
884 .uninit = uninit,
885 .activate = activate,
886 .priv_size = sizeof(ConvolveContext),
890};
891
892#endif /* CONFIG_CONVOLVE_FILTER */
893
894#if CONFIG_DECONVOLVE_FILTER
895
896static const AVOption deconvolve_options[] = {
897 { "planes", "set planes to deconvolve", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
898 { "impulse", "when to process impulses", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "impulse" },
899 { "first", "process only first impulse, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "impulse" },
900 { "all", "process all impulses", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "impulse" },
901 { "noise", "set noise", OFFSET(noise), AV_OPT_TYPE_FLOAT, {.dbl=0.0000001}, 0, 1, FLAGS },
902 { NULL },
903};
904
905FRAMESYNC_DEFINE_PURE_CLASS(deconvolve, "deconvolve", convolve, deconvolve_options);
906
908 .p.name = "deconvolve",
909 .p.description = NULL_IF_CONFIG_SMALL("Deconvolve first video stream with second video stream."),
910 .p.priv_class = &deconvolve_class,
912 .preinit = convolve_framesync_preinit,
913 .init = init,
914 .uninit = uninit,
915 .activate = activate,
916 .priv_size = sizeof(ConvolveContext),
920};
921
922#endif /* CONFIG_DECONVOLVE_FILTER */
923
924#if CONFIG_XCORRELATE_FILTER
925
926static const AVOption xcorrelate_options[] = {
927 { "planes", "set planes to cross-correlate", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
928 { "secondary", "when to process secondary frame", OFFSET(impulse), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "impulse" },
929 { "first", "process only first secondary frame, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "impulse" },
930 { "all", "process all secondary frames", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "impulse" },
931 { NULL },
932};
933
934FRAMESYNC_DEFINE_PURE_CLASS(xcorrelate, "xcorrelate", convolve, xcorrelate_options);
935
936static int config_input_secondary(AVFilterLink *inlink)
937{
938 AVFilterContext *ctx = inlink->dst;
939
940 if (ctx->inputs[0]->w <= ctx->inputs[1]->w ||
941 ctx->inputs[0]->h <= ctx->inputs[1]->h) {
942 av_log(ctx, AV_LOG_ERROR, "Width and height of second input videos must be less than first input.\n");
943 return AVERROR(EINVAL);
944 }
945
946 return 0;
947}
948
949static const AVFilterPad xcorrelate_inputs[] = {
950 {
951 .name = "primary",
952 .type = AVMEDIA_TYPE_VIDEO,
953 .config_props = config_input,
954 },{
955 .name = "secondary",
956 .type = AVMEDIA_TYPE_VIDEO,
957 .config_props = config_input_secondary,
958 },
959};
960
961#define xcorrelate_outputs convolve_outputs
962
964 .p.name = "xcorrelate",
965 .p.description = NULL_IF_CONFIG_SMALL("Cross-correlate first video stream with second video stream."),
966 .p.priv_class = &xcorrelate_class,
968 .preinit = convolve_framesync_preinit,
969 .init = init,
970 .uninit = uninit,
971 .activate = activate,
972 .priv_size = sizeof(ConvolveContext),
973 FILTER_INPUTS(xcorrelate_inputs),
974 FILTER_OUTPUTS(xcorrelate_outputs),
976};
977
978#endif /* CONFIG_XCORRELATE_FILTER */
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static int config_input(AVFilterLink *inlink)
const FFFilter ff_vf_xcorrelate
const FFFilter ff_vf_convolve
const FFFilter ff_vf_deconvolve
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition avfilter.c:1696
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition avfilter.c:846
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define fs(width, name, subs,...)
Definition cbs_vp9.c:200
#define FLAGS
Definition cmdutils.c:598
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define av_clip
Definition common.h:100
#define av_clip_uint8
Definition common.h:106
#define NULL
Definition coverity.c:32
static __device__ float sqrtf(float a)
#define max(a, b)
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static int get_input(AVFrame *frame, int frame_num)
#define MAX_THREADS
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition framesync.c:137
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition framesync.c:390
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition framesync.c:352
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition framesync.c:372
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition framesync.c:301
#define FRAMESYNC_AUXILIARY_FUNCS(func_prefix, context, field)
Definition framesync.h:335
#define FRAMESYNC_DEFINE_PURE_CLASS(name, desc, func_prefix, options)
Definition framesync.h:321
static void convolve(float *tgt, const float *src, int len, int n)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition avfilter.h:166
#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:204
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define av_log2
Definition intmath.h:84
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition intra.c:278
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
const char * arg
Definition jacosubdec.c:65
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
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:763
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
const char * desc
Definition libsvtav1.c:83
static const struct @257111027162314367033347246032313251342043035002 planes[]
uint8_t w
Definition llvidencdsp.c:39
#define FFMAX(a, b)
Definition macros.h:47
#define FFMIN3(a, b, c)
Definition macros.h:50
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
static int noise(AVBSFContext *ctx, AVPacket *pkt)
Definition noise.c:124
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_GBRAP12
Definition pixfmt.h:569
#define AV_PIX_FMT_YUV420P16
Definition pixfmt.h:556
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_YUV444P9
Definition pixfmt.h:544
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
#define AV_PIX_FMT_YUV440P12
Definition pixfmt.h:551
#define AV_PIX_FMT_GRAY9
Definition pixfmt.h:524
#define AV_PIX_FMT_GBRAP16
Definition pixfmt.h:571
#define AV_PIX_FMT_GBRP9
Definition pixfmt.h:563
#define AV_PIX_FMT_YUV422P9
Definition pixfmt.h:543
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUVA420P16
Definition pixfmt.h:601
#define AV_PIX_FMT_YUV420P12
Definition pixfmt.h:549
#define AV_PIX_FMT_YUVA420P10
Definition pixfmt.h:596
#define AV_PIX_FMT_YUVA422P9
Definition pixfmt.h:594
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
#define AV_PIX_FMT_GBRP12
Definition pixfmt.h:565
#define AV_PIX_FMT_YUV420P9
Definition pixfmt.h:542
#define AV_PIX_FMT_YUVA420P9
Definition pixfmt.h:593
#define AV_PIX_FMT_YUVA422P10
Definition pixfmt.h:597
#define AV_PIX_FMT_YUV420P14
Definition pixfmt.h:553
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ 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:107
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
@ 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:283
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition pixfmt.h:212
@ 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:86
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition pixfmt.h:173
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
@ 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:87
@ 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:85
#define AV_PIX_FMT_YUV422P14
Definition pixfmt.h:554
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_GRAY14
Definition pixfmt.h:527
#define AV_PIX_FMT_YUV422P16
Definition pixfmt.h:557
#define AV_PIX_FMT_GRAY16
Definition pixfmt.h:528
#define AV_PIX_FMT_GBRAP10
Definition pixfmt.h:568
#define AV_PIX_FMT_YUVA444P16
Definition pixfmt.h:603
#define AV_PIX_FMT_YUVA422P16
Definition pixfmt.h:602
#define AV_PIX_FMT_GBRP16
Definition pixfmt.h:567
#define AV_PIX_FMT_YUV444P14
Definition pixfmt.h:555
#define AV_PIX_FMT_YUVA444P9
Definition pixfmt.h:595
#define AV_PIX_FMT_GBRP14
Definition pixfmt.h:566
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
Describe the class of an AVClass context structure.
Definition log.h:76
float im
Definition tx.h:28
float re
Definition tx.h:28
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
AVComplexFloat * fft_vdata_impulse_in[4]
Definition vf_convolve.c:61
FFFrameSync fs
Definition vf_convolve.c:38
void(* get_output)(struct ConvolveContext *s, AVComplexFloat *input, AVFrame *out, int w, int h, int n, int plane, float scale)
Definition vf_convolve.c:75
AVComplexFloat * fft_hdata_out[4]
Definition vf_convolve.c:58
int primaryheight[4]
Definition vf_convolve.c:51
void(* prepare_impulse)(AVFilterContext *ctx, AVFrame *impulsepic, int plane)
Definition vf_convolve.c:77
int(* filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition vf_convolve.c:79
int secondarywidth[4]
Definition vf_convolve.c:53
av_tx_fn itx_fn[4]
Definition vf_convolve.c:44
int primarywidth[4]
Definition vf_convolve.c:50
AVComplexFloat * fft_vdata_in[4]
Definition vf_convolve.c:57
AVTXContext * fft[4][MAX_THREADS]
Definition vf_convolve.c:40
int secondaryheight[4]
Definition vf_convolve.c:54
AVComplexFloat * fft_vdata_out[4]
Definition vf_convolve.c:59
void(* get_input)(struct ConvolveContext *s, AVComplexFloat *fft_hdata, AVFrame *in, int w, int h, int n, int plane, float scale)
Definition vf_convolve.c:72
AVComplexFloat * fft_vdata_impulse_out[4]
Definition vf_convolve.c:63
av_tx_fn tx_fn[4]
Definition vf_convolve.c:43
AVTXContext * ifft[4][MAX_THREADS]
Definition vf_convolve.c:41
AVComplexFloat * fft_hdata_impulse_in[4]
Definition vf_convolve.c:60
AVComplexFloat * fft_hdata_impulse_out[4]
Definition vf_convolve.c:62
AVComplexFloat * fft_hdata_in[4]
Definition vf_convolve.c:56
Frame sync structure.
Definition framesync.h:168
Used for passing data between threads.
Definition dsddec.c:71
AVComplexFloat * hdata_out
AVComplexFloat * vdata_out
AVComplexFloat * hdata_in
AVComplexFloat * vdata_in
int plane
Definition vf_blend.c:61
#define av_freep(p)
#define av_log(a,...)
static int imax(const int a, const int b)
Definition internal.h:177
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition tx.c:295
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition tx.c:903
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition tx.h:47
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition tx.h:151
static int complex_xcorrelate(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVFilterPad convolve_outputs[]
static const AVOption convolve_options[]
Definition vf_convolve.c:85
static int do_convolve(FFFrameSync *fs)
static int config_input_impulse(AVFilterLink *inlink)
static void prepare_impulse(AVFilterContext *ctx, AVFrame *impulsepic, int plane)
static void get_xoutput(ConvolveContext *s, AVComplexFloat *input, AVFrame *out, int w, int h, int n, int plane, float scale)
static int fft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int config_input(AVFilterLink *inlink)
static int fft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define MAX_THREADS
Definition vf_convolve.c:34
static const AVFilterPad convolve_inputs[]
#define SQR(x)
static int complex_multiply(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static int ifft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static void prepare_secondary(AVFilterContext *ctx, AVFrame *secondary, int plane)
static void get_zeropadded_input(ConvolveContext *s, AVComplexFloat *fft_hdata, AVFrame *in, int w, int h, int n, int plane, float scale)
static int ifft_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define OFFSET(x)
Definition vf_convolve.c:82
static int config_output(AVFilterLink *outlink)
static void get_input(ConvolveContext *s, AVComplexFloat *fft_hdata, AVFrame *in, int w, int h, int n, int plane, float scale)
static int complex_divide(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static enum AVPixelFormat pixel_fmts_fftfilt[]
Definition vf_convolve.c:94
static void get_output(ConvolveContext *s, AVComplexFloat *input, AVFrame *out, int w, int h, int n, int plane, float scale)
static float mean(const float *input, int size)
Definition vf_nnedi.c:861