FFmpeg  4.4.5
vf_ssim.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003-2013 Loren Merritt
3  * Copyright (c) 2015 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /* Computes the Structural Similarity Metric between two video streams.
23  * original algorithm:
24  * Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli,
25  * "Image quality assessment: From error visibility to structural similarity,"
26  * IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004.
27  *
28  * To improve speed, this implementation uses the standard approximation of
29  * overlapped 8x8 block sums, rather than the original gaussian weights.
30  */
31 
32 /*
33  * @file
34  * Caculate the SSIM between two input videos.
35  */
36 
37 #include "libavutil/avstring.h"
38 #include "libavutil/opt.h"
39 #include "libavutil/pixdesc.h"
40 #include "avfilter.h"
41 #include "drawutils.h"
42 #include "formats.h"
43 #include "framesync.h"
44 #include "internal.h"
45 #include "ssim.h"
46 #include "video.h"
47 
48 typedef struct SSIMContext {
49  const AVClass *class;
51  FILE *stats_file;
55  int max;
56  uint64_t nb_frames;
57  double ssim[4], ssim_total;
58  char comps[4];
59  double coefs[4];
61  int planewidth[4];
62  int planeheight[4];
63  int **temp;
64  int is_rgb;
65  double **score;
67  int jobnr, int nb_jobs);
69 } SSIMContext;
70 
71 #define OFFSET(x) offsetof(SSIMContext, x)
72 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
73 
74 static const AVOption ssim_options[] = {
75  {"stats_file", "Set file where to store per-frame difference information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
76  {"f", "Set file where to store per-frame difference information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
77  { NULL }
78 };
79 
81 
82 static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
83 {
84  char value[128];
85  snprintf(value, sizeof(value), "%f", d);
86  if (comp) {
87  char key2[128];
88  snprintf(key2, sizeof(key2), "%s%c", key, comp);
89  av_dict_set(metadata, key2, value, 0);
90  } else {
91  av_dict_set(metadata, key, value, 0);
92  }
93 }
94 
95 static void ssim_4x4xn_16bit(const uint8_t *main8, ptrdiff_t main_stride,
96  const uint8_t *ref8, ptrdiff_t ref_stride,
97  int64_t (*sums)[4], int width)
98 {
99  const uint16_t *main16 = (const uint16_t *)main8;
100  const uint16_t *ref16 = (const uint16_t *)ref8;
101  int x, y, z;
102 
103  main_stride >>= 1;
104  ref_stride >>= 1;
105 
106  for (z = 0; z < width; z++) {
107  uint64_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
108 
109  for (y = 0; y < 4; y++) {
110  for (x = 0; x < 4; x++) {
111  unsigned a = main16[x + y * main_stride];
112  unsigned b = ref16[x + y * ref_stride];
113 
114  s1 += a;
115  s2 += b;
116  ss += a*a;
117  ss += b*b;
118  s12 += a*b;
119  }
120  }
121 
122  sums[z][0] = s1;
123  sums[z][1] = s2;
124  sums[z][2] = ss;
125  sums[z][3] = s12;
126  main16 += 4;
127  ref16 += 4;
128  }
129 }
130 
131 static void ssim_4x4xn_8bit(const uint8_t *main, ptrdiff_t main_stride,
132  const uint8_t *ref, ptrdiff_t ref_stride,
133  int (*sums)[4], int width)
134 {
135  int x, y, z;
136 
137  for (z = 0; z < width; z++) {
138  uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
139 
140  for (y = 0; y < 4; y++) {
141  for (x = 0; x < 4; x++) {
142  int a = main[x + y * main_stride];
143  int b = ref[x + y * ref_stride];
144 
145  s1 += a;
146  s2 += b;
147  ss += a*a;
148  ss += b*b;
149  s12 += a*b;
150  }
151  }
152 
153  sums[z][0] = s1;
154  sums[z][1] = s2;
155  sums[z][2] = ss;
156  sums[z][3] = s12;
157  main += 4;
158  ref += 4;
159  }
160 }
161 
162 static float ssim_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max)
163 {
164  int64_t ssim_c1 = (int64_t)(.01*.01*max*max*64 + .5);
165  int64_t ssim_c2 = (int64_t)(.03*.03*max*max*64*63 + .5);
166 
167  int64_t fs1 = s1;
168  int64_t fs2 = s2;
169  int64_t fss = ss;
170  int64_t fs12 = s12;
171  int64_t vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
172  int64_t covar = fs12 * 64 - fs1 * fs2;
173 
174  return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2)
175  / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2));
176 }
177 
178 static float ssim_end1(int s1, int s2, int ss, int s12)
179 {
180  static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5);
181  static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5);
182 
183  int fs1 = s1;
184  int fs2 = s2;
185  int fss = ss;
186  int fs12 = s12;
187  int vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
188  int covar = fs12 * 64 - fs1 * fs2;
189 
190  return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2)
191  / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2));
192 }
193 
194 static float ssim_endn_16bit(const int64_t (*sum0)[4], const int64_t (*sum1)[4], int width, int max)
195 {
196  float ssim = 0.0;
197  int i;
198 
199  for (i = 0; i < width; i++)
200  ssim += ssim_end1x(sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0],
201  sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1],
202  sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2],
203  sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3],
204  max);
205  return ssim;
206 }
207 
208 static double ssim_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width)
209 {
210  double ssim = 0.0;
211  int i;
212 
213  for (i = 0; i < width; i++)
214  ssim += ssim_end1(sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0],
215  sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1],
216  sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2],
217  sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3]);
218  return ssim;
219 }
220 
221 #define SUM_LEN(w) (((w) >> 2) + 3)
222 
223 typedef struct ThreadData {
224  const uint8_t *main_data[4];
225  const uint8_t *ref_data[4];
226  int main_linesize[4];
227  int ref_linesize[4];
228  int planewidth[4];
229  int planeheight[4];
230  double **score;
231  int **temp;
232  int nb_components;
233  int max;
235 } ThreadData;
236 
238  int jobnr, int nb_jobs)
239 {
240  ThreadData *td = arg;
241  double *score = td->score[jobnr];
242  void *temp = td->temp[jobnr];
243  const int max = td->max;
244 
245  for (int c = 0; c < td->nb_components; c++) {
246  const uint8_t *main_data = td->main_data[c];
247  const uint8_t *ref_data = td->ref_data[c];
248  const int main_stride = td->main_linesize[c];
249  const int ref_stride = td->ref_linesize[c];
250  int width = td->planewidth[c];
251  int height = td->planeheight[c];
252  const int slice_start = ((height >> 2) * jobnr) / nb_jobs;
253  const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs;
254  const int ystart = FFMAX(1, slice_start);
255  int z = ystart - 1;
256  double ssim = 0.0;
257  int64_t (*sum0)[4] = temp;
258  int64_t (*sum1)[4] = sum0 + SUM_LEN(width);
259 
260  width >>= 2;
261  height >>= 2;
262 
263  for (int y = ystart; y < slice_end; y++) {
264  for (; z <= y; z++) {
265  FFSWAP(void*, sum0, sum1);
266  ssim_4x4xn_16bit(&main_data[4 * z * main_stride], main_stride,
267  &ref_data[4 * z * ref_stride], ref_stride,
268  sum0, width);
269  }
270 
271  ssim += ssim_endn_16bit((const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, width - 1, max);
272  }
273 
274  score[c] = ssim;
275  }
276 
277  return 0;
278 }
279 
280 static int ssim_plane(AVFilterContext *ctx, void *arg,
281  int jobnr, int nb_jobs)
282 {
283  ThreadData *td = arg;
284  double *score = td->score[jobnr];
285  void *temp = td->temp[jobnr];
286  SSIMDSPContext *dsp = td->dsp;
287 
288  for (int c = 0; c < td->nb_components; c++) {
289  const uint8_t *main_data = td->main_data[c];
290  const uint8_t *ref_data = td->ref_data[c];
291  const int main_stride = td->main_linesize[c];
292  const int ref_stride = td->ref_linesize[c];
293  int width = td->planewidth[c];
294  int height = td->planeheight[c];
295  const int slice_start = ((height >> 2) * jobnr) / nb_jobs;
296  const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs;
297  const int ystart = FFMAX(1, slice_start);
298  int z = ystart - 1;
299  double ssim = 0.0;
300  int (*sum0)[4] = temp;
301  int (*sum1)[4] = sum0 + SUM_LEN(width);
302 
303  width >>= 2;
304  height >>= 2;
305 
306  for (int y = ystart; y < slice_end; y++) {
307  for (; z <= y; z++) {
308  FFSWAP(void*, sum0, sum1);
309  dsp->ssim_4x4_line(&main_data[4 * z * main_stride], main_stride,
310  &ref_data[4 * z * ref_stride], ref_stride,
311  sum0, width);
312  }
313 
314  ssim += dsp->ssim_end_line((const int (*)[4])sum0, (const int (*)[4])sum1, width - 1);
315  }
316 
317  score[c] = ssim;
318  }
319 
320  return 0;
321 }
322 
323 static double ssim_db(double ssim, double weight)
324 {
325  return (fabs(weight - ssim) > 1e-9) ? 10.0 * log10(weight / (weight - ssim)) : INFINITY;
326 }
327 
328 static int do_ssim(FFFrameSync *fs)
329 {
330  AVFilterContext *ctx = fs->parent;
331  SSIMContext *s = ctx->priv;
332  AVFrame *master, *ref;
333  AVDictionary **metadata;
334  double c[4] = {0}, ssimv = 0.0;
335  ThreadData td;
336  int ret, i;
337 
339  if (ret < 0)
340  return ret;
341  if (ctx->is_disabled || !ref)
342  return ff_filter_frame(ctx->outputs[0], master);
343  metadata = &master->metadata;
344 
345  s->nb_frames++;
346 
347  td.nb_components = s->nb_components;
348  td.dsp = &s->dsp;
349  td.score = s->score;
350  td.temp = s->temp;
351  td.max = s->max;
352 
353  for (int n = 0; n < s->nb_components; n++) {
354  td.main_data[n] = master->data[n];
355  td.ref_data[n] = ref->data[n];
356  td.main_linesize[n] = master->linesize[n];
357  td.ref_linesize[n] = ref->linesize[n];
358  td.planewidth[n] = s->planewidth[n];
359  td.planeheight[n] = s->planeheight[n];
360  }
361 
362  ctx->internal->execute(ctx, s->ssim_plane, &td, NULL, FFMIN((s->planeheight[1] + 3) >> 2, s->nb_threads));
363 
364  for (i = 0; i < s->nb_components; i++) {
365  for (int j = 0; j < s->nb_threads; j++)
366  c[i] += s->score[j][i];
367  c[i] = c[i] / (((s->planewidth[i] >> 2) - 1) * ((s->planeheight[i] >> 2) - 1));
368  }
369 
370  for (i = 0; i < s->nb_components; i++) {
371  ssimv += s->coefs[i] * c[i];
372  s->ssim[i] += c[i];
373  }
374 
375  for (i = 0; i < s->nb_components; i++) {
376  int cidx = s->is_rgb ? s->rgba_map[i] : i;
377  set_meta(metadata, "lavfi.ssim.", s->comps[i], c[cidx]);
378  }
379  s->ssim_total += ssimv;
380 
381  set_meta(metadata, "lavfi.ssim.All", 0, ssimv);
382  set_meta(metadata, "lavfi.ssim.dB", 0, ssim_db(ssimv, 1.0));
383 
384  if (s->stats_file) {
385  fprintf(s->stats_file, "n:%"PRId64" ", s->nb_frames);
386 
387  for (i = 0; i < s->nb_components; i++) {
388  int cidx = s->is_rgb ? s->rgba_map[i] : i;
389  fprintf(s->stats_file, "%c:%f ", s->comps[i], c[cidx]);
390  }
391 
392  fprintf(s->stats_file, "All:%f (%f)\n", ssimv, ssim_db(ssimv, 1.0));
393  }
394 
395  return ff_filter_frame(ctx->outputs[0], master);
396 }
397 
399 {
400  SSIMContext *s = ctx->priv;
401 
402  if (s->stats_file_str) {
403  if (!strcmp(s->stats_file_str, "-")) {
404  s->stats_file = stdout;
405  } else {
406  s->stats_file = fopen(s->stats_file_str, "w");
407  if (!s->stats_file) {
408  int err = AVERROR(errno);
409  char buf[128];
410  av_strerror(err, buf, sizeof(buf));
411  av_log(ctx, AV_LOG_ERROR, "Could not open stats file %s: %s\n",
412  s->stats_file_str, buf);
413  return err;
414  }
415  }
416  }
417 
418  s->fs.on_event = do_ssim;
419  return 0;
420 }
421 
423 {
424  static const enum AVPixelFormat pix_fmts[] = {
432 #define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf, AV_PIX_FMT_GBR##suf
433  PF(P9), PF(P10), PF(P12), PF(P14), PF(P16),
435  };
436 
438  if (!fmts_list)
439  return AVERROR(ENOMEM);
440  return ff_set_common_formats(ctx, fmts_list);
441 }
442 
443 static int config_input_ref(AVFilterLink *inlink)
444 {
446  AVFilterContext *ctx = inlink->dst;
447  SSIMContext *s = ctx->priv;
448  int sum = 0, i;
449 
450  s->nb_threads = ff_filter_get_nb_threads(ctx);
451  s->nb_components = desc->nb_components;
452 
453  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
454  ctx->inputs[0]->h != ctx->inputs[1]->h) {
455  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
456  return AVERROR(EINVAL);
457  }
458  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
459  av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n");
460  return AVERROR(EINVAL);
461  }
462 
463  s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0;
464  s->comps[0] = s->is_rgb ? 'R' : 'Y';
465  s->comps[1] = s->is_rgb ? 'G' : 'U';
466  s->comps[2] = s->is_rgb ? 'B' : 'V';
467  s->comps[3] = 'A';
468 
469  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
470  s->planeheight[0] = s->planeheight[3] = inlink->h;
471  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
472  s->planewidth[0] = s->planewidth[3] = inlink->w;
473  for (i = 0; i < s->nb_components; i++)
474  sum += s->planeheight[i] * s->planewidth[i];
475  for (i = 0; i < s->nb_components; i++)
476  s->coefs[i] = (double) s->planeheight[i] * s->planewidth[i] / sum;
477 
478  s->temp = av_calloc(s->nb_threads, sizeof(*s->temp));
479  if (!s->temp)
480  return AVERROR(ENOMEM);
481 
482  for (int t = 0; t < s->nb_threads; t++) {
483  s->temp[t] = av_mallocz_array(2 * SUM_LEN(inlink->w), (desc->comp[0].depth > 8) ? sizeof(int64_t[4]) : sizeof(int[4]));
484  if (!s->temp[t])
485  return AVERROR(ENOMEM);
486  }
487  s->max = (1 << desc->comp[0].depth) - 1;
488 
489  s->ssim_plane = desc->comp[0].depth > 8 ? ssim_plane_16bit : ssim_plane;
490  s->dsp.ssim_4x4_line = ssim_4x4xn_8bit;
491  s->dsp.ssim_end_line = ssim_endn_8bit;
492  if (ARCH_X86)
493  ff_ssim_init_x86(&s->dsp);
494 
495  s->score = av_calloc(s->nb_threads, sizeof(*s->score));
496  if (!s->score)
497  return AVERROR(ENOMEM);
498 
499  for (int t = 0; t < s->nb_threads && s->score; t++) {
500  s->score[t] = av_calloc(s->nb_components, sizeof(*s->score[0]));
501  if (!s->score[t])
502  return AVERROR(ENOMEM);
503  }
504 
505  return 0;
506 }
507 
508 static int config_output(AVFilterLink *outlink)
509 {
510  AVFilterContext *ctx = outlink->src;
511  SSIMContext *s = ctx->priv;
512  AVFilterLink *mainlink = ctx->inputs[0];
513  int ret;
514 
515  ret = ff_framesync_init_dualinput(&s->fs, ctx);
516  if (ret < 0)
517  return ret;
518  outlink->w = mainlink->w;
519  outlink->h = mainlink->h;
520  outlink->time_base = mainlink->time_base;
521  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
522  outlink->frame_rate = mainlink->frame_rate;
523 
524  if ((ret = ff_framesync_configure(&s->fs)) < 0)
525  return ret;
526 
527  outlink->time_base = s->fs.time_base;
528 
529  if (av_cmp_q(mainlink->time_base, outlink->time_base) ||
530  av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base))
531  av_log(ctx, AV_LOG_WARNING, "not matching timebases found between first input: %d/%d and second input %d/%d, results may be incorrect!\n",
532  mainlink->time_base.num, mainlink->time_base.den,
533  ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den);
534 
535  return 0;
536 }
537 
539 {
540  SSIMContext *s = ctx->priv;
541  return ff_framesync_activate(&s->fs);
542 }
543 
545 {
546  SSIMContext *s = ctx->priv;
547 
548  if (s->nb_frames > 0) {
549  char buf[256];
550  int i;
551  buf[0] = 0;
552  for (i = 0; i < s->nb_components; i++) {
553  int c = s->is_rgb ? s->rgba_map[i] : i;
554  av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[i], s->ssim[c] / s->nb_frames,
555  ssim_db(s->ssim[c], s->nb_frames));
556  }
557  av_log(ctx, AV_LOG_INFO, "SSIM%s All:%f (%f)\n", buf,
558  s->ssim_total / s->nb_frames, ssim_db(s->ssim_total, s->nb_frames));
559  }
560 
561  ff_framesync_uninit(&s->fs);
562 
563  if (s->stats_file && s->stats_file != stdout)
564  fclose(s->stats_file);
565 
566  for (int t = 0; t < s->nb_threads && s->score; t++)
567  av_freep(&s->score[t]);
568  av_freep(&s->score);
569 
570  for (int t = 0; t < s->nb_threads && s->temp; t++)
571  av_freep(&s->temp[t]);
572  av_freep(&s->temp);
573 }
574 
575 static const AVFilterPad ssim_inputs[] = {
576  {
577  .name = "main",
578  .type = AVMEDIA_TYPE_VIDEO,
579  },{
580  .name = "reference",
581  .type = AVMEDIA_TYPE_VIDEO,
582  .config_props = config_input_ref,
583  },
584  { NULL }
585 };
586 
587 static const AVFilterPad ssim_outputs[] = {
588  {
589  .name = "default",
590  .type = AVMEDIA_TYPE_VIDEO,
591  .config_props = config_output,
592  },
593  { NULL }
594 };
595 
597  .name = "ssim",
598  .description = NULL_IF_CONFIG_SMALL("Calculate the SSIM between two video streams."),
599  .preinit = ssim_framesync_preinit,
600  .init = init,
601  .uninit = uninit,
602  .query_formats = query_formats,
603  .activate = activate,
604  .priv_size = sizeof(SSIMContext),
605  .priv_class = &ssim_class,
606  .inputs = ssim_inputs,
609 };
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_cold
Definition: attributes.h:88
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[])
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
static const uint8_t vars[2][12]
Definition: camellia.c:179
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
#define s(width, name)
Definition: cbs_vp9.c:257
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:259
#define FFSWAP(type, a, b)
Definition: common.h:108
#define FFMIN(a, b)
Definition: common.h:105
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
#define FFMAX(a, b)
Definition: common.h:103
#define ARCH_X86
Definition: config.h:39
#define NULL
Definition: coverity.c:32
long long int64_t
Definition: coverity.c:34
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
#define max(a, b)
Definition: cuda_runtime.h:33
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
misc drawing utilities
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:85
double value
Definition: eval.c:98
int
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
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:358
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:290
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
#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
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:105
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#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
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
void * av_mallocz_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_mallocz().
Definition: mem.c:190
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
for(j=16;j >0;--j)
const char * key
int i
Definition: input.c:407
static int weight(int i, int blen, int offset)
Definition: diracdec.c:1561
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
const char * desc
Definition: libsvtav1.c:79
#define INFINITY
Definition: mathematics.h:67
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_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
@ 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 s1
Definition: regdef.h:38
#define s2
Definition: regdef.h:39
#define td
Definition: regdef.h:70
#define snprintf
Definition: snprintf.h:34
void ff_ssim_init_x86(SSIMDSPContext *dsp)
Definition: vf_ssim_init.c:33
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
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
int num
Numerator.
Definition: rational.h:59
int den
Denominator.
Definition: rational.h:60
Frame sync structure.
Definition: framesync.h:146
FILE * stats_file
Definition: vf_ssim.c:51
int planewidth[4]
Definition: vf_ssim.c:61
int nb_components
Definition: vf_ssim.c:53
double ssim_total
Definition: vf_ssim.c:57
char comps[4]
Definition: vf_ssim.c:58
uint8_t rgba_map[4]
Definition: vf_ssim.c:60
int max
Definition: vf_ssim.c:55
uint64_t nb_frames
Definition: vf_ssim.c:56
double coefs[4]
Definition: vf_ssim.c:59
double ssim[4]
Definition: vf_ssim.c:57
int nb_threads
Definition: vf_ssim.c:54
double ** score
Definition: vf_ssim.c:65
char * stats_file_str
Definition: vf_ssim.c:52
SSIMDSPContext dsp
Definition: vf_ssim.c:68
int is_rgb
Definition: vf_ssim.c:64
int ** temp
Definition: vf_ssim.c:63
FFFrameSync fs
Definition: vf_ssim.c:50
int planeheight[4]
Definition: vf_ssim.c:62
int(* ssim_plane)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:66
double(* ssim_end_line)(const int(*sum0)[4], const int(*sum1)[4], int w)
Definition: ssim.h:31
void(* ssim_4x4_line)(const uint8_t *buf, ptrdiff_t buf_stride, const uint8_t *ref, ptrdiff_t ref_stride, int(*sums)[4], int w)
Definition: ssim.h:28
Used for passing data between threads.
Definition: dsddec.c:67
int nb_components
Definition: vf_identity.c:91
double ** score
Definition: vf_ssim.c:230
int max
Definition: vf_ssim.c:233
int ** temp
Definition: vf_ssim.c:231
int planeheight[4]
Definition: vf_identity.c:89
const uint8_t * ref_data[4]
Definition: vf_identity.c:85
int main_linesize[4]
Definition: vf_identity.c:86
int planewidth[4]
Definition: vf_identity.c:88
const uint8_t * main_data[4]
Definition: vf_identity.c:84
int ref_linesize
Definition: vf_bm3d.c:59
SSIMDSPContext * dsp
Definition: vf_ssim.c:234
#define av_freep(p)
#define av_log(a,...)
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
AVFormatContext * ctx
Definition: movenc.c:48
#define height
#define width
const char * b
Definition: vf_curves.c:118
const char * master
Definition: vf_curves.c:119
else temp
Definition: vf_mcdeint.c:259
static int ssim_plane(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:280
static int do_ssim(FFFrameSync *fs)
Definition: vf_ssim.c:328
FRAMESYNC_DEFINE_CLASS(ssim, SSIMContext, fs)
static float ssim_end1(int s1, int s2, int ss, int s12)
Definition: vf_ssim.c:178
static int query_formats(AVFilterContext *ctx)
Definition: vf_ssim.c:422
static double ssim_db(double ssim, double weight)
Definition: vf_ssim.c:323
AVFilter ff_vf_ssim
Definition: vf_ssim.c:596
static void ssim_4x4xn_8bit(const uint8_t *main, ptrdiff_t main_stride, const uint8_t *ref, ptrdiff_t ref_stride, int(*sums)[4], int width)
Definition: vf_ssim.c:131
#define FLAGS
Definition: vf_ssim.c:72
#define SUM_LEN(w)
Definition: vf_ssim.c:221
static const AVOption ssim_options[]
Definition: vf_ssim.c:74
static float ssim_endn_16bit(const int64_t(*sum0)[4], const int64_t(*sum1)[4], int width, int max)
Definition: vf_ssim.c:194
static const AVFilterPad ssim_outputs[]
Definition: vf_ssim.c:587
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_ssim.c:443
static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
Definition: vf_ssim.c:82
#define PF(suf)
static int activate(AVFilterContext *ctx)
Definition: vf_ssim.c:538
static av_cold int init(AVFilterContext *ctx)
Definition: vf_ssim.c:398
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_ssim.c:544
static void ssim_4x4xn_16bit(const uint8_t *main8, ptrdiff_t main_stride, const uint8_t *ref8, ptrdiff_t ref_stride, int64_t(*sums)[4], int width)
Definition: vf_ssim.c:95
#define OFFSET(x)
Definition: vf_ssim.c:71
static int config_output(AVFilterLink *outlink)
Definition: vf_ssim.c:508
static double ssim_endn_8bit(const int(*sum0)[4], const int(*sum1)[4], int width)
Definition: vf_ssim.c:208
static float ssim_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max)
Definition: vf_ssim.c:162
static int ssim_plane_16bit(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:237
static const AVFilterPad ssim_inputs[]
Definition: vf_ssim.c:575
static double c[64]