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