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