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