FFmpeg  4.4.8
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 "filters.h"
42 #include "drawutils.h"
43 #include "formats.h"
44 #include "framesync.h"
45 #include "internal.h"
46 #include "ssim.h"
47 #include "video.h"
48 
49 typedef struct SSIMContext {
50  const AVClass *class;
52  FILE *stats_file;
56  int max;
57  uint64_t nb_frames;
58  double ssim[4], ssim_total;
59  char comps[4];
60  double coefs[4];
62  int planewidth[4];
63  int planeheight[4];
64  int **temp;
65  int is_rgb;
66  double **score;
68  int jobnr, int nb_jobs);
70 } SSIMContext;
71 
72 #define OFFSET(x) offsetof(SSIMContext, x)
73 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
74 
75 static const AVOption ssim_options[] = {
76  {"stats_file", "Set file where to store per-frame difference information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
77  {"f", "Set file where to store per-frame difference information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
78  { NULL }
79 };
80 
82 
83 static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
84 {
85  char value[128];
86  snprintf(value, sizeof(value), "%f", d);
87  if (comp) {
88  char key2[128];
89  snprintf(key2, sizeof(key2), "%s%c", key, comp);
90  av_dict_set(metadata, key2, value, 0);
91  } else {
92  av_dict_set(metadata, key, value, 0);
93  }
94 }
95 
96 static void ssim_4x4xn_16bit(const uint8_t *main8, ptrdiff_t main_stride,
97  const uint8_t *ref8, ptrdiff_t ref_stride,
98  int64_t (*sums)[4], int width)
99 {
100  const uint16_t *main16 = (const uint16_t *)main8;
101  const uint16_t *ref16 = (const uint16_t *)ref8;
102  int x, y, z;
103 
104  main_stride >>= 1;
105  ref_stride >>= 1;
106 
107  for (z = 0; z < width; z++) {
108  uint64_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
109 
110  for (y = 0; y < 4; y++) {
111  for (x = 0; x < 4; x++) {
112  unsigned a = main16[x + y * main_stride];
113  unsigned b = ref16[x + y * ref_stride];
114 
115  s1 += a;
116  s2 += b;
117  ss += a*a;
118  ss += b*b;
119  s12 += a*b;
120  }
121  }
122 
123  sums[z][0] = s1;
124  sums[z][1] = s2;
125  sums[z][2] = ss;
126  sums[z][3] = s12;
127  main16 += 4;
128  ref16 += 4;
129  }
130 }
131 
132 static void ssim_4x4xn_8bit(const uint8_t *main, ptrdiff_t main_stride,
133  const uint8_t *ref, ptrdiff_t ref_stride,
134  int (*sums)[4], int width)
135 {
136  int x, y, z;
137 
138  for (z = 0; z < width; z++) {
139  uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
140 
141  for (y = 0; y < 4; y++) {
142  for (x = 0; x < 4; x++) {
143  int a = main[x + y * main_stride];
144  int b = ref[x + y * ref_stride];
145 
146  s1 += a;
147  s2 += b;
148  ss += a*a;
149  ss += b*b;
150  s12 += a*b;
151  }
152  }
153 
154  sums[z][0] = s1;
155  sums[z][1] = s2;
156  sums[z][2] = ss;
157  sums[z][3] = s12;
158  main += 4;
159  ref += 4;
160  }
161 }
162 
163 static float ssim_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max)
164 {
165  int64_t ssim_c1 = (int64_t)(.01*.01*max*max*64 + .5);
166  int64_t ssim_c2 = (int64_t)(.03*.03*max*max*64*63 + .5);
167 
168  int64_t fs1 = s1;
169  int64_t fs2 = s2;
170  int64_t fss = ss;
171  int64_t fs12 = s12;
172  int64_t vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
173  int64_t covar = fs12 * 64 - fs1 * fs2;
174 
175  return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2)
176  / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2));
177 }
178 
179 static float ssim_end1(int s1, int s2, int ss, int s12)
180 {
181  static const int ssim_c1 = (int)(.01*.01*255*255*64 + .5);
182  static const int ssim_c2 = (int)(.03*.03*255*255*64*63 + .5);
183 
184  int fs1 = s1;
185  int fs2 = s2;
186  int fss = ss;
187  int fs12 = s12;
188  int vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
189  int covar = fs12 * 64 - fs1 * fs2;
190 
191  return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2)
192  / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars + ssim_c2));
193 }
194 
195 static float ssim_endn_16bit(const int64_t (*sum0)[4], const int64_t (*sum1)[4], int width, int max)
196 {
197  float ssim = 0.0;
198  int i;
199 
200  for (i = 0; i < width; i++)
201  ssim += ssim_end1x(sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0],
202  sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1],
203  sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2],
204  sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3],
205  max);
206  return ssim;
207 }
208 
209 static double ssim_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width)
210 {
211  double ssim = 0.0;
212  int i;
213 
214  for (i = 0; i < width; i++)
215  ssim += ssim_end1(sum0[i][0] + sum0[i + 1][0] + sum1[i][0] + sum1[i + 1][0],
216  sum0[i][1] + sum0[i + 1][1] + sum1[i][1] + sum1[i + 1][1],
217  sum0[i][2] + sum0[i + 1][2] + sum1[i][2] + sum1[i + 1][2],
218  sum0[i][3] + sum0[i + 1][3] + sum1[i][3] + sum1[i + 1][3]);
219  return ssim;
220 }
221 
222 #define SUM_LEN(w) (((w) >> 2) + 3)
223 
224 typedef struct ThreadData {
225  const uint8_t *main_data[4];
226  const uint8_t *ref_data[4];
227  int main_linesize[4];
228  int ref_linesize[4];
229  int planewidth[4];
230  int planeheight[4];
231  double **score;
232  int **temp;
233  int nb_components;
234  int max;
236 } ThreadData;
237 
239  int jobnr, int nb_jobs)
240 {
241  ThreadData *td = arg;
242  double *score = td->score[jobnr];
243  void *temp = td->temp[jobnr];
244  const int max = td->max;
245 
246  for (int c = 0; c < td->nb_components; c++) {
247  const uint8_t *main_data = td->main_data[c];
248  const uint8_t *ref_data = td->ref_data[c];
249  const int main_stride = td->main_linesize[c];
250  const int ref_stride = td->ref_linesize[c];
251  int width = td->planewidth[c];
252  int height = td->planeheight[c];
253  const int slice_start = ff_slice_pos(height >> 2, jobnr, nb_jobs);
254  const int slice_end = ff_slice_pos(height >> 2, jobnr + 1, nb_jobs);
255  const int ystart = FFMAX(1, slice_start);
256  int z = ystart - 1;
257  double ssim = 0.0;
258  int64_t (*sum0)[4] = temp;
259  int64_t (*sum1)[4] = sum0 + SUM_LEN(width);
260 
261  width >>= 2;
262  height >>= 2;
263 
264  for (int y = ystart; y < slice_end; y++) {
265  for (; z <= y; z++) {
266  FFSWAP(void*, sum0, sum1);
267  ssim_4x4xn_16bit(&main_data[4 * z * main_stride], main_stride,
268  &ref_data[4 * z * ref_stride], ref_stride,
269  sum0, width);
270  }
271 
272  ssim += ssim_endn_16bit((const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, width - 1, max);
273  }
274 
275  score[c] = ssim;
276  }
277 
278  return 0;
279 }
280 
281 static int ssim_plane(AVFilterContext *ctx, void *arg,
282  int jobnr, int nb_jobs)
283 {
284  ThreadData *td = arg;
285  double *score = td->score[jobnr];
286  void *temp = td->temp[jobnr];
287  SSIMDSPContext *dsp = td->dsp;
288 
289  for (int c = 0; c < td->nb_components; c++) {
290  const uint8_t *main_data = td->main_data[c];
291  const uint8_t *ref_data = td->ref_data[c];
292  const int main_stride = td->main_linesize[c];
293  const int ref_stride = td->ref_linesize[c];
294  int width = td->planewidth[c];
295  int height = td->planeheight[c];
296  const int slice_start = ff_slice_pos(height >> 2, jobnr, nb_jobs);
297  const int slice_end = ff_slice_pos(height >> 2, jobnr + 1, nb_jobs);
298  const int ystart = FFMAX(1, slice_start);
299  int z = ystart - 1;
300  double ssim = 0.0;
301  int (*sum0)[4] = temp;
302  int (*sum1)[4] = sum0 + SUM_LEN(width);
303 
304  width >>= 2;
305  height >>= 2;
306 
307  for (int y = ystart; y < slice_end; y++) {
308  for (; z <= y; z++) {
309  FFSWAP(void*, sum0, sum1);
310  dsp->ssim_4x4_line(&main_data[4 * z * main_stride], main_stride,
311  &ref_data[4 * z * ref_stride], ref_stride,
312  sum0, width);
313  }
314 
315  ssim += dsp->ssim_end_line((const int (*)[4])sum0, (const int (*)[4])sum1, width - 1);
316  }
317 
318  score[c] = ssim;
319  }
320 
321  return 0;
322 }
323 
324 static double ssim_db(double ssim, double weight)
325 {
326  return (fabs(weight - ssim) > 1e-9) ? 10.0 * log10(weight / (weight - ssim)) : INFINITY;
327 }
328 
329 static int do_ssim(FFFrameSync *fs)
330 {
331  AVFilterContext *ctx = fs->parent;
332  SSIMContext *s = ctx->priv;
333  AVFrame *master, *ref;
334  AVDictionary **metadata;
335  double c[4] = {0}, ssimv = 0.0;
336  ThreadData td;
337  int ret, i;
338 
340  if (ret < 0)
341  return ret;
342  if (ctx->is_disabled || !ref)
343  return ff_filter_frame(ctx->outputs[0], master);
344  metadata = &master->metadata;
345 
346  s->nb_frames++;
347 
348  td.nb_components = s->nb_components;
349  td.dsp = &s->dsp;
350  td.score = s->score;
351  td.temp = s->temp;
352  td.max = s->max;
353 
354  for (int n = 0; n < s->nb_components; n++) {
355  td.main_data[n] = master->data[n];
356  td.ref_data[n] = ref->data[n];
357  td.main_linesize[n] = master->linesize[n];
358  td.ref_linesize[n] = ref->linesize[n];
359  td.planewidth[n] = s->planewidth[n];
360  td.planeheight[n] = s->planeheight[n];
361  }
362 
363  ctx->internal->execute(ctx, s->ssim_plane, &td, NULL, FFMIN((s->planeheight[1] + 3) >> 2, s->nb_threads));
364 
365  for (i = 0; i < s->nb_components; i++) {
366  for (int j = 0; j < s->nb_threads; j++)
367  c[i] += s->score[j][i];
368  c[i] = c[i] / (((s->planewidth[i] >> 2) - 1) * ((s->planeheight[i] >> 2) - 1));
369  }
370 
371  for (i = 0; i < s->nb_components; i++) {
372  ssimv += s->coefs[i] * c[i];
373  s->ssim[i] += c[i];
374  }
375 
376  for (i = 0; i < s->nb_components; i++) {
377  int cidx = s->is_rgb ? s->rgba_map[i] : i;
378  set_meta(metadata, "lavfi.ssim.", s->comps[i], c[cidx]);
379  }
380  s->ssim_total += ssimv;
381 
382  set_meta(metadata, "lavfi.ssim.All", 0, ssimv);
383  set_meta(metadata, "lavfi.ssim.dB", 0, ssim_db(ssimv, 1.0));
384 
385  if (s->stats_file) {
386  fprintf(s->stats_file, "n:%"PRId64" ", s->nb_frames);
387 
388  for (i = 0; i < s->nb_components; i++) {
389  int cidx = s->is_rgb ? s->rgba_map[i] : i;
390  fprintf(s->stats_file, "%c:%f ", s->comps[i], c[cidx]);
391  }
392 
393  fprintf(s->stats_file, "All:%f (%f)\n", ssimv, ssim_db(ssimv, 1.0));
394  }
395 
396  return ff_filter_frame(ctx->outputs[0], master);
397 }
398 
400 {
401  SSIMContext *s = ctx->priv;
402 
403  if (s->stats_file_str) {
404  if (!strcmp(s->stats_file_str, "-")) {
405  s->stats_file = stdout;
406  } else {
407  s->stats_file = fopen(s->stats_file_str, "w");
408  if (!s->stats_file) {
409  int err = AVERROR(errno);
410  char buf[128];
411  av_strerror(err, buf, sizeof(buf));
412  av_log(ctx, AV_LOG_ERROR, "Could not open stats file %s: %s\n",
413  s->stats_file_str, buf);
414  return err;
415  }
416  }
417  }
418 
419  s->fs.on_event = do_ssim;
420  return 0;
421 }
422 
424 {
425  static const enum AVPixelFormat pix_fmts[] = {
433 #define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf, AV_PIX_FMT_GBR##suf
434  PF(P9), PF(P10), PF(P12), PF(P14), PF(P16),
436  };
437 
439  if (!fmts_list)
440  return AVERROR(ENOMEM);
441  return ff_set_common_formats(ctx, fmts_list);
442 }
443 
444 static int config_input_ref(AVFilterLink *inlink)
445 {
447  AVFilterContext *ctx = inlink->dst;
448  SSIMContext *s = ctx->priv;
449  int sum = 0, i;
450 
451  s->nb_threads = ff_filter_get_nb_threads(ctx);
452  s->nb_components = desc->nb_components;
453 
454  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
455  ctx->inputs[0]->h != ctx->inputs[1]->h) {
456  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
457  return AVERROR(EINVAL);
458  }
459  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
460  av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n");
461  return AVERROR(EINVAL);
462  }
463 
464  s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0;
465  s->comps[0] = s->is_rgb ? 'R' : 'Y';
466  s->comps[1] = s->is_rgb ? 'G' : 'U';
467  s->comps[2] = s->is_rgb ? 'B' : 'V';
468  s->comps[3] = 'A';
469 
470  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
471  s->planeheight[0] = s->planeheight[3] = inlink->h;
472  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
473  s->planewidth[0] = s->planewidth[3] = inlink->w;
474  for (i = 0; i < s->nb_components; i++)
475  sum += s->planeheight[i] * s->planewidth[i];
476  for (i = 0; i < s->nb_components; i++)
477  s->coefs[i] = (double) s->planeheight[i] * s->planewidth[i] / sum;
478 
479  s->temp = av_calloc(s->nb_threads, sizeof(*s->temp));
480  if (!s->temp)
481  return AVERROR(ENOMEM);
482 
483  for (int t = 0; t < s->nb_threads; t++) {
484  s->temp[t] = av_mallocz_array(2 * SUM_LEN(inlink->w), (desc->comp[0].depth > 8) ? sizeof(int64_t[4]) : sizeof(int[4]));
485  if (!s->temp[t])
486  return AVERROR(ENOMEM);
487  }
488  s->max = (1 << desc->comp[0].depth) - 1;
489 
490  s->ssim_plane = desc->comp[0].depth > 8 ? ssim_plane_16bit : ssim_plane;
491  s->dsp.ssim_4x4_line = ssim_4x4xn_8bit;
492  s->dsp.ssim_end_line = ssim_endn_8bit;
493  if (ARCH_X86)
494  ff_ssim_init_x86(&s->dsp);
495 
496  s->score = av_calloc(s->nb_threads, sizeof(*s->score));
497  if (!s->score)
498  return AVERROR(ENOMEM);
499 
500  for (int t = 0; t < s->nb_threads && s->score; t++) {
501  s->score[t] = av_calloc(s->nb_components, sizeof(*s->score[0]));
502  if (!s->score[t])
503  return AVERROR(ENOMEM);
504  }
505 
506  return 0;
507 }
508 
509 static int config_output(AVFilterLink *outlink)
510 {
511  AVFilterContext *ctx = outlink->src;
512  SSIMContext *s = ctx->priv;
513  AVFilterLink *mainlink = ctx->inputs[0];
514  int ret;
515 
516  ret = ff_framesync_init_dualinput(&s->fs, ctx);
517  if (ret < 0)
518  return ret;
519  outlink->w = mainlink->w;
520  outlink->h = mainlink->h;
521  outlink->time_base = mainlink->time_base;
522  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
523  outlink->frame_rate = mainlink->frame_rate;
524 
525  if ((ret = ff_framesync_configure(&s->fs)) < 0)
526  return ret;
527 
528  outlink->time_base = s->fs.time_base;
529 
530  if (av_cmp_q(mainlink->time_base, outlink->time_base) ||
531  av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base))
532  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",
533  mainlink->time_base.num, mainlink->time_base.den,
534  ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den);
535 
536  return 0;
537 }
538 
540 {
541  SSIMContext *s = ctx->priv;
542  return ff_framesync_activate(&s->fs);
543 }
544 
546 {
547  SSIMContext *s = ctx->priv;
548 
549  if (s->nb_frames > 0) {
550  char buf[256];
551  int i;
552  buf[0] = 0;
553  for (i = 0; i < s->nb_components; i++) {
554  int c = s->is_rgb ? s->rgba_map[i] : i;
555  av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[i], s->ssim[c] / s->nb_frames,
556  ssim_db(s->ssim[c], s->nb_frames));
557  }
558  av_log(ctx, AV_LOG_INFO, "SSIM%s All:%f (%f)\n", buf,
559  s->ssim_total / s->nb_frames, ssim_db(s->ssim_total, s->nb_frames));
560  }
561 
562  ff_framesync_uninit(&s->fs);
563 
564  if (s->stats_file && s->stats_file != stdout)
565  fclose(s->stats_file);
566 
567  for (int t = 0; t < s->nb_threads && s->score; t++)
568  av_freep(&s->score[t]);
569  av_freep(&s->score);
570 
571  for (int t = 0; t < s->nb_threads && s->temp; t++)
572  av_freep(&s->temp[t]);
573  av_freep(&s->temp);
574 }
575 
576 static const AVFilterPad ssim_inputs[] = {
577  {
578  .name = "main",
579  .type = AVMEDIA_TYPE_VIDEO,
580  },{
581  .name = "reference",
582  .type = AVMEDIA_TYPE_VIDEO,
583  .config_props = config_input_ref,
584  },
585  { NULL }
586 };
587 
588 static const AVFilterPad ssim_outputs[] = {
589  {
590  .name = "default",
591  .type = AVMEDIA_TYPE_VIDEO,
592  .config_props = config_output,
593  },
594  { NULL }
595 };
596 
598  .name = "ssim",
599  .description = NULL_IF_CONFIG_SMALL("Calculate the SSIM between two video streams."),
600  .preinit = ssim_framesync_preinit,
601  .init = init,
602  .uninit = uninit,
603  .query_formats = query_formats,
604  .activate = activate,
605  .priv_size = sizeof(SSIMContext),
606  .priv_class = &ssim_class,
607  .inputs = ssim_inputs,
610 };
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:100
int
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
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:52
int planewidth[4]
Definition: vf_ssim.c:62
int nb_components
Definition: vf_ssim.c:54
double ssim_total
Definition: vf_ssim.c:58
char comps[4]
Definition: vf_ssim.c:59
uint8_t rgba_map[4]
Definition: vf_ssim.c:61
int max
Definition: vf_ssim.c:56
uint64_t nb_frames
Definition: vf_ssim.c:57
double coefs[4]
Definition: vf_ssim.c:60
double ssim[4]
Definition: vf_ssim.c:58
int nb_threads
Definition: vf_ssim.c:55
double ** score
Definition: vf_ssim.c:66
char * stats_file_str
Definition: vf_ssim.c:53
SSIMDSPContext dsp
Definition: vf_ssim.c:69
int is_rgb
Definition: vf_ssim.c:65
int ** temp
Definition: vf_ssim.c:64
FFFrameSync fs
Definition: vf_ssim.c:51
int planeheight[4]
Definition: vf_ssim.c:63
int(* ssim_plane)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:67
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:92
double ** score
Definition: vf_ssim.c:231
int max
Definition: vf_ssim.c:234
int ** temp
Definition: vf_ssim.c:232
int planeheight[4]
Definition: vf_identity.c:90
const uint8_t * ref_data[4]
Definition: vf_identity.c:86
int main_linesize[4]
Definition: vf_identity.c:87
int planewidth[4]
Definition: vf_identity.c:89
const uint8_t * main_data[4]
Definition: vf_identity.c:85
int ref_linesize
Definition: vf_bm3d.c:59
SSIMDSPContext * dsp
Definition: vf_ssim.c:235
#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:119
const char * master
Definition: vf_curves.c:120
else temp
Definition: vf_mcdeint.c:259
static int ssim_plane(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:281
static int do_ssim(FFFrameSync *fs)
Definition: vf_ssim.c:329
FRAMESYNC_DEFINE_CLASS(ssim, SSIMContext, fs)
static float ssim_end1(int s1, int s2, int ss, int s12)
Definition: vf_ssim.c:179
static int query_formats(AVFilterContext *ctx)
Definition: vf_ssim.c:423
static double ssim_db(double ssim, double weight)
Definition: vf_ssim.c:324
AVFilter ff_vf_ssim
Definition: vf_ssim.c:597
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:132
#define FLAGS
Definition: vf_ssim.c:73
#define SUM_LEN(w)
Definition: vf_ssim.c:222
static const AVOption ssim_options[]
Definition: vf_ssim.c:75
static float ssim_endn_16bit(const int64_t(*sum0)[4], const int64_t(*sum1)[4], int width, int max)
Definition: vf_ssim.c:195
static const AVFilterPad ssim_outputs[]
Definition: vf_ssim.c:588
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_ssim.c:444
static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
Definition: vf_ssim.c:83
#define PF(suf)
static int activate(AVFilterContext *ctx)
Definition: vf_ssim.c:539
static av_cold int init(AVFilterContext *ctx)
Definition: vf_ssim.c:399
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_ssim.c:545
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:96
#define OFFSET(x)
Definition: vf_ssim.c:72
static int config_output(AVFilterLink *outlink)
Definition: vf_ssim.c:509
static double ssim_endn_8bit(const int(*sum0)[4], const int(*sum1)[4], int width)
Definition: vf_ssim.c:209
static float ssim_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max)
Definition: vf_ssim.c:163
static int ssim_plane_16bit(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_ssim.c:238
static const AVFilterPad ssim_inputs[]
Definition: vf_ssim.c:576
static double c[64]