FFmpeg  4.3
vf_bm3d.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2016 mawen1250
3  * Copyright (c) 2018 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 /**
27  * @todo
28  * - non-power of 2 DCT
29  * - opponent color space
30  * - temporal support
31  */
32 
33 #include <float.h>
34 
35 #include "libavutil/avassert.h"
36 #include "libavutil/imgutils.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/pixdesc.h"
39 #include "libavcodec/avfft.h"
40 #include "avfilter.h"
41 #include "filters.h"
42 #include "formats.h"
43 #include "framesync.h"
44 #include "internal.h"
45 #include "video.h"
46 
47 #define MAX_NB_THREADS 32
48 
53 };
54 
55 typedef struct ThreadData {
56  const uint8_t *src;
58  const uint8_t *ref;
60  int plane;
61 } ThreadData;
62 
63 typedef struct PosCode {
64  int x, y;
65 } PosCode;
66 
67 typedef struct PosPairCode {
68  double score;
69  int x, y;
70 } PosPairCode;
71 
72 typedef struct SliceContext {
73  DCTContext *gdctf, *gdcti;
74  DCTContext *dctf, *dcti;
83  float *num, *den;
84  PosPairCode match_blocks[256];
87 } SliceContext;
88 
89 typedef struct BM3DContext {
90  const AVClass *class;
91 
92  float sigma;
96  int bm_range;
97  int bm_step;
98  float th_mse;
100  int mode;
101  int ref;
102  int planes;
103 
104  int depth;
105  int max;
107  int planewidth[4];
108  int planeheight[4];
111 
113 
116 
117  void (*get_block_row)(const uint8_t *srcp, int src_linesize,
118  int y, int x, int block_size, float *dst);
119  double (*do_block_ssd)(struct BM3DContext *s, PosCode *pos,
120  const uint8_t *src, int src_stride,
121  int r_y, int r_x);
123  int plane, int nb_jobs);
125  const uint8_t *src, int src_linesize,
126  const uint8_t *ref, int ref_linesize,
127  int y, int x, int plane, int jobnr);
128 } BM3DContext;
129 
130 #define OFFSET(x) offsetof(BM3DContext, x)
131 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
132 static const AVOption bm3d_options[] = {
133  { "sigma", "set denoising strength",
134  OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 99999.9, FLAGS },
135  { "block", "set log2(size) of local patch",
136  OFFSET(block_size), AV_OPT_TYPE_INT, {.i64=4}, 4, 6, FLAGS },
137  { "bstep", "set sliding step for processing blocks",
138  OFFSET(block_step), AV_OPT_TYPE_INT, {.i64=4}, 1, 64, FLAGS },
139  { "group", "set maximal number of similar blocks",
140  OFFSET(group_size), AV_OPT_TYPE_INT, {.i64=1}, 1, 256, FLAGS },
141  { "range", "set block matching range",
142  OFFSET(bm_range), AV_OPT_TYPE_INT, {.i64=9}, 1, INT32_MAX, FLAGS },
143  { "mstep", "set step for block matching",
144  OFFSET(bm_step), AV_OPT_TYPE_INT, {.i64=1}, 1, 64, FLAGS },
145  { "thmse", "set threshold of mean square error for block matching",
146  OFFSET(th_mse), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT32_MAX, FLAGS },
147  { "hdthr", "set hard threshold for 3D transfer domain",
148  OFFSET(hard_threshold), AV_OPT_TYPE_FLOAT, {.dbl=2.7}, 0, INT32_MAX, FLAGS },
149  { "estim", "set filtering estimation mode",
150  OFFSET(mode), AV_OPT_TYPE_INT, {.i64=BASIC}, 0, NB_MODES-1, FLAGS, "mode" },
151  { "basic", "basic estimate",
152  0, AV_OPT_TYPE_CONST, {.i64=BASIC}, 0, 0, FLAGS, "mode" },
153  { "final", "final estimate",
154  0, AV_OPT_TYPE_CONST, {.i64=FINAL}, 0, 0, FLAGS, "mode" },
155  { "ref", "have reference stream",
156  OFFSET(ref), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
157  { "planes", "set planes to filter",
158  OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
159  { NULL }
160 };
161 
163 
165 {
166  static const enum AVPixelFormat pix_fmts[] = {
190  };
191 
192  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
193  if (!fmts_list)
194  return AVERROR(ENOMEM);
195  return ff_set_common_formats(ctx, fmts_list);
196 }
197 
198 static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
199 {
200  int search_boundary;
201 
202  search_range = search_range / search_step * search_step;
203 
204  if (pos == plane_boundary) {
205  search_boundary = plane_boundary;
206  } else if (pos > plane_boundary) {
207  search_boundary = pos - search_range;
208 
209  while (search_boundary < plane_boundary) {
210  search_boundary += search_step;
211  }
212  } else {
213  search_boundary = pos + search_range;
214 
215  while (search_boundary > plane_boundary) {
216  search_boundary -= search_step;
217  }
218  }
219 
220  return search_boundary;
221 }
222 
223 static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
224 {
225  return do_search_boundary(vertical ? y : x, plane_boundary, search_range, search_step);
226 }
227 
228 static int cmp_scores(const void *a, const void *b)
229 {
230  const struct PosPairCode *pair1 = a;
231  const struct PosPairCode *pair2 = b;
232  return FFDIFFSIGN(pair1->score, pair2->score);
233 }
234 
235 static double do_block_ssd(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
236 {
237  const uint8_t *srcp = src + pos->y * src_stride + pos->x;
238  const uint8_t *refp = src + r_y * src_stride + r_x;
239  const int block_size = s->block_size;
240  double dist = 0.;
241  int x, y;
242 
243  for (y = 0; y < block_size; y++) {
244  for (x = 0; x < block_size; x++) {
245  double temp = refp[x] - srcp[x];
246  dist += temp * temp;
247  }
248 
249  srcp += src_stride;
250  refp += src_stride;
251  }
252 
253  return dist;
254 }
255 
256 static double do_block_ssd16(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
257 {
258  const uint16_t *srcp = (uint16_t *)src + pos->y * src_stride / 2 + pos->x;
259  const uint16_t *refp = (uint16_t *)src + r_y * src_stride / 2 + r_x;
260  const int block_size = s->block_size;
261  double dist = 0.;
262  int x, y;
263 
264  for (y = 0; y < block_size; y++) {
265  for (x = 0; x < block_size; x++) {
266  double temp = refp[x] - srcp[x];
267  dist += temp * temp;
268  }
269 
270  srcp += src_stride / 2;
271  refp += src_stride / 2;
272  }
273 
274  return dist;
275 }
276 
277 static void do_block_matching_multi(BM3DContext *s, const uint8_t *src, int src_stride, int src_range,
278  const PosCode *search_pos, int search_size, float th_mse,
279  int r_y, int r_x, int plane, int jobnr)
280 {
281  SliceContext *sc = &s->slices[jobnr];
282  double MSE2SSE = s->group_size * s->block_size * s->block_size * src_range * src_range / (s->max * s->max);
283  double distMul = 1. / MSE2SSE;
284  double th_sse = th_mse * MSE2SSE;
285  int i, index = sc->nb_match_blocks;
286 
287  for (i = 0; i < search_size; i++) {
288  PosCode pos = search_pos[i];
289  double dist;
290 
291  dist = s->do_block_ssd(s, &pos, src, src_stride, r_y, r_x);
292 
293  // Only match similar blocks but not identical blocks
294  if (dist <= th_sse && dist != 0) {
295  const double score = dist * distMul;
296 
297  if (index >= s->group_size && score >= sc->match_blocks[index - 1].score) {
298  continue;
299  }
300 
301  if (index >= s->group_size)
302  index = s->group_size - 1;
303 
304  sc->match_blocks[index].score = score;
305  sc->match_blocks[index].y = pos.y;
306  sc->match_blocks[index].x = pos.x;
307  index++;
308  qsort(sc->match_blocks, index, sizeof(PosPairCode), cmp_scores);
309  }
310  }
311 
312  sc->nb_match_blocks = index;
313 }
314 
315 static void block_matching_multi(BM3DContext *s, const uint8_t *ref, int ref_linesize, int y, int x,
316  int exclude_cur_pos, int plane, int jobnr)
317 {
318  SliceContext *sc = &s->slices[jobnr];
319  const int width = s->planewidth[plane];
320  const int height = s->planeheight[plane];
321  const int block_size = s->block_size;
322  const int step = s->bm_step;
323  const int range = s->bm_range / step * step;
324  int l = search_boundary(0, range, step, 0, y, x);
325  int r = search_boundary(width - block_size, range, step, 0, y, x);
326  int t = search_boundary(0, range, step, 1, y, x);
327  int b = search_boundary(height - block_size, range, step, 1, y, x);
328  int j, i, index = 0;
329 
330  for (j = t; j <= b; j += step) {
331  for (i = l; i <= r; i += step) {
332  PosCode pos;
333 
334  if (exclude_cur_pos > 0 && j == y && i == x) {
335  continue;
336  }
337 
338  pos.y = j;
339  pos.x = i;
340  sc->search_positions[index++] = pos;
341  }
342  }
343 
344  if (exclude_cur_pos == 1) {
345  sc->match_blocks[0].score = 0;
346  sc->match_blocks[0].y = y;
347  sc->match_blocks[0].x = x;
348  sc->nb_match_blocks = 1;
349  }
350 
351  do_block_matching_multi(s, ref, ref_linesize, s->bm_range,
352  sc->search_positions, index, s->th_mse, y, x, plane, jobnr);
353 }
354 
356  int j, int i, int plane, int jobnr)
357 {
358  SliceContext *sc = &s->slices[jobnr];
359 
360  if (s->group_size == 1 || s->th_mse <= 0.f) {
361  sc->match_blocks[0].score = 1;
362  sc->match_blocks[0].x = i;
363  sc->match_blocks[0].y = j;
364  sc->nb_match_blocks = 1;
365  return;
366  }
367 
368  sc->nb_match_blocks = 0;
369  block_matching_multi(s, ref, ref_linesize, j, i, 1, plane, jobnr);
370 }
371 
372 static void get_block_row(const uint8_t *srcp, int src_linesize,
373  int y, int x, int block_size, float *dst)
374 {
375  const uint8_t *src = srcp + y * src_linesize + x;
376  int j;
377 
378  for (j = 0; j < block_size; j++) {
379  dst[j] = src[j];
380  }
381 }
382 
383 static void get_block_row16(const uint8_t *srcp, int src_linesize,
384  int y, int x, int block_size, float *dst)
385 {
386  const uint16_t *src = (uint16_t *)srcp + y * src_linesize / 2 + x;
387  int j;
388 
389  for (j = 0; j < block_size; j++) {
390  dst[j] = src[j];
391  }
392 }
393 
395  const uint8_t *ref, int ref_linesize,
396  int y, int x, int plane, int jobnr)
397 {
398  SliceContext *sc = &s->slices[jobnr];
399  const int buffer_linesize = s->block_size * s->block_size;
400  const int nb_match_blocks = sc->nb_match_blocks;
401  const int block_size = s->block_size;
402  const int width = s->planewidth[plane];
403  const int pgroup_size = s->pgroup_size;
404  const int group_size = s->group_size;
405  float *buffer = sc->buffer;
406  float *bufferh = sc->bufferh;
407  float *bufferv = sc->bufferv;
408  float *bufferz = sc->bufferz;
409  float threshold[4];
410  float den_weight, num_weight;
411  int retained = 0;
412  int i, j, k;
413 
414  for (k = 0; k < nb_match_blocks; k++) {
415  const int y = sc->match_blocks[k].y;
416  const int x = sc->match_blocks[k].x;
417 
418  for (i = 0; i < block_size; i++) {
419  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + block_size * i);
420  av_dct_calc(sc->dctf, bufferh + block_size * i);
421  }
422 
423  for (i = 0; i < block_size; i++) {
424  for (j = 0; j < block_size; j++) {
425  bufferv[i * block_size + j] = bufferh[j * block_size + i];
426  }
427  av_dct_calc(sc->dctf, bufferv + i * block_size);
428  }
429 
430  for (i = 0; i < block_size; i++) {
431  memcpy(buffer + k * buffer_linesize + i * block_size,
432  bufferv + i * block_size, block_size * 4);
433  }
434  }
435 
436  for (i = 0; i < block_size; i++) {
437  for (j = 0; j < block_size; j++) {
438  for (k = 0; k < nb_match_blocks; k++)
439  bufferz[k] = buffer[buffer_linesize * k + i * block_size + j];
440  if (group_size > 1)
441  av_dct_calc(sc->gdctf, bufferz);
442  bufferz += pgroup_size;
443  }
444  }
445 
446  threshold[0] = s->hard_threshold * s->sigma * M_SQRT2 * block_size * block_size * (1 << (s->depth - 8)) / 255.f;
447  threshold[1] = threshold[0] * sqrtf(2.f);
448  threshold[2] = threshold[0] * 2.f;
449  threshold[3] = threshold[0] * sqrtf(8.f);
450  bufferz = sc->bufferz;
451 
452  for (i = 0; i < block_size; i++) {
453  for (j = 0; j < block_size; j++) {
454  for (k = 0; k < nb_match_blocks; k++) {
455  const float thresh = threshold[(j == 0) + (i == 0) + (k == 0)];
456 
457  if (bufferz[k] > thresh || bufferz[k] < -thresh) {
458  retained++;
459  } else {
460  bufferz[k] = 0;
461  }
462  }
463  bufferz += pgroup_size;
464  }
465  }
466 
467  bufferz = sc->bufferz;
468  buffer = sc->buffer;
469  for (i = 0; i < block_size; i++) {
470  for (j = 0; j < block_size; j++) {
471  if (group_size > 1)
472  av_dct_calc(sc->gdcti, bufferz);
473  for (k = 0; k < nb_match_blocks; k++) {
474  buffer[buffer_linesize * k + i * block_size + j] = bufferz[k];
475  }
476  bufferz += pgroup_size;
477  }
478  }
479 
480  den_weight = retained < 1 ? 1.f : 1.f / retained;
481  num_weight = den_weight;
482 
483  buffer = sc->buffer;
484  for (k = 0; k < nb_match_blocks; k++) {
485  float *num = sc->num + y * width + x;
486  float *den = sc->den + y * width + x;
487 
488  for (i = 0; i < block_size; i++) {
489  memcpy(bufferv + i * block_size,
490  buffer + k * buffer_linesize + i * block_size,
491  block_size * 4);
492  }
493 
494  for (i = 0; i < block_size; i++) {
495  av_dct_calc(sc->dcti, bufferv + block_size * i);
496  for (j = 0; j < block_size; j++) {
497  bufferh[j * block_size + i] = bufferv[i * block_size + j];
498  }
499  }
500 
501  for (i = 0; i < block_size; i++) {
502  av_dct_calc(sc->dcti, bufferh + block_size * i);
503  for (j = 0; j < block_size; j++) {
504  num[j] += bufferh[i * block_size + j] * num_weight;
505  den[j] += den_weight;
506  }
507  num += width;
508  den += width;
509  }
510  }
511 }
512 
514  const uint8_t *ref, int ref_linesize,
515  int y, int x, int plane, int jobnr)
516 {
517  SliceContext *sc = &s->slices[jobnr];
518  const int buffer_linesize = s->block_size * s->block_size;
519  const int nb_match_blocks = sc->nb_match_blocks;
520  const int block_size = s->block_size;
521  const int width = s->planewidth[plane];
522  const int pgroup_size = s->pgroup_size;
523  const int group_size = s->group_size;
524  const float sigma_sqr = s->sigma * s->sigma;
525  float *buffer = sc->buffer;
526  float *bufferh = sc->bufferh;
527  float *bufferv = sc->bufferv;
528  float *bufferz = sc->bufferz;
529  float *rbuffer = sc->rbuffer;
530  float *rbufferh = sc->rbufferh;
531  float *rbufferv = sc->rbufferv;
532  float *rbufferz = sc->rbufferz;
533  float den_weight, num_weight;
534  float l2_wiener = 0;
535  int i, j, k;
536 
537  for (k = 0; k < nb_match_blocks; k++) {
538  const int y = sc->match_blocks[k].y;
539  const int x = sc->match_blocks[k].x;
540 
541  for (i = 0; i < block_size; i++) {
542  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + block_size * i);
543  s->get_block_row(ref, ref_linesize, y + i, x, block_size, rbufferh + block_size * i);
544  av_dct_calc(sc->dctf, bufferh + block_size * i);
545  av_dct_calc(sc->dctf, rbufferh + block_size * i);
546  }
547 
548  for (i = 0; i < block_size; i++) {
549  for (j = 0; j < block_size; j++) {
550  bufferv[i * block_size + j] = bufferh[j * block_size + i];
551  rbufferv[i * block_size + j] = rbufferh[j * block_size + i];
552  }
553  av_dct_calc(sc->dctf, bufferv + i * block_size);
554  av_dct_calc(sc->dctf, rbufferv + i * block_size);
555  }
556 
557  for (i = 0; i < block_size; i++) {
558  memcpy(buffer + k * buffer_linesize + i * block_size,
559  bufferv + i * block_size, block_size * 4);
560  memcpy(rbuffer + k * buffer_linesize + i * block_size,
561  rbufferv + i * block_size, block_size * 4);
562  }
563  }
564 
565  for (i = 0; i < block_size; i++) {
566  for (j = 0; j < block_size; j++) {
567  for (k = 0; k < nb_match_blocks; k++) {
568  bufferz[k] = buffer[buffer_linesize * k + i * block_size + j];
569  rbufferz[k] = rbuffer[buffer_linesize * k + i * block_size + j];
570  }
571  if (group_size > 1) {
572  av_dct_calc(sc->gdctf, bufferz);
573  av_dct_calc(sc->gdctf, rbufferz);
574  }
575  bufferz += pgroup_size;
576  rbufferz += pgroup_size;
577  }
578  }
579 
580  bufferz = sc->bufferz;
581  rbufferz = sc->rbufferz;
582 
583  for (i = 0; i < block_size; i++) {
584  for (j = 0; j < block_size; j++) {
585  for (k = 0; k < nb_match_blocks; k++) {
586  const float ref_sqr = rbufferz[k] * rbufferz[k];
587  float wiener_coef = ref_sqr / (ref_sqr + sigma_sqr);
588 
589  if (isnan(wiener_coef))
590  wiener_coef = 1;
591  bufferz[k] *= wiener_coef;
592  l2_wiener += wiener_coef * wiener_coef;
593  }
594  bufferz += pgroup_size;
595  rbufferz += pgroup_size;
596  }
597  }
598 
599  bufferz = sc->bufferz;
600  buffer = sc->buffer;
601  for (i = 0; i < block_size; i++) {
602  for (j = 0; j < block_size; j++) {
603  if (group_size > 1)
604  av_dct_calc(sc->gdcti, bufferz);
605  for (k = 0; k < nb_match_blocks; k++) {
606  buffer[buffer_linesize * k + i * block_size + j] = bufferz[k];
607  }
608  bufferz += pgroup_size;
609  }
610  }
611 
612  l2_wiener = FFMAX(l2_wiener, 1e-15f);
613  den_weight = 1.f / l2_wiener;
614  num_weight = den_weight;
615 
616  for (k = 0; k < nb_match_blocks; k++) {
617  float *num = sc->num + y * width + x;
618  float *den = sc->den + y * width + x;
619 
620  for (i = 0; i < block_size; i++) {
621  memcpy(bufferv + i * block_size,
622  buffer + k * buffer_linesize + i * block_size,
623  block_size * 4);
624  }
625 
626  for (i = 0; i < block_size; i++) {
627  av_dct_calc(sc->dcti, bufferv + block_size * i);
628  for (j = 0; j < block_size; j++) {
629  bufferh[j * block_size + i] = bufferv[i * block_size + j];
630  }
631  }
632 
633  for (i = 0; i < block_size; i++) {
634  av_dct_calc(sc->dcti, bufferh + block_size * i);
635  for (j = 0; j < block_size; j++) {
636  num[j] += bufferh[i * block_size + j] * num_weight;
637  den[j] += den_weight;
638  }
639  num += width;
640  den += width;
641  }
642  }
643 }
644 
646  int plane, int nb_jobs)
647 {
648  const int height = s->planeheight[plane];
649  const int width = s->planewidth[plane];
650  int i, j, k;
651 
652  for (i = 0; i < height; i++) {
653  for (j = 0; j < width; j++) {
654  uint8_t *dstp = dst + i * dst_linesize;
655  float sum_den = 0.f;
656  float sum_num = 0.f;
657 
658  for (k = 0; k < nb_jobs; k++) {
659  SliceContext *sc = &s->slices[k];
660  float num = sc->num[i * width + j];
661  float den = sc->den[i * width + j];
662 
663  sum_num += num;
664  sum_den += den;
665  }
666 
667  dstp[j] = av_clip_uint8(lrintf(sum_num / sum_den));
668  }
669  }
670 }
671 
673  int plane, int nb_jobs)
674 {
675  const int height = s->planeheight[plane];
676  const int width = s->planewidth[plane];
677  const int depth = s->depth;
678  int i, j, k;
679 
680  for (i = 0; i < height; i++) {
681  for (j = 0; j < width; j++) {
682  uint16_t *dstp = (uint16_t *)dst + i * dst_linesize / 2;
683  float sum_den = 0.f;
684  float sum_num = 0.f;
685 
686  for (k = 0; k < nb_jobs; k++) {
687  SliceContext *sc = &s->slices[k];
688  float num = sc->num[i * width + j];
689  float den = sc->den[i * width + j];
690 
691  sum_num += num;
692  sum_den += den;
693  }
694 
695  dstp[j] = av_clip_uintp2_c(lrintf(sum_num / sum_den), depth);
696  }
697  }
698 }
699 
700 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
701 {
702  BM3DContext *s = ctx->priv;
703  SliceContext *sc = &s->slices[jobnr];
704  const int block_step = s->block_step;
705  ThreadData *td = arg;
706  const uint8_t *src = td->src;
707  const uint8_t *ref = td->ref;
708  const int src_linesize = td->src_linesize;
709  const int ref_linesize = td->ref_linesize;
710  const int plane = td->plane;
711  const int width = s->planewidth[plane];
712  const int height = s->planeheight[plane];
713  const int block_pos_bottom = FFMAX(0, height - s->block_size);
714  const int block_pos_right = FFMAX(0, width - s->block_size);
715  const int slice_start = (((height + block_step - 1) / block_step) * jobnr / nb_jobs) * block_step;
716  const int slice_end = (jobnr == nb_jobs - 1) ? block_pos_bottom + block_step :
717  (((height + block_step - 1) / block_step) * (jobnr + 1) / nb_jobs) * block_step;
718  int i, j;
719 
720  memset(sc->num, 0, width * height * sizeof(FFTSample));
721  memset(sc->den, 0, width * height * sizeof(FFTSample));
722 
723  for (j = slice_start; j < slice_end; j += block_step) {
724  if (j > block_pos_bottom) {
725  j = block_pos_bottom;
726  }
727 
728  for (i = 0; i < block_pos_right + block_step; i += block_step) {
729  if (i > block_pos_right) {
730  i = block_pos_right;
731  }
732 
733  block_matching(s, ref, ref_linesize, j, i, plane, jobnr);
734 
735  s->block_filtering(s, src, src_linesize,
736  ref, ref_linesize, j, i, plane, jobnr);
737  }
738  }
739 
740  return 0;
741 }
742 
744 {
745  BM3DContext *s = ctx->priv;
746  AVFilterLink *outlink = ctx->outputs[0];
747  int p;
748 
749  *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
750  if (!*out)
751  return AVERROR(ENOMEM);
752  av_frame_copy_props(*out, in);
753 
754  for (p = 0; p < s->nb_planes; p++) {
755  const int nb_jobs = FFMAX(1, FFMIN(s->nb_threads, s->planeheight[p] / s->block_size));
756  ThreadData td;
757 
758  if (!((1 << p) & s->planes) || ctx->is_disabled) {
759  av_image_copy_plane((*out)->data[p], (*out)->linesize[p],
760  in->data[p], in->linesize[p],
761  s->planewidth[p], s->planeheight[p]);
762  continue;
763  }
764 
765  td.src = in->data[p];
766  td.src_linesize = in->linesize[p];
767  td.ref = ref->data[p];
768  td.ref_linesize = ref->linesize[p];
769  td.plane = p;
770  ctx->internal->execute(ctx, filter_slice, &td, NULL, nb_jobs);
771 
772  s->do_output(s, (*out)->data[p], (*out)->linesize[p], p, nb_jobs);
773  }
774 
775  return 0;
776 }
777 
778 #define SQR(x) ((x) * (x))
779 
781 {
783  AVFilterContext *ctx = inlink->dst;
784  BM3DContext *s = ctx->priv;
785  int i, group_bits;
786 
789  s->depth = desc->comp[0].depth;
790  s->max = (1 << s->depth) - 1;
791  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
792  s->planeheight[0] = s->planeheight[3] = inlink->h;
793  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
794  s->planewidth[0] = s->planewidth[3] = inlink->w;
795 
796  for (group_bits = 4; 1 << group_bits < s->group_size; group_bits++);
797  s->group_bits = group_bits;
798  s->pgroup_size = 1 << group_bits;
799 
800  for (i = 0; i < s->nb_threads; i++) {
801  SliceContext *sc = &s->slices[i];
802 
803  sc->num = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(FFTSample));
804  sc->den = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(FFTSample));
805  if (!sc->num || !sc->den)
806  return AVERROR(ENOMEM);
807 
810  if (!sc->dctf || !sc->dcti)
811  return AVERROR(ENOMEM);
812 
813  if (s->group_bits > 1) {
814  sc->gdctf = av_dct_init(s->group_bits, DCT_II);
815  sc->gdcti = av_dct_init(s->group_bits, DCT_III);
816  if (!sc->gdctf || !sc->gdcti)
817  return AVERROR(ENOMEM);
818  }
819 
820  sc->buffer = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->buffer));
821  sc->bufferz = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->bufferz));
822  sc->bufferh = av_calloc(s->block_size * s->block_size, sizeof(*sc->bufferh));
823  sc->bufferv = av_calloc(s->block_size * s->block_size, sizeof(*sc->bufferv));
824  if (!sc->bufferh || !sc->bufferv || !sc->buffer || !sc->bufferz)
825  return AVERROR(ENOMEM);
826 
827  if (s->mode == FINAL) {
828  sc->rbuffer = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->rbuffer));
829  sc->rbufferz = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->rbufferz));
830  sc->rbufferh = av_calloc(s->block_size * s->block_size, sizeof(*sc->rbufferh));
831  sc->rbufferv = av_calloc(s->block_size * s->block_size, sizeof(*sc->rbufferv));
832  if (!sc->rbufferh || !sc->rbufferv || !sc->rbuffer || !sc->rbufferz)
833  return AVERROR(ENOMEM);
834  }
835 
836  sc->search_positions = av_calloc(SQR(2 * s->bm_range / s->bm_step + 1), sizeof(*sc->search_positions));
837  if (!sc->search_positions)
838  return AVERROR(ENOMEM);
839  }
840 
841  s->do_output = do_output;
844 
845  if (s->depth > 8) {
846  s->do_output = do_output16;
849  }
850 
851  return 0;
852 }
853 
855 {
856  BM3DContext *s = ctx->priv;
857 
858  if (!s->ref) {
859  AVFrame *frame = NULL;
860  AVFrame *out = NULL;
861  int ret, status;
862  int64_t pts;
863 
864  FF_FILTER_FORWARD_STATUS_BACK(ctx->outputs[0], ctx->inputs[0]);
865 
866  if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) {
867  ret = filter_frame(ctx, &out, frame, frame);
868  av_frame_free(&frame);
869  if (ret < 0)
870  return ret;
871  ret = ff_filter_frame(ctx->outputs[0], out);
872  }
873  if (ret < 0) {
874  return ret;
875  } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
876  ff_outlink_set_status(ctx->outputs[0], status, pts);
877  return 0;
878  } else {
879  if (ff_outlink_frame_wanted(ctx->outputs[0]))
881  return 0;
882  }
883  } else {
884  return ff_framesync_activate(&s->fs);
885  }
886 }
887 
889 {
890  AVFilterContext *ctx = fs->parent;
891  BM3DContext *s = fs->opaque;
892  AVFilterLink *outlink = ctx->outputs[0];
893  AVFrame *out = NULL, *src, *ref;
894  int ret;
895 
896  if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 ||
897  (ret = ff_framesync_get_frame(&s->fs, 1, &ref, 0)) < 0)
898  return ret;
899 
900  if ((ret = filter_frame(ctx, &out, src, ref)) < 0)
901  return ret;
902 
903  out->pts = av_rescale_q(src->pts, s->fs.time_base, outlink->time_base);
904 
905  return ff_filter_frame(outlink, out);
906 }
907 
909 {
910  BM3DContext *s = ctx->priv;
911  AVFilterPad pad = { 0 };
912  int ret;
913 
914  if (s->mode == BASIC) {
915  if (s->th_mse == 0.f)
916  s->th_mse = 400.f + s->sigma * 80.f;
918  } else if (s->mode == FINAL) {
919  if (!s->ref) {
920  av_log(ctx, AV_LOG_WARNING, "Reference stream is mandatory in final estimation mode.\n");
921  s->ref = 1;
922  }
923  if (s->th_mse == 0.f)
924  s->th_mse = 200.f + s->sigma * 10.f;
925 
927  } else {
928  return AVERROR_BUG;
929  }
930 
931  s->block_size = 1 << s->block_size;
932 
933  if (s->block_step > s->block_size) {
934  av_log(ctx, AV_LOG_WARNING, "bstep: %d can't be bigger than block size. Changing to %d.\n",
935  s->block_step, s->block_size);
936  s->block_step = s->block_size;
937  }
938  if (s->bm_step > s->bm_range) {
939  av_log(ctx, AV_LOG_WARNING, "mstep: %d can't be bigger than block matching range. Changing to %d.\n",
940  s->bm_step, s->bm_range);
941  s->bm_step = s->bm_range;
942  }
943 
944  pad.type = AVMEDIA_TYPE_VIDEO;
945  pad.name = av_strdup("source");
947  if (!pad.name)
948  return AVERROR(ENOMEM);
949 
950  if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) {
951  av_freep(&pad.name);
952  return ret;
953  }
954 
955  if (s->ref) {
956  pad.type = AVMEDIA_TYPE_VIDEO;
957  pad.name = av_strdup("reference");
958  pad.config_props = NULL;
959  if (!pad.name)
960  return AVERROR(ENOMEM);
961 
962  if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) {
963  av_freep(&pad.name);
964  return ret;
965  }
966  }
967 
968  return 0;
969 }
970 
971 static int config_output(AVFilterLink *outlink)
972 {
973  AVFilterContext *ctx = outlink->src;
974  BM3DContext *s = ctx->priv;
975  AVFilterLink *src = ctx->inputs[0];
976  AVFilterLink *ref;
977  FFFrameSyncIn *in;
978  int ret;
979 
980  if (s->ref) {
981  ref = ctx->inputs[1];
982 
983  if (src->format != ref->format) {
984  av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
985  return AVERROR(EINVAL);
986  }
987  if (src->w != ref->w ||
988  src->h != ref->h) {
989  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
990  "(size %dx%d) do not match the corresponding "
991  "second input link %s parameters (%dx%d) ",
992  ctx->input_pads[0].name, src->w, src->h,
993  ctx->input_pads[1].name, ref->w, ref->h);
994  return AVERROR(EINVAL);
995  }
996  }
997 
998  outlink->w = src->w;
999  outlink->h = src->h;
1000  outlink->time_base = src->time_base;
1001  outlink->sample_aspect_ratio = src->sample_aspect_ratio;
1002  outlink->frame_rate = src->frame_rate;
1003 
1004  if (!s->ref)
1005  return 0;
1006 
1007  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
1008  return ret;
1009 
1010  in = s->fs.in;
1011  in[0].time_base = src->time_base;
1012  in[1].time_base = ref->time_base;
1013  in[0].sync = 1;
1014  in[0].before = EXT_STOP;
1015  in[0].after = EXT_STOP;
1016  in[1].sync = 1;
1017  in[1].before = EXT_STOP;
1018  in[1].after = EXT_STOP;
1019  s->fs.opaque = s;
1020  s->fs.on_event = process_frame;
1021 
1022  return ff_framesync_configure(&s->fs);
1023 }
1024 
1026 {
1027  BM3DContext *s = ctx->priv;
1028  int i;
1029 
1030  for (i = 0; i < ctx->nb_inputs; i++)
1031  av_freep(&ctx->input_pads[i].name);
1032 
1033  if (s->ref)
1034  ff_framesync_uninit(&s->fs);
1035 
1036  for (i = 0; i < s->nb_threads; i++) {
1037  SliceContext *sc = &s->slices[i];
1038 
1039  av_freep(&sc->num);
1040  av_freep(&sc->den);
1041 
1042  av_dct_end(sc->gdctf);
1043  av_dct_end(sc->gdcti);
1044  av_dct_end(sc->dctf);
1045  av_dct_end(sc->dcti);
1046 
1047  av_freep(&sc->buffer);
1048  av_freep(&sc->bufferh);
1049  av_freep(&sc->bufferv);
1050  av_freep(&sc->bufferz);
1051  av_freep(&sc->rbuffer);
1052  av_freep(&sc->rbufferh);
1053  av_freep(&sc->rbufferv);
1054  av_freep(&sc->rbufferz);
1055 
1056  av_freep(&sc->search_positions);
1057  }
1058 }
1059 
1060 static const AVFilterPad bm3d_outputs[] = {
1061  {
1062  .name = "default",
1063  .type = AVMEDIA_TYPE_VIDEO,
1064  .config_props = config_output,
1065  },
1066  { NULL }
1067 };
1068 
1070  .name = "bm3d",
1071  .description = NULL_IF_CONFIG_SMALL("Block-Matching 3D denoiser."),
1072  .priv_size = sizeof(BM3DContext),
1073  .init = init,
1074  .uninit = uninit,
1075  .activate = activate,
1077  .inputs = NULL,
1078  .outputs = bm3d_outputs,
1079  .priv_class = &bm3d_class,
1083 };
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1476
#define NULL
Definition: coverity.c:32
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:440
AVFrame * out
Definition: af_adeclick.c:494
static int filter_frame(AVFilterContext *ctx, AVFrame **out, AVFrame *in, AVFrame *ref)
Definition: vf_bm3d.c:743
#define AV_PIX_FMT_YUV440P10
Definition: pixfmt.h:399
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:432
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2549
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:645
AVOption.
Definition: opt.h:246
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:434
AVFILTER_DEFINE_CLASS(bm3d)
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:407
FFTSample * rbufferv
Definition: vf_bm3d.c:80
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:417
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:435
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2589
AVFrame * frame
Definition: dsddec.c:68
Definition: avfft.h:95
Main libavfilter public API header.
else temp
Definition: vf_mcdeint.c:256
static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
Definition: vf_bm3d.c:223
AVFilter ff_vf_bm3d
Definition: vf_bm3d.c:1069
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:105
DCTContext * av_dct_init(int nbits, enum DCTTransformType type)
Set up DCT.
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:413
SliceContext slices[MAX_NB_THREADS]
Definition: vf_bm3d.c:112
int nb_planes
Definition: vf_bm3d.c:106
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:377
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:65
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:401
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:117
FFTSample * bufferv
Definition: vf_bm3d.c:76
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
int src_stride
Definition: vf_unsharp.c:55
int is_disabled
the enabled state from the last expression evaluation
Definition: avfilter.h:385
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1602
int ref_linesize
Definition: vf_bm3d.c:59
static int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition: filters.h:172
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition: framesync.h:86
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:247
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:378
static void get_block_row(const uint8_t *srcp, int src_linesize, int y, int x, int block_size, float *dst)
Definition: vf_bm3d.c:372
int block_size
Definition: vf_bm3d.c:93
Definition: vf_bm3d.c:50
static const AVFilterPad bm3d_outputs[]
Definition: vf_bm3d.c:1060
const char * name
Pad name.
Definition: internal.h:60
AVFilterContext * parent
Parent filter context.
Definition: framesync.h:152
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:379
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1075
void(* get_block_row)(const uint8_t *srcp, int src_linesize, int y, int x, int block_size, float *dst)
Definition: vf_bm3d.c:117
static char buffer[20]
Definition: seek.c:32
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
static const AVOption bm3d_options[]
Definition: vf_bm3d.c:132
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:88
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:259
DCTContext * gdctf
Definition: vf_bm3d.c:73
AVOptions.
int nb_threads
Definition: vf_bm3d.c:115
#define f(width, name)
Definition: cbs_vp9.c:255
FFTSample * buffer
Definition: vf_bm3d.c:78
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:393
FFFrameSyncIn * in
Pointer to array of inputs.
Definition: framesync.h:203
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:431
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:412
int height
Definition: vf_avgblur.c:61
static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:672
AVFrame * dst
Definition: vf_blend.c:56
int plane
Definition: vf_blend.c:58
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range...
Definition: pixfmt.h:100
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
#define lrintf(x)
Definition: libm_mips.h:70
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:410
int nb_match_blocks
Definition: vf_bm3d.c:85
enum FFFrameSyncExtMode after
Extrapolation mode for timestamps after the last frame.
Definition: framesync.h:91
static void get_block_row16(const uint8_t *srcp, int src_linesize, int y, int x, int block_size, float *dst)
Definition: vf_bm3d.c:383
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_bm3d.c:700
Input stream structure.
Definition: framesync.h:81
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:402
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:439
FFTSample * rbuffer
Definition: vf_bm3d.c:82
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
Definition: vf_bm3d.c:51
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
A filter pad used for either input or output.
Definition: internal.h:54
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1431
AVFilterPad * input_pads
array of input pads
Definition: avfilter.h:345
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
DCTContext * dcti
Definition: vf_bm3d.c:74
int bm_range
Definition: vf_bm3d.c:96
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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:600
#define td
Definition: regdef.h:70
int step
Definition: vf_remap.c:82
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:283
FFTSample * bufferh
Definition: vf_bm3d.c:75
Frame sync structure.
Definition: framesync.h:146
#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 y
Definition: vf_bm3d.c:64
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const uint8_t * src
Definition: vf_bm3d.c:56
const char * r
Definition: vf_curves.c:114
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:116
unsigned int pos
Definition: spdifenc.c:410
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:441
const char * arg
Definition: jacosubdec.c:66
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:418
simple assert() macros that are a bit more flexible than ISO C assert().
AVRational time_base
Time base for the incoming frames.
Definition: framesync.h:96
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter&#39;s input and try to produce output.
Definition: framesync.c:334
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:400
#define FLAGS
Definition: vf_bm3d.c:131
int(* on_event)(struct FFFrameSync *fs)
Callback called when a frame event is ready.
Definition: framesync.h:172
#define FFMAX(a, b)
Definition: common.h:94
float FFTSample
Definition: avfft.h:35
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:419
int group_bits
Definition: vf_bm3d.c:109
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
FFTSample * rbufferh
Definition: vf_bm3d.c:79
#define FFDIFFSIGN(x, y)
Comparator.
Definition: common.h:92
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:395
static const struct @315 planes[]
int(* config_props)(AVFilterLink *link)
Link configuration callback.
Definition: internal.h:118
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:416
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:784
unsigned nb_inputs
number of input pads
Definition: avfilter.h:347
int group_size
Definition: vf_bm3d.c:95
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:381
#define FFMIN(a, b)
Definition: common.h:96
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
void(* block_filtering)(struct BM3DContext *s, const uint8_t *src, int src_linesize, const uint8_t *ref, int ref_linesize, int y, int x, int plane, int jobnr)
Definition: vf_bm3d.c:124
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:438
int planeheight[4]
Definition: vf_bm3d.c:108
int depth
Definition: vf_bm3d.c:104
static av_cold int init(AVFilterContext *ctx)
Definition: vf_bm3d.c:908
float th_mse
Definition: vf_bm3d.c:98
static int cmp_scores(const void *a, const void *b)
Definition: vf_bm3d.c:228
static void do_block_matching_multi(BM3DContext *s, const uint8_t *src, int src_stride, int src_range, const PosCode *search_pos, int search_size, float th_mse, int r_y, int r_x, int plane, int jobnr)
Definition: vf_bm3d.c:277
AVFormatContext * ctx
Definition: movenc.c:48
Definition: dct.h:32
AVRational time_base
Time base for the output events.
Definition: framesync.h:162
double(* do_block_ssd)(struct BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
Definition: vf_bm3d.c:119
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:436
static int process_frame(FFFrameSync *fs)
Definition: vf_bm3d.c:888
#define MAX_NB_THREADS
Definition: vf_bm3d.c:47
float * den
Definition: vf_bm3d.c:83
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
void * opaque
Opaque pointer, not used by the API.
Definition: framesync.h:177
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:396
static double do_block_ssd(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
Definition: vf_bm3d.c:235
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:415
static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
Definition: vf_bm3d.c:198
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_log2
Definition: intmath.h:83
static int activate(AVFilterContext *ctx)
Definition: vf_bm3d.c:854
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:408
static double do_block_ssd16(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
Definition: vf_bm3d.c:256
#define OFFSET(x)
Definition: vf_bm3d.c:130
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:405
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:255
int block_step
Definition: vf_bm3d.c:94
typedef void(RENAME(mix_any_func_type))
Used for passing data between threads.
Definition: dsddec.c:67
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:331
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:77
int planes
Definition: vf_bm3d.c:102
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_bm3d.c:1025
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
FFT functions.
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:380
DCTContext * dctf
Definition: vf_bm3d.c:74
int x
Definition: vf_bm3d.c:64
FilterModes
Definition: vf_bm3d.c:49
float * num
Definition: vf_bm3d.c:83
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
void av_dct_end(DCTContext *s)
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:397
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events...
Definition: framesync.h:139
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
int index
Definition: gxfenc.c:89
double score
Definition: vf_bm3d.c:68
#define isnan(x)
Definition: libm.h:340
AVFrame * b
void(* do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:122
const char * name
Filter name.
Definition: avfilter.h:148
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:403
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:394
int bm_step
Definition: vf_bm3d.c:97
#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:133
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
#define SQR(x)
Definition: vf_bm3d.c:778
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:406
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:414
static int64_t pts
#define flags(name, subs,...)
Definition: cbs_av1.c:564
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:378
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:398
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:404
int mode
Definition: vf_bm3d.c:100
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
float hard_threshold
Definition: vf_bm3d.c:99
#define M_SQRT2
Definition: mathematics.h:61
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
int pgroup_size
Definition: vf_bm3d.c:110
PosPairCode match_blocks[256]
Definition: vf_bm3d.c:84
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
AVFrame * threshold
Definition: vf_threshold.c:73
DCTContext * gdcti
Definition: vf_bm3d.c:73
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:433
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
FFTSample * rbufferz
Definition: vf_bm3d.c:81
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
Definition: avfft.h:94
avfilter_execute_func * execute
Definition: internal.h:144
void av_dct_calc(DCTContext *s, FFTSample *data)
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2040
Completely stop all streams with this one.
Definition: framesync.h:65
static void final_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize, const uint8_t *ref, int ref_linesize, int y, int x, int plane, int jobnr)
Definition: vf_bm3d.c:513
static void block_matching(BM3DContext *s, const uint8_t *ref, int ref_linesize, int j, int i, int plane, int jobnr)
Definition: vf_bm3d.c:355
const AVPixFmtDescriptor * desc
Definition: vf_tonemap.c:196
const uint8_t * ref
Definition: vf_bm3d.c:58
A list of supported formats for one end of a filter link.
Definition: formats.h:64
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
static int config_input(AVFilterLink *inlink)
Definition: vf_bm3d.c:780
static void block_matching_multi(BM3DContext *s, const uint8_t *ref, int ref_linesize, int y, int x, int exclude_cur_pos, int plane, int jobnr)
Definition: vf_bm3d.c:315
An instance of a filter.
Definition: avfilter.h:338
FFFrameSync fs
Definition: vf_bm3d.c:114
int planewidth[4]
Definition: vf_bm3d.c:107
#define av_freep(p)
const void ** s
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
float sigma
Definition: vf_bm3d.c:92
static int query_formats(AVFilterContext *ctx)
Definition: vf_bm3d.c:164
AVFrame * in
Definition: af_afftdn.c:1083
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:338
FFTSample * bufferz
Definition: vf_bm3d.c:77
AVFilterLink * inlink
Definition: vf_blend.c:57
PosCode * search_positions
Definition: vf_bm3d.c:86
internal API functions
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition: framesync.c:246
int depth
Number of bits in the component.
Definition: pixdesc.h:58
AVFrame * a
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int src_linesize
Definition: vf_bm3d.c:57
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:409
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:659
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:437
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
static int ff_insert_inpad(AVFilterContext *f, unsigned index, AVFilterPad *p)
Insert a new input pad for the filter.
Definition: internal.h:266
static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)
Clip a signed integer to an unsigned power of two range.
Definition: common.h:229
static int config_output(AVFilterLink *outlink)
Definition: vf_bm3d.c:971
static void basic_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize, const uint8_t *ref, int ref_linesize, int y, int x, int plane, int jobnr)
Definition: vf_bm3d.c:394