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/avstring.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/pixdesc.h"
33 #include "avfilter.h"
34 #include "framesync.h"
35 #include "drawutils.h"
36 #include "formats.h"
37 #include "internal.h"
38 #include "vif.h"
39 #include "video.h"
40 
41 typedef struct VIFContext {
42  const AVClass *class;
45  int width;
46  int height;
48  float factor;
49  float *data_buf[13];
50  float **temp;
51  float *ref_data;
52  float *main_data;
53  double vif_sum[4];
54  double vif_min[4];
55  double vif_max[4];
56  uint64_t nb_frames;
57 } VIFContext;
58 
59 #define OFFSET(x) offsetof(VIFContext, x)
60 
61 static const AVOption vif_options[] = {
62  { NULL }
63 };
64 
66 
67 static const uint8_t vif_filter1d_width1[4] = { 17, 9, 5, 3 };
68 
69 static const float vif_filter1d_table[4][17] =
70 {
71  {
72  0.00745626912, 0.0142655009, 0.0250313189, 0.0402820669, 0.0594526194,
73  0.0804751068, 0.0999041125, 0.113746084, 0.118773937, 0.113746084,
74  0.0999041125, 0.0804751068, 0.0594526194, 0.0402820669, 0.0250313189,
75  0.0142655009, 0.00745626912
76  },
77  {
78  0.0189780835, 0.0558981746, 0.120920904, 0.192116052, 0.224173605,
79  0.192116052, 0.120920904, 0.0558981746, 0.0189780835
80  },
81  {
82  0.054488685, 0.244201347, 0.402619958, 0.244201347, 0.054488685
83  },
84  {
85  0.166378498, 0.667243004, 0.166378498
86  }
87 };
88 
89 typedef struct ThreadData {
90  const float *filter;
91  const float *src;
92  float *dst;
93  int w, h;
97  float **temp;
98 } ThreadData;
99 
100 static void vif_dec2(const float *src, float *dst, int w, int h,
101  int src_stride, int dst_stride)
102 {
103  const int dst_px_stride = dst_stride / 2;
104 
105  for (int i = 0; i < h / 2; i++) {
106  for (int j = 0; j < w / 2; j++)
107  dst[i * dst_px_stride + j] = src[(i * 2) * src_stride + (j * 2)];
108  }
109 }
110 
111 static void vif_statistic(const float *mu1_sq, const float *mu2_sq,
112  const float *mu1_mu2, const float *xx_filt,
113  const float *yy_filt, const float *xy_filt,
114  float *num, float *den, int w, int h)
115 {
116  static const float sigma_nsq = 2;
117  float mu1_sq_val, mu2_sq_val, mu1_mu2_val, xx_filt_val, yy_filt_val, xy_filt_val;
118  float sigma1_sq, sigma2_sq, sigma12, g, sv_sq, eps = 1.0e-10f;
119  float gain_limit = 100.f;
120  float num_val, den_val;
121  float accum_num = 0.0f;
122  float accum_den = 0.0f;
123 
124  for (int i = 0; i < h; i++) {
125  float accum_inner_num = 0.f;
126  float accum_inner_den = 0.f;
127 
128  for (int j = 0; j < w; j++) {
129  mu1_sq_val = mu1_sq[i * w + j];
130  mu2_sq_val = mu2_sq[i * w + j];
131  mu1_mu2_val = mu1_mu2[i * w + j];
132  xx_filt_val = xx_filt[i * w + j];
133  yy_filt_val = yy_filt[i * w + j];
134  xy_filt_val = xy_filt[i * w + j];
135 
136  sigma1_sq = xx_filt_val - mu1_sq_val;
137  sigma2_sq = yy_filt_val - mu2_sq_val;
138  sigma12 = xy_filt_val - mu1_mu2_val;
139 
140  sigma1_sq = FFMAX(sigma1_sq, 0.0f);
141  sigma2_sq = FFMAX(sigma2_sq, 0.0f);
142  sigma12 = FFMAX(sigma12, 0.0f);
143 
144  g = sigma12 / (sigma1_sq + eps);
145  sv_sq = sigma2_sq - g * sigma12;
146 
147  if (sigma1_sq < eps) {
148  g = 0.0f;
149  sv_sq = sigma2_sq;
150  sigma1_sq = 0.0f;
151  }
152 
153  if (sigma2_sq < eps) {
154  g = 0.0f;
155  sv_sq = 0.0f;
156  }
157 
158  if (g < 0.0f) {
159  sv_sq = sigma2_sq;
160  g = 0.0f;
161  }
162  sv_sq = FFMAX(sv_sq, eps);
163 
164  g = FFMIN(g, gain_limit);
165 
166  num_val = log2f(1.0f + g * g * sigma1_sq / (sv_sq + sigma_nsq));
167  den_val = log2f(1.0f + sigma1_sq / sigma_nsq);
168 
169  if (isnan(den_val))
170  num_val = den_val = 1.f;
171 
172  accum_inner_num += num_val;
173  accum_inner_den += den_val;
174  }
175 
176  accum_num += accum_inner_num;
177  accum_den += accum_inner_den;
178  }
179 
180  num[0] = accum_num;
181  den[0] = accum_den;
182 }
183 
184 static void vif_xx_yy_xy(const float *x, const float *y, float *xx, float *yy,
185  float *xy, int w, int h)
186 {
187  for (int i = 0; i < h; i++) {
188  for (int j = 0; j < w; j++) {
189  float xval = x[j];
190  float yval = y[j];
191  float xxval = xval * xval;
192  float yyval = yval * yval;
193  float xyval = xval * yval;
194 
195  xx[j] = xxval;
196  yy[j] = yyval;
197  xy[j] = xyval;
198  }
199 
200  xx += w;
201  yy += w;
202  xy += w;
203  x += w;
204  y += w;
205  }
206 }
207 
208 static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
209 {
210  ThreadData *td = arg;
211  const float *filter = td->filter;
212  const float *src = td->src;
213  float *dst = td->dst;
214  int w = td->w;
215  int h = td->h;
216  int src_stride = td->src_stride;
217  int dst_stride = td->dst_stride;
218  int filt_w = td->filter_width;
219  float *temp = td->temp[jobnr];
220  const int slice_start = (h * jobnr) / nb_jobs;
221  const int slice_end = (h * (jobnr+1)) / nb_jobs;
222 
223  for (int i = slice_start; i < slice_end; i++) {
224  /** Vertical pass. */
225  for (int j = 0; j < w; j++) {
226  float sum = 0.f;
227 
228  if (i >= filt_w / 2 && i < h - filt_w / 2 - 1) {
229  for (int filt_i = 0; filt_i < filt_w; filt_i++) {
230  const float filt_coeff = filter[filt_i];
231  float img_coeff;
232  int ii = i - filt_w / 2 + filt_i;
233 
234  img_coeff = src[ii * src_stride + j];
235  sum += filt_coeff * img_coeff;
236  }
237  } else {
238  for (int filt_i = 0; filt_i < filt_w; filt_i++) {
239  const float filt_coeff = filter[filt_i];
240  int ii = i - filt_w / 2 + filt_i;
241  float img_coeff;
242 
243  ii = ii < 0 ? -ii : (ii >= h ? 2 * h - ii - 1 : ii);
244 
245  img_coeff = src[ii * src_stride + j];
246  sum += filt_coeff * img_coeff;
247  }
248  }
249 
250  temp[j] = sum;
251  }
252 
253  /** Horizontal pass. */
254  for (int j = 0; j < w; j++) {
255  float sum = 0.f;
256 
257  if (j >= filt_w / 2 && j < w - filt_w / 2 - 1) {
258  for (int filt_j = 0; filt_j < filt_w; filt_j++) {
259  const float filt_coeff = filter[filt_j];
260  int jj = j - filt_w / 2 + filt_j;
261  float img_coeff;
262 
263  img_coeff = temp[jj];
264  sum += filt_coeff * img_coeff;
265  }
266  } else {
267  for (int filt_j = 0; filt_j < filt_w; filt_j++) {
268  const float filt_coeff = filter[filt_j];
269  int jj = j - filt_w / 2 + filt_j;
270  float img_coeff;
271 
272  jj = jj < 0 ? -jj : (jj >= w ? 2 * w - jj - 1 : jj);
273 
274  img_coeff = temp[jj];
275  sum += filt_coeff * img_coeff;
276  }
277  }
278 
279  dst[i * dst_stride + j] = sum;
280  }
281  }
282 
283  return 0;
284 }
285 
287  const float *ref, const float *main, int w, int h,
288  int ref_stride, int main_stride, float *score,
289  float *data_buf[14], float **temp,
290  int gnb_threads)
291 {
292  ThreadData td;
293  float *ref_scale = data_buf[0];
294  float *main_scale = data_buf[1];
295  float *ref_sq = data_buf[2];
296  float *main_sq = data_buf[3];
297  float *ref_main = data_buf[4];
298  float *mu1 = data_buf[5];
299  float *mu2 = data_buf[6];
300  float *mu1_sq = data_buf[7];
301  float *mu2_sq = data_buf[8];
302  float *mu1_mu2 = data_buf[9];
303  float *ref_sq_filt = data_buf[10];
304  float *main_sq_filt = data_buf[11];
305  float *ref_main_filt = data_buf[12];
306 
307  float *curr_ref_scale = (float *)ref;
308  float *curr_main_scale = (float *)main;
309  int curr_ref_stride = ref_stride;
310  int curr_main_stride = main_stride;
311 
312  float num = 0.f;
313  float den = 0.f;
314 
315  for (int scale = 0; scale < 4; scale++) {
316  const float *filter = vif_filter1d_table[scale];
317  int filter_width = vif_filter1d_width1[scale];
318  const int nb_threads = FFMIN(h, gnb_threads);
319  int buf_valid_w = w;
320  int buf_valid_h = h;
321 
322  td.filter = filter;
323  td.filter_width = filter_width;
324 
325  if (scale > 0) {
326  td.src = curr_ref_scale;
327  td.dst = mu1;
328  td.w = w;
329  td.h = h;
330  td.src_stride = curr_ref_stride;
331  td.dst_stride = w;
332  td.temp = temp;
333  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
334 
335  td.src = curr_main_scale;
336  td.dst = mu2;
337  td.src_stride = curr_main_stride;
338  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
339 
340  vif_dec2(mu1, ref_scale, buf_valid_w, buf_valid_h, w, w);
341  vif_dec2(mu2, main_scale, buf_valid_w, buf_valid_h, w, w);
342 
343  w = buf_valid_w / 2;
344  h = buf_valid_h / 2;
345 
346  buf_valid_w = w;
347  buf_valid_h = h;
348 
349  curr_ref_scale = ref_scale;
350  curr_main_scale = main_scale;
351 
352  curr_ref_stride = w;
353  curr_main_stride = w;
354  }
355 
356  td.src = curr_ref_scale;
357  td.dst = mu1;
358  td.w = w;
359  td.h = h;
360  td.src_stride = curr_ref_stride;
361  td.dst_stride = w;
362  td.temp = temp;
363  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
364 
365  td.src = curr_main_scale;
366  td.dst = mu2;
367  td.src_stride = curr_main_stride;
368  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
369 
370  vif_xx_yy_xy(mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, w, h);
371 
372  vif_xx_yy_xy(curr_ref_scale, curr_main_scale, ref_sq, main_sq, ref_main, w, h);
373 
374  td.src = ref_sq;
375  td.dst = ref_sq_filt;
376  td.src_stride = w;
377  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
378 
379  td.src = main_sq;
380  td.dst = main_sq_filt;
381  td.src_stride = w;
382  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
383 
384  td.src = ref_main;
385  td.dst = ref_main_filt;
386  ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads);
387 
388  vif_statistic(mu1_sq, mu2_sq, mu1_mu2, ref_sq_filt, main_sq_filt,
389  ref_main_filt, &num, &den, w, h);
390 
391  score[scale] = den <= FLT_EPSILON ? 1.f : num / den;
392  }
393 
394  return 0;
395 }
396 
397 #define offset_fn(type, bits) \
398 static void offset_##bits##bit(VIFContext *s, \
399  const AVFrame *ref, \
400  AVFrame *main, int stride)\
401 { \
402  int w = s->width; \
403  int h = s->height; \
404  \
405  int ref_stride = ref->linesize[0]; \
406  int main_stride = main->linesize[0]; \
407  \
408  const type *ref_ptr = (const type *) ref->data[0]; \
409  const type *main_ptr = (const type *) main->data[0]; \
410  \
411  const float factor = s->factor; \
412  \
413  float *ref_ptr_data = s->ref_data; \
414  float *main_ptr_data = s->main_data; \
415  \
416  for (int i = 0; i < h; i++) { \
417  for (int j = 0; j < w; j++) { \
418  ref_ptr_data[j] = ref_ptr[j] * factor - 128.f; \
419  main_ptr_data[j] = main_ptr[j] * factor - 128.f; \
420  } \
421  ref_ptr += ref_stride / sizeof(type); \
422  ref_ptr_data += w; \
423  main_ptr += main_stride / sizeof(type); \
424  main_ptr_data += w; \
425  } \
426 }
427 
429 offset_fn(uint16_t, 16)
430 
431 static void set_meta(AVDictionary **metadata, const char *key, float d)
432 {
433  char value[257];
434  snprintf(value, sizeof(value), "%f", d);
435  av_dict_set(metadata, key, value, 0);
436 }
437 
439 {
440  VIFContext *s = ctx->priv;
441  AVDictionary **metadata = &main->metadata;
442  float score[4];
443 
444  s->factor = 1.f / (1 << (s->desc->comp[0].depth - 8));
445  if (s->desc->comp[0].depth <= 8) {
446  offset_8bit(s, ref, main, s->width);
447  } else {
448  offset_16bit(s, ref, main, s->width);
449  }
450 
452  s->ref_data, s->main_data, s->width,
453  s->height, s->width, s->width,
454  score, s->data_buf, s->temp,
455  s->nb_threads);
456 
457  set_meta(metadata, "lavfi.vif.scale.0", score[0]);
458  set_meta(metadata, "lavfi.vif.scale.1", score[1]);
459  set_meta(metadata, "lavfi.vif.scale.2", score[2]);
460  set_meta(metadata, "lavfi.vif.scale.3", score[3]);
461 
462  for (int i = 0; i < 4; i++) {
463  s->vif_min[i] = FFMIN(s->vif_min[i], score[i]);
464  s->vif_max[i] = FFMAX(s->vif_max[i], score[i]);
465  s->vif_sum[i] += score[i];
466  }
467 
468  s->nb_frames++;
469 
470  return main;
471 }
472 
474 {
475  static const enum AVPixelFormat pix_fmts[] = {
482 #define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf
483  PF(P9), PF(P10), PF(P12), PF(P14), PF(P16),
485  };
486 
488  if (!fmts_list)
489  return AVERROR(ENOMEM);
490  return ff_set_common_formats(ctx, fmts_list);
491 }
492 
494 {
495  AVFilterContext *ctx = inlink->dst;
496  VIFContext *s = ctx->priv;
497 
498  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
499  ctx->inputs[0]->h != ctx->inputs[1]->h) {
500  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
501  return AVERROR(EINVAL);
502  }
503  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
504  av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n");
505  return AVERROR(EINVAL);
506  }
507 
508  s->desc = av_pix_fmt_desc_get(inlink->format);
509  s->width = ctx->inputs[0]->w;
510  s->height = ctx->inputs[0]->h;
511  s->nb_threads = ff_filter_get_nb_threads(ctx);
512 
513  for (int i = 0; i < 4; i++) {
514  s->vif_min[i] = DBL_MAX;
515  s->vif_max[i] = -DBL_MAX;
516  }
517 
518  for (int i = 0; i < 13; i++) {
519  if (!(s->data_buf[i] = av_calloc(s->width, s->height * sizeof(float))))
520  return AVERROR(ENOMEM);
521  }
522 
523  if (!(s->ref_data = av_calloc(s->width, s->height * sizeof(float))))
524  return AVERROR(ENOMEM);
525 
526  if (!(s->main_data = av_calloc(s->width, s->height * sizeof(float))))
527  return AVERROR(ENOMEM);
528 
529  if (!(s->temp = av_calloc(s->nb_threads, sizeof(s->temp[0]))))
530  return AVERROR(ENOMEM);
531 
532  for (int i = 0; i < s->nb_threads; i++) {
533  if (!(s->temp[i] = av_calloc(s->width, sizeof(float))))
534  return AVERROR(ENOMEM);
535  }
536 
537  return 0;
538 }
539 
541 {
542  AVFilterContext *ctx = fs->parent;
543  VIFContext *s = fs->opaque;
544  AVFilterLink *outlink = ctx->outputs[0];
545  AVFrame *out_frame, *main_frame = NULL, *ref_frame = NULL;
546  int ret;
547 
548  ret = ff_framesync_dualinput_get(fs, &main_frame, &ref_frame);
549  if (ret < 0)
550  return ret;
551 
552  if (ctx->is_disabled || !ref_frame) {
553  out_frame = main_frame;
554  } else {
555  out_frame = do_vif(ctx, main_frame, ref_frame);
556  }
557 
558  out_frame->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base);
559 
560  return ff_filter_frame(outlink, out_frame);
561 }
562 
563 
564 static int config_output(AVFilterLink *outlink)
565 {
566  AVFilterContext *ctx = outlink->src;
567  VIFContext *s = ctx->priv;
568  AVFilterLink *mainlink = ctx->inputs[0];
569  FFFrameSyncIn *in;
570  int ret;
571 
572  outlink->w = mainlink->w;
573  outlink->h = mainlink->h;
574  outlink->time_base = mainlink->time_base;
575  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
576  outlink->frame_rate = mainlink->frame_rate;
577  if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
578  return ret;
579 
580  in = s->fs.in;
581  in[0].time_base = mainlink->time_base;
582  in[1].time_base = ctx->inputs[1]->time_base;
583  in[0].sync = 2;
584  in[0].before = EXT_STOP;
585  in[0].after = EXT_STOP;
586  in[1].sync = 1;
587  in[1].before = EXT_STOP;
588  in[1].after = EXT_STOP;
589  s->fs.opaque = s;
590  s->fs.on_event = process_frame;
591 
592  return ff_framesync_configure(&s->fs);
593 }
594 
596 {
597  VIFContext *s = ctx->priv;
598  return ff_framesync_activate(&s->fs);
599 }
600 
602 {
603  VIFContext *s = ctx->priv;
604 
605  if (s->nb_frames > 0) {
606  for (int i = 0; i < 4; i++)
607  av_log(ctx, AV_LOG_INFO, "VIF scale=%d average:%f min:%f: max:%f\n",
608  i, s->vif_sum[i] / s->nb_frames, s->vif_min[i], s->vif_max[i]);
609  }
610 
611  for (int i = 0; i < 13; i++)
612  av_freep(&s->data_buf[i]);
613 
614  av_freep(&s->ref_data);
615  av_freep(&s->main_data);
616 
617  for (int i = 0; i < s->nb_threads && s->temp; i++)
618  av_freep(&s->temp[i]);
619 
620  av_freep(&s->temp);
621 
622  ff_framesync_uninit(&s->fs);
623 }
624 
625 static const AVFilterPad vif_inputs[] = {
626  {
627  .name = "main",
628  .type = AVMEDIA_TYPE_VIDEO,
629  },{
630  .name = "reference",
631  .type = AVMEDIA_TYPE_VIDEO,
632  .config_props = config_input_ref,
633  },
634  { NULL }
635 };
636 
637 static const AVFilterPad vif_outputs[] = {
638  {
639  .name = "default",
640  .type = AVMEDIA_TYPE_VIDEO,
641  .config_props = config_output,
642  },
643  { NULL }
644 };
645 
647  .name = "vif",
648  .description = NULL_IF_CONFIG_SMALL("Calculate the VIF between two video streams."),
649  .uninit = uninit,
650  .query_formats = query_formats,
651  .priv_size = sizeof(VIFContext),
652  .priv_class = &vif_class,
653  .activate = activate,
654  .inputs = vif_inputs,
655  .outputs = vif_outputs,
657 };
VIFContext::vif_sum
double vif_sum[4]
Definition: vf_vif.c:53
ThreadData::src_stride
int src_stride
Definition: vf_vif.c:94
vif_outputs
static const AVFilterPad vif_outputs[]
Definition: vf_vif.c:637
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:124
td
#define td
Definition: regdef.h:70
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
set_meta
static void set_meta(AVDictionary **metadata, int chan, const char *key, const char *fmt, double val)
Definition: af_astats.c:393
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_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
ThreadData::filter_width
int filter_width
Definition: vf_vif.c:96
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:290
VIFContext::vif_max
double vif_max[4]
Definition: vf_vif.c:55
VIFContext::fs
FFFrameSync fs
Definition: vf_vif.c:43
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
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:2573
ThreadData::dst_stride
int dst_stride
Definition: vf_vif.c:95
process_frame
static int process_frame(FFFrameSync *fs)
Definition: vf_vif.c:540
VIFContext::nb_threads
int nb_threads
Definition: vf_vif.c:47
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:397
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:184
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:411
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_vif.c:601
w
uint8_t w
Definition: llviddspenc.c:39
AVOption
AVOption.
Definition: opt.h:248
VIFContext::height
int height
Definition: vf_vif.c:46
vif_filter1d_table
static const float vif_filter1d_table[4][17]
Definition: vf_vif.c:69
float.h
ThreadData::w
int w
Definition: vf_blend.c:59
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
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
AVDictionary
Definition: dict.c:30
ff_compute_vif2
int ff_compute_vif2(AVFilterContext *ctx, const float *ref, const float *main, int w, int h, int ref_stride, int main_stride, float *score, float *data_buf[14], float **temp, int gnb_threads)
Definition: vf_vif.c:286
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_vif.c:473
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:149
FFFrameSync
Frame sync structure.
Definition: framesync.h:146
vif_filter1d
static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_vif.c:208
vif_filter1d_width1
static const uint8_t vif_filter1d_width1[4]
Definition: vf_vif.c:67
video.h
AVFormatContext::internal
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1699
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:379
VIFContext::desc
const AVPixFmtDescriptor * desc
Definition: vf_vif.c:44
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:65
formats.h
vif.h
EXT_STOP
@ EXT_STOP
Completely stop all streams with this one.
Definition: framesync.h:65
FFFrameSyncIn
Input stream structure.
Definition: framesync.h:81
VIFContext::main_data
float * main_data
Definition: vf_vif.c:52
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:100
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
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:258
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
av_cold
#define av_cold
Definition: attributes.h:90
ff_set_common_formats
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:587
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
s
#define s(width, name)
Definition: cbs_vp9.c:257
g
const char * g
Definition: vf_curves.c:117
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:382
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:438
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
key
const char * key
Definition: hwcontext_opencl.c:168
f
#define f(width, name)
Definition: cbs_vp9.c:255
ThreadData::h
int h
Definition: vf_blend.c:59
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:66
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:380
ThreadData::dst
AVFrame * dst
Definition: vf_blend.c:56
main
int main(int argc, char *argv[])
Definition: avio_list_dir.c:112
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:259
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
VIFContext::vif_min
double vif_min[4]
Definition: vf_vif.c:54
src
#define src
Definition: vp8dsp.c:255
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
ff_vf_vif
AVFilter ff_vf_vif
Definition: vf_vif.c:646
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:117
VIFContext::data_buf
float * data_buf[13]
Definition: vf_vif.c:49
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
ThreadData::src
const float * src
Definition: vf_vif.c:91
ThreadData::temp
float ** temp
Definition: vf_vif.c:97
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
VIFContext::factor
float factor
Definition: vf_vif.c:48
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
internal.h
VIFContext::width
int width
Definition: vf_vif.c:45
in
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
i
int i
Definition: input.c:407
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
ThreadData
Used for passing data between threads.
Definition: dsddec.c:67
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
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
uint8_t
uint8_t
Definition: audio_convert.c:194
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_vif.c:564
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:111
AVFilter
Filter definition.
Definition: avfilter.h:145
ret
ret
Definition: filter_design.txt:187
VIFContext::nb_frames
uint64_t nb_frames
Definition: vf_vif.c:56
ff_framesync_init
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:84
VIFContext::ref_data
float * ref_data
Definition: vf_vif.c:51
VIFContext::temp
float ** temp
Definition: vf_vif.c:50
PF
#define PF(suf)
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
framesync.h
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
avfilter.h
vif_inputs
static const AVFilterPad vif_inputs[]
Definition: vf_vif.c:625
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
temp
else temp
Definition: vf_mcdeint.c:259
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(vif)
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:341
activate
static int activate(AVFilterContext *ctx)
Definition: vf_vif.c:595
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
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
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
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:70
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
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:134
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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:28
h
h
Definition: vp9dsp_template.c:2038
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:341
avstring.h
ff_framesync_dualinput_get
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:376
vif_options
static const AVOption vif_options[]
Definition: vf_vif.c:61
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:381
drawutils.h
ThreadData::filter
const float * filter
Definition: vf_vif.c:90
snprintf
#define snprintf
Definition: snprintf.h:34
VIFContext
Definition: vf_vif.c:41
config_input_ref
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_vif.c:493