FFmpeg
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;
54  int max;
55  uint64_t nb_frames;
56  double ssim[4], ssim_total;
57  char comps[4];
58  float coefs[4];
60  int planewidth[4];
61  int planeheight[4];
62  int *temp;
63  int is_rgb;
65  uint8_t *main, int main_stride,
66  uint8_t *ref, int ref_stride,
67  int width, int height, void *temp,
68  int max);
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), "%0.2f", 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 float ssim_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width)
210 {
211  float 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 
225  uint8_t *main, int main_stride,
226  uint8_t *ref, int ref_stride,
227  int width, int height, void *temp,
228  int max)
229 {
230  int z = 0, y;
231  float ssim = 0.0;
232  int64_t (*sum0)[4] = temp;
233  int64_t (*sum1)[4] = sum0 + SUM_LEN(width);
234 
235  width >>= 2;
236  height >>= 2;
237 
238  for (y = 1; y < height; y++) {
239  for (; z <= y; z++) {
240  FFSWAP(void*, sum0, sum1);
241  ssim_4x4xn_16bit(&main[4 * z * main_stride], main_stride,
242  &ref[4 * z * ref_stride], ref_stride,
243  sum0, width);
244  }
245 
246  ssim += ssim_endn_16bit((const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, width - 1, max);
247  }
248 
249  return ssim / ((height - 1) * (width - 1));
250 }
251 
252 static float ssim_plane(SSIMDSPContext *dsp,
253  uint8_t *main, int main_stride,
254  uint8_t *ref, int ref_stride,
255  int width, int height, void *temp,
256  int max)
257 {
258  int z = 0, y;
259  float ssim = 0.0;
260  int (*sum0)[4] = temp;
261  int (*sum1)[4] = sum0 + SUM_LEN(width);
262 
263  width >>= 2;
264  height >>= 2;
265 
266  for (y = 1; y < height; y++) {
267  for (; z <= y; z++) {
268  FFSWAP(void*, sum0, sum1);
269  dsp->ssim_4x4_line(&main[4 * z * main_stride], main_stride,
270  &ref[4 * z * ref_stride], ref_stride,
271  sum0, width);
272  }
273 
274  ssim += dsp->ssim_end_line((const int (*)[4])sum0, (const int (*)[4])sum1, width - 1);
275  }
276 
277  return ssim / ((height - 1) * (width - 1));
278 }
279 
280 static double ssim_db(double ssim, double weight)
281 {
282  return 10 * log10(weight / (weight - ssim));
283 }
284 
285 static int do_ssim(FFFrameSync *fs)
286 {
287  AVFilterContext *ctx = fs->parent;
288  SSIMContext *s = ctx->priv;
289  AVFrame *master, *ref;
290  AVDictionary **metadata;
291  float c[4], ssimv = 0.0;
292  int ret, i;
293 
295  if (ret < 0)
296  return ret;
297  if (!ref)
298  return ff_filter_frame(ctx->outputs[0], master);
299  metadata = &master->metadata;
300 
301  s->nb_frames++;
302 
303  for (i = 0; i < s->nb_components; i++) {
304  c[i] = s->ssim_plane(&s->dsp, master->data[i], master->linesize[i],
305  ref->data[i], ref->linesize[i],
306  s->planewidth[i], s->planeheight[i], s->temp,
307  s->max);
308  ssimv += s->coefs[i] * c[i];
309  s->ssim[i] += c[i];
310  }
311  for (i = 0; i < s->nb_components; i++) {
312  int cidx = s->is_rgb ? s->rgba_map[i] : i;
313  set_meta(metadata, "lavfi.ssim.", s->comps[i], c[cidx]);
314  }
315  s->ssim_total += ssimv;
316 
317  set_meta(metadata, "lavfi.ssim.All", 0, ssimv);
318  set_meta(metadata, "lavfi.ssim.dB", 0, ssim_db(ssimv, 1.0));
319 
320  if (s->stats_file) {
321  fprintf(s->stats_file, "n:%"PRId64" ", s->nb_frames);
322 
323  for (i = 0; i < s->nb_components; i++) {
324  int cidx = s->is_rgb ? s->rgba_map[i] : i;
325  fprintf(s->stats_file, "%c:%f ", s->comps[i], c[cidx]);
326  }
327 
328  fprintf(s->stats_file, "All:%f (%f)\n", ssimv, ssim_db(ssimv, 1.0));
329  }
330 
331  return ff_filter_frame(ctx->outputs[0], master);
332 }
333 
335 {
336  SSIMContext *s = ctx->priv;
337 
338  if (s->stats_file_str) {
339  if (!strcmp(s->stats_file_str, "-")) {
340  s->stats_file = stdout;
341  } else {
342  s->stats_file = fopen(s->stats_file_str, "w");
343  if (!s->stats_file) {
344  int err = AVERROR(errno);
345  char buf[128];
346  av_strerror(err, buf, sizeof(buf));
347  av_log(ctx, AV_LOG_ERROR, "Could not open stats file %s: %s\n",
348  s->stats_file_str, buf);
349  return err;
350  }
351  }
352  }
353 
354  s->fs.on_event = do_ssim;
355  return 0;
356 }
357 
359 {
360  static const enum AVPixelFormat pix_fmts[] = {
368 #define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf, AV_PIX_FMT_GBR##suf
369  PF(P9), PF(P10), PF(P12), PF(P14), PF(P16),
371  };
372 
374  if (!fmts_list)
375  return AVERROR(ENOMEM);
376  return ff_set_common_formats(ctx, fmts_list);
377 }
378 
380 {
382  AVFilterContext *ctx = inlink->dst;
383  SSIMContext *s = ctx->priv;
384  int sum = 0, i;
385 
386  s->nb_components = desc->nb_components;
387 
388  if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
389  ctx->inputs[0]->h != ctx->inputs[1]->h) {
390  av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n");
391  return AVERROR(EINVAL);
392  }
393  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
394  av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n");
395  return AVERROR(EINVAL);
396  }
397 
398  s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0;
399  s->comps[0] = s->is_rgb ? 'R' : 'Y';
400  s->comps[1] = s->is_rgb ? 'G' : 'U';
401  s->comps[2] = s->is_rgb ? 'B' : 'V';
402  s->comps[3] = 'A';
403 
404  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
405  s->planeheight[0] = s->planeheight[3] = inlink->h;
406  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
407  s->planewidth[0] = s->planewidth[3] = inlink->w;
408  for (i = 0; i < s->nb_components; i++)
409  sum += s->planeheight[i] * s->planewidth[i];
410  for (i = 0; i < s->nb_components; i++)
411  s->coefs[i] = (double) s->planeheight[i] * s->planewidth[i] / sum;
412 
413  s->temp = av_mallocz_array(2 * SUM_LEN(inlink->w), (desc->comp[0].depth > 8) ? sizeof(int64_t[4]) : sizeof(int[4]));
414  if (!s->temp)
415  return AVERROR(ENOMEM);
416  s->max = (1 << desc->comp[0].depth) - 1;
417 
418  s->ssim_plane = desc->comp[0].depth > 8 ? ssim_plane_16bit : ssim_plane;
419  s->dsp.ssim_4x4_line = ssim_4x4xn_8bit;
420  s->dsp.ssim_end_line = ssim_endn_8bit;
421  if (ARCH_X86)
422  ff_ssim_init_x86(&s->dsp);
423 
424  return 0;
425 }
426 
427 static int config_output(AVFilterLink *outlink)
428 {
429  AVFilterContext *ctx = outlink->src;
430  SSIMContext *s = ctx->priv;
431  AVFilterLink *mainlink = ctx->inputs[0];
432  int ret;
433 
435  if (ret < 0)
436  return ret;
437  outlink->w = mainlink->w;
438  outlink->h = mainlink->h;
439  outlink->time_base = mainlink->time_base;
440  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
441  outlink->frame_rate = mainlink->frame_rate;
442 
443  if ((ret = ff_framesync_configure(&s->fs)) < 0)
444  return ret;
445 
446  return 0;
447 }
448 
450 {
451  SSIMContext *s = ctx->priv;
452  return ff_framesync_activate(&s->fs);
453 }
454 
456 {
457  SSIMContext *s = ctx->priv;
458 
459  if (s->nb_frames > 0) {
460  char buf[256];
461  int i;
462  buf[0] = 0;
463  for (i = 0; i < s->nb_components; i++) {
464  int c = s->is_rgb ? s->rgba_map[i] : i;
465  av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[i], s->ssim[c] / s->nb_frames,
466  ssim_db(s->ssim[c], s->nb_frames));
467  }
468  av_log(ctx, AV_LOG_INFO, "SSIM%s All:%f (%f)\n", buf,
469  s->ssim_total / s->nb_frames, ssim_db(s->ssim_total, s->nb_frames));
470  }
471 
472  ff_framesync_uninit(&s->fs);
473 
474  if (s->stats_file && s->stats_file != stdout)
475  fclose(s->stats_file);
476 
477  av_freep(&s->temp);
478 }
479 
480 static const AVFilterPad ssim_inputs[] = {
481  {
482  .name = "main",
483  .type = AVMEDIA_TYPE_VIDEO,
484  },{
485  .name = "reference",
486  .type = AVMEDIA_TYPE_VIDEO,
487  .config_props = config_input_ref,
488  },
489  { NULL }
490 };
491 
492 static const AVFilterPad ssim_outputs[] = {
493  {
494  .name = "default",
495  .type = AVMEDIA_TYPE_VIDEO,
496  .config_props = config_output,
497  },
498  { NULL }
499 };
500 
502  .name = "ssim",
503  .description = NULL_IF_CONFIG_SMALL("Calculate the SSIM between two video streams."),
504  .preinit = ssim_framesync_preinit,
505  .init = init,
506  .uninit = uninit,
507  .query_formats = query_formats,
508  .activate = activate,
509  .priv_size = sizeof(SSIMContext),
510  .priv_class = &ssim_class,
511  .inputs = ssim_inputs,
513 };
SSIMContext::comps
char comps[4]
Definition: vf_ssim.c:57
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:117
ff_ssim_init_x86
void ff_ssim_init_x86(SSIMDSPContext *dsp)
Definition: vf_ssim_init.c:33
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
SSIMContext::rgba_map
uint8_t rgba_map[4]
Definition: vf_ssim.c:59
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:293
FFSWAP
#define FFSWAP(type, a, b)
Definition: common.h:99
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:83
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
ssim_end1x
static float ssim_end1x(int64_t s1, int64_t s2, int64_t ss, int64_t s12, int max)
Definition: vf_ssim.c:163
activate
static int activate(AVFilterContext *ctx)
Definition: vf_ssim.c:449
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
config_input_ref
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_ssim.c:379
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
pixdesc.h
AVOption
AVOption.
Definition: opt.h:246
b
#define b
Definition: input.c:41
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
max
#define max(a, b)
Definition: cuda_runtime.h:33
FLAGS
#define FLAGS
Definition: vf_ssim.c:73
AVDictionary
Definition: dict.c:30
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:148
FFFrameSync
Frame sync structure.
Definition: framesync.h:146
video.h
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:367
SSIMContext::fs
FFFrameSync fs
Definition: vf_ssim.c:50
ssim.h
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
formats.h
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_ssim.c:358
ssim_options
static const AVOption ssim_options[]
Definition: vf_ssim.c:75
PF
#define PF(suf)
av_strerror
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
SSIMContext::ssim
double ssim[4]
Definition: vf_ssim.c:56
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:371
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
AV_PIX_FMT_YUVJ411P
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
av_cold
#define av_cold
Definition: attributes.h:84
ff_set_common_formats
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
width
#define width
ssim_endn_16bit
static float ssim_endn_16bit(const int64_t(*sum0)[4], const int64_t(*sum1)[4], int width, int max)
Definition: vf_ssim.c:195
s
#define s(width, name)
Definition: cbs_vp9.c:257
SSIMDSPContext::ssim_4x4_line
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
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
ssim_inputs
static const AVFilterPad ssim_inputs[]
Definition: vf_ssim.c:480
SSIMDSPContext::ssim_end_line
float(* ssim_end_line)(const int(*sum0)[4], const int(*sum1)[4], int w)
Definition: ssim.h:31
s1
#define s1
Definition: regdef.h:38
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
SSIMContext::planeheight
int planeheight[4]
Definition: vf_ssim.c:61
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:370
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
key
const char * key
Definition: hwcontext_opencl.c:168
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
ssim_4x4xn_8bit
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
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:368
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:259
vars
static const uint8_t vars[2][12]
Definition: camellia.c:179
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
FRAMESYNC_DEFINE_CLASS
FRAMESYNC_DEFINE_CLASS(ssim, SSIMContext, fs)
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
SUM_LEN
#define SUM_LEN(w)
Definition: vf_ssim.c:222
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
weight
static int weight(int i, int blen, int offset)
Definition: diracdec.c:1564
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
s2
#define s2
Definition: regdef.h:39
desc
const char * desc
Definition: nvenc.c:68
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
ff_framesync_init_dualinput
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:361
master
const char * master
Definition: vf_curves.c:117
ssim_db
static double ssim_db(double ssim, double weight)
Definition: vf_ssim.c:280
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_ssim.c:334
SSIMContext::planewidth
int planewidth[4]
Definition: vf_ssim.c:60
ssim_endn_8bit
static float ssim_endn_8bit(const int(*sum0)[4], const int(*sum1)[4], int width)
Definition: vf_ssim.c:209
height
#define height
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
main
int main(int argc, char *argv[])
Definition: avio_dir_cmd.c:134
SSIMContext::nb_components
int nb_components
Definition: vf_ssim.c:53
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_ssim.c:455
internal.h
ssim_outputs
static const AVFilterPad ssim_outputs[]
Definition: vf_ssim.c:492
ssim_plane_16bit
static float ssim_plane_16bit(SSIMDSPContext *dsp, uint8_t *main, int main_stride, uint8_t *ref, int ref_stride, int width, int height, void *temp, int max)
Definition: vf_ssim.c:224
do_ssim
static int do_ssim(FFFrameSync *fs)
Definition: vf_ssim.c:285
ssim_4x4xn_16bit
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
SSIMContext::ssim_total
double ssim_total
Definition: vf_ssim.c:56
ssim_end1
static float ssim_end1(int s1, int s2, int ss, int s12)
Definition: vf_ssim.c:179
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
ff_vf_ssim
AVFilter ff_vf_ssim
Definition: vf_ssim.c:501
OFFSET
#define OFFSET(x)
Definition: vf_ssim.c:72
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
uint8_t
uint8_t
Definition: audio_convert.c:194
SSIMContext::nb_frames
uint64_t nb_frames
Definition: vf_ssim.c:55
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
SSIMContext::stats_file_str
char * stats_file_str
Definition: vf_ssim.c:52
AVFilter
Filter definition.
Definition: avfilter.h:144
ret
ret
Definition: filter_design.txt:187
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_ssim.c:427
SSIMContext::is_rgb
int is_rgb
Definition: vf_ssim.c:63
SSIMContext::dsp
SSIMDSPContext dsp
Definition: vf_ssim.c:69
framesync.h
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
avfilter.h
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
temp
else temp
Definition: vf_mcdeint.c:256
SSIMDSPContext
Definition: ssim.h:27
set_meta
static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
Definition: vf_ssim.c:83
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
ssim_plane
static float ssim_plane(SSIMDSPContext *dsp, uint8_t *main, int main_stride, uint8_t *ref, int ref_stride, int width, int height, void *temp, int max)
Definition: vf_ssim.c:252
AVFilterContext
An instance of a filter.
Definition: avfilter.h:338
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
SSIMContext::ssim_plane
float(* ssim_plane)(SSIMDSPContext *dsp, uint8_t *main, int main_stride, uint8_t *ref, int ref_stride, int width, int height, void *temp, int max)
Definition: vf_ssim.c:64
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
SSIMContext
Definition: vf_ssim.c:48
SSIMContext::temp
int * temp
Definition: vf_ssim.c:62
AV_PIX_FMT_YUV410P
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
SSIMContext::max
int max
Definition: vf_ssim.c:54
SSIMContext::stats_file
FILE * stats_file
Definition: vf_ssim.c:51
ff_framesync_activate
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:344
avstring.h
ff_framesync_dualinput_get
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:379
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:369
drawutils.h
SSIMContext::coefs
float coefs[4]
Definition: vf_ssim.c:58
int
int
Definition: ffmpeg_filter.c:191
snprintf
#define snprintf
Definition: snprintf.h:34