FFmpeg
vf_xpsnr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 Christian R. Helmrich
3  * Copyright (c) 2024 Christian Lehmann
4  * Copyright (c) 2024 Christian Stoffers
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 the extended perceptually weighted PSNR (XPSNR) between two input videos.
26  *
27  * Authors: Christian Helmrich, Lehmann, and Stoffers, Fraunhofer HHI, Berlin, Germany
28  */
29 
30 #include "libavutil/avstring.h"
31 #include "libavutil/file_open.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/pixdesc.h"
35 #include "avfilter.h"
36 #include "drawutils.h"
37 #include "filters.h"
38 #include "framesync.h"
39 #include "psnr.h"
40 #include "xpsnr.h"
41 
42 /* XPSNR structure definition */
43 
44 typedef struct XPSNRContext {
45  /* required basic variables */
46  const AVClass *class;
47  int bpp; /* unpacked */
48  int depth; /* packed */
49  char comps[4];
50  int num_comps;
51  uint64_t num_frames_64;
52  unsigned frame_rate;
54  int line_sizes[4];
55  int plane_height[4];
56  int plane_width[4];
57  uint8_t rgba_map[4];
58  FILE *stats_file;
60  /* XPSNR specific variables */
61  double *sse_luma;
62  double *weights;
63  int16_t *buf_org_m1;
64  int16_t *buf_org_m2;
65  int16_t *buf_org [3];
66  int16_t *buf_rec [3];
67  uint64_t max_error_64;
68  double sum_wdist [3];
69  double sum_xpsnr [3];
70  int and_is_inf[3];
71  int is_rgb;
74 } XPSNRContext;
75 
76 /* required macro definitions */
77 
78 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
79 #define OFFSET(x) offsetof(XPSNRContext, x)
80 #define XPSNR_GAMMA 2
81 
82 static const AVOption xpsnr_options[] = {
83  {"stats_file", "Set file where to store per-frame XPSNR information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
84  {"f", "Set file where to store per-frame XPSNR information", OFFSET(stats_file_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
85  { NULL }
86 };
87 
89 
90 /* XPSNR function definitions */
91 
92 static uint64_t highds(const int x_act, const int y_act, const int w_act, const int h_act, const int16_t *o_m0, const int o)
93 {
94  uint64_t sa_act = 0;
95 
96  for (int y = y_act; y < h_act; y += 2) {
97  for (int x = x_act; x < w_act; x += 2) {
98  const int f = 12 * ((int)o_m0[ y *o + x ] + (int)o_m0[ y *o + x+1] + (int)o_m0[(y+1)*o + x ] + (int)o_m0[(y+1)*o + x+1])
99  - 3 * ((int)o_m0[(y-1)*o + x ] + (int)o_m0[(y-1)*o + x+1] + (int)o_m0[(y+2)*o + x ] + (int)o_m0[(y+2)*o + x+1])
100  - 3 * ((int)o_m0[ y *o + x-1] + (int)o_m0[ y *o + x+2] + (int)o_m0[(y+1)*o + x-1] + (int)o_m0[(y+1)*o + x+2])
101  - 2 * ((int)o_m0[(y-1)*o + x-1] + (int)o_m0[(y-1)*o + x+2] + (int)o_m0[(y+2)*o + x-1] + (int)o_m0[(y+2)*o + x+2])
102  - ((int)o_m0[(y-2)*o + x-1] + (int)o_m0[(y-2)*o + x ] + (int)o_m0[(y-2)*o + x+1] + (int)o_m0[(y-2)*o + x+2]
103  + (int)o_m0[(y+3)*o + x-1] + (int)o_m0[(y+3)*o + x ] + (int)o_m0[(y+3)*o + x+1] + (int)o_m0[(y+3)*o + x+2]
104  + (int)o_m0[(y-1)*o + x-2] + (int)o_m0[ y *o + x-2] + (int)o_m0[(y+1)*o + x-2] + (int)o_m0[(y+2)*o + x-2]
105  + (int)o_m0[(y-1)*o + x+3] + (int)o_m0[ y *o + x+3] + (int)o_m0[(y+1)*o + x+3] + (int)o_m0[(y+2)*o + x+3]);
106  sa_act += (uint64_t) abs(f);
107  }
108  }
109  return sa_act;
110 }
111 
112 static uint64_t diff1st(const uint32_t w_act, const uint32_t h_act, const int16_t *o_m0, int16_t *o_m1, const int o)
113 {
114  uint64_t ta_act = 0;
115 
116  for (uint32_t y = 0; y < h_act; y += 2) {
117  for (uint32_t x = 0; x < w_act; x += 2) {
118  const int t = (int)o_m0[y*o + x] + (int)o_m0[y*o + x+1] + (int)o_m0[(y+1)*o + x] + (int)o_m0[(y+1)*o + x+1]
119  - ((int)o_m1[y*o + x] + (int)o_m1[y*o + x+1] + (int)o_m1[(y+1)*o + x] + (int)o_m1[(y+1)*o + x+1]);
120  ta_act += (uint64_t) abs(t);
121  o_m1[y*o + x ] = o_m0[y*o + x ]; o_m1[(y+1)*o + x ] = o_m0[(y+1)*o + x ];
122  o_m1[y*o + x+1] = o_m0[y*o + x+1]; o_m1[(y+1)*o + x+1] = o_m0[(y+1)*o + x+1];
123  }
124  }
125  return (ta_act * XPSNR_GAMMA);
126 }
127 
128 static uint64_t diff2nd(const uint32_t w_act, const uint32_t h_act, const int16_t *o_m0, int16_t *o_m1, int16_t *o_m2, const int o)
129 {
130  uint64_t ta_act = 0;
131 
132  for (uint32_t y = 0; y < h_act; y += 2) {
133  for (uint32_t x = 0; x < w_act; x += 2) {
134  const int t = (int)o_m0[y*o + x] + (int)o_m0[y*o + x+1] + (int)o_m0[(y+1)*o + x] + (int)o_m0[(y+1)*o + x+1]
135  - 2 * ((int)o_m1[y*o + x] + (int)o_m1[y*o + x+1] + (int)o_m1[(y+1)*o + x] + (int)o_m1[(y+1)*o + x+1])
136  + (int)o_m2[y*o + x] + (int)o_m2[y*o + x+1] + (int)o_m2[(y+1)*o + x] + (int)o_m2[(y+1)*o + x+1];
137  ta_act += (uint64_t) abs(t);
138  o_m2[y*o + x ] = o_m1[y*o + x ]; o_m2[(y+1)*o + x ] = o_m1[(y+1)*o + x ];
139  o_m2[y*o + x+1] = o_m1[y*o + x+1]; o_m2[(y+1)*o + x+1] = o_m1[(y+1)*o + x+1];
140  o_m1[y*o + x ] = o_m0[y*o + x ]; o_m1[(y+1)*o + x ] = o_m0[(y+1)*o + x ];
141  o_m1[y*o + x+1] = o_m0[y*o + x+1]; o_m1[(y+1)*o + x+1] = o_m0[(y+1)*o + x+1];
142  }
143  }
144  return (ta_act * XPSNR_GAMMA);
145 }
146 
147 static inline uint64_t calc_squared_error(XPSNRContext const *s,
148  const int16_t *blk_org, const uint32_t stride_org,
149  const int16_t *blk_rec, const uint32_t stride_rec,
150  const uint32_t block_width, const uint32_t block_height)
151 {
152  uint64_t sse = 0; /* sum of squared errors */
153 
154  for (uint32_t y = 0; y < block_height; y++) {
155  sse += s->pdsp.sse_line((const uint8_t *) blk_org, (const uint8_t *) blk_rec, (int) block_width);
156  blk_org += stride_org;
157  blk_rec += stride_rec;
158  }
159 
160  /* return nonweighted sum of squared errors */
161  return sse;
162 }
163 
164 static inline double calc_squared_error_and_weight (XPSNRContext const *s,
165  const int16_t *pic_org, const uint32_t stride_org,
166  int16_t *pic_org_m1, int16_t *pic_org_m2,
167  const int16_t *pic_rec, const uint32_t stride_rec,
168  const uint32_t offset_x, const uint32_t offset_y,
169  const uint32_t block_width, const uint32_t block_height,
170  const uint32_t bit_depth, const uint32_t int_frame_rate, double *ms_act)
171 {
172  const int o = (int) stride_org;
173  const int r = (int) stride_rec;
174  const int16_t *o_m0 = pic_org + offset_y * o + offset_x;
175  int16_t *o_m1 = pic_org_m1 + offset_y * o + offset_x;
176  int16_t *o_m2 = pic_org_m2 + offset_y * o + offset_x;
177  const int16_t *r_m0 = pic_rec + offset_y * r + offset_x;
178  const int b_val = (s->plane_width[0] * s->plane_height[0] > 2048 * 1152 ? 2 : 1); /* threshold is a bit more than HD resolution */
179  const int x_act = (offset_x > 0 ? 0 : b_val);
180  const int y_act = (offset_y > 0 ? 0 : b_val);
181  const int w_act = (offset_x + block_width < (uint32_t) s->plane_width [0] ? (int) block_width : (int) block_width - b_val);
182  const int h_act = (offset_y + block_height < (uint32_t) s->plane_height[0] ? (int) block_height : (int) block_height - b_val);
183 
184  const double sse = (double) calc_squared_error (s, o_m0, stride_org,
185  r_m0, stride_rec,
186  block_width, block_height);
187  uint64_t sa_act = 0; /* spatial abs. activity */
188  uint64_t ta_act = 0; /* temporal abs. activity */
189 
190  if (w_act <= x_act || h_act <= y_act) /* small */
191  return sse;
192 
193  if (b_val > 1) { /* highpass with downsampling */
194  if (w_act > 12)
195  sa_act = s->dsp.highds_func(x_act, y_act, w_act, h_act, o_m0, o);
196  else
197  highds(x_act, y_act, w_act, h_act, o_m0, o);
198  } else { /* <=HD highpass without downsampling */
199  for (int y = y_act; y < h_act; y++) {
200  for (int x = x_act; x < w_act; x++) {
201  const int f = 12 * (int)o_m0[y*o + x] - 2 * ((int)o_m0[y*o + x-1] + (int)o_m0[y*o + x+1] + (int)o_m0[(y-1)*o + x] + (int)o_m0[(y+1)*o + x])
202  - ((int)o_m0[(y-1)*o + x-1] + (int)o_m0[(y-1)*o + x+1] + (int)o_m0[(y+1)*o + x-1] + (int)o_m0[(y+1)*o + x+1]);
203  sa_act += (uint64_t) abs(f);
204  }
205  }
206  }
207 
208  /* calculate weight (average squared activity) */
209  *ms_act = (double) sa_act / ((double) (w_act - x_act) * (double) (h_act - y_act));
210 
211  if (b_val > 1) { /* highpass with downsampling */
212  if (int_frame_rate < 32) /* 1st-order diff */
213  ta_act = s->dsp.diff1st_func(block_width, block_height, o_m0, o_m1, o);
214  else /* 2nd-order diff (diff of two diffs) */
215  ta_act = s->dsp.diff2nd_func(block_width, block_height, o_m0, o_m1, o_m2, o);
216  } else { /* <=HD highpass without downsampling */
217  if (int_frame_rate < 32) { /* 1st-order diff */
218  for (uint32_t y = 0; y < block_height; y++) {
219  for (uint32_t x = 0; x < block_width; x++) {
220  const int t = (int)o_m0[y * o + x] - (int)o_m1[y * o + x];
221 
222  ta_act += XPSNR_GAMMA * (uint64_t) abs(t);
223  o_m1[y * o + x] = o_m0[y * o + x];
224  }
225  }
226  } else { /* 2nd-order diff (diff of 2 diffs) */
227  for (uint32_t y = 0; y < block_height; y++) {
228  for (uint32_t x = 0; x < block_width; x++) {
229  const int t = (int)o_m0[y * o + x] - 2 * (int)o_m1[y * o + x] + (int)o_m2[y * o + x];
230 
231  ta_act += XPSNR_GAMMA * (uint64_t) abs(t);
232  o_m2[y * o + x] = o_m1[y * o + x];
233  o_m1[y * o + x] = o_m0[y * o + x];
234  }
235  }
236  }
237  }
238 
239  /* weight += mean squared temporal activity */
240  *ms_act += (double) ta_act / ((double) block_width * (double) block_height);
241 
242  /* lower limit, accounts for high-pass gain */
243  if (*ms_act < (double) (1 << (bit_depth - 6)))
244  *ms_act = (double) (1 << (bit_depth - 6));
245 
246  *ms_act *= *ms_act; /* since SSE is squared */
247 
248  /* return nonweighted sum of squared errors */
249  return sse;
250 }
251 
252 static inline double get_avg_xpsnr (const double sqrt_wsse_val, const double sum_xpsnr_val,
253  const uint32_t image_width, const uint32_t image_height,
254  const uint64_t max_error_64, const uint64_t num_frames_64)
255 {
256  if (num_frames_64 == 0)
257  return INFINITY;
258 
259  if (sqrt_wsse_val >= (double) num_frames_64) { /* square-mean-root average */
260  const double avg_dist = sqrt_wsse_val / (double) num_frames_64;
261  const uint64_t num64 = (uint64_t) image_width * (uint64_t) image_height * max_error_64;
262 
263  return 10.0 * log10((double) num64 / ((double) avg_dist * (double) avg_dist));
264  }
265 
266  return sum_xpsnr_val / (double) num_frames_64; /* older log-domain average */
267 }
268 
269 static int get_wsse(AVFilterContext *ctx, int16_t **org, int16_t *org_m1,
270  int16_t *org_m2, int16_t **rec, uint64_t *const wsse64)
271 {
272  XPSNRContext *const s = ctx->priv;
273  const uint32_t w = s->plane_width [0]; /* luma image width in pixels */
274  const uint32_t h = s->plane_height[0];/* luma image height in pixels */
275  const double r = (double)(w * h) / (3840.0 * 2160.0); /* UHD ratio */
276  const uint32_t b = FFMAX(0, 4 * (int32_t) (32.0 * sqrt(r) +
277  0.5)); /* block size, integer multiple of 4 for SIMD */
278  const uint32_t w_blk = (w + b - 1) / b; /* luma width in units of blocks */
279  const double avg_act = sqrt(16.0 * (double) (1 << (2 * s->depth - 9)) / sqrt(FFMAX(0.00001,
280  r))); /* the sqrt(a_pic) */
281  const int *stride_org = (s->bpp == 1 ? s->plane_width : s->line_sizes);
282  uint32_t x, y, idx_blk = 0; /* the "16.0" above is due to fixed-point code */
283  double *const sse_luma = s->sse_luma;
284  double *const weights = s->weights;
285  int c;
286 
287  if (!wsse64 || (s->depth < 6) || (s->depth > 16) || (s->num_comps <= 0) ||
288  (s->num_comps > 3) || (w == 0) || (h == 0)) {
289  av_log(ctx, AV_LOG_ERROR, "Error in XPSNR routine: invalid argument(s).\n");
290  return AVERROR(EINVAL);
291  }
292  if (!weights || (b >= 4 && !sse_luma)) {
293  av_log(ctx, AV_LOG_ERROR, "Failed to allocate temporary block memory.\n");
294  return AVERROR(ENOMEM);
295  }
296 
297  if (b >= 4) {
298  const int16_t *p_org = org[0];
299  const uint32_t s_org = stride_org[0] / s->bpp;
300  const int16_t *p_rec = rec[0];
301  const uint32_t s_rec = s->plane_width[0];
302  double wsse_luma = 0.0;
303 
304  for (y = 0; y < h; y += b) { /* calculate block SSE and perceptual weights */
305  const uint32_t block_height = (y + b > h ? h - y : b);
306 
307  for (x = 0; x < w; x += b, idx_blk++) {
308  const uint32_t block_width = (x + b > w ? w - x : b);
309  double ms_act = 1.0, ms_act_prev = 0.0;
310 
311  sse_luma[idx_blk] = calc_squared_error_and_weight(s, p_org, s_org,
312  org_m1 /* pixel */,
313  org_m2 /* memory */,
314  p_rec, s_rec,
315  x, y,
316  block_width, block_height,
317  s->depth, s->frame_rate, &ms_act);
318  weights[idx_blk] = 1.0 / sqrt(ms_act);
319 
320  if (w * h <= 640 * 480) { /* in-line "min-smoothing" as in paper */
321  if (x == 0) /* first column */
322  ms_act_prev = (idx_blk > 1 ? weights[idx_blk - 2] : 0);
323  else /* after first column */
324  ms_act_prev = (x > b ? FFMAX(weights[idx_blk - 2], weights[idx_blk]) : weights[idx_blk]);
325 
326  if (idx_blk > w_blk) /* after the first row and first column */
327  ms_act_prev = FFMAX(ms_act_prev, weights[idx_blk - 1 - w_blk]); /* min (L, T) */
328  if ((idx_blk > 0) && (weights[idx_blk - 1] > ms_act_prev))
329  weights[idx_blk - 1] = ms_act_prev;
330 
331  if ((x + b >= w) && (y + b >= h) && (idx_blk > w_blk)) { /* last block in picture */
332  ms_act_prev = FFMAX(weights[idx_blk - 1], weights[idx_blk - w_blk]);
333  if (weights[idx_blk] > ms_act_prev)
334  weights[idx_blk] = ms_act_prev;
335  }
336  }
337  } /* for x */
338  } /* for y */
339 
340  for (y = idx_blk = 0; y < h; y += b) { /* calculate sum for luma (Y) XPSNR */
341  for (x = 0; x < w; x += b, idx_blk++) {
342  wsse_luma += sse_luma[idx_blk] * weights[idx_blk];
343  }
344  }
345  wsse64[0] = (wsse_luma <= 0.0 ? 0 : (uint64_t) (wsse_luma * avg_act + 0.5));
346  } /* b >= 4 */
347 
348  for (c = 0; c < s->num_comps; c++) { /* finalize WSSE value for each component */
349  const int16_t *p_org = org[c];
350  const uint32_t s_org = stride_org[c] / s->bpp;
351  const int16_t *p_rec = rec[c];
352  const uint32_t s_rec = s->plane_width[c];
353  const uint32_t w_pln = s->plane_width[c];
354  const uint32_t h_pln = s->plane_height[c];
355 
356  if (b < 4) /* picture is too small for XPSNR, calculate nonweighted PSNR */
357  wsse64[c] = calc_squared_error (s, p_org, s_org,
358  p_rec, s_rec,
359  w_pln, h_pln);
360  else if (c > 0) { /* b >= 4 so Y XPSNR has already been calculated above */
361  const uint32_t bx = (b * w_pln) / w;
362  const uint32_t by = (b * h_pln) / h; /* up to chroma downsampling by 4 */
363  double wsse_chroma = 0.0;
364 
365  for (y = idx_blk = 0; y < h_pln; y += by) { /* calc chroma (Cb/Cr) XPSNR */
366  const uint32_t block_height = (y + by > h_pln ? h_pln - y : by);
367 
368  for (x = 0; x < w_pln; x += bx, idx_blk++) {
369  const uint32_t block_width = (x + bx > w_pln ? w_pln - x : bx);
370 
371  wsse_chroma += (double) calc_squared_error (s, p_org + y * s_org + x, s_org,
372  p_rec + y * s_rec + x, s_rec,
373  block_width, block_height) * weights[idx_blk];
374  }
375  }
376  wsse64[c] = (wsse_chroma <= 0.0 ? 0 : (uint64_t) (wsse_chroma * avg_act + 0.5));
377  }
378  } /* for c */
379 
380  return 0;
381 }
382 
383 static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
384 {
385  char value[128];
386  snprintf(value, sizeof(value), "%f", d);
387  if (comp) {
388  char key2[128];
389  snprintf(key2, sizeof(key2), "%s%c", key, comp);
390  av_dict_set(metadata, key2, value, 0);
391  } else {
392  av_dict_set(metadata, key, value, 0);
393  }
394 }
395 
396 static int do_xpsnr(FFFrameSync *fs)
397 {
398  AVFilterContext *ctx = fs->parent;
399  XPSNRContext *const s = ctx->priv;
400  const uint32_t w = s->plane_width [0]; /* luma image width in pixels */
401  const uint32_t h = s->plane_height[0]; /* luma image height in pixels */
402  const uint32_t b = FFMAX(0, 4 * (int32_t) (32.0 * sqrt((double) (w * h) / (3840.0 * 2160.0)) + 0.5)); /* block size */
403  const uint32_t w_blk = (w + b - 1) / b; /* luma width in units of blocks */
404  const uint32_t h_blk = (h + b - 1) / b; /* luma height in units of blocks */
405  AVFrame *master, *ref = NULL;
406  int16_t *porg [3];
407  int16_t *prec [3];
408  uint64_t wsse64 [3] = {0, 0, 0};
409  double cur_xpsnr[3] = {INFINITY, INFINITY, INFINITY};
410  int c, ret_value, stride_org_bpp;
411  AVDictionary **metadata;
412 
413  if ((ret_value = ff_framesync_dualinput_get(fs, &master, &ref)) < 0)
414  return ret_value;
415  if (ctx->is_disabled || !ref)
416  return ff_filter_frame(ctx->outputs[0], master);
417  metadata = &master->metadata;
418 
419  /* prepare XPSNR calculations: allocate temporary picture and block memory */
420  if (!s->sse_luma)
421  s->sse_luma = av_malloc_array(w_blk * h_blk, sizeof(double));
422  if (!s->weights)
423  s->weights = av_malloc_array(w_blk * h_blk, sizeof(double));
424 
425  for (c = 0; c < s->num_comps; c++) /* create temporal org buffer memory */
426  s->line_sizes[c] = master->linesize[c];
427 
428  stride_org_bpp = (s->bpp == 1 ? s->plane_width[0] : s->line_sizes[0] / s->bpp);
429 
430  if (!s->buf_org_m1)
431  s->buf_org_m1 = av_calloc(s->plane_height[0], stride_org_bpp * sizeof(int16_t));
432  if (!s->buf_org_m2)
433  s->buf_org_m2 = av_calloc(s->plane_height[0], stride_org_bpp * sizeof(int16_t));
434 
435  if (s->bpp == 1) { /* 8 bit */
436  for (c = 0; c < s->num_comps; c++) { /* allocate org/rec buffer memory */
437  const int m = s->line_sizes[c]; /* master stride */
438  const int r = ref->linesize[c]; /* ref/c stride */
439  const int o = s->plane_width[c]; /* XPSNR stride */
440 
441  if (!s->buf_org[c])
442  s->buf_org[c] = av_calloc(s->plane_width[c], s->plane_height[c] * sizeof(int16_t));
443  if (!s->buf_rec[c])
444  s->buf_rec[c] = av_calloc(s->plane_width[c], s->plane_height[c] * sizeof(int16_t));
445 
446  porg[c] = s->buf_org[c];
447  prec[c] = s->buf_rec[c];
448 
449  for (int y = 0; y < s->plane_height[c]; y++) {
450  for (int x = 0; x < s->plane_width[c]; x++) {
451  porg[c][y * o + x] = (int16_t) master->data[c][y * m + x];
452  prec[c][y * o + x] = (int16_t) ref->data[c][y * r + x];
453  }
454  }
455  }
456  } else { /* 10, 12, 14 bit */
457  for (c = 0; c < s->num_comps; c++) {
458  porg[c] = (int16_t *) master->data[c];
459  prec[c] = (int16_t *) ref->data[c];
460  }
461  }
462 
463  /* extended perceptually weighted peak signal-to-noise ratio (XPSNR) value */
464  ret_value = get_wsse(ctx, porg, s->buf_org_m1, s->buf_org_m2, prec, wsse64);
465  if ( ret_value < 0 )
466  return ret_value; /* an error here means something went wrong earlier! */
467 
468  for (c = 0; c < s->num_comps; c++) {
469  const double sqrt_wsse = sqrt((double) wsse64[c]);
470 
471  cur_xpsnr[c] = get_avg_xpsnr (sqrt_wsse, INFINITY,
472  s->plane_width[c], s->plane_height[c],
473  s->max_error_64, 1 /* single frame */);
474  s->sum_wdist[c] += sqrt_wsse;
475  s->sum_xpsnr[c] += cur_xpsnr[c];
476  s->and_is_inf[c] &= isinf(cur_xpsnr[c]);
477  }
478  s->num_frames_64++;
479 
480  for (int j = 0; j < s->num_comps; j++) {
481  int c = s->is_rgb ? s->rgba_map[j] : j;
482  set_meta(metadata, "lavfi.xpsnr.xpsnr.", s->comps[j], cur_xpsnr[c]);
483  }
484 
485  if (s->stats_file) { /* print out frame- and component-wise XPSNR averages */
486  fprintf(s->stats_file, "n: %4"PRId64"", s->num_frames_64);
487 
488  for (c = 0; c < s->num_comps; c++)
489  fprintf(s->stats_file, " XPSNR %c: %3.4f", s->comps[c], cur_xpsnr[c]);
490  fprintf(s->stats_file, "\n");
491  }
492 
493  return ff_filter_frame(ctx->outputs[0], master);
494 }
495 
497 {
498  XPSNRContext *const s = ctx->priv;
499  int c;
500 
501  if (s->stats_file_str) {
502  if (!strcmp(s->stats_file_str, "-")) /* no stats file, so use stdout */
503  s->stats_file = stdout;
504  else {
505  s->stats_file = avpriv_fopen_utf8(s->stats_file_str, "w");
506 
507  if (!s->stats_file) {
508  const int err = AVERROR(errno);
509  char buf[128];
510 
511  av_strerror(err, buf, sizeof(buf));
512  av_log(ctx, AV_LOG_ERROR, "Could not open statistics file %s: %s\n", s->stats_file_str, buf);
513  return err;
514  }
515  }
516  }
517 
518  s->sse_luma = NULL;
519  s->weights = NULL;
520 
521  for (c = 0; c < 3; c++) { /* initialize XPSNR data of each color component */
522  s->buf_org [c] = NULL;
523  s->buf_rec [c] = NULL;
524  s->sum_wdist [c] = 0.0;
525  s->sum_xpsnr [c] = 0.0;
526  s->and_is_inf[c] = 1;
527  }
528 
529  s->fs.on_event = do_xpsnr;
530 
531  return 0;
532 }
533 
534 static const enum AVPixelFormat xpsnr_formats[] = {
536 #define PF_NOALPHA(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf
537 #define PF_ALPHA(suf) AV_PIX_FMT_YUVA420##suf, AV_PIX_FMT_YUVA422##suf, AV_PIX_FMT_YUVA444##suf
538 #define PF(suf) PF_NOALPHA(suf), PF_ALPHA(suf)
539  PF(P), PF(P9), PF(P10), PF_NOALPHA(P12), PF_NOALPHA(P14), PF(P16),
547 };
548 
550 {
552  AVFilterContext *ctx = inlink->dst;
553  XPSNRContext *const s = ctx->priv;
555 
556  if ((ctx->inputs[0]->w != ctx->inputs[1]->w) ||
557  (ctx->inputs[0]->h != ctx->inputs[1]->h)) {
558  av_log(ctx, AV_LOG_ERROR, "Width and height of the input videos must match.\n");
559  return AVERROR(EINVAL);
560  }
561  if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
562  av_log(ctx, AV_LOG_ERROR, "The input videos must be of the same pixel format.\n");
563  return AVERROR(EINVAL);
564  }
565 
566  s->bpp = (desc->comp[0].depth <= 8 ? 1 : 2);
567  s->depth = desc->comp[0].depth;
568  s->max_error_64 = (1 << s->depth) - 1; /* conventional limit */
569  s->max_error_64 *= s->max_error_64;
570 
571  s->frame_rate = il->frame_rate.num / il->frame_rate.den;
572 
573  s->num_comps = (desc->nb_components > 3 ? 3 : desc->nb_components);
574 
575  s->is_rgb = (ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0);
576  s->comps[0] = (s->is_rgb ? 'r' : 'y');
577  s->comps[1] = (s->is_rgb ? 'g' : 'u');
578  s->comps[2] = (s->is_rgb ? 'b' : 'v');
579  s->comps[3] = 'a';
580 
581  s->plane_width [1] = s->plane_width [2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
582  s->plane_width [0] = s->plane_width [3] = inlink->w;
583  s->plane_height[1] = s->plane_height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
584  s->plane_height[0] = s->plane_height[3] = inlink->h;
585 
586  /* XPSNR always operates with 16-bit internal precision */
587  ff_psnr_init(&s->pdsp, 15);
588  s->dsp.highds_func = highds; /* initialize filtering methods */
589  s->dsp.diff1st_func = diff1st;
590  s->dsp.diff2nd_func = diff2nd;
591 
592  return 0;
593 }
594 
595 static int config_output(AVFilterLink *outlink)
596 {
597  AVFilterContext *ctx = outlink->src;
598  XPSNRContext *s = ctx->priv;
599  AVFilterLink *mainlink = ctx->inputs[0];
600  FilterLink *il = ff_filter_link(mainlink);
601  FilterLink *ol = ff_filter_link(outlink);
602  int ret;
603 
604  if ((ret = ff_framesync_init_dualinput(&s->fs, ctx)) < 0)
605  return ret;
606 
607  outlink->w = mainlink->w;
608  outlink->h = mainlink->h;
609  outlink->time_base = mainlink->time_base;
610  outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
611  ol->frame_rate = il->frame_rate;
612 
613  if ((ret = ff_framesync_configure(&s->fs)) < 0)
614  return ret;
615 
616  outlink->time_base = s->fs.time_base;
617 
618  if (av_cmp_q(mainlink->time_base, outlink->time_base) ||
619  av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base))
620  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",
621  mainlink->time_base.num, mainlink->time_base.den,
622  ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den);
623 
624  return 0;
625 }
626 
628 {
629  XPSNRContext *s = ctx->priv;
630 
631  return ff_framesync_activate(&s->fs);
632 }
633 
635 {
636  XPSNRContext *const s = ctx->priv;
637  int c;
638 
639  if (s->num_frames_64 > 0) { /* print out overall component-wise mean XPSNR */
640  const double xpsnr_luma = get_avg_xpsnr(s->sum_wdist[0], s->sum_xpsnr[0],
641  s->plane_width[0], s->plane_height[0],
642  s->max_error_64, s->num_frames_64);
643  double xpsnr_min = xpsnr_luma;
644 
645  /* luma */
646  av_log(ctx, AV_LOG_INFO, "XPSNR %c: %3.4f", s->comps[0], xpsnr_luma);
647  if (s->stats_file) {
648  fprintf(s->stats_file, "\nXPSNR average, %"PRId64" frames", s->num_frames_64);
649  fprintf(s->stats_file, " %c: %3.4f", s->comps[0], xpsnr_luma);
650  }
651  /* chroma */
652  for (c = 1; c < s->num_comps; c++) {
653  const double xpsnr_chroma = get_avg_xpsnr(s->sum_wdist[c], s->sum_xpsnr[c],
654  s->plane_width[c], s->plane_height[c],
655  s->max_error_64, s->num_frames_64);
656  if (xpsnr_min > xpsnr_chroma)
657  xpsnr_min = xpsnr_chroma;
658 
659  av_log(ctx, AV_LOG_INFO, " %c: %3.4f", s->comps[c], xpsnr_chroma);
660  if (s->stats_file && s->stats_file != stdout)
661  fprintf(s->stats_file, " %c: %3.4f", s->comps[c], xpsnr_chroma);
662  }
663  /* print out line break, and minimum XPSNR across the color components */
664  if (s->num_comps > 1) {
665  av_log(ctx, AV_LOG_INFO, " (minimum: %3.4f)\n", xpsnr_min);
666  if (s->stats_file && s->stats_file != stdout)
667  fprintf(s->stats_file, " (minimum: %3.4f)\n", xpsnr_min);
668  } else {
669  av_log(ctx, AV_LOG_INFO, "\n");
670  if (s->stats_file && s->stats_file != stdout)
671  fprintf(s->stats_file, "\n");
672  }
673  }
674 
675  ff_framesync_uninit(&s->fs); /* free temporary picture or block buf memory */
676 
677  if (s->stats_file && s->stats_file != stdout)
678  fclose(s->stats_file);
679 
680  av_freep(&s->sse_luma);
681  av_freep(&s->weights );
682 
683  av_freep(&s->buf_org_m1);
684  av_freep(&s->buf_org_m2);
685 
686  for (c = 0; c < s->num_comps; c++) {
687  av_freep(&s->buf_org[c]);
688  av_freep(&s->buf_rec[c]);
689  }
690 }
691 
692 static const AVFilterPad xpsnr_inputs[] = {
693  {
694  .name = "main",
695  .type = AVMEDIA_TYPE_VIDEO,
696  }, {
697  .name = "reference",
698  .type = AVMEDIA_TYPE_VIDEO,
699  .config_props = config_input_ref,
700  }
701 };
702 
703 static const AVFilterPad xpsnr_outputs[] = {
704  {
705  .name = "default",
706  .type = AVMEDIA_TYPE_VIDEO,
707  .config_props = config_output,
708  }
709 };
710 
712  .p.name = "xpsnr",
713  .p.description = NULL_IF_CONFIG_SMALL("Calculate the extended perceptually weighted peak signal-to-noise ratio (XPSNR) between two video streams."),
714  .p.priv_class = &xpsnr_class,
716  .preinit = xpsnr_framesync_preinit,
717  .init = init,
718  .uninit = uninit,
719  .activate = activate,
720  .priv_size = sizeof(XPSNRContext),
724 };
XPSNRContext::and_is_inf
int and_is_inf[3]
Definition: vf_xpsnr.c:70
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:533
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:137
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
ff_psnr_init
void ff_psnr_init(PSNRDSPContext *dsp, int bpp)
Definition: psnr.c:58
XPSNRContext::pdsp
PSNRDSPContext pdsp
Definition: vf_xpsnr.c:73
INFINITY
#define INFINITY
Definition: mathematics.h:118
r
const char * r
Definition: vf_curves.c:127
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
get_wsse
static int get_wsse(AVFilterContext *ctx, int16_t **org, int16_t *org_m1, int16_t *org_m2, int16_t **rec, uint64_t *const wsse64)
Definition: vf_xpsnr.c:269
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: filters.h:242
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:301
FRAMESYNC_DEFINE_CLASS
FRAMESYNC_DEFINE_CLASS(xpsnr, XPSNRContext, fs)
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:81
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1078
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3244
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_xpsnr.c:496
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
XPSNRContext::comps
char comps[4]
Definition: vf_xpsnr.c:49
FLAGS
#define FLAGS
Definition: vf_xpsnr.c:78
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:410
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:41
XPSNRContext::frame_rate
unsigned frame_rate
Definition: vf_xpsnr.c:52
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_xpsnr.c:634
OFFSET
#define OFFSET(x)
Definition: vf_xpsnr.c:79
XPSNRContext::is_rgb
int is_rgb
Definition: vf_xpsnr.c:71
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:106
AVDictionary
Definition: dict.c:34
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:203
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
bit_depth
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition: af_astats.c:246
XPSNRContext::buf_org_m1
int16_t * buf_org_m1
Definition: vf_xpsnr.c:63
AV_PIX_FMT_GRAY9
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:490
activate
static int activate(AVFilterContext *ctx)
Definition: vf_xpsnr.c:627
XPSNRContext::num_comps
int num_comps
Definition: vf_xpsnr.c:50
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:528
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:212
XPSNRContext::depth
int depth
Definition: vf_xpsnr.c:48
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:109
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:526
XPSNRContext::num_frames_64
uint64_t num_frames_64
Definition: vf_xpsnr.c:51
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:494
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
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:283
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
calc_squared_error_and_weight
static double calc_squared_error_and_weight(XPSNRContext const *s, const int16_t *pic_org, const uint32_t stride_org, int16_t *pic_org_m1, int16_t *pic_org_m2, const int16_t *pic_rec, const uint32_t stride_rec, const uint32_t offset_x, const uint32_t offset_y, const uint32_t block_width, const uint32_t block_height, const uint32_t bit_depth, const uint32_t int_frame_rate, double *ms_act)
Definition: vf_xpsnr.c:164
av_cold
#define av_cold
Definition: attributes.h:90
XPSNRContext::fs
FFFrameSync fs
Definition: vf_xpsnr.c:53
FFFilter
Definition: filters.h:265
psnr.h
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:86
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:530
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:531
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_xpsnr.c:595
XPSNRContext::dsp
XPSNRDSPContext dsp
Definition: vf_xpsnr.c:72
filters.h
XPSNRContext::line_sizes
int line_sizes[4]
Definition: vf_xpsnr.c:54
ctx
AVFormatContext * ctx
Definition: movenc.c:49
XPSNRContext::stats_file_str
char * stats_file_str
Definition: vf_xpsnr.c:59
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:493
key
const char * key
Definition: hwcontext_opencl.c:189
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
file_open.h
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:87
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:491
XPSNRContext::rgba_map
uint8_t rgba_map[4]
Definition: vf_xpsnr.c:57
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:529
XPSNRContext::buf_rec
int16_t * buf_rec[3]
Definition: vf_xpsnr.c:66
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
XPSNRContext::buf_org_m2
int16_t * buf_org_m2
Definition: vf_xpsnr.c:64
NULL
#define NULL
Definition: coverity.c:32
XPSNRContext::buf_org
int16_t * buf_org[3]
Definition: vf_xpsnr.c:65
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:200
XPSNRContext::sum_wdist
double sum_wdist[3]
Definition: vf_xpsnr.c:68
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:85
set_meta
static void set_meta(AVDictionary **metadata, const char *key, char comp, float d)
Definition: vf_xpsnr.c:383
isinf
#define isinf(x)
Definition: libm.h:317
double
double
Definition: af_crystalizer.c:132
abs
#define abs(x)
Definition: cuda_runtime.h:35
XPSNRContext::plane_width
int plane_width[4]
Definition: vf_xpsnr.c:56
diff1st
static uint64_t diff1st(const uint32_t w_act, const uint32_t h_act, const int16_t *o_m0, int16_t *o_m1, const int o)
Definition: vf_xpsnr.c:112
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
PF
#define PF(suf)
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:525
PSNRDSPContext
Definition: psnr.h:27
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
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:197
xpsnr_formats
static enum AVPixelFormat xpsnr_formats[]
Definition: vf_xpsnr.c:534
xpsnr_options
static const AVOption xpsnr_options[]
Definition: vf_xpsnr.c:82
f
f
Definition: af_crystalizer.c:122
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:94
ff_framesync_init_dualinput
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:372
master
const char * master
Definition: vf_curves.c:130
XPSNRContext::sse_luma
double * sse_luma
Definition: vf_xpsnr.c:61
P
#define P
calc_squared_error
static uint64_t calc_squared_error(XPSNRContext const *s, const int16_t *blk_org, const uint32_t stride_org, const int16_t *blk_rec, const uint32_t stride_rec, const uint32_t block_width, const uint32_t block_height)
Definition: vf_xpsnr.c:147
PF_NOALPHA
#define PF_NOALPHA(suf)
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
xpsnr_outputs
static const AVFilterPad xpsnr_outputs[]
Definition: vf_xpsnr.c:703
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:527
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
weights
static const int weights[]
Definition: hevc_pel.c:32
XPSNRContext::max_error_64
uint64_t max_error_64
Definition: vf_xpsnr.c:67
get_avg_xpsnr
static double get_avg_xpsnr(const double sqrt_wsse_val, const double sum_xpsnr_val, const uint32_t image_width, const uint32_t image_height, const uint64_t max_error_64, const uint64_t num_frames_64)
Definition: vf_xpsnr.c:252
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
highds
static uint64_t highds(const int x_act, const int y_act, const int w_act, const int h_act, const int16_t *o_m0, const int o)
Definition: vf_xpsnr.c:92
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:107
XPSNRContext::sum_xpsnr
double sum_xpsnr[3]
Definition: vf_xpsnr.c:69
XPSNRContext::bpp
int bpp
Definition: vf_xpsnr.c:47
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
avpriv_fopen_utf8
FILE * avpriv_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
Definition: file_open.c:161
ff_vf_xpsnr
const FFFilter ff_vf_xpsnr
Definition: vf_xpsnr.c:711
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
xpsnr.h
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
ret
ret
Definition: filter_design.txt:187
XPSNRDSPContext
Definition: xpsnr.h:39
xpsnr_inputs
static const AVFilterPad xpsnr_inputs[]
Definition: vf_xpsnr.c:692
framesync.h
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
XPSNR_GAMMA
#define XPSNR_GAMMA
Definition: vf_xpsnr.c:80
avfilter.h
AVFILTER_FLAG_METADATA_ONLY
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition: avfilter.h:166
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
AVFilterContext
An instance of a filter.
Definition: avfilter.h:257
config_input_ref
static int config_input_ref(AVFilterLink *inlink)
Definition: vf_xpsnr.c:549
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:165
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
FFFilter::p
AVFilter p
The public AVFilter.
Definition: filters.h:269
mem.h
XPSNRContext
Definition: vf_xpsnr.c:44
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
XPSNRContext::plane_height
int plane_height[4]
Definition: vf_xpsnr.c:55
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
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:88
XPSNRContext::stats_file
FILE * stats_file
Definition: vf_xpsnr.c:58
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:80
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:79
int32_t
int32_t
Definition: audioconvert.c:56
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#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:188
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:79
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
sse
static int sse(MpegEncContext *s, const uint8_t *src1, const uint8_t *src2, int w, int h, int stride)
Definition: mpegvideo_enc.c:2666
h
h
Definition: vp9dsp_template.c:2070
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:352
avstring.h
do_xpsnr
static int do_xpsnr(FFFrameSync *fs)
Definition: vf_xpsnr.c:396
ff_framesync_dualinput_get
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Definition: framesync.c:390
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:492
drawutils.h
XPSNRContext::weights
double * weights
Definition: vf_xpsnr.c:62
snprintf
#define snprintf
Definition: snprintf.h:34
diff2nd
static uint64_t diff2nd(const uint32_t w_act, const uint32_t h_act, const int16_t *o_m0, int16_t *o_m1, int16_t *o_m2, const int o)
Definition: vf_xpsnr.c:128