FFmpeg
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  * - opponent color space
29  * - temporal support
30  */
31 
32 #include <float.h>
33 
34 #include "libavutil/cpu.h"
35 #include "libavutil/imgutils.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/pixdesc.h"
38 #include "libavutil/tx.h"
39 #include "avfilter.h"
40 #include "filters.h"
41 #include "formats.h"
42 #include "framesync.h"
43 #include "internal.h"
44 #include "video.h"
45 
46 #define MAX_NB_THREADS 32
47 
52 };
53 
54 typedef struct ThreadData {
55  const uint8_t *src;
57  const uint8_t *ref;
59  int plane;
60 } ThreadData;
61 
62 typedef struct PosCode {
63  int x, y;
64 } PosCode;
65 
66 typedef struct PosPairCode {
67  double score;
68  int x, y;
69 } PosPairCode;
70 
71 typedef struct SliceContext {
76  float *bufferh;
77  float *buffert;
78  float *bufferv;
79  float *bufferz;
80  float *buffer;
81  float *rbufferh;
82  float *rbufferv;
83  float *rbufferz;
84  float *rbuffer;
85  float *num, *den;
89 } SliceContext;
90 
91 typedef struct BM3DContext {
92  const AVClass *class;
93 
94  float sigma;
98  int bm_range;
99  int bm_step;
100  float th_mse;
102  int mode;
103  int ref;
104  int planes;
105 
106  int depth;
107  int max;
109  int planewidth[4];
110  int planeheight[4];
113 
115 
118 
119  void (*get_block_row)(const uint8_t *srcp, int src_linesize,
120  int y, int x, int block_size, float *dst);
122  const uint8_t *src, int src_stride,
123  int r_y, int r_x);
124  void (*do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize,
125  int plane, int nb_jobs);
126  void (*block_filtering)(struct BM3DContext *s,
127  const uint8_t *src, int src_linesize,
128  const uint8_t *ref, int ref_linesize,
129  int y, int x, int plane, int jobnr);
130 } BM3DContext;
131 
132 #define OFFSET(x) offsetof(BM3DContext, x)
133 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
134 
135 static const AVOption bm3d_options[] = {
136  { "sigma", "set denoising strength",
137  OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 99999.9, FLAGS },
138  { "block", "set size of local patch",
139  OFFSET(block_size), AV_OPT_TYPE_INT, {.i64=16}, 8, 64, FLAGS },
140  { "bstep", "set sliding step for processing blocks",
141  OFFSET(block_step), AV_OPT_TYPE_INT, {.i64=4}, 1, 64, FLAGS },
142  { "group", "set maximal number of similar blocks",
143  OFFSET(group_size), AV_OPT_TYPE_INT, {.i64=1}, 1, 256, FLAGS },
144  { "range", "set block matching range",
145  OFFSET(bm_range), AV_OPT_TYPE_INT, {.i64=9}, 1, INT32_MAX, FLAGS },
146  { "mstep", "set step for block matching",
147  OFFSET(bm_step), AV_OPT_TYPE_INT, {.i64=1}, 1, 64, FLAGS },
148  { "thmse", "set threshold of mean square error for block matching",
149  OFFSET(th_mse), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT32_MAX, FLAGS },
150  { "hdthr", "set hard threshold for 3D transfer domain",
151  OFFSET(hard_threshold), AV_OPT_TYPE_FLOAT, {.dbl=2.7}, 0, INT32_MAX, FLAGS },
152  { "estim", "set filtering estimation mode",
153  OFFSET(mode), AV_OPT_TYPE_INT, {.i64=BASIC}, 0, NB_MODES-1, FLAGS, "mode" },
154  { "basic", "basic estimate",
155  0, AV_OPT_TYPE_CONST, {.i64=BASIC}, 0, 0, FLAGS, "mode" },
156  { "final", "final estimate",
157  0, AV_OPT_TYPE_CONST, {.i64=FINAL}, 0, 0, FLAGS, "mode" },
158  { "ref", "have reference stream",
159  OFFSET(ref), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
160  { "planes", "set planes to filter",
161  OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS },
162  { NULL }
163 };
164 
166 
167 static const enum AVPixelFormat pix_fmts[] = {
191 };
192 
193 static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
194 {
195  int search_boundary;
196 
197  search_range = search_range / search_step * search_step;
198 
199  if (pos == plane_boundary) {
200  search_boundary = plane_boundary;
201  } else if (pos > plane_boundary) {
202  search_boundary = pos - search_range;
203 
204  while (search_boundary < plane_boundary) {
205  search_boundary += search_step;
206  }
207  } else {
208  search_boundary = pos + search_range;
209 
210  while (search_boundary > plane_boundary) {
211  search_boundary -= search_step;
212  }
213  }
214 
215  return search_boundary;
216 }
217 
218 static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
219 {
220  return do_search_boundary(vertical ? y : x, plane_boundary, search_range, search_step);
221 }
222 
223 static int cmp_scores(const void *a, const void *b)
224 {
225  const struct PosPairCode *pair1 = a;
226  const struct PosPairCode *pair2 = b;
227  return FFDIFFSIGN(pair1->score, pair2->score);
228 }
229 
230 static double do_block_ssd(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
231 {
232  const uint8_t *srcp = src + pos->y * src_stride + pos->x;
233  const uint8_t *refp = src + r_y * src_stride + r_x;
234  const int block_size = s->block_size;
235  double dist = 0.;
236  int x, y;
237 
238  for (y = 0; y < block_size; y++) {
239  for (x = 0; x < block_size; x++) {
240  double temp = refp[x] - srcp[x];
241  dist += temp * temp;
242  }
243 
244  srcp += src_stride;
245  refp += src_stride;
246  }
247 
248  return dist;
249 }
250 
251 static double do_block_ssd16(BM3DContext *s, PosCode *pos, const uint8_t *src, int src_stride, int r_y, int r_x)
252 {
253  const uint16_t *srcp = (uint16_t *)src + pos->y * src_stride / 2 + pos->x;
254  const uint16_t *refp = (uint16_t *)src + r_y * src_stride / 2 + r_x;
255  const int block_size = s->block_size;
256  double dist = 0.;
257  int x, y;
258 
259  for (y = 0; y < block_size; y++) {
260  for (x = 0; x < block_size; x++) {
261  double temp = refp[x] - srcp[x];
262  dist += temp * temp;
263  }
264 
265  srcp += src_stride / 2;
266  refp += src_stride / 2;
267  }
268 
269  return dist;
270 }
271 
272 static void do_block_matching_multi(BM3DContext *s, const uint8_t *src, int src_stride, int src_range,
273  const PosCode *search_pos, int search_size, float th_mse,
274  int r_y, int r_x, int plane, int jobnr)
275 {
276  SliceContext *sc = &s->slices[jobnr];
277  double MSE2SSE = s->group_size * s->block_size * s->block_size * src_range * src_range / (s->max * s->max);
278  double distMul = 1. / MSE2SSE;
279  double th_sse = th_mse * MSE2SSE;
280  int index = sc->nb_match_blocks;
281 
282  for (int i = 0; i < search_size; i++) {
283  PosCode pos = search_pos[i];
284  double dist;
285 
286  dist = s->do_block_ssd(s, &pos, src, src_stride, r_y, r_x);
287 
288  // Only match similar blocks but not identical blocks
289  if (dist <= th_sse && dist != 0) {
290  const double score = dist * distMul;
291 
292  if (index >= s->group_size && score >= sc->match_blocks[index - 1].score) {
293  continue;
294  }
295 
296  if (index >= s->group_size)
297  index = s->group_size - 1;
298 
299  sc->match_blocks[index].score = score;
300  sc->match_blocks[index].y = pos.y;
301  sc->match_blocks[index].x = pos.x;
302  index++;
303  qsort(sc->match_blocks, index, sizeof(PosPairCode), cmp_scores);
304  }
305  }
306 
307  sc->nb_match_blocks = index;
308 }
309 
310 static void block_matching_multi(BM3DContext *s, const uint8_t *ref, int ref_linesize, int y, int x,
311  int exclude_cur_pos, int plane, int jobnr)
312 {
313  SliceContext *sc = &s->slices[jobnr];
314  const int width = s->planewidth[plane];
315  const int height = s->planeheight[plane];
316  const int block_size = s->block_size;
317  const int step = s->bm_step;
318  const int range = s->bm_range / step * step;
319  int l = search_boundary(0, range, step, 0, y, x);
320  int r = search_boundary(width - block_size, range, step, 0, y, x);
321  int t = search_boundary(0, range, step, 1, y, x);
322  int b = search_boundary(height - block_size, range, step, 1, y, x);
323  int index = 0;
324 
325  for (int j = t; j <= b; j += step) {
326  for (int i = l; i <= r; i += step) {
327  PosCode pos;
328 
329  if (exclude_cur_pos > 0 && j == y && i == x) {
330  continue;
331  }
332 
333  pos.y = j;
334  pos.x = i;
335  sc->search_positions[index++] = pos;
336  }
337  }
338 
339  if (exclude_cur_pos == 1) {
340  sc->match_blocks[0].score = 0;
341  sc->match_blocks[0].y = y;
342  sc->match_blocks[0].x = x;
343  sc->nb_match_blocks = 1;
344  }
345 
346  do_block_matching_multi(s, ref, ref_linesize, s->bm_range,
347  sc->search_positions, index, s->th_mse, y, x, plane, jobnr);
348 }
349 
350 static void block_matching(BM3DContext *s, const uint8_t *ref, int ref_linesize,
351  int j, int i, int plane, int jobnr)
352 {
353  SliceContext *sc = &s->slices[jobnr];
354 
355  if (s->group_size == 1 || s->th_mse <= 0.f) {
356  sc->match_blocks[0].score = 1;
357  sc->match_blocks[0].x = i;
358  sc->match_blocks[0].y = j;
359  sc->nb_match_blocks = 1;
360  return;
361  }
362 
363  sc->nb_match_blocks = 0;
364  block_matching_multi(s, ref, ref_linesize, j, i, 1, plane, jobnr);
365 }
366 
367 static void get_block_row(const uint8_t *srcp, int src_linesize,
368  int y, int x, int block_size, float *dst)
369 {
370  const uint8_t *src = srcp + y * src_linesize + x;
371 
372  for (int j = 0; j < block_size; j++)
373  dst[j] = src[j];
374 }
375 
376 static void get_block_row16(const uint8_t *srcp, int src_linesize,
377  int y, int x, int block_size, float *dst)
378 {
379  const uint16_t *src = (uint16_t *)srcp + y * src_linesize / 2 + x;
380 
381  for (int j = 0; j < block_size; j++)
382  dst[j] = src[j];
383 }
384 
385 static void basic_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
386  const uint8_t *ref, int ref_linesize,
387  int y, int x, int plane, int jobnr)
388 {
389  SliceContext *sc = &s->slices[jobnr];
390  const int pblock_size = s->pblock_size;
391  const int buffer_linesize = s->pblock_size * s->pblock_size;
392  const int nb_match_blocks = sc->nb_match_blocks;
393  const int block_size = s->block_size;
394  const int width = s->planewidth[plane];
395  const int pgroup_size = s->pgroup_size;
396  const int group_size = s->group_size;
397  float *buffer = sc->buffer;
398  float *bufferh = sc->bufferh;
399  float *buffert = sc->buffert;
400  float *bufferv = sc->bufferv;
401  float *bufferz = sc->bufferz;
402  float threshold[4];
403  float den_weight, num_weight;
404  int retained = 0;
405 
406  for (int k = 0; k < nb_match_blocks; k++) {
407  const int y = sc->match_blocks[k].y;
408  const int x = sc->match_blocks[k].x;
409 
410  for (int i = 0; i < block_size; i++) {
411  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + pblock_size * i);
412  sc->tx_fn(sc->dctf, buffert, bufferh + pblock_size * i, sizeof(float));
413  for (int j = 0; j < block_size; j++)
414  bufferv[j * pblock_size + i] = buffert[j];
415  }
416 
417  for (int i = 0; i < block_size; i++) {
418  sc->tx_fn(sc->dctf, buffert, bufferv + i * pblock_size, sizeof(float));
419  memcpy(buffer + k * buffer_linesize + i * pblock_size,
420  buffert, block_size * sizeof(float));
421  }
422  }
423 
424  for (int i = 0; i < block_size; i++) {
425  for (int j = 0; j < block_size; j++) {
426  for (int k = 0; k < nb_match_blocks; k++)
427  bufferz[k] = buffer[buffer_linesize * k + i * pblock_size + j];
428  if (group_size > 1)
429  sc->tx_fn_g(sc->gdctf, bufferz, bufferz, sizeof(float));
430  bufferz += pgroup_size;
431  }
432  }
433 
434  threshold[0] = s->hard_threshold * s->sigma * M_SQRT2 * 4.f * block_size * block_size * (1 << (s->depth - 8)) / 255.f;
435  threshold[1] = threshold[0] * sqrtf(2.f);
436  threshold[2] = threshold[0] * 2.f;
437  threshold[3] = threshold[0] * sqrtf(8.f);
438  bufferz = sc->bufferz;
439 
440  for (int i = 0; i < block_size; i++) {
441  for (int j = 0; j < block_size; j++) {
442  for (int k = 0; k < nb_match_blocks; k++) {
443  const float thresh = threshold[(j == 0) + (i == 0) + (k == 0)];
444 
445  if (bufferz[k] > thresh || bufferz[k] < -thresh) {
446  retained++;
447  } else {
448  bufferz[k] = 0;
449  }
450  }
451  bufferz += pgroup_size;
452  }
453  }
454 
455  bufferz = sc->bufferz;
456  buffer = sc->buffer;
457  for (int i = 0; i < block_size; i++) {
458  for (int j = 0; j < block_size; j++) {
459  if (group_size > 1)
460  sc->itx_fn_g(sc->gdcti, bufferz, bufferz, sizeof(float));
461  for (int k = 0; k < nb_match_blocks; k++)
462  buffer[buffer_linesize * k + i * pblock_size + j] = bufferz[k];
463  bufferz += pgroup_size;
464  }
465  }
466 
467  den_weight = retained < 1 ? 1.f : 1.f / retained;
468  num_weight = den_weight;
469 
470  buffer = sc->buffer;
471  for (int k = 0; k < nb_match_blocks; k++) {
472  float *num = sc->num + y * width + x;
473  float *den = sc->den + y * width + x;
474 
475  for (int i = 0; i < block_size; i++) {
476  memcpy(bufferv + i * pblock_size,
477  buffer + k * buffer_linesize + i * pblock_size,
478  block_size * sizeof(float));
479  }
480 
481  for (int i = 0; i < block_size; i++) {
482  sc->itx_fn(sc->dcti, buffert, bufferv + i * pblock_size, sizeof(float));
483  for (int j = 0; j < block_size; j++)
484  bufferh[j * pblock_size + i] = buffert[j];
485  }
486 
487  for (int i = 0; i < block_size; i++) {
488  sc->itx_fn(sc->dcti, buffert, bufferh + pblock_size * i, sizeof(float));
489  for (int j = 0; j < block_size; j++) {
490  num[j] += buffert[j] * num_weight;
491  den[j] += den_weight;
492  }
493  num += width;
494  den += width;
495  }
496  }
497 }
498 
499 static void final_block_filtering(BM3DContext *s, const uint8_t *src, int src_linesize,
500  const uint8_t *ref, int ref_linesize,
501  int y, int x, int plane, int jobnr)
502 {
503  SliceContext *sc = &s->slices[jobnr];
504  const int pblock_size = s->pblock_size;
505  const int buffer_linesize = s->pblock_size * s->pblock_size;
506  const int nb_match_blocks = sc->nb_match_blocks;
507  const int block_size = s->block_size;
508  const int width = s->planewidth[plane];
509  const int pgroup_size = s->pgroup_size;
510  const int group_size = s->group_size;
511  const float sigma_sqr = s->sigma * s->sigma;
512  float *buffer = sc->buffer;
513  float *bufferh = sc->bufferh;
514  float *bufferv = sc->bufferv;
515  float *bufferz = sc->bufferz;
516  float *rbuffer = sc->rbuffer;
517  float *rbufferh = sc->rbufferh;
518  float *rbufferv = sc->rbufferv;
519  float *rbufferz = sc->rbufferz;
520  float den_weight, num_weight;
521  float l2_wiener = 0;
522 
523  for (int k = 0; k < nb_match_blocks; k++) {
524  const int y = sc->match_blocks[k].y;
525  const int x = sc->match_blocks[k].x;
526 
527  for (int i = 0; i < block_size; i++) {
528  s->get_block_row(src, src_linesize, y + i, x, block_size, bufferh + pblock_size * i);
529  s->get_block_row(ref, ref_linesize, y + i, x, block_size, rbufferh + pblock_size * i);
530  sc->tx_fn(sc->dctf, bufferh + pblock_size * i, bufferh + pblock_size * i, sizeof(float));
531  sc->tx_fn(sc->dctf, rbufferh + pblock_size * i, rbufferh + pblock_size * i, sizeof(float));
532  }
533 
534  for (int i = 0; i < block_size; i++) {
535  for (int j = 0; j < block_size; j++) {
536  bufferv[i * pblock_size + j] = bufferh[j * pblock_size + i];
537  rbufferv[i * pblock_size + j] = rbufferh[j * pblock_size + i];
538  }
539  sc->tx_fn(sc->dctf, bufferv + i * pblock_size, bufferv + i * pblock_size, sizeof(float));
540  sc->tx_fn(sc->dctf, rbufferv + i * pblock_size, rbufferv + i * pblock_size, sizeof(float));
541  }
542 
543  for (int i = 0; i < block_size; i++) {
544  memcpy(buffer + k * buffer_linesize + i * pblock_size,
545  bufferv + i * pblock_size, block_size * sizeof(float));
546  memcpy(rbuffer + k * buffer_linesize + i * pblock_size,
547  rbufferv + i * pblock_size, block_size * sizeof(float));
548  }
549  }
550 
551  for (int i = 0; i < block_size; i++) {
552  for (int j = 0; j < block_size; j++) {
553  for (int k = 0; k < nb_match_blocks; k++) {
554  bufferz[k] = buffer[buffer_linesize * k + i * pblock_size + j];
555  rbufferz[k] = rbuffer[buffer_linesize * k + i * pblock_size + j];
556  }
557  if (group_size > 1) {
558  sc->tx_fn_g(sc->gdctf, bufferz, bufferz, sizeof(float));
559  sc->tx_fn_g(sc->gdctf, rbufferz, rbufferz, sizeof(float));
560  }
561  bufferz += pgroup_size;
562  rbufferz += pgroup_size;
563  }
564  }
565 
566  bufferz = sc->bufferz;
567  rbufferz = sc->rbufferz;
568 
569  for (int i = 0; i < block_size; i++) {
570  for (int j = 0; j < block_size; j++) {
571  for (int k = 0; k < nb_match_blocks; k++) {
572  const float ref_sqr = rbufferz[k] * rbufferz[k];
573  float wiener_coef = ref_sqr / (ref_sqr + sigma_sqr);
574 
575  if (isnan(wiener_coef))
576  wiener_coef = 1;
577  bufferz[k] *= wiener_coef;
578  l2_wiener += wiener_coef * wiener_coef;
579  }
580  bufferz += pgroup_size;
581  rbufferz += pgroup_size;
582  }
583  }
584 
585  bufferz = sc->bufferz;
586  buffer = sc->buffer;
587  for (int i = 0; i < block_size; i++) {
588  for (int j = 0; j < block_size; j++) {
589  if (group_size > 1)
590  sc->itx_fn_g(sc->gdcti, bufferz, bufferz, sizeof(float));
591  for (int k = 0; k < nb_match_blocks; k++) {
592  buffer[buffer_linesize * k + i * pblock_size + j] = bufferz[k];
593  }
594  bufferz += pgroup_size;
595  }
596  }
597 
598  l2_wiener = FFMAX(l2_wiener, 1e-15f);
599  den_weight = 1.f / l2_wiener;
600  num_weight = den_weight;
601 
602  for (int k = 0; k < nb_match_blocks; k++) {
603  float *num = sc->num + y * width + x;
604  float *den = sc->den + y * width + x;
605 
606  for (int i = 0; i < block_size; i++) {
607  memcpy(bufferv + i * pblock_size,
608  buffer + k * buffer_linesize + i * pblock_size,
609  block_size * sizeof(float));
610  }
611 
612  for (int i = 0; i < block_size; i++) {
613  sc->itx_fn(sc->dcti, bufferv + pblock_size * i, bufferv + pblock_size * i, sizeof(float));
614  for (int j = 0; j < block_size; j++) {
615  bufferh[j * pblock_size + i] = bufferv[i * pblock_size + j];
616  }
617  }
618 
619  for (int i = 0; i < block_size; i++) {
620  sc->itx_fn(sc->dcti, bufferh + pblock_size * i, bufferh + pblock_size * i, sizeof(float));
621  for (int j = 0; j < block_size; j++) {
622  num[j] += bufferh[i * pblock_size + j] * num_weight;
623  den[j] += den_weight;
624  }
625  num += width;
626  den += width;
627  }
628  }
629 }
630 
631 static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize,
632  int plane, int nb_jobs)
633 {
634  const int height = s->planeheight[plane];
635  const int width = s->planewidth[plane];
636 
637  for (int i = 0; i < height; i++) {
638  for (int j = 0; j < width; j++) {
639  uint8_t *dstp = dst + i * dst_linesize;
640  float sum_den = 0.f;
641  float sum_num = 0.f;
642 
643  for (int k = 0; k < nb_jobs; k++) {
644  SliceContext *sc = &s->slices[k];
645  float num = sc->num[i * width + j];
646  float den = sc->den[i * width + j];
647 
648  sum_num += num;
649  sum_den += den;
650  }
651 
652  dstp[j] = av_clip_uint8(lrintf(sum_num / sum_den));
653  }
654  }
655 }
656 
657 static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize,
658  int plane, int nb_jobs)
659 {
660  const int height = s->planeheight[plane];
661  const int width = s->planewidth[plane];
662  const int depth = s->depth;
663 
664  for (int i = 0; i < height; i++) {
665  for (int j = 0; j < width; j++) {
666  uint16_t *dstp = (uint16_t *)dst + i * dst_linesize / 2;
667  float sum_den = 0.f;
668  float sum_num = 0.f;
669 
670  for (int k = 0; k < nb_jobs; k++) {
671  SliceContext *sc = &s->slices[k];
672  float num = sc->num[i * width + j];
673  float den = sc->den[i * width + j];
674 
675  sum_num += num;
676  sum_den += den;
677  }
678 
679  dstp[j] = av_clip_uintp2_c(lrintf(sum_num / sum_den), depth);
680  }
681  }
682 }
683 
684 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
685 {
686  BM3DContext *s = ctx->priv;
687  SliceContext *sc = &s->slices[jobnr];
688  const int block_step = s->block_step;
689  ThreadData *td = arg;
690  const uint8_t *src = td->src;
691  const uint8_t *ref = td->ref;
692  const int src_linesize = td->src_linesize;
693  const int ref_linesize = td->ref_linesize;
694  const int plane = td->plane;
695  const int width = s->planewidth[plane];
696  const int height = s->planeheight[plane];
697  const int block_pos_bottom = FFMAX(0, height - s->block_size);
698  const int block_pos_right = FFMAX(0, width - s->block_size);
699  const int slice_start = (((height + block_step - 1) / block_step) * jobnr / nb_jobs) * block_step;
700  const int slice_end = (jobnr == nb_jobs - 1) ? block_pos_bottom + block_step :
701  (((height + block_step - 1) / block_step) * (jobnr + 1) / nb_jobs) * block_step;
702 
703  memset(sc->num, 0, width * height * sizeof(float));
704  memset(sc->den, 0, width * height * sizeof(float));
705 
706  for (int j = slice_start; j < slice_end; j += block_step) {
707  if (j > block_pos_bottom) {
708  j = block_pos_bottom;
709  }
710 
711  for (int i = 0; i < block_pos_right + block_step; i += block_step) {
712  if (i > block_pos_right) {
713  i = block_pos_right;
714  }
715 
716  block_matching(s, ref, ref_linesize, j, i, plane, jobnr);
717 
718  s->block_filtering(s, src, src_linesize,
719  ref, ref_linesize, j, i, plane, jobnr);
720  }
721  }
722 
723  return 0;
724 }
725 
727 {
728  BM3DContext *s = ctx->priv;
729  AVFilterLink *outlink = ctx->outputs[0];
730  int p;
731 
732  *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
733  if (!*out)
734  return AVERROR(ENOMEM);
735  av_frame_copy_props(*out, in);
736 
737  for (p = 0; p < s->nb_planes; p++) {
738  const int nb_jobs = FFMAX(1, FFMIN(s->nb_threads, s->planeheight[p] / s->block_size));
739  ThreadData td;
740 
741  if (!((1 << p) & s->planes) || ctx->is_disabled) {
742  av_image_copy_plane((*out)->data[p], (*out)->linesize[p],
743  in->data[p], in->linesize[p],
744  s->planewidth[p] * (1 + (s->depth > 8)), s->planeheight[p]);
745  continue;
746  }
747 
748  td.src = in->data[p];
749  td.src_linesize = in->linesize[p];
750  td.ref = ref->data[p];
751  td.ref_linesize = ref->linesize[p];
752  td.plane = p;
753  ff_filter_execute(ctx, filter_slice, &td, NULL, nb_jobs);
754 
755  s->do_output(s, (*out)->data[p], (*out)->linesize[p], p, nb_jobs);
756  }
757 
758  return 0;
759 }
760 
761 #define SQR(x) ((x) * (x))
762 
764 {
766  AVFilterContext *ctx = inlink->dst;
767  BM3DContext *s = ctx->priv;
768 
770  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
771  s->depth = desc->comp[0].depth;
772  s->max = (1 << s->depth) - 1;
773  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
774  s->planeheight[0] = s->planeheight[3] = inlink->h;
775  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
776  s->planewidth[0] = s->planewidth[3] = inlink->w;
777  s->pblock_size = FFALIGN(s->block_size * 2, av_cpu_max_align());
778  s->pgroup_size = FFALIGN(s->group_size * 2, av_cpu_max_align());
779 
780  for (int i = 0; i < s->nb_threads; i++) {
781  SliceContext *sc = &s->slices[i];
782  float iscale = 0.5f / s->block_size;
783  float scale = 1.f;
784  int ret;
785 
786  sc->num = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(float));
787  sc->den = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(float));
788  if (!sc->num || !sc->den)
789  return AVERROR(ENOMEM);
790 
791  ret = av_tx_init(&sc->dctf, &sc->tx_fn, AV_TX_FLOAT_DCT, 0, s->block_size >> 0, &scale, 0);
792  if (ret < 0)
793  return ret;
794 
795  ret = av_tx_init(&sc->dcti, &sc->itx_fn, AV_TX_FLOAT_DCT, 1, s->block_size >> 1, &iscale, 0);
796  if (ret < 0)
797  return ret;
798 
799  if (s->group_size > 1) {
800  float iscale = 0.5f / s->group_size;
801 
802  ret = av_tx_init(&sc->gdctf, &sc->tx_fn_g, AV_TX_FLOAT_DCT, 0, s->group_size >> 0, &scale, 0);
803  if (ret < 0)
804  return ret;
805 
806  ret = av_tx_init(&sc->gdcti, &sc->itx_fn_g, AV_TX_FLOAT_DCT, 1, s->group_size >> 1, &iscale, 0);
807  if (ret < 0)
808  return ret;
809  }
810 
811  sc->buffer = av_calloc(s->pblock_size * s->pblock_size * s->pgroup_size, sizeof(*sc->buffer));
812  sc->bufferz = av_calloc(s->pblock_size * s->pblock_size * s->pgroup_size, sizeof(*sc->bufferz));
813  sc->bufferh = av_calloc(s->pblock_size * s->pblock_size, sizeof(*sc->bufferh));
814  sc->bufferv = av_calloc(s->pblock_size * s->pblock_size, sizeof(*sc->bufferv));
815  sc->buffert = av_calloc(s->pblock_size, sizeof(*sc->buffert));
816  if (!sc->bufferh || !sc->bufferv || !sc->buffer || !sc->bufferz || !sc->buffert)
817  return AVERROR(ENOMEM);
818 
819  if (s->mode == FINAL) {
820  sc->rbuffer = av_calloc(s->pblock_size * s->pblock_size * s->pgroup_size, sizeof(*sc->rbuffer));
821  sc->rbufferz = av_calloc(s->pblock_size * s->pblock_size * s->pgroup_size, sizeof(*sc->rbufferz));
822  sc->rbufferh = av_calloc(s->pblock_size * s->pblock_size, sizeof(*sc->rbufferh));
823  sc->rbufferv = av_calloc(s->pblock_size * s->pblock_size, sizeof(*sc->rbufferv));
824  if (!sc->rbufferh || !sc->rbufferv || !sc->rbuffer || !sc->rbufferz)
825  return AVERROR(ENOMEM);
826  }
827 
828  sc->search_positions = av_calloc(SQR(2 * s->bm_range / s->bm_step + 1), sizeof(*sc->search_positions));
829  if (!sc->search_positions)
830  return AVERROR(ENOMEM);
831  }
832 
833  s->do_output = do_output;
834  s->do_block_ssd = do_block_ssd;
835  s->get_block_row = get_block_row;
836 
837  if (s->depth > 8) {
838  s->do_output = do_output16;
839  s->do_block_ssd = do_block_ssd16;
840  s->get_block_row = get_block_row16;
841  }
842 
843  return 0;
844 }
845 
847 {
848  BM3DContext *s = ctx->priv;
849 
850  if (!s->ref) {
851  AVFrame *frame = NULL;
852  AVFrame *out = NULL;
853  int ret, status;
854  int64_t pts;
855 
856  FF_FILTER_FORWARD_STATUS_BACK(ctx->outputs[0], ctx->inputs[0]);
857 
858  if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) {
861  if (ret < 0)
862  return ret;
863  ret = ff_filter_frame(ctx->outputs[0], out);
864  }
865  if (ret < 0) {
866  return ret;
867  } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
868  ff_outlink_set_status(ctx->outputs[0], status, pts);
869  return 0;
870  } else {
871  if (ff_outlink_frame_wanted(ctx->outputs[0]))
872  ff_inlink_request_frame(ctx->inputs[0]);
873  return 0;
874  }
875  } else {
876  return ff_framesync_activate(&s->fs);
877  }
878 }
879 
881 {
882  AVFilterContext *ctx = fs->parent;
883  BM3DContext *s = fs->opaque;
884  AVFilterLink *outlink = ctx->outputs[0];
885  AVFrame *out = NULL, *src, *ref;
886  int ret;
887 
888  if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 ||
889  (ret = ff_framesync_get_frame(&s->fs, 1, &ref, 0)) < 0)
890  return ret;
891 
892  if ((ret = filter_frame(ctx, &out, src, ref)) < 0)
893  return ret;
894 
895  out->pts = av_rescale_q(src->pts, s->fs.time_base, outlink->time_base);
896 
897  return ff_filter_frame(outlink, out);
898 }
899 
901 {
902  BM3DContext *s = ctx->priv;
903  AVFilterPad pad = { 0 };
904  int ret;
905 
906  if (s->mode == BASIC) {
907  if (s->th_mse == 0.f)
908  s->th_mse = 400.f + s->sigma * 80.f;
909  s->block_filtering = basic_block_filtering;
910  } else if (s->mode == FINAL) {
911  if (!s->ref) {
912  av_log(ctx, AV_LOG_WARNING, "Reference stream is mandatory in final estimation mode.\n");
913  s->ref = 1;
914  }
915  if (s->th_mse == 0.f)
916  s->th_mse = 200.f + s->sigma * 10.f;
917 
918  s->block_filtering = final_block_filtering;
919  } else {
920  return AVERROR_BUG;
921  }
922 
923  if (s->block_step > s->block_size) {
924  av_log(ctx, AV_LOG_WARNING, "bstep: %d can't be bigger than block size. Changing to %d.\n",
925  s->block_step, s->block_size);
926  s->block_step = s->block_size;
927  }
928 
929  if (s->bm_step > s->bm_range) {
930  av_log(ctx, AV_LOG_WARNING, "mstep: %d can't be bigger than block matching range. Changing to %d.\n",
931  s->bm_step, s->bm_range);
932  s->bm_step = s->bm_range;
933  }
934 
935  pad.type = AVMEDIA_TYPE_VIDEO;
936  pad.name = "source";
938 
939  if ((ret = ff_append_inpad(ctx, &pad)) < 0)
940  return ret;
941 
942  if (s->ref) {
943  pad.type = AVMEDIA_TYPE_VIDEO;
944  pad.name = "reference";
945  pad.config_props = NULL;
946 
947  if ((ret = ff_append_inpad(ctx, &pad)) < 0)
948  return ret;
949  }
950 
951  return 0;
952 }
953 
954 static int config_output(AVFilterLink *outlink)
955 {
956  AVFilterContext *ctx = outlink->src;
957  BM3DContext *s = ctx->priv;
958  AVFilterLink *src = ctx->inputs[0];
959  AVFilterLink *ref;
960  FFFrameSyncIn *in;
961  int ret;
962 
963  if (s->ref) {
964  ref = ctx->inputs[1];
965 
966  if (src->w != ref->w ||
967  src->h != ref->h) {
968  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
969  "(size %dx%d) do not match the corresponding "
970  "second input link %s parameters (%dx%d) ",
971  ctx->input_pads[0].name, src->w, src->h,
972  ctx->input_pads[1].name, ref->w, ref->h);
973  return AVERROR(EINVAL);
974  }
975  }
976 
977  outlink->w = src->w;
978  outlink->h = src->h;
979  outlink->time_base = src->time_base;
980  outlink->sample_aspect_ratio = src->sample_aspect_ratio;
981  outlink->frame_rate = src->frame_rate;
982 
983  if (!s->ref)
984  return 0;
985 
986  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
987  return ret;
988 
989  in = s->fs.in;
990  in[0].time_base = src->time_base;
991  in[1].time_base = ref->time_base;
992  in[0].sync = 1;
993  in[0].before = EXT_STOP;
994  in[0].after = EXT_STOP;
995  in[1].sync = 1;
996  in[1].before = EXT_STOP;
997  in[1].after = EXT_STOP;
998  s->fs.opaque = s;
999  s->fs.on_event = process_frame;
1000 
1001  return ff_framesync_configure(&s->fs);
1002 }
1003 
1005 {
1006  BM3DContext *s = ctx->priv;
1007 
1008  if (s->ref)
1009  ff_framesync_uninit(&s->fs);
1010 
1011  for (int i = 0; i < s->nb_threads; i++) {
1012  SliceContext *sc = &s->slices[i];
1013 
1014  av_freep(&sc->num);
1015  av_freep(&sc->den);
1016 
1017  av_tx_uninit(&sc->gdctf);
1018  av_tx_uninit(&sc->gdcti);
1019  av_tx_uninit(&sc->dctf);
1020  av_tx_uninit(&sc->dcti);
1021 
1022  av_freep(&sc->buffer);
1023  av_freep(&sc->bufferh);
1024  av_freep(&sc->buffert);
1025  av_freep(&sc->bufferv);
1026  av_freep(&sc->bufferz);
1027  av_freep(&sc->rbuffer);
1028  av_freep(&sc->rbufferh);
1029  av_freep(&sc->rbufferv);
1030  av_freep(&sc->rbufferz);
1031 
1032  av_freep(&sc->search_positions);
1033  }
1034 }
1035 
1036 static const AVFilterPad bm3d_outputs[] = {
1037  {
1038  .name = "default",
1039  .type = AVMEDIA_TYPE_VIDEO,
1040  .config_props = config_output,
1041  },
1042 };
1043 
1045  .name = "bm3d",
1046  .description = NULL_IF_CONFIG_SMALL("Block-Matching 3D denoiser."),
1047  .priv_size = sizeof(BM3DContext),
1048  .init = init,
1049  .uninit = uninit,
1050  .activate = activate,
1051  .inputs = NULL,
1054  .priv_class = &bm3d_class,
1058 };
SliceContext::num
float * num
Definition: vf_bm3d.c:85
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:101
AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:502
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:481
FFFrameSyncIn::time_base
AVRational time_base
Time base for the incoming frames.
Definition: framesync.h:117
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:134
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
BM3DContext::slices
SliceContext slices[MAX_NB_THREADS]
Definition: vf_bm3d.c:114
td
#define td
Definition: regdef.h:70
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
planes
static const struct @346 planes[]
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:304
out
FILE * out
Definition: movenc.c:54
FLAGS
#define FLAGS
Definition: vf_bm3d.c:133
SliceContext::bufferh
float * bufferh
Definition: vf_bm3d.c:76
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:969
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2888
ff_framesync_get_frame
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition: framesync.c:267
BM3DContext::pblock_size
int pblock_size
Definition: vf_bm3d.c:111
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: internal.h:174
AVTXContext
Definition: tx_priv.h:228
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:99
BM3DContext::do_block_ssd
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:121
BM3DContext::th_mse
float th_mse
Definition: vf_bm3d.c:100
AV_PIX_FMT_YUVA422P9
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:494
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
pixdesc.h
av_clip_uintp2_c
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:275
bm3d_options
static const AVOption bm3d_options[]
Definition: vf_bm3d.c:135
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:501
ThreadData::ref_linesize
int ref_linesize
Definition: vf_bm3d.c:58
AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:496
SliceContext::rbufferz
float * rbufferz
Definition: vf_bm3d.c:83
AVOption
AVOption.
Definition: opt.h:251
BASIC
@ BASIC
Definition: vf_bm3d.c:49
b
#define b
Definition: input.c:41
NB_MODES
@ NB_MODES
Definition: vf_bm3d.c:51
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:459
float.h
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:165
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
block_matching
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:350
BM3DContext::block_step
int block_step
Definition: vf_bm3d.c:96
video.h
AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:497
SliceContext::nb_match_blocks
int nb_match_blocks
Definition: vf_bm3d.c:87
FF_FILTER_FORWARD_STATUS_BACK
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
BM3DContext::planes
int planes
Definition: vf_bm3d.c:104
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:883
BM3DContext::mode
int mode
Definition: vf_bm3d.c:102
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:439
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:351
av_image_copy_plane
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:374
do_block_ssd
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:230
formats.h
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(bm3d)
ff_inlink_consume_frame
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:1364
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2928
AV_PIX_FMT_YUVA420P9
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:493
EXT_STOP
@ EXT_STOP
Completely stop all streams with this one.
Definition: framesync.h:65
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: vf_bm3d.c:167
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:477
ff_append_inpad
int ff_append_inpad(AVFilterContext *f, AVFilterPad *p)
Append a new input/output pad to the filter's list of such pads.
Definition: avfilter.c:126
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
BM3DContext::ref
int ref
Definition: vf_bm3d.c:103
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:475
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:503
FFFrameSyncIn
Input stream structure.
Definition: framesync.h:102
BM3DContext::hard_threshold
float hard_threshold
Definition: vf_bm3d.c:101
AV_PIX_FMT_YUV422P9
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:457
PosPairCode::x
int x
Definition: vf_bm3d.c:68
SliceContext::den
float * den
Definition: vf_bm3d.c:85
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
SliceContext::dctf
AVTXContext * dctf
Definition: vf_bm3d.c:74
pts
static int64_t pts
Definition: transcode_aac.c:653
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:443
FFFrameSyncIn::sync
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events.
Definition: framesync.h:160
AVFILTER_FLAG_DYNAMIC_INPUTS
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:106
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
FFDIFFSIGN
#define FFDIFFSIGN(x, y)
Comparator.
Definition: macros.h:45
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:462
AV_PIX_FMT_YUVJ411P
@ 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:276
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:471
SliceContext::match_blocks
PosPairCode match_blocks[256]
Definition: vf_bm3d.c:86
BM3DContext::fs
FFFrameSync fs
Definition: vf_bm3d.c:116
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:127
BM3DContext::do_output
void(* do_output)(struct BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:124
AV_PIX_FMT_YUVJ422P
@ 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_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:479
ThreadData::plane
int plane
Definition: vf_blend.c:58
ff_outlink_set_status
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
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1481
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:256
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:480
AV_PIX_FMT_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
search_boundary
static int search_boundary(int plane_boundary, int search_range, int search_step, int vertical, int y, int x)
Definition: vf_bm3d.c:218
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:472
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:50
BM3DContext::bm_range
int bm_range
Definition: vf_bm3d.c:98
PosCode::x
int x
Definition: vf_bm3d.c:63
SliceContext::buffer
float * buffer
Definition: vf_bm3d.c:80
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2006
PosCode
Definition: vf_bm3d.c:62
SliceContext::itx_fn_g
av_tx_fn itx_fn_g
Definition: vf_bm3d.c:73
filters.h
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:500
AV_PIX_FMT_YUV420P9
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:456
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:470
ctx
AVFormatContext * ctx
Definition: movenc.c:48
final_block_filtering
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:499
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:442
av_rescale_q
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
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
BM3DContext::max
int max
Definition: vf_bm3d.c:107
filter_slice
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_bm3d.c:684
AV_PIX_FMT_YUVJ444P
@ 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
arg
const char * arg
Definition: jacosubdec.c:67
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:440
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:478
SQR
#define SQR(x)
Definition: vf_bm3d.c:761
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
SliceContext::gdctf
AVTXContext * gdctf
Definition: vf_bm3d.c:72
NULL
#define NULL
Definition: coverity.c:32
process_frame
static int process_frame(FFFrameSync *fs)
Definition: vf_bm3d.c:880
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:594
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:258
ThreadData::src
const uint8_t * src
Definition: vf_bm3d.c:55
basic_block_filtering
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:385
isnan
#define isnan(x)
Definition: libm.h:340
AV_PIX_FMT_YUVJ420P
@ 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
SliceContext::buffert
float * buffert
Definition: vf_bm3d.c:77
do_output
static void do_output(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:631
AV_PIX_FMT_YUV440P10
#define AV_PIX_FMT_YUV440P10
Definition: pixfmt.h:461
sqrtf
static __device__ float sqrtf(float a)
Definition: cuda_runtime.h:184
double
double
Definition: af_crystalizer.c:132
av_cpu_max_align
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
Definition: cpu.c:265
MAX_NB_THREADS
#define MAX_NB_THREADS
Definition: vf_bm3d.c:46
SliceContext::rbuffer
float * rbuffer
Definition: vf_bm3d.c:84
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:460
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:474
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_bm3d.c:1004
BM3DContext::planewidth
int planewidth[4]
Definition: vf_bm3d.c:109
ff_inlink_acknowledge_status
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:1318
index
int index
Definition: gxfenc.c:89
SliceContext
Definition: mss12.h:70
FINAL
@ FINAL
Definition: vf_bm3d.c:50
AVFilterPad::config_props
int(* config_props)(AVFilterLink *link)
Link configuration callback.
Definition: internal.h:129
cmp_scores
static int cmp_scores(const void *a, const void *b)
Definition: vf_bm3d.c:223
f
f
Definition: af_crystalizer.c:122
OFFSET
#define OFFSET(x)
Definition: vf_bm3d.c:132
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:115
BM3DContext::pgroup_size
int pgroup_size
Definition: vf_bm3d.c:112
SliceContext::rbufferv
float * rbufferv
Definition: vf_bm3d.c:82
cpu.h
PosPairCode
Definition: vf_bm3d.c:66
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:464
SliceContext::rbufferh
float * rbufferh
Definition: vf_bm3d.c:81
bm3d_outputs
static const AVFilterPad bm3d_outputs[]
Definition: vf_bm3d.c:1036
SliceContext::bufferv
float * bufferv
Definition: vf_bm3d.c:78
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:466
SliceContext::dcti
AVTXContext * dcti
Definition: vf_bm3d.c:74
BM3DContext::bm_step
int bm_step
Definition: vf_bm3d.c:99
height
#define height
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:167
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:498
BM3DContext::group_size
int group_size
Definition: vf_bm3d.c:97
SliceContext::search_positions
PosCode * search_positions
Definition: vf_bm3d.c:88
BM3DContext::planeheight
int planeheight[4]
Definition: vf_bm3d.c:110
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition: tx.c:294
internal.h
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
SliceContext::tx_fn_g
av_tx_fn tx_fn_g
Definition: vf_bm3d.c:73
BM3DContext::get_block_row
void(* get_block_row)(const uint8_t *srcp, int src_linesize, int y, int x, int block_size, float *dst)
Definition: vf_bm3d.c:119
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:476
do_output16
static void do_output16(BM3DContext *s, uint8_t *dst, int dst_linesize, int plane, int nb_jobs)
Definition: vf_bm3d.c:657
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:777
ThreadData
Used for passing data between threads.
Definition: dsddec.c:69
do_search_boundary
static int do_search_boundary(int pos, int plane_boundary, int search_range, int search_step)
Definition: vf_bm3d.c:193
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_bm3d.c:763
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
PosPairCode::y
int y
Definition: vf_bm3d.c:68
block_matching_multi
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:310
AV_PIX_FMT_YUVJ440P
@ 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
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
AV_PIX_FMT_YUV444P9
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:458
filter_frame
static int filter_frame(AVFilterContext *ctx, AVFrame **out, AVFrame *in, AVFrame *ref)
Definition: vf_bm3d.c:726
do_block_matching_multi
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:272
AVFilter
Filter definition.
Definition: avfilter.h:161
ret
ret
Definition: filter_design.txt:187
AVFilterPad::type
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:60
SliceContext::bufferz
float * bufferz
Definition: vf_bm3d.c:79
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
ThreadData::ref
const uint8_t * ref
Definition: vf_bm3d.c:57
AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:495
ff_framesync_init
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:86
pos
unsigned int pos
Definition: spdifenc.c:413
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:463
AV_PIX_FMT_YUV422P14
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:468
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_bm3d.c:900
ThreadData::src_linesize
int src_linesize
Definition: vf_bm3d.c:56
FFFrameSyncIn::before
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition: framesync.h:107
BM3DContext::sigma
float sigma
Definition: vf_bm3d.c:94
framesync.h
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
get_block_row
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:367
SliceContext::tx_fn
av_tx_fn tx_fn
Definition: vf_bm3d.c:75
AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:499
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
BM3DContext::block_size
int block_size
Definition: vf_bm3d.c:95
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_bm3d.c:954
PosCode::y
int y
Definition: vf_bm3d.c:63
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
temp
else temp
Definition: vf_mcdeint.c:248
do_block_ssd16
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:251
PosPairCode::score
double score
Definition: vf_bm3d.c:67
av_clip_uint8
#define av_clip_uint8
Definition: common.h:101
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:392
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
desc
const char * desc
Definition: libsvtav1.c:83
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
BM3DContext::nb_planes
int nb_planes
Definition: vf_bm3d.c:108
M_SQRT2
#define M_SQRT2
Definition: mathematics.h:61
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:195
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
AV_TX_FLOAT_DCT
@ AV_TX_FLOAT_DCT
Real to real (DCT) transforms.
Definition: tx.h:104
BM3DContext::nb_threads
int nb_threads
Definition: vf_bm3d.c:117
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
SliceContext::itx_fn
av_tx_fn itx_fn
Definition: vf_bm3d.c:75
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#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:150
imgutils.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:375
AV_PIX_FMT_YUV410P
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFFrameSyncIn::after
enum FFFrameSyncExtMode after
Extrapolation mode for timestamps after the last frame.
Definition: framesync.h:112
SliceContext::gdcti
AVTXContext * gdcti
Definition: vf_bm3d.c:72
BM3DContext::depth
int depth
Definition: vf_bm3d.c:106
AV_PIX_FMT_YUV440P12
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:465
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:469
BM3DContext::block_filtering
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:126
get_block_row16
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:376
ff_framesync_activate
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:355
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:441
BM3DContext
Definition: vf_bm3d.c:91
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:146
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
ff_vf_bm3d
const AVFilter ff_vf_bm3d
Definition: vf_bm3d.c:1044
AV_PIX_FMT_YUVA422P
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:166
AV_PIX_FMT_YUV420P14
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:467
activate
static int activate(AVFilterContext *ctx)
Definition: vf_bm3d.c:846
FilterModes
FilterModes
Definition: vf_bm3d.c:48
tx.h