FFmpeg  4.4
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 {
83  float *num, *den;
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);
122  void (*do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize,
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 
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 
355 static void block_matching(BM3DContext *s, const uint8_t *ref, int ref_linesize,
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 
394 static void basic_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
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 
513 static void final_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
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 
645 static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize,
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 
672 static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize,
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);
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 
780 static int config_input(AVFilterLink *inlink)
781 {
783  AVFilterContext *ctx = inlink->dst;
784  BM3DContext *s = ctx->priv;
785  int i, group_bits;
786 
788  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
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 
808  sc->dctf = av_dct_init(av_log2(s->block_size), DCT_II);
809  sc->dcti = av_dct_init(av_log2(s->block_size), DCT_III);
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;
842  s->do_block_ssd = do_block_ssd;
843  s->get_block_row = get_block_row;
844 
845  if (s->depth > 8) {
846  s->do_output = do_output16;
847  s->do_block_ssd = do_block_ssd16;
848  s->get_block_row = get_block_row16;
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);
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]))
880  ff_inlink_request_frame(ctx->inputs[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;
917  s->block_filtering = basic_block_filtering;
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 
926  s->block_filtering = final_block_filtering;
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 = "source";
947 
948  if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0)
949  return ret;
950 
951  if (s->ref) {
952  pad.type = AVMEDIA_TYPE_VIDEO;
953  pad.name = "reference";
954  pad.config_props = NULL;
955 
956  if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0)
957  return ret;
958  }
959 
960  return 0;
961 }
962 
963 static int config_output(AVFilterLink *outlink)
964 {
965  AVFilterContext *ctx = outlink->src;
966  BM3DContext *s = ctx->priv;
967  AVFilterLink *src = ctx->inputs[0];
968  AVFilterLink *ref;
969  FFFrameSyncIn *in;
970  int ret;
971 
972  if (s->ref) {
973  ref = ctx->inputs[1];
974 
975  if (src->format != ref->format) {
976  av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
977  return AVERROR(EINVAL);
978  }
979  if (src->w != ref->w ||
980  src->h != ref->h) {
981  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
982  "(size %dx%d) do not match the corresponding "
983  "second input link %s parameters (%dx%d) ",
984  ctx->input_pads[0].name, src->w, src->h,
985  ctx->input_pads[1].name, ref->w, ref->h);
986  return AVERROR(EINVAL);
987  }
988  }
989 
990  outlink->w = src->w;
991  outlink->h = src->h;
992  outlink->time_base = src->time_base;
993  outlink->sample_aspect_ratio = src->sample_aspect_ratio;
994  outlink->frame_rate = src->frame_rate;
995 
996  if (!s->ref)
997  return 0;
998 
999  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
1000  return ret;
1001 
1002  in = s->fs.in;
1003  in[0].time_base = src->time_base;
1004  in[1].time_base = ref->time_base;
1005  in[0].sync = 1;
1006  in[0].before = EXT_STOP;
1007  in[0].after = EXT_STOP;
1008  in[1].sync = 1;
1009  in[1].before = EXT_STOP;
1010  in[1].after = EXT_STOP;
1011  s->fs.opaque = s;
1012  s->fs.on_event = process_frame;
1013 
1014  return ff_framesync_configure(&s->fs);
1015 }
1016 
1018 {
1019  BM3DContext *s = ctx->priv;
1020  int i;
1021 
1022  if (s->ref)
1023  ff_framesync_uninit(&s->fs);
1024 
1025  for (i = 0; i < s->nb_threads; i++) {
1026  SliceContext *sc = &s->slices[i];
1027 
1028  av_freep(&sc->num);
1029  av_freep(&sc->den);
1030 
1031  av_dct_end(sc->gdctf);
1032  av_dct_end(sc->gdcti);
1033  av_dct_end(sc->dctf);
1034  av_dct_end(sc->dcti);
1035 
1036  av_freep(&sc->buffer);
1037  av_freep(&sc->bufferh);
1038  av_freep(&sc->bufferv);
1039  av_freep(&sc->bufferz);
1040  av_freep(&sc->rbuffer);
1041  av_freep(&sc->rbufferh);
1042  av_freep(&sc->rbufferv);
1043  av_freep(&sc->rbufferz);
1044 
1045  av_freep(&sc->search_positions);
1046  }
1047 }
1048 
1049 static const AVFilterPad bm3d_outputs[] = {
1050  {
1051  .name = "default",
1052  .type = AVMEDIA_TYPE_VIDEO,
1053  .config_props = config_output,
1054  },
1055  { NULL }
1056 };
1057 
1059  .name = "bm3d",
1060  .description = NULL_IF_CONFIG_SMALL("Block-Matching 3D denoiser."),
1061  .priv_size = sizeof(BM3DContext),
1062  .init = init,
1063  .uninit = uninit,
1064  .activate = activate,
1066  .inputs = NULL,
1067  .outputs = bm3d_outputs,
1068  .priv_class = &bm3d_class,
1072 };
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#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
simple assert() macros that are a bit more flexible than ISO C assert().
FFT functions.
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:1447
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1094
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1492
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1618
Main libavfilter public API header.
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define s(width, name)
Definition: cbs_vp9.c:257
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:259
#define FFMIN(a, b)
Definition: common.h:105
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
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:302
#define FFMAX(a, b)
Definition: common.h:103
#define av_clip_uint8
Definition: common.h:128
#define FFDIFFSIGN(x, y)
Comparator.
Definition: common.h:101
#define NULL
Definition: coverity.c:32
static AVFrame * frame
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
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
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
static int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition: filters.h:172
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_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:341
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition: framesync.c:253
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:290
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:84
@ EXT_STOP
Completely stop all streams with this one.
Definition: framesync.h:65
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
@ AV_OPT_TYPE_INT
Definition: opt.h:225
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
void av_dct_calc(DCTContext *s, FFTSample *data)
DCTContext * av_dct_init(int nbits, enum DCTTransformType type)
Set up DCT.
float FFTSample
Definition: avfft.h:35
void av_dct_end(DCTContext *s)
@ DCT_III
Definition: avfft.h:95
@ DCT_II
Definition: avfft.h:94
#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 AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:106
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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
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
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:373
int index
Definition: gxfenc.c:89
misc image utilities
int i
Definition: input.c:407
#define av_log2
Definition: intmath.h:83
const char * arg
Definition: jacosubdec.c:66
static int ff_insert_inpad(AVFilterContext *f, unsigned index, AVFilterPad *p)
Insert a new input pad for the filter.
Definition: internal.h:240
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:303
#define isnan(x)
Definition: libm.h:340
#define lrintf(x)
Definition: libm_mips.h:70
const char * desc
Definition: libsvtav1.c:79
static const struct @322 planes[]
#define FFALIGN(x, a)
Definition: macros.h:48
#define M_SQRT2
Definition: mathematics.h:61
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2613
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:410
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:406
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:398
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:399
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:405
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:379
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:421
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:397
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:438
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:441
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:403
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:436
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:434
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:404
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:400
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:381
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:396
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:433
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:437
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:407
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:439
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:408
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:380
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:382
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:411
#define AV_PIX_FMT_YUV440P10
Definition: pixfmt.h:401
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:443
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:442
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:418
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:409
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:435
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:417
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:440
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:412
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:402
#define td
Definition: regdef.h:70
typedef void(RENAME(mix_any_func_type))
static char buffer[20]
Definition: seek.c:32
unsigned int pos
Definition: spdifenc.c:412
Describe the class of an AVClass context structure.
Definition: log.h:67
An instance of a filter.
Definition: avfilter.h:341
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
int(* config_props)(AVFilterLink *link)
Link configuration callback.
Definition: internal.h:118
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:65
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
float hard_threshold
Definition: vf_bm3d.c:99
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
int nb_threads
Definition: vf_bm3d.c:115
void(* do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:122
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
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
int group_size
Definition: vf_bm3d.c:95
float th_mse
Definition: vf_bm3d.c:98
int bm_range
Definition: vf_bm3d.c:96
int block_step
Definition: vf_bm3d.c:94
SliceContext slices[MAX_NB_THREADS]
Definition: vf_bm3d.c:112
FFFrameSync fs
Definition: vf_bm3d.c:114
int planeheight[4]
Definition: vf_bm3d.c:108
int mode
Definition: vf_bm3d.c:100
int block_size
Definition: vf_bm3d.c:93
int bm_step
Definition: vf_bm3d.c:97
int group_bits
Definition: vf_bm3d.c:109
int planes
Definition: vf_bm3d.c:102
int nb_planes
Definition: vf_bm3d.c:106
int pgroup_size
Definition: vf_bm3d.c:110
int depth
Definition: vf_bm3d.c:104
int planewidth[4]
Definition: vf_bm3d.c:107
float sigma
Definition: vf_bm3d.c:92
Definition: dct.h:32
Input stream structure.
Definition: framesync.h:81
Frame sync structure.
Definition: framesync.h:146
int x
Definition: vf_bm3d.c:64
int y
Definition: vf_bm3d.c:64
double score
Definition: vf_bm3d.c:68
PosPairCode match_blocks[256]
Definition: vf_bm3d.c:84
DCTContext * gdctf
Definition: vf_bm3d.c:73
DCTContext * dctf
Definition: vf_bm3d.c:74
PosCode * search_positions
Definition: vf_bm3d.c:86
FFTSample * buffer
Definition: vf_bm3d.c:78
FFTSample * bufferz
Definition: vf_bm3d.c:77
FFTSample * rbufferh
Definition: vf_bm3d.c:79
FFTSample * rbuffer
Definition: vf_bm3d.c:82
FFTSample * bufferv
Definition: vf_bm3d.c:76
FFTSample * rbufferv
Definition: vf_bm3d.c:80
FFTSample * rbufferz
Definition: vf_bm3d.c:81
int nb_match_blocks
Definition: vf_bm3d.c:85
float * den
Definition: vf_bm3d.c:83
DCTContext * dcti
Definition: vf_bm3d.c:74
float * num
Definition: vf_bm3d.c:83
FFTSample * bufferh
Definition: vf_bm3d.c:75
DCTContext * gdcti
Definition: vf_bm3d.c:73
Used for passing data between threads.
Definition: dsddec.c:67
const uint8_t * ref
Definition: vf_bm3d.c:58
int src_linesize
Definition: vf_bm3d.c:57
int ref_linesize
Definition: vf_bm3d.c:59
const uint8_t * src
Definition: vf_bm3d.c:56
int plane
Definition: vf_blend.c:58
#define av_freep(p)
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
#define height
#define width
static int64_t pts
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_bm3d.c:700
AVFILTER_DEFINE_CLASS(bm3d)
static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
Definition: vf_bm3d.c:198
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
static int cmp_scores(const void *a, const void *b)
Definition: vf_bm3d.c:228
FilterModes
Definition: vf_bm3d.c:49
@ BASIC
Definition: vf_bm3d.c:50
@ NB_MODES
Definition: vf_bm3d.c:52
@ FINAL
Definition: vf_bm3d.c:51
#define MAX_NB_THREADS
Definition: vf_bm3d.c:47
static int query_formats(AVFilterContext *ctx)
Definition: vf_bm3d.c:164
static int config_input(AVFilterLink *inlink)
Definition: vf_bm3d.c:780
#define FLAGS
Definition: vf_bm3d.c:131
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
static int filter_frame(AVFilterContext *ctx, AVFrame **out, AVFrame *in, AVFrame *ref)
Definition: vf_bm3d.c:743
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
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
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
#define SQR(x)
Definition: vf_bm3d.c:778
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 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
static const AVOption bm3d_options[]
Definition: vf_bm3d.c:132
static int activate(AVFilterContext *ctx)
Definition: vf_bm3d.c:854
static av_cold int init(AVFilterContext *ctx)
Definition: vf_bm3d.c:908
static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:645
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_bm3d.c:1017
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
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 const AVFilterPad bm3d_outputs[]
Definition: vf_bm3d.c:1049
#define OFFSET(x)
Definition: vf_bm3d.c:130
static int config_output(AVFilterLink *outlink)
Definition: vf_bm3d.c:963
static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:672
AVFilter ff_vf_bm3d
Definition: vf_bm3d.c:1058
static int process_frame(FFFrameSync *fs)
Definition: vf_bm3d.c:888
static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
Definition: vf_bm3d.c:223
const char * b
Definition: vf_curves.c:118
const char * r
Definition: vf_curves.c:116
else temp
Definition: vf_mcdeint.c:259
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