FFmpeg
vf_vif.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Ronald S. Bultje <rsbultje@gmail.com>
3  * Copyright (c) 2017 Ashish Pratap Singh <ashk43712@gmail.com>
4  * Copyright (c) 2021 Paul B Mahol
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /**
24  * @file
25  * Calculate VIF between two input videos.
26  */
27 
28 #include <float.h>
29 
30 #include "libavutil/mem.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/pixdesc.h"
33 #include "avfilter.h"
34 #include "filters.h"
35 #include "framesync.h"
36 
37 #define NUM_DATA_BUFS 13
38 
39 typedef struct VIFContext {
40  const AVClass *class;
43  int width;
44  int height;
46  float factor;
48  float **temp;
49  float *ref_data;
50  float *main_data;
51  double vif_sum[4];
52  double vif_min[4];
53  double vif_max[4];
54  uint64_t nb_frames;
55 } VIFContext;
56 
57 #define OFFSET(x) offsetof(VIFContext, x)
58 
59 static const AVOption vif_options[] = {
60  { NULL }
61 };
62 
64 
65 static const uint8_t vif_filter1d_width1[4] = { 17, 9, 5, 3 };
66 
67 static const float vif_filter1d_table[4][17] =
68 {
69  {
70  0.00745626912, 0.0142655009, 0.0250313189, 0.0402820669, 0.0594526194,
71  0.0804751068, 0.0999041125, 0.113746084, 0.118773937, 0.113746084,
72  0.0999041125, 0.0804751068, 0.0594526194, 0.0402820669, 0.0250313189,
73  0.0142655009, 0.00745626912
74  },
75  {
76  0.0189780835, 0.0558981746, 0.120920904, 0.192116052, 0.224173605,
77  0.192116052, 0.120920904, 0.0558981746, 0.0189780835
78  },
79  {
80  0.054488685, 0.244201347, 0.402619958, 0.244201347, 0.054488685
81  },
82  {
83  0.166378498, 0.667243004, 0.166378498
84  }
85 };
86 
87 typedef struct ThreadData {
88  const float *filter;
89  const float *src;
90  float *dst;
91  int w, h;
95  float **temp;
96 } ThreadData;
97 
98 static void vif_dec2(const float *src, float *dst, int w, int h,
99  int src_stride, int dst_stride)
100 {
101  const int dst_px_stride = dst_stride / 2;
102 
103  for (int i = 0; i < h / 2; i++) {
104  for (int j = 0; j < w / 2; j++)
105  dst[i * dst_px_stride + j] = src[(i * 2) * src_stride + (j * 2)];
106  }
107 }
108 
109 static void vif_statistic(const float *mu1_sq, const float *mu2_sq,
110  const float *mu1_mu2, const float *xx_filt,
111  const float *yy_filt, const float *xy_filt,
112  float *num, float *den, int w, int h)
113 {
114  static const float sigma_nsq = 2;
115  float mu1_sq_val, mu2_sq_val, mu1_mu2_val, xx_filt_val, yy_filt_val, xy_filt_val;
116  float sigma1_sq, sigma2_sq, sigma12, g, sv_sq, eps = 1.0e-10f;
117  float gain_limit = 100.f;
118  float num_val, den_val;
119  float accum_num = 0.0f;
120  float accum_den = 0.0f;
121 
122  for (int i = 0; i < h; i++) {
123  float accum_inner_num = 0.f;
124  float accum_inner_den = 0.f;
125 
126  for (int j = 0; j < w; j++) {
127  mu1_sq_val = mu1_sq[i * w + j];
128  mu2_sq_val = mu2_sq[i * w + j];
129  mu1_mu2_val = mu1_mu2[i * w + j];
130  xx_filt_val = xx_filt[i * w + j];
131  yy_filt_val = yy_filt[i * w + j];
132  xy_filt_val = xy_filt[i * w + j];
133 
134  sigma1_sq = xx_filt_val - mu1_sq_val;
135  sigma2_sq = yy_filt_val - mu2_sq_val;
136  sigma12 = xy_filt_val - mu1_mu2_val;
137 
138  sigma1_sq = FFMAX(sigma1_sq, 0.0f);
139  sigma2_sq = FFMAX(sigma2_sq, 0.0f);
140  sigma12 = FFMAX(sigma12, 0.0f);
141 
142  g = sigma12 / (sigma1_sq + eps);
143  sv_sq = sigma2_sq - g * sigma12;
144 
145  if (sigma1_sq < eps) {
146  g = 0.0f;
147  sv_sq = sigma2_sq;
148  sigma1_sq = 0.0f;
149  }
150 
151  if (sigma2_sq < eps) {
152  g = 0.0f;
153  sv_sq = 0.0f;
154  }
155 
156  if (g < 0.0f) {
157  sv_sq = sigma2_sq;
158  g = 0.0f;
159  }
160  sv_sq = FFMAX(sv_sq, eps);
161 
162  g = FFMIN(g, gain_limit);
163 
164  num_val = log2f(1.0f + g * g * sigma1_sq / (sv_sq + sigma_nsq));
165  den_val = log2f(1.0f + sigma1_sq / sigma_nsq);
166 
167  if (isnan(den_val))
168  num_val = den_val = 1.f;
169 
170  accum_inner_num += num_val;
171  accum_inner_den += den_val;
172  }
173 
174  accum_num += accum_inner_num;
175  accum_den += accum_inner_den;
176  }
177 
178  num[0] = accum_num;
179  den[0] = accum_den;
180 }
181 
182 static void vif_xx_yy_xy(const float *x, const float *y, float *xx, float *yy,
183  float *xy, int w, int h)
184 {
185  for (int i = 0; i < h; i++) {
186  for (int j = 0; j < w; j++) {
187  float xval = x[j];
188  float yval = y[j];
189  float xxval = xval * xval;
190  float yyval = yval * yval;
191  float xyval = xval * yval;
192 
193  xx[j] = xxval;
194  yy[j] = yyval;
195  xy[j] = xyval;
196  }
197 
198  xx += w;
199  yy += w;
200  xy += w;
201  x += w;
202  y += w;
203  }
204 }
205 
206 static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
207 {
208  ThreadData *td = arg;
209  const float *filter = td->filter;
210  const float *src = td->src;
211  float *dst = td->dst;
212  int w = td->w;
213  int h = td->h;
214  int src_stride = td->src_stride;
215  int dst_stride = td->dst_stride;
216  int filt_w = td->filter_width;
217  float *temp = td->temp[jobnr];
218  const int slice_start = (h * jobnr) / nb_jobs;
219  const int slice_end = (h * (jobnr+1)) / nb_jobs;
220 
221  for (int i = slice_start; i < slice_end; i++) {
222  /** Vertical pass. */
223  for (int j = 0; j < w; j++) {
224  float sum = 0.f;
225 
226  if (i >= filt_w / 2 && i < h - filt_w / 2 - 1) {
227  for (int filt_i = 0; filt_i < filt_w; filt_i++) {
228  const float filt_coeff = filter[filt_i];
229  float img_coeff;
230  int ii = i - filt_w / 2 + filt_i;
231 
232  img_coeff = src[ii * src_stride + j];
233  sum += filt_coeff * img_coeff;
234  }
235  } else {
236  for (int filt_i = 0; filt_i < filt_w; filt_i++) {
237  const float filt_coeff = filter[filt_i];
238  int ii = i - filt_w / 2 + filt_i;
239  float img_coeff;
240 
241  ii = ii < 0 ? -ii : (ii >= h ? 2 * h - ii - 1 : ii);
242 
243  img_coeff = src[ii * src_stride + j];
244  sum += filt_coeff * img_coeff;
245  }
246  }
247 
248  temp[j] = sum;
249  }
250 
251  /** Horizontal pass. */
252  for (int j = 0; j < w; j++) {
253  float sum = 0.f;
254 
255  if (j >= filt_w / 2 && j < w - filt_w / 2 - 1) {
256  for (int filt_j = 0; filt_j < filt_w; filt_j++) {
257  const float filt_coeff = filter[filt_j];
258  int jj = j - filt_w / 2 + filt_j;
259  float img_coeff;
260 
261  img_coeff = temp[jj];
262  sum += filt_coeff * img_coeff;
263  }
264  } else {
265  for (int filt_j = 0; filt_j < filt_w; filt_j++) {
266  const float filt_coeff = filter[filt_j];
267  int jj = j - filt_w / 2 + filt_j;
268  float img_coeff;
269 
270  jj = jj < 0 ? -jj : (jj >= w ? 2 * w - jj - 1 : jj);
271 
272  img_coeff = temp[jj];
273  sum += filt_coeff * img_coeff;
274  }
275  }
276 
277  dst[i * dst_stride + j] = sum;
278  }
279  }
280 
281  return 0;
282 }
283 
285  const float *ref, const float *main, int w, int h,
286  int ref_stride, int main_stride, float *score,
287  float *const data_buf[NUM_DATA_BUFS], float **temp,
288  int gnb_threads)
289 {
290  ThreadData td;
291  float *ref_scale = data_buf[0];
292  float *main_scale = data_buf[1];
293  float *ref_sq = data_buf[2];
294  float *main_sq = data_buf[3];
295  float *ref_main = data_buf[4];
296  float *mu1 = data_buf[5];
297  float *mu2 = data_buf[6];
298  float *mu1_sq = data_buf[7];
299  float *mu2_sq = data_buf[8];
300  float *mu1_mu2 = data_buf[9];
301  float *ref_sq_filt = data_buf[10];
302  float *main_sq_filt = data_buf[11];
303  float *ref_main_filt = data_buf[12];
304 
305  const float *curr_ref_scale = ref;
306  const float *curr_main_scale = main;
307  int curr_ref_stride = ref_stride;
308  int curr_main_stride = main_stride;
309 
310  float num = 0.f;
311  float den = 0.f;
312 
313  for (int scale = 0; scale < 4; scale++) {
314  const float *filter = vif_filter1d_table[scale];
315  int filter_width = vif_filter1d_width1[scale];
316  const int nb_threads = FFMIN(h, gnb_threads);
317  int buf_valid_w = w;
318  int buf_valid_h = h;
319 
320  td.filter = filter;
321  td.filter_width = filter_width;
322 
323  if (scale > 0) {
324  td.src = curr_ref_scale;
325  td.dst = mu1;
326  td.w = w;
327  td.h = h;
328  td.src_stride = curr_ref_stride;
329  td.dst_stride = w;
330  td.temp = temp;
331  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
332 
333  td.src = curr_main_scale;
334  td.dst = mu2;
335  td.src_stride = curr_main_stride;
336  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
337 
338  vif_dec2(mu1, ref_scale, buf_valid_w, buf_valid_h, w, w);
339  vif_dec2(mu2, main_scale, buf_valid_w, buf_valid_h, w, w);
340 
341  w = buf_valid_w / 2;
342  h = buf_valid_h / 2;
343 
344  buf_valid_w = w;
345  buf_valid_h = h;
346 
347  curr_ref_scale = ref_scale;
348  curr_main_scale = main_scale;
349 
350  curr_ref_stride = w;
351  curr_main_stride = w;
352  }
353 
354  td.src = curr_ref_scale;
355  td.dst = mu1;
356  td.w = w;
357  td.h = h;
358  td.src_stride = curr_ref_stride;
359  td.dst_stride = w;
360  td.temp = temp;
361  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
362 
363  td.src = curr_main_scale;
364  td.dst = mu2;
365  td.src_stride = curr_main_stride;
366  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
367 
368  vif_xx_yy_xy(mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, w, h);
369 
370  vif_xx_yy_xy(curr_ref_scale, curr_main_scale, ref_sq, main_sq, ref_main, w, h);
371 
372  td.src = ref_sq;
373  td.dst = ref_sq_filt;
374  td.src_stride = w;
375  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
376 
377  td.src = main_sq;
378  td.dst = main_sq_filt;
379  td.src_stride = w;
380  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
381 
382  td.src = ref_main;
383  td.dst = ref_main_filt;
384  ff_filter_execute(ctx, vif_filter1d, &td, NULL, nb_threads);
385 
386  vif_statistic(mu1_sq, mu2_sq, mu1_mu2, ref_sq_filt, main_sq_filt,
387  ref_main_filt, &num, &den, w, h);
388 
389  score[scale] = den <= FLT_EPSILON ? 1.f : num / den;
390  }
391 
392  return 0;
393 }
394 
395 #define offset_fn(type, bits) \
396 static void offset_##bits##bit(VIFContext *s, \
397  const AVFrame *ref, \
398  AVFrame *main, int stride)\
399 { \
400  int w = s->width; \
401  int h = s->height; \
402  \
403  int ref_stride = ref->linesize[0]; \
404  int main_stride = main->linesize[0]; \
405  \
406  const type *ref_ptr = (const type *) ref->data[0]; \
407  const type *main_ptr = (const type *) main->data[0]; \
408  \
409  const float factor = s->factor; \
410  \
411  float *ref_ptr_data = s->ref_data; \
412  float *main_ptr_data = s->main_data; \
413  \
414  for (int i = 0; i < h; i++) { \
415  for (int j = 0; j < w; j++) { \
416  ref_ptr_data[j] = ref_ptr[j] * factor - 128.f; \
417  main_ptr_data[j] = main_ptr[j] * factor - 128.f; \
418  } \
419  ref_ptr += ref_stride / sizeof(type); \
420  ref_ptr_data += w; \
421  main_ptr += main_stride / sizeof(type); \
422  main_ptr_data += w; \
423  } \
424 }
425 
426 offset_fn(uint8_t, 8)
427 offset_fn(uint16_t, 16)
428 
429 static void set_meta(AVDictionary **metadata, const char *key, float d)
430 {
431  char value[257];
432  snprintf(value, sizeof(value), "%f", d);
433  av_dict_set(metadata, key, value, 0);
434 }
435 
437 {
438  VIFContext *s = ctx->priv;
439  AVDictionary **metadata = &main->metadata;
440  float score[4];
441 
442  s->factor = 1.f / (1 << (s->desc->comp[0].depth - 8));
443  if (s->desc->comp[0].depth <= 8) {
444  offset_8bit(s, ref, main, s->width);
445  } else {
446  offset_16bit(s, ref, main, s->width);
447  }
448 
449  compute_vif2(ctx, s->ref_data, s->main_data,
450  s->width, s->height, s->width, s->width,
451  score, s->data_buf, s->temp, s->nb_threads);
452 
453  set_meta(metadata, "lavfi.vif.scale.0", score[0]);
454  set_meta(metadata, "lavfi.vif.scale.1", score[1]);
455  set_meta(metadata, "lavfi.vif.scale.2", score[2]);
456  set_meta(metadata, "lavfi.vif.scale.3", score[3]);
457 
458  for (int i = 0; i < 4; i++) {
459  s->vif_min[i] = FFMIN(s->vif_min[i], score[i]);
460  s->vif_max[i] = FFMAX(s->vif_max[i], score[i]);
461  s->vif_sum[i] += score[i];
462  }
463 
464  s->nb_frames++;
465 
466  return main;
467 }
468 
469 static const enum AVPixelFormat pix_fmts[] = {
476 #define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf
477  PF(P9), PF(P10), PF(P12), PF(P14), PF(P16),
479 };
480 
482 {
483  AVFilterContext *ctx = inlink->dst;
484  VIFContext *s = ctx->priv;
485 
486  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
487  ctx->inputs[0]->h != ctx->inputs[1]->h) {
488  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
489  return AVERROR(EINVAL);
490  }
491 
492  s->desc = av_pix_fmt_desc_get(inlink->format);
493  s->width = ctx->inputs[0]->w;
494  s->height = ctx->inputs[0]->h;
495  s->nb_threads = ff_filter_get_nb_threads(ctx);
496 
497  for (int i = 0; i < 4; i++) {
498  s->vif_min[i] = DBL_MAX;
499  s->vif_max[i] = -DBL_MAX;
500  }
501 
502  for (int i = 0; i < NUM_DATA_BUFS; i++) {
503  if (!(s->data_buf[i] = av_calloc(s->width, s->height * sizeof(float))))
504  return AVERROR(ENOMEM);
505  }
506 
507  if (!(s->ref_data = av_calloc(s->width, s->height * sizeof(float))))
508  return AVERROR(ENOMEM);
509 
510  if (!(s->main_data = av_calloc(s->width, s->height * sizeof(float))))
511  return AVERROR(ENOMEM);
512 
513  if (!(s->temp = av_calloc(s->nb_threads, sizeof(s->temp[0]))))
514  return AVERROR(ENOMEM);
515 
516  for (int i = 0; i < s->nb_threads; i++) {
517  if (!(s->temp[i] = av_calloc(s->width, sizeof(float))))
518  return AVERROR(ENOMEM);
519  }
520 
521  return 0;
522 }
523 
525 {
526  AVFilterContext *ctx = fs->parent;
527  VIFContext *s = fs->opaque;
528  AVFilterLink *outlink = ctx->outputs[0];
529  AVFrame *out_frame, *main_frame = NULL, *ref_frame = NULL;
530  int ret;
531 
532  ret = ff_framesync_dualinput_get(fs, &main_frame, &ref_frame);
533  if (ret < 0)
534  return ret;
535 
536  if (ctx->is_disabled || !ref_frame) {
537  out_frame = main_frame;
538  } else {
539  out_frame = do_vif(ctx, main_frame, ref_frame);
540  }
541 
542  out_frame->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base);
543 
544  return ff_filter_frame(outlink, out_frame);
545 }
546 
547 
548 static int config_output(AVFilterLink *outlink)
549 {
550  AVFilterContext *ctx = outlink->src;
551  VIFContext *s = ctx->priv;
552  AVFilterLink *mainlink = ctx->inputs[0];
553  FilterLink *il = ff_filter_link(mainlink);
554  FilterLink *ol = ff_filter_link(outlink);
555  FFFrameSyncIn *in;
556  int ret;
557 
558  outlink->w = mainlink->w;
559  outlink->h = mainlink->h;
560  outlink->time_base = mainlink->time_base;
561  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
562  ol->frame_rate = il->frame_rate;
563  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
564  return ret;
565 
566  in = s->fs.in;
567  in[0].time_base = mainlink->time_base;
568  in[1].time_base = ctx->inputs[1]->time_base;
569  in[0].sync = 2;
570  in[0].before = EXT_STOP;
571  in[0].after = EXT_STOP;
572  in[1].sync = 1;
573  in[1].before = EXT_STOP;
574  in[1].after = EXT_STOP;
575  s->fs.opaque = s;
576  s->fs.on_event = process_frame;
577 
578  return ff_framesync_configure(&s->fs);
579 }
580 
582 {
583  VIFContext *s = ctx->priv;
584  return ff_framesync_activate(&s->fs);
585 }
586 
588 {
589  VIFContext *s = ctx->priv;
590 
591  if (s->nb_frames > 0) {
592  for (int i = 0; i < 4; i++)
593  av_log(ctx, AV_LOG_INFO, "VIF scale=%d average:%f min:%f: max:%f\n",
594  i, s->vif_sum[i] / s->nb_frames, s->vif_min[i], s->vif_max[i]);
595  }
596 
597  for (int i = 0; i < NUM_DATA_BUFS; i++)
598  av_freep(&s->data_buf[i]);
599 
600  av_freep(&s->ref_data);
601  av_freep(&s->main_data);
602 
603  for (int i = 0; i < s->nb_threads && s->temp; i++)
604  av_freep(&s->temp[i]);
605 
606  av_freep(&s->temp);
607 
608  ff_framesync_uninit(&s->fs);
609 }
610 
611 static const AVFilterPad vif_inputs[] = {
612  {
613  .name = "main",
614  .type = AVMEDIA_TYPE_VIDEO,
615  },{
616  .name = "reference",
617  .type = AVMEDIA_TYPE_VIDEO,
618  .config_props = config_input_ref,
619  },
620 };
621 
622 static const AVFilterPad vif_outputs[] = {
623  {
624  .name = "default",
625  .type = AVMEDIA_TYPE_VIDEO,
626  .config_props = config_output,
627  },
628 };
629 
631  .name = "vif",
632  .description = NULL_IF_CONFIG_SMALL("Calculate the VIF between two video streams."),
633  .preinit = vif_framesync_preinit,
634  .uninit = uninit,
635  .priv_size = sizeof(VIFContext),
636  .priv_class = &vif_class,
637  .activate = activate,
644 };
VIFContext::vif_sum
double vif_sum[4]
Definition: vf_vif.c:51
ThreadData::temp
int ** temp
Definition: vf_ssim.c:229
ThreadData::src_stride
int src_stride
Definition: vf_vif.c:92
vif_outputs
static const AVFilterPad vif_outputs[]
Definition: vf_vif.c:622
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:137
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
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
ThreadData::filter_width
int filter_width
Definition: vf_vif.c:94
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: filters.h:242
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:301
VIFContext::vif_max
double vif_max[4]
Definition: vf_vif.c:53
VIFContext::fs
FFFrameSync fs
Definition: vf_vif.c:41
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1062
log2f
#define log2f(x)
Definition: libm.h:409
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3170
ThreadData::dst_stride
int dst_stride
Definition: vf_vif.c:93
process_frame
static int process_frame(FFFrameSync *fs)
Definition: vf_vif.c:524
VIFContext::nb_threads
int nb_threads
Definition: vf_vif.c:45
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
offset_fn
#define offset_fn(type, bits)
Definition: vf_vif.c:395
vif_xx_yy_xy
static void vif_xx_yy_xy(const float *x, const float *y, float *xx, float *yy, float *xy, int w, int h)
Definition: vf_vif.c:182
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:501
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_vif.c:587
w
uint8_t w
Definition: llviddspenc.c:38
AVOption
AVOption.
Definition: opt.h:429
VIFContext::height
int height
Definition: vf_vif.c:44
vif_filter1d_table
static const float vif_filter1d_table[4][17]
Definition: vf_vif.c:67
float.h
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
ThreadData::w
int w
Definition: vf_blend.c:61
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:106
AVDictionary
Definition: dict.c:34
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
vif_filter1d
static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_vif.c:206
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: vf_vif.c:469
vif_filter1d_width1
static const uint8_t vif_filter1d_width1[4]
Definition: vf_vif.c:65
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:482
VIFContext::desc
const AVPixFmtDescriptor * desc
Definition: vf_vif.c:42
EXT_STOP
@ EXT_STOP
Completely stop all streams with this one.
Definition: framesync.h:65
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
Definition: mpeg12dec.c:1719
FFFrameSyncIn
Input stream structure.
Definition: framesync.h:102
VIFContext::main_data
float * main_data
Definition: vf_vif.c:50
vif_dec2
static void vif_dec2(const float *src, float *dst, int w, int h, int src_stride, int dst_stride)
Definition: vf_vif.c:98
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:486
FFFrameSyncIn::sync
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events.
Definition: framesync.h:160
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
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:283
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
ff_vf_vif
const AVFilter ff_vf_vif
Definition: vf_vif.c:630
main
int main
Definition: dovi_rpuenc.c:37
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:86
s
#define s(width, name)
Definition: cbs_vp9.c:198
g
const char * g
Definition: vf_curves.c:128
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:485
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
do_vif
static AVFrame * do_vif(AVFilterContext *ctx, AVFrame *main, const AVFrame *ref)
Definition: vf_vif.c:436
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:73
key
const char * key
Definition: hwcontext_opencl.c:189
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
ThreadData::h
int h
Definition: vf_blend.c:61
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:87
arg
const char * arg
Definition: jacosubdec.c:67
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:483
ThreadData::dst
AVFrame * dst
Definition: vf_blend.c:58
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:200
ThreadData::src
const uint8_t * src
Definition: vf_bm3d.c:54
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:85
VIFContext::vif_min
double vif_min[4]
Definition: vf_vif.c:52
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:197
f
f
Definition: af_crystalizer.c:122
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:94
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
ThreadData::src
const float * src
Definition: vf_vif.c:89
ref_frame
static int ref_frame(VVCFrame *dst, const VVCFrame *src)
Definition: dec.c:595
ThreadData::temp
float ** temp
Definition: vf_vif.c:95
VIFContext::factor
float factor
Definition: vf_vif.c:46
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
compute_vif2
static int compute_vif2(AVFilterContext *ctx, const float *ref, const float *main, int w, int h, int ref_stride, int main_stride, float *score, float *const data_buf[NUM_DATA_BUFS], float **temp, int gnb_threads)
Definition: vf_vif.c:284
VIFContext::width
int width
Definition: vf_vif.c:43
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:841
ThreadData
Used for passing data between threads.
Definition: dsddec.c:71
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
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:107
NUM_DATA_BUFS
#define NUM_DATA_BUFS
Definition: vf_vif.c:37
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_vif.c:548
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
vif_statistic
static void vif_statistic(const float *mu1_sq, const float *mu2_sq, const float *mu1_mu2, const float *xx_filt, const float *yy_filt, const float *xy_filt, float *num, float *den, int w, int h)
Definition: vf_vif.c:109
slice_start
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
Definition: dec.c:738
AVFilter
Filter definition.
Definition: avfilter.h:201
ret
ret
Definition: filter_design.txt:187
VIFContext::nb_frames
uint64_t nb_frames
Definition: vf_vif.c:54
ff_framesync_init
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:86
VIFContext::ref_data
float * ref_data
Definition: vf_vif.c:49
set_meta
static void set_meta(AVDictionary **metadata, int chan, const char *key, const char *fmt, float val)
Definition: af_aspectralstats.c:183
FFFrameSyncIn::before
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition: framesync.h:107
VIFContext::temp
float ** temp
Definition: vf_vif.c:48
PF
#define PF(suf)
framesync.h
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1667
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
avfilter.h
vif_inputs
static const AVFilterPad vif_inputs[]
Definition: vf_vif.c:611
AVFILTER_FLAG_METADATA_ONLY
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition: avfilter.h:168
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
temp
else temp
Definition: vf_mcdeint.c:263
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:78
VIFContext::data_buf
float * data_buf[NUM_DATA_BUFS]
Definition: vf_vif.c:47
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
activate
static int activate(AVFilterContext *ctx)
Definition: vf_vif.c:581
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:152
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:77
mem.h
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:88
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:80
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:190
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:79
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
h
h
Definition: vp9dsp_template.c:2070
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:352
ff_framesync_dualinput_get
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:390
vif_options
static const AVOption vif_options[]
Definition: vf_vif.c:59
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:484
ThreadData::filter
const float * filter
Definition: vf_vif.c:88
snprintf
#define snprintf
Definition: snprintf.h:34
src
#define src
Definition: vp8dsp.c:248
VIFContext
Definition: vf_vif.c:39
FRAMESYNC_DEFINE_CLASS
FRAMESYNC_DEFINE_CLASS(vif, VIFContext, fs)
config_input_ref
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_vif.c:481