FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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_INT, {.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[] = {
186  };
187 
188  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
189  if (!fmts_list)
190  return AVERROR(ENOMEM);
191  return ff_set_common_formats(ctx, fmts_list);
192 }
193 
194 static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
195 {
196  int search_boundary;
197 
198  search_range = search_range / search_step * search_step;
199 
200  if (pos == plane_boundary) {
201  search_boundary = plane_boundary;
202  } else if (pos > plane_boundary) {
203  search_boundary = pos - search_range;
204 
205  while (search_boundary < plane_boundary) {
206  search_boundary += search_step;
207  }
208  } else {
209  search_boundary = pos + search_range;
210 
211  while (search_boundary > plane_boundary) {
212  search_boundary -= search_step;
213  }
214  }
215 
216  return search_boundary;
217 }
218 
219 static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
220 {
221  return do_search_boundary(vertical ? y : x, plane_boundary, search_range, search_step);
222 }
223 
224 static int cmp_scores(const void *a, const void *b)
225 {
226  const struct PosPairCode *pair1 = a;
227  const struct PosPairCode *pair2 = b;
228  return FFDIFFSIGN(pair1->score, pair2->score);
229 }
230 
231 static double do_block_ssd(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
232 {
233  const uint8_t *srcp = src + pos->y * src_stride + pos->x;
234  const uint8_t *refp = src + r_y * src_stride + r_x;
235  const int block_size = s->block_size;
236  double dist = 0.;
237  int x, y;
238 
239  for (y = 0; y < block_size; y++) {
240  for (x = 0; x < block_size; x++) {
241  double temp = refp[x] - srcp[x];
242  dist += temp * temp;
243  }
244 
245  srcp += src_stride;
246  refp += src_stride;
247  }
248 
249  return dist;
250 }
251 
252 static double do_block_ssd16(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
253 {
254  const uint16_t *srcp = (uint16_t *)src + pos->y * src_stride / 2 + pos->x;
255  const uint16_t *refp = (uint16_t *)src + r_y * src_stride / 2 + r_x;
256  const int block_size = s->block_size;
257  double dist = 0.;
258  int x, y;
259 
260  for (y = 0; y < block_size; y++) {
261  for (x = 0; x < block_size; x++) {
262  double temp = refp[x] - srcp[x];
263  dist += temp * temp;
264  }
265 
266  srcp += src_stride / 2;
267  refp += src_stride / 2;
268  }
269 
270  return dist;
271 }
272 
273 static void do_block_matching_multi(BM3DContext *s, const uint8_t *src, int src_stride, int src_range,
274  const PosCode *search_pos, int search_size, float th_mse,
275  int r_y, int r_x, int plane, int jobnr)
276 {
277  SliceContext *sc = &s->slices[jobnr];
278  double MSE2SSE = s->group_size * s->block_size * s->block_size * src_range * src_range / (s->max * s->max);
279  double distMul = 1. / MSE2SSE;
280  double th_sse = th_mse * MSE2SSE;
281  int i, index = sc->nb_match_blocks;
282 
283  for (i = 0; i < search_size; i++) {
284  PosCode pos = search_pos[i];
285  double dist;
286 
287  dist = s->do_block_ssd(s, &pos, src, src_stride, r_y, r_x);
288 
289  // Only match similar blocks but not identical blocks
290  if (dist <= th_sse && dist != 0) {
291  const double score = dist * distMul;
292 
293  if (index >= s->group_size && score >= sc->match_blocks[index - 1].score) {
294  continue;
295  }
296 
297  if (index >= s->group_size)
298  index = s->group_size - 1;
299 
300  sc->match_blocks[index].score = score;
301  sc->match_blocks[index].y = pos.y;
302  sc->match_blocks[index].x = pos.x;
303  index++;
304  qsort(sc->match_blocks, index, sizeof(PosPairCode), cmp_scores);
305  }
306  }
307 
308  sc->nb_match_blocks = index;
309 }
310 
311 static void block_matching_multi(BM3DContext *s, const uint8_t *ref, int ref_linesize, int y, int x,
312  int exclude_cur_pos, int plane, int jobnr)
313 {
314  SliceContext *sc = &s->slices[jobnr];
315  const int width = s->planewidth[plane];
316  const int height = s->planeheight[plane];
317  const int block_size = s->block_size;
318  const int step = s->bm_step;
319  const int range = s->bm_range / step * step;
320  int l = search_boundary(0, range, step, 0, y, x);
321  int r = search_boundary(width - block_size, range, step, 0, y, x);
322  int t = search_boundary(0, range, step, 1, y, x);
323  int b = search_boundary(height - block_size, range, step, 1, y, x);
324  int j, i, index = 0;
325 
326  for (j = t; j <= b; j += step) {
327  for (i = l; i <= r; i += step) {
328  PosCode pos;
329 
330  if (exclude_cur_pos > 0 && j == y && i == x) {
331  continue;
332  }
333 
334  pos.y = j;
335  pos.x = i;
336  sc->search_positions[index++] = pos;
337  }
338  }
339 
340  if (exclude_cur_pos == 1) {
341  sc->match_blocks[0].score = 0;
342  sc->match_blocks[0].y = y;
343  sc->match_blocks[0].x = x;
344  sc->nb_match_blocks = 1;
345  }
346 
347  do_block_matching_multi(s, ref, ref_linesize, s->bm_range,
348  sc->search_positions, index, s->th_mse, y, x, plane, jobnr);
349 }
350 
351 static void block_matching(BM3DContext *s, const uint8_t *ref, int ref_linesize,
352  int j, int i, int plane, int jobnr)
353 {
354  SliceContext *sc = &s->slices[jobnr];
355 
356  if (s->group_size == 1 || s->th_mse <= 0.f) {
357  sc->match_blocks[0].score = 1;
358  sc->match_blocks[0].x = i;
359  sc->match_blocks[0].y = j;
360  sc->nb_match_blocks = 1;
361  return;
362  }
363 
364  sc->nb_match_blocks = 0;
365  block_matching_multi(s, ref, ref_linesize, j, i, 1, plane, jobnr);
366 }
367 
368 static void get_block_row(const uint8_t *srcp, int src_linesize,
369  int y, int x, int block_size, float *dst)
370 {
371  const uint8_t *src = srcp + y * src_linesize + x;
372  int j;
373 
374  for (j = 0; j < block_size; j++) {
375  dst[j] = src[j];
376  }
377 }
378 
379 static void get_block_row16(const uint8_t *srcp, int src_linesize,
380  int y, int x, int block_size, float *dst)
381 {
382  const uint16_t *src = (uint16_t *)srcp + y * src_linesize / 2 + x;
383  int j;
384 
385  for (j = 0; j < block_size; j++) {
386  dst[j] = src[j];
387  }
388 }
389 
390 static void basic_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
391  const uint8_t *ref, int ref_linesize,
392  int y, int x, int plane, int jobnr)
393 {
394  SliceContext *sc = &s->slices[jobnr];
395  const int buffer_linesize = s->block_size * s->block_size;
396  const int nb_match_blocks = sc->nb_match_blocks;
397  const int block_size = s->block_size;
398  const int width = s->planewidth[plane];
399  const int pgroup_size = s->pgroup_size;
400  const int group_size = s->group_size;
401  float *buffer = sc->buffer;
402  float *bufferh = sc->bufferh;
403  float *bufferv = sc->bufferv;
404  float *bufferz = sc->bufferz;
405  float threshold[4];
406  float den_weight, num_weight;
407  int retained = 0;
408  int i, j, k;
409 
410  for (k = 0; k < nb_match_blocks; k++) {
411  const int y = sc->match_blocks[k].y;
412  const int x = sc->match_blocks[k].x;
413 
414  for (i = 0; i < block_size; i++) {
415  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + block_size * i);
416  av_dct_calc(sc->dctf, bufferh + block_size * i);
417  }
418 
419  for (i = 0; i < block_size; i++) {
420  for (j = 0; j < block_size; j++) {
421  bufferv[i * block_size + j] = bufferh[j * block_size + i];
422  }
423  av_dct_calc(sc->dctf, bufferv + i * block_size);
424  }
425 
426  for (i = 0; i < block_size; i++) {
427  memcpy(buffer + k * buffer_linesize + i * block_size,
428  bufferv + i * block_size, block_size * 4);
429  }
430  }
431 
432  for (i = 0; i < block_size; i++) {
433  for (j = 0; j < block_size; j++) {
434  for (k = 0; k < nb_match_blocks; k++)
435  bufferz[k] = buffer[buffer_linesize * k + i * block_size + j];
436  if (group_size > 1)
437  av_dct_calc(sc->gdctf, bufferz);
438  bufferz += pgroup_size;
439  }
440  }
441 
442  threshold[0] = s->hard_threshold * s->sigma;
443  threshold[1] = threshold[0] * sqrtf(2.f);
444  threshold[2] = threshold[0] * 2.f;
445  threshold[3] = threshold[0] * sqrtf(8.f);
446  bufferz = sc->bufferz;
447 
448  for (i = 0; i < block_size; i++) {
449  for (j = 0; j < block_size; j++) {
450  for (k = 0; k < nb_match_blocks; k++) {
451  const float thresh = threshold[(j == 0) + (i == 0) + (k == 0)];
452 
453  if (bufferz[k] > thresh || bufferz[k] < -thresh) {
454  retained++;
455  } else {
456  bufferz[k] = 0;
457  }
458  }
459  bufferz += pgroup_size;
460  }
461  }
462 
463  bufferz = sc->bufferz;
464  buffer = sc->buffer;
465  for (i = 0; i < block_size; i++) {
466  for (j = 0; j < block_size; j++) {
467  if (group_size > 1)
468  av_dct_calc(sc->gdcti, bufferz);
469  for (k = 0; k < nb_match_blocks; k++) {
470  buffer[buffer_linesize * k + i * block_size + j] = bufferz[k];
471  }
472  bufferz += pgroup_size;
473  }
474  }
475 
476  den_weight = retained < 1 ? 1.f : 1.f / retained;
477  num_weight = den_weight;
478 
479  buffer = sc->buffer;
480  for (k = 0; k < nb_match_blocks; k++) {
481  float *num = sc->num + y * width + x;
482  float *den = sc->den + y * width + x;
483 
484  for (i = 0; i < block_size; i++) {
485  memcpy(bufferv + i * block_size,
486  buffer + k * buffer_linesize + i * block_size,
487  block_size * 4);
488  }
489 
490  for (i = 0; i < block_size; i++) {
491  av_dct_calc(sc->dcti, bufferv + block_size * i);
492  for (j = 0; j < block_size; j++) {
493  bufferh[j * block_size + i] = bufferv[i * block_size + j];
494  }
495  }
496 
497  for (i = 0; i < block_size; i++) {
498  av_dct_calc(sc->dcti, bufferh + block_size * i);
499  for (j = 0; j < block_size; j++) {
500  num[j] += bufferh[i * block_size + j] * num_weight;
501  den[j] += den_weight;
502  }
503  num += width;
504  den += width;
505  }
506  }
507 }
508 
509 static void final_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
510  const uint8_t *ref, int ref_linesize,
511  int y, int x, int plane, int jobnr)
512 {
513  SliceContext *sc = &s->slices[jobnr];
514  const int buffer_linesize = s->block_size * s->block_size;
515  const int nb_match_blocks = sc->nb_match_blocks;
516  const int block_size = s->block_size;
517  const int width = s->planewidth[plane];
518  const int pgroup_size = s->pgroup_size;
519  const int group_size = s->group_size;
520  const float sigma_sqr = s->sigma * s->sigma;
521  float *buffer = sc->buffer;
522  float *bufferh = sc->bufferh;
523  float *bufferv = sc->bufferv;
524  float *bufferz = sc->bufferz;
525  float *rbuffer = sc->rbuffer;
526  float *rbufferh = sc->rbufferh;
527  float *rbufferv = sc->rbufferv;
528  float *rbufferz = sc->rbufferz;
529  float den_weight, num_weight;
530  float l2_wiener = 0;
531  int i, j, k;
532 
533  for (k = 0; k < nb_match_blocks; k++) {
534  const int y = sc->match_blocks[k].y;
535  const int x = sc->match_blocks[k].x;
536 
537  for (i = 0; i < block_size; i++) {
538  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + block_size * i);
539  s->get_block_row(ref, ref_linesize, y + i, x, block_size, rbufferh + block_size * i);
540  av_dct_calc(sc->dctf, bufferh + block_size * i);
541  av_dct_calc(sc->dctf, rbufferh + block_size * i);
542  }
543 
544  for (i = 0; i < block_size; i++) {
545  for (j = 0; j < block_size; j++) {
546  bufferv[i * block_size + j] = bufferh[j * block_size + i];
547  rbufferv[i * block_size + j] = rbufferh[j * block_size + i];
548  }
549  av_dct_calc(sc->dctf, bufferv + i * block_size);
550  av_dct_calc(sc->dctf, rbufferv + i * block_size);
551  }
552 
553  for (i = 0; i < block_size; i++) {
554  memcpy(buffer + k * buffer_linesize + i * block_size,
555  bufferv + i * block_size, block_size * 4);
556  memcpy(rbuffer + k * buffer_linesize + i * block_size,
557  rbufferv + i * block_size, block_size * 4);
558  }
559  }
560 
561  for (i = 0; i < block_size; i++) {
562  for (j = 0; j < block_size; j++) {
563  for (k = 0; k < nb_match_blocks; k++) {
564  bufferz[k] = buffer[buffer_linesize * k + i * block_size + j];
565  rbufferz[k] = rbuffer[buffer_linesize * k + i * block_size + j];
566  }
567  if (group_size > 1) {
568  av_dct_calc(sc->gdctf, bufferz);
569  av_dct_calc(sc->gdctf, rbufferz);
570  }
571  bufferz += pgroup_size;
572  rbufferz += pgroup_size;
573  }
574  }
575 
576  bufferz = sc->bufferz;
577  rbufferz = sc->rbufferz;
578 
579  for (i = 0; i < block_size; i++) {
580  for (j = 0; j < block_size; j++) {
581  for (k = 0; k < nb_match_blocks; k++) {
582  const float ref_sqr = rbufferz[k] * rbufferz[k];
583  float wiener_coef = ref_sqr / (ref_sqr + sigma_sqr);
584 
585  if (isnan(wiener_coef))
586  wiener_coef = 1;
587  bufferz[k] *= wiener_coef;
588  l2_wiener += wiener_coef * wiener_coef;
589  }
590  bufferz += pgroup_size;
591  rbufferz += pgroup_size;
592  }
593  }
594 
595  bufferz = sc->bufferz;
596  buffer = sc->buffer;
597  for (i = 0; i < block_size; i++) {
598  for (j = 0; j < block_size; j++) {
599  if (group_size > 1)
600  av_dct_calc(sc->gdcti, bufferz);
601  for (k = 0; k < nb_match_blocks; k++) {
602  buffer[buffer_linesize * k + i * block_size + j] = bufferz[k];
603  }
604  bufferz += pgroup_size;
605  }
606  }
607 
608  l2_wiener = FFMAX(l2_wiener, 1e-15f);
609  den_weight = 1.f / l2_wiener;
610  num_weight = den_weight;
611 
612  for (k = 0; k < nb_match_blocks; k++) {
613  float *num = sc->num + y * width + x;
614  float *den = sc->den + y * width + x;
615 
616  for (i = 0; i < block_size; i++) {
617  memcpy(bufferv + i * block_size,
618  buffer + k * buffer_linesize + i * block_size,
619  block_size * 4);
620  }
621 
622  for (i = 0; i < block_size; i++) {
623  av_dct_calc(sc->dcti, bufferv + block_size * i);
624  for (j = 0; j < block_size; j++) {
625  bufferh[j * block_size + i] = bufferv[i * block_size + j];
626  }
627  }
628 
629  for (i = 0; i < block_size; i++) {
630  av_dct_calc(sc->dcti, bufferh + block_size * i);
631  for (j = 0; j < block_size; j++) {
632  num[j] += bufferh[i * block_size + j] * num_weight;
633  den[j] += den_weight;
634  }
635  num += width;
636  den += width;
637  }
638  }
639 }
640 
641 static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize,
642  int plane, int nb_jobs)
643 {
644  const int height = s->planeheight[plane];
645  const int width = s->planewidth[plane];
646  int i, j, k;
647 
648  for (i = 0; i < height; i++) {
649  for (j = 0; j < width; j++) {
650  uint8_t *dstp = dst + i * dst_linesize;
651  float sum_den = 0.f;
652  float sum_num = 0.f;
653 
654  for (k = 0; k < nb_jobs; k++) {
655  SliceContext *sc = &s->slices[k];
656  float num = sc->num[i * width + j];
657  float den = sc->den[i * width + j];
658 
659  sum_num += num;
660  sum_den += den;
661  }
662 
663  dstp[j] = av_clip_uint8(sum_num / sum_den);
664  }
665  }
666 }
667 
668 static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize,
669  int plane, int nb_jobs)
670 {
671  const int height = s->planeheight[plane];
672  const int width = s->planewidth[plane];
673  const int depth = s->depth;
674  int i, j, k;
675 
676  for (i = 0; i < height; i++) {
677  for (j = 0; j < width; j++) {
678  uint16_t *dstp = (uint16_t *)dst + i * dst_linesize / 2;
679  float sum_den = 0.f;
680  float sum_num = 0.f;
681 
682  for (k = 0; k < nb_jobs; k++) {
683  SliceContext *sc = &s->slices[k];
684  float num = sc->num[i * width + j];
685  float den = sc->den[i * width + j];
686 
687  sum_num += num;
688  sum_den += den;
689  }
690 
691  dstp[j] = av_clip_uintp2_c(sum_num / sum_den, depth);
692  }
693  }
694 }
695 
696 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
697 {
698  BM3DContext *s = ctx->priv;
699  SliceContext *sc = &s->slices[jobnr];
700  const int block_step = s->block_step;
701  ThreadData *td = arg;
702  const uint8_t *src = td->src;
703  const uint8_t *ref = td->ref;
704  const int src_linesize = td->src_linesize;
705  const int ref_linesize = td->ref_linesize;
706  const int plane = td->plane;
707  const int width = s->planewidth[plane];
708  const int height = s->planeheight[plane];
709  const int block_pos_bottom = height - s->block_size;
710  const int block_pos_right = width - s->block_size;
711  const int slice_start = (((height + block_step - 1) / block_step) * jobnr / nb_jobs) * block_step;
712  const int slice_end = (jobnr == nb_jobs - 1) ? block_pos_bottom + block_step :
713  (((height + block_step - 1) / block_step) * (jobnr + 1) / nb_jobs) * block_step;
714  int i, j;
715 
716  memset(sc->num, 0, width * height * sizeof(FFTSample));
717  memset(sc->den, 0, width * height * sizeof(FFTSample));
718 
719  for (j = slice_start; j < slice_end; j += block_step) {
720  if (j > block_pos_bottom) {
721  j = block_pos_bottom;
722  }
723 
724  for (i = 0; i < block_pos_right + block_step; i += block_step) {
725  if (i > block_pos_right) {
726  i = block_pos_right;
727  }
728 
729  block_matching(s, ref, ref_linesize, j, i, plane, jobnr);
730 
731  s->block_filtering(s, src, src_linesize,
732  ref, ref_linesize, j, i, plane, jobnr);
733  }
734  }
735 
736  return 0;
737 }
738 
740 {
741  BM3DContext *s = ctx->priv;
742  AVFilterLink *outlink = ctx->outputs[0];
743  int p;
744 
745  *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
746  if (!*out)
747  return AVERROR(ENOMEM);
748  av_frame_copy_props(*out, in);
749 
750  for (p = 0; p < s->nb_planes; p++) {
751  const int nb_jobs = FFMIN(s->nb_threads, s->planeheight[p] / s->block_step);
752  ThreadData td;
753 
754  if (!((1 << p) & s->planes) || ctx->is_disabled) {
755  av_image_copy_plane((*out)->data[p], (*out)->linesize[p],
756  in->data[p], in->linesize[p],
757  s->planewidth[p], s->planeheight[p]);
758  continue;
759  }
760 
761  td.src = in->data[p];
762  td.src_linesize = in->linesize[p];
763  td.ref = ref->data[p];
764  td.ref_linesize = ref->linesize[p];
765  td.plane = p;
766  ctx->internal->execute(ctx, filter_slice, &td, NULL, nb_jobs);
767 
768  s->do_output(s, (*out)->data[p], (*out)->linesize[p], p, nb_jobs);
769  }
770 
771  return 0;
772 }
773 
774 #define SQR(x) ((x) * (x))
775 
776 static int config_input(AVFilterLink *inlink)
777 {
779  AVFilterContext *ctx = inlink->dst;
780  BM3DContext *s = ctx->priv;
781  int i, group_bits;
782 
785  s->depth = desc->comp[0].depth;
786  s->max = (1 << s->depth) - 1;
787  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
788  s->planeheight[0] = s->planeheight[3] = inlink->h;
789  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
790  s->planewidth[0] = s->planewidth[3] = inlink->w;
791 
792  for (group_bits = 4; 1 << group_bits < s->group_size; group_bits++);
793  s->group_bits = group_bits;
794  s->pgroup_size = 1 << group_bits;
795 
796  for (i = 0; i < s->nb_threads; i++) {
797  SliceContext *sc = &s->slices[i];
798 
799  sc->num = av_calloc(s->planewidth[0] * s->planeheight[0], sizeof(FFTSample));
800  sc->den = av_calloc(s->planewidth[0] * s->planeheight[0], sizeof(FFTSample));
801  if (!sc->num || !sc->den)
802  return AVERROR(ENOMEM);
803 
806  if (!sc->dctf || !sc->dcti)
807  return AVERROR(ENOMEM);
808 
809  if (s->group_bits > 1) {
810  sc->gdctf = av_dct_init(s->group_bits, DCT_II);
811  sc->gdcti = av_dct_init(s->group_bits, DCT_III);
812  if (!sc->gdctf || !sc->gdcti)
813  return AVERROR(ENOMEM);
814  }
815 
816  sc->buffer = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->buffer));
817  sc->bufferz = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->bufferz));
818  sc->bufferh = av_calloc(s->block_size * s->block_size, sizeof(*sc->bufferh));
819  sc->bufferv = av_calloc(s->block_size * s->block_size, sizeof(*sc->bufferv));
820  if (!sc->bufferh || !sc->bufferv || !sc->buffer || !sc->bufferz)
821  return AVERROR(ENOMEM);
822 
823  if (s->mode == FINAL) {
824  sc->rbuffer = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->rbuffer));
825  sc->rbufferz = av_calloc(s->block_size * s->block_size * s->pgroup_size, sizeof(*sc->rbufferz));
826  sc->rbufferh = av_calloc(s->block_size * s->block_size, sizeof(*sc->rbufferh));
827  sc->rbufferv = av_calloc(s->block_size * s->block_size, sizeof(*sc->rbufferv));
828  if (!sc->rbufferh || !sc->rbufferv || !sc->rbuffer || !sc->rbufferz)
829  return AVERROR(ENOMEM);
830  }
831 
832  sc->search_positions = av_calloc(SQR(2 * s->bm_range / s->bm_step + 1), sizeof(*sc->search_positions));
833  if (!sc->search_positions)
834  return AVERROR(ENOMEM);
835  }
836 
837  s->do_output = do_output;
840 
841  if (s->depth > 8) {
842  s->do_output = do_output16;
845  }
846 
847  return 0;
848 }
849 
851 {
852  BM3DContext *s = ctx->priv;
853 
854  if (!s->ref) {
855  AVFrame *frame = NULL;
856  AVFrame *out = NULL;
857  int ret, status;
858  int64_t pts;
859 
860  if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) {
861  ret = filter_frame(ctx, &out, frame, frame);
862  av_frame_free(&frame);
863  if (ret < 0)
864  return ret;
865  ret = ff_filter_frame(ctx->outputs[0], out);
866  }
867  if (ret < 0) {
868  return ret;
869  } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
870  ff_outlink_set_status(ctx->outputs[0], status, pts);
871  return 0;
872  } else {
873  if (ff_outlink_frame_wanted(ctx->outputs[0]))
875  return 0;
876  }
877  } else {
878  return ff_framesync_activate(&s->fs);
879  }
880 }
881 
883 {
884  AVFilterContext *ctx = fs->parent;
885  BM3DContext *s = fs->opaque;
886  AVFilterLink *outlink = ctx->outputs[0];
887  AVFrame *out = NULL, *src, *ref;
888  int ret;
889 
890  if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 ||
891  (ret = ff_framesync_get_frame(&s->fs, 1, &ref, 0)) < 0)
892  return ret;
893 
894  if ((ret = filter_frame(ctx, &out, src, ref)) < 0)
895  return ret;
896 
897  out->pts = av_rescale_q(src->pts, s->fs.time_base, outlink->time_base);
898 
899  return ff_filter_frame(outlink, out);
900 }
901 
903 {
904  BM3DContext *s = ctx->priv;
905  AVFilterPad pad = { 0 };
906  int ret;
907 
908  if (s->mode == BASIC) {
909  if (s->th_mse == 0.f)
910  s->th_mse = 400.f + s->sigma * 80.f;
912  } else if (s->mode == FINAL) {
913  if (!s->ref) {
914  av_log(ctx, AV_LOG_WARNING, "Reference stream is mandatory in final estimation mode.\n");
915  s->ref = 1;
916  }
917  if (s->th_mse == 0.f)
918  s->th_mse = 200.f + s->sigma * 10.f;
919 
921  } else {
922  return AVERROR_BUG;
923  }
924 
925  s->block_size = 1 << s->block_size;
926 
927  if (s->block_step > s->block_size) {
928  av_log(ctx, AV_LOG_WARNING, "bstep: %d can't be bigger than block size. Changing to %d.\n",
929  s->block_step, s->block_size);
930  s->block_step = s->block_size;
931  }
932  if (s->bm_step > s->bm_range) {
933  av_log(ctx, AV_LOG_WARNING, "mstep: %d can't be bigger than block matching range. Changing to %d.\n",
934  s->bm_step, s->bm_range);
935  s->bm_step = s->bm_range;
936  }
937 
938  pad.type = AVMEDIA_TYPE_VIDEO;
939  pad.name = av_strdup("source");
941  if (!pad.name)
942  return AVERROR(ENOMEM);
943 
944  if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) {
945  av_freep(&pad.name);
946  return ret;
947  }
948 
949  if (s->ref) {
950  pad.type = AVMEDIA_TYPE_VIDEO;
951  pad.name = av_strdup("reference");
952  pad.config_props = NULL;
953  if (!pad.name)
954  return AVERROR(ENOMEM);
955 
956  if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) {
957  av_freep(&pad.name);
958  return ret;
959  }
960  }
961 
962  return 0;
963 }
964 
965 static int config_output(AVFilterLink *outlink)
966 {
967  AVFilterContext *ctx = outlink->src;
968  BM3DContext *s = ctx->priv;
969  AVFilterLink *src = ctx->inputs[0];
970  AVFilterLink *ref;
971  FFFrameSyncIn *in;
972  int ret;
973 
974  if (s->ref) {
975  ref = ctx->inputs[1];
976 
977  if (src->format != ref->format) {
978  av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
979  return AVERROR(EINVAL);
980  }
981  if (src->w != ref->w ||
982  src->h != ref->h) {
983  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
984  "(size %dx%d) do not match the corresponding "
985  "second input link %s parameters (%dx%d) ",
986  ctx->input_pads[0].name, src->w, src->h,
987  ctx->input_pads[1].name, ref->w, ref->h);
988  return AVERROR(EINVAL);
989  }
990  }
991 
992  outlink->w = src->w;
993  outlink->h = src->h;
994  outlink->time_base = src->time_base;
996  outlink->frame_rate = src->frame_rate;
997 
998  if (!s->ref)
999  return 0;
1000 
1001  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
1002  return ret;
1003 
1004  in = s->fs.in;
1005  in[0].time_base = src->time_base;
1006  in[1].time_base = ref->time_base;
1007  in[0].sync = 1;
1008  in[0].before = EXT_STOP;
1009  in[0].after = EXT_STOP;
1010  in[1].sync = 1;
1011  in[1].before = EXT_STOP;
1012  in[1].after = EXT_STOP;
1013  s->fs.opaque = s;
1014  s->fs.on_event = process_frame;
1015 
1016  return ff_framesync_configure(&s->fs);
1017 }
1018 
1020 {
1021  BM3DContext *s = ctx->priv;
1022  int i;
1023 
1024  for (i = 0; i < ctx->nb_inputs; i++)
1025  av_freep(&ctx->input_pads[i].name);
1026 
1027  if (s->ref)
1028  ff_framesync_uninit(&s->fs);
1029 
1030  for (i = 0; i < s->nb_threads; i++) {
1031  SliceContext *sc = &s->slices[i];
1032 
1033  av_freep(&sc->num);
1034  av_freep(&sc->den);
1035 
1036  av_dct_end(sc->gdctf);
1037  av_dct_end(sc->gdcti);
1038  av_dct_end(sc->dctf);
1039  av_dct_end(sc->dcti);
1040 
1041  av_freep(&sc->buffer);
1042  av_freep(&sc->bufferh);
1043  av_freep(&sc->bufferv);
1044  av_freep(&sc->bufferz);
1045  av_freep(&sc->rbuffer);
1046  av_freep(&sc->rbufferh);
1047  av_freep(&sc->rbufferv);
1048  av_freep(&sc->rbufferz);
1049 
1050  av_freep(&sc->search_positions);
1051  }
1052 }
1053 
1054 static const AVFilterPad bm3d_outputs[] = {
1055  {
1056  .name = "default",
1057  .type = AVMEDIA_TYPE_VIDEO,
1058  .config_props = config_output,
1059  },
1060  { NULL }
1061 };
1062 
1064  .name = "bm3d",
1065  .description = NULL_IF_CONFIG_SMALL("Block-Matching 3D denoiser."),
1066  .priv_size = sizeof(BM3DContext),
1067  .init = init,
1068  .uninit = uninit,
1069  .activate = activate,
1071  .inputs = NULL,
1072  .outputs = bm3d_outputs,
1073  .priv_class = &bm3d_class,
1077 };
int plane
Definition: avisynth_c.h:422
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:1481
#define NULL
Definition: coverity.c:32
static int filter_frame(AVFilterContext *ctx, AVFrame **out, AVFrame *in, AVFrame *ref)
Definition: vf_bm3d.c:739
#define AV_PIX_FMT_YUV440P10
Definition: pixfmt.h:381
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2446
This structure describes decoded (raw) audio or video data.
Definition: frame.h:226
static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:641
AVOption.
Definition: opt.h:246
AVFILTER_DEFINE_CLASS(bm3d)
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:389
FFTSample * rbufferv
Definition: vf_bm3d.c:80
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:2486
Definition: avfft.h:95
Main libavfilter public API header.
else temp
Definition: vf_mcdeint.c:256
const char * desc
Definition: nvenc.c:65
static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
Definition: vf_bm3d.c:219
int(* on_event)(struct FFFrameSync *fs)
Callback called when a frame event is ready.
Definition: framesync.h:172
AVFilter ff_vf_bm3d
Definition: vf_bm3d.c:1063
#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
const char * b
Definition: vf_curves.c:116
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:395
SliceContext slices[MAX_NB_THREADS]
Definition: vf_bm3d.c:112
int av_log2(unsigned v)
Definition: intmath.c:26
int nb_planes
Definition: vf_bm3d.c:106
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:359
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:65
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:383
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
#define src
Definition: vp8dsp.c:254
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 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:1607
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:244
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:360
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:368
int block_size
Definition: vf_bm3d.c:93
Definition: vf_bm3d.c:50
static const AVFilterPad bm3d_outputs[]
Definition: vf_bm3d.c:1054
BYTE int const BYTE * srcp
Definition: avisynth_c.h:813
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:361
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:1080
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:82
#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:319
FFFrameSyncIn * in
Pointer to array of inputs.
Definition: framesync.h:203
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:394
static AVFrame * frame
static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:668
#define height
int plane
Definition: vf_blend.c:57
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 AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:392
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:379
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_bm3d.c:696
Input stream structure.
Definition: framesync.h:81
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:384
FFTSample * rbuffer
Definition: vf_bm3d.c:82
#define av_log(a,...)
Definition: vf_bm3d.c:51
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:1436
AVFilterPad * input_pads
array of input pads
Definition: avfilter.h:345
DCTContext * dcti
Definition: vf_bm3d.c:74
int bm_range
Definition: vf_bm3d.c:96
#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:568
#define td
Definition: regdef.h:70
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:293
FFTSample * bufferh
Definition: vf_bm3d.c:75
Frame sync structure.
Definition: framesync.h:146
BYTE * dstp
Definition: avisynth_c.h:813
#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:202
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 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 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
const char * arg
Definition: jacosubdec.c:66
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's input and try to produce output.
Definition: framesync.c:344
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:382
#define FLAGS
Definition: vf_bm3d.c:131
#define FFMAX(a, b)
Definition: common.h:94
float FFTSample
Definition: avfft.h:35
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:377
static const struct @304 planes[]
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:398
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
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:363
#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
#define width
int planeheight[4]
Definition: vf_bm3d.c:108
int depth
Definition: vf_bm3d.c:104
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static av_cold int init(AVFilterContext *ctx)
Definition: vf_bm3d.c:902
float th_mse
Definition: vf_bm3d.c:98
static int cmp_scores(const void *a, const void *b)
Definition: vf_bm3d.c:224
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:273
AVFormatContext * ctx
Definition: movenc.c:48
Definition: dct.h:32
AVRational time_base
Time base for the output events.
Definition: framesync.h:162
#define s(width, name)
Definition: cbs_vp9.c:257
static int process_frame(FFFrameSync *fs)
Definition: vf_bm3d.c:882
#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:378
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:231
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:397
static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
Definition: vf_bm3d.c:194
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
static int activate(AVFilterContext *ctx)
Definition: vf_bm3d.c:850
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:390
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:252
#define OFFSET(x)
Definition: vf_bm3d.c:130
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:387
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
int block_step
Definition: vf_bm3d.c:94
Used for passing data between threads.
Definition: af_adeclick.c:484
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:257
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
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_bm3d.c:1019
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.
DCTContext * dctf
Definition: vf_bm3d.c:74
int x
Definition: vf_bm3d.c:64
FilterModes
Definition: vf_bm3d.c:49
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;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);returnNULL;}returnac;}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;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->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);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
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:379
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
void(* do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:122
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
const char * name
Filter name.
Definition: avfilter.h:148
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:385
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:376
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:774
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:388
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:396
static int64_t pts
#define flags(name, subs,...)
Definition: cbs_av1.c:596
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:378
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:380
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:386
int mode
Definition: vf_bm3d.c:100
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:240
float hard_threshold
Definition: vf_bm3d.c:99
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
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
PosPairCode match_blocks[256]
Definition: vf_bm3d.c:84
DCTContext * gdcti
Definition: vf_bm3d.c:73
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:155
const uint8_t * src
Definition: vf_bm3d.c:56
void av_dct_calc(DCTContext *s, FFTSample *data)
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2029
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
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:509
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:351
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:776
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:311
An instance of a filter.
Definition: avfilter.h:338
FFFrameSync fs
Definition: vf_bm3d.c:114
FILE * out
Definition: movenc.c:54
int planewidth[4]
Definition: vf_bm3d.c:107
#define av_freep(p)
int(* config_props)(AVFilterLink *link)
Link configuration callback.
Definition: internal.h:129
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
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
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:256
int depth
Number of bits in the component.
Definition: pixdesc.h:58
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int src_linesize
Definition: vf_bm3d.c:57
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:391
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
GLuint buffer
Definition: opengl_enc.c:102
#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:277
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:965
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:390