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;
94  int src_stride;
95  int dst_stride;
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 
451  ff_compute_vif2(ctx,
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 
487  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
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;
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;
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 };
#define NULL
Definition: coverity.c:32
static const uint8_t vif_filter1d_width1[4]
Definition: vf_vif.c:67
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
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
AVOption.
Definition: opt.h:248
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
static int process_frame(FFFrameSync *fs)
Definition: vf_vif.c:540
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
Main libavfilter public API header.
const char * g
Definition: vf_curves.c:117
const AVPixFmtDescriptor * desc
Definition: vf_vif.c:44
const float * filter
Definition: vf_vif.c:90
FFFrameSync fs
Definition: vf_vif.c:43
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:379
static const AVFilterPad vif_outputs[]
Definition: vf_vif.c:637
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:124
const char * key
int src_stride
Definition: vf_unsharp.c:55
int is_disabled
the enabled state from the last expression evaluation
Definition: avfilter.h:388
int64_t pts
Timestamp of the current event.
Definition: framesync.h:167
#define offset_fn(type, bits)
Definition: vf_vif.c:397
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition: framesync.h:86
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:287
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:380
double vif_sum[4]
Definition: vf_vif.c:53
const char * name
Pad name.
Definition: internal.h:60
AVFilterContext * parent
Parent filter context.
Definition: framesync.h:152
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:381
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:349
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1094
static void vif_dec2(const float *src, float *dst, int w, int h, int src_stride, int dst_stride)
Definition: vf_vif.c:100
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_vif.c:208
#define av_cold
Definition: attributes.h:88
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_vif.c:601
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:376
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
int nb_threads
Definition: vf_vif.c:47
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:411
double vif_min[4]
Definition: vf_vif.c:54
FFFrameSyncIn * in
Pointer to array of inputs.
Definition: framesync.h:203
static const float vif_filter1d_table[4][17]
Definition: vf_vif.c:69
AVFrame * dst
Definition: vf_blend.c:56
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range...
Definition: pixfmt.h:100
static int query_formats(AVFilterContext *ctx)
Definition: vf_vif.c:473
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
AVDictionary * metadata
metadata.
Definition: frame.h:604
enum FFFrameSyncExtMode after
Extrapolation mode for timestamps after the last frame.
Definition: framesync.h:91
Input stream structure.
Definition: framesync.h:81
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
#define src
Definition: vp8dsp.c:255
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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:588
#define td
Definition: regdef.h:70
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:290
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
Frame sync structure.
Definition: framesync.h:146
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:117
const uint8_t * src
Definition: vf_bm3d.c:56
void * priv
private data for use by the filter
Definition: avfilter.h:356
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
const char * arg
Definition: jacosubdec.c:66
AVRational time_base
Time base for the incoming frames.
Definition: framesync.h:96
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter&#39;s input and try to produce output.
Definition: framesync.c:341
int(* on_event)(struct FFFrameSync *fs)
Callback called when a frame event is ready.
Definition: framesync.h:172
#define FFMAX(a, b)
Definition: common.h:103
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
float * data_buf[13]
Definition: vf_vif.c:49
AVFilter ff_vf_vif
Definition: vf_vif.c:646
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
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
#define FFMIN(a, b)
Definition: common.h:105
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
uint8_t w
Definition: llviddspenc.c:39
AVFormatContext * ctx
Definition: movenc.c:48
AVRational time_base
Time base for the output events.
Definition: framesync.h:162
float factor
Definition: vf_vif.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
static AVFrame * do_vif(AVFilterContext *ctx, AVFrame *main, const AVFrame *ref)
Definition: vf_vif.c:438
int main(int argc, char *argv[])
void * opaque
Opaque pointer, not used by the API.
Definition: framesync.h:177
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
misc drawing utilities
Used for passing data between threads.
Definition: dsddec.c:67
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:84
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:382
static const AVFilterPad vif_inputs[]
Definition: vf_vif.c:625
static int config_output(AVFilterLink *outlink)
Definition: vf_vif.c:564
float ** temp
Definition: vf_vif.c:97
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
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
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events...
Definition: framesync.h:139
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:145
#define isnan(x)
Definition: libm.h:340
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
static int activate(AVFilterContext *ctx)
Definition: vf_vif.c:595
const char * name
Filter name.
Definition: avfilter.h:149
#define snprintf
Definition: snprintf.h:34
#define PF(suf)
#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
const float * src
Definition: vf_vif.c:91
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:353
float ** temp
Definition: vf_vif.c:50
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:303
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:381
float * main_data
Definition: vf_vif.c:52
float * ref_data
Definition: vf_vif.c:51
int width
Definition: vf_vif.c:45
AVFILTER_DEFINE_CLASS(vif)
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
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
#define log2f(x)
Definition: libm.h:409
double vif_max[4]
Definition: vf_vif.c:55
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
static void set_meta(AVDictionary **metadata, int chan, const char *key, const char *fmt, double val)
Definition: af_astats.c:393
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
avfilter_execute_func * execute
Definition: internal.h:136
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2032
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_vif.c:493
Completely stop all streams with this one.
Definition: framesync.h:65
uint64_t nb_frames
Definition: vf_vif.c:56
A list of supported formats for one end of a filter link.
Definition: formats.h:65
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
An instance of a filter.
Definition: avfilter.h:341
static const AVOption vif_options[]
Definition: vf_vif.c:61
int filter_width
Definition: vf_vif.c:96
#define av_freep(p)
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
int height
Definition: vf_vif.c:46
int dst_stride
Definition: vf_unsharp.c:54
internal API functions
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
int depth
Number of bits in the component.
Definition: pixdesc.h:58
int ** temp
Definition: vf_ssim.c:231
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int i
Definition: input.c:407