FFmpeg
swscale.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Nikles Haas
3  * Copyright (C) 2003-2011 Michael Niedermayer <michaelni@gmx.at>
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 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <inttypes.h>
26 #include <stdarg.h>
27 #include <signal.h>
28 
29 #undef HAVE_AV_CONFIG_H
30 #include "libavutil/cpu.h"
31 #include "libavutil/pixdesc.h"
32 #include "libavutil/lfg.h"
33 #include "libavutil/sfc64.h"
34 #include "libavutil/frame.h"
35 #include "libavutil/opt.h"
36 #include "libavutil/time.h"
37 #include "libavutil/pixfmt.h"
38 #include "libavutil/avassert.h"
39 #include "libavutil/macros.h"
40 
41 #include "libswscale/swscale.h"
42 
43 struct options {
46  double prob;
47  int w, h;
48  int threads;
49  int iters;
50  int bench;
51  int flags;
52  int dither;
53  int unscaled;
54 };
55 
56 struct mode {
59 };
60 
61 const SwsFlags flags[] = {
62  0, // test defaults
67  SWS_POINT,
70 };
71 
73 static SwsContext *sws[3]; /* reused between tests for efficiency */
74 
75 static double speedup_logavg;
76 static double speedup_min = 1e10;
77 static double speedup_max = 0;
78 static int speedup_count;
79 
80 static const char *speedup_color(double ratio)
81 {
82  return ratio > 10.00 ? "\033[1;94m" : /* bold blue */
83  ratio > 2.00 ? "\033[1;32m" : /* bold green */
84  ratio > 1.02 ? "\033[32m" : /* green */
85  ratio > 0.98 ? "" : /* default */
86  ratio > 0.90 ? "\033[33m" : /* yellow */
87  ratio > 0.75 ? "\033[31m" : /* red */
88  "\033[1;31m"; /* bold red */
89 }
90 
91 static void exit_handler(int sig)
92 {
93  if (speedup_count) {
94  double ratio = exp(speedup_logavg / speedup_count);
95  printf("Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
96  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower",
98  }
99 
100  exit(sig);
101 }
102 
103 /* Estimate luma variance assuming uniform dither noise distribution */
105 {
107  float variance = 1.0 / 12;
108  if (desc->comp[0].depth < 8) {
109  /* Extra headroom for very low bit depth output */
110  variance *= (8 - desc->comp[0].depth);
111  }
112 
113  if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
114  return 0.0;
115  } else if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
116  const float r = 0.299 / (1 << desc->comp[0].depth);
117  const float g = 0.587 / (1 << desc->comp[1].depth);
118  const float b = 0.114 / (1 << desc->comp[2].depth);
119  return (r * r + g * g + b * b) * variance;
120  } else {
121  const float y = 1.0 / (1 << desc->comp[0].depth);
122  return y * y * variance;
123  }
124 }
125 
126 static int fmt_comps(enum AVPixelFormat fmt)
127 {
129  int comps = desc->nb_components >= 3 ? 0x7 : 0x1;
130  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
131  comps |= 0x8;
132  return comps;
133 }
134 
135 static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
136 {
137  av_assert1(out->format == AV_PIX_FMT_YUVA444P);
138  av_assert1(ref->format == out->format);
139  av_assert1(ref->width == out->width && ref->height == out->height);
140 
141  for (int p = 0; p < 4; p++) {
142  const int stride_a = out->linesize[p];
143  const int stride_b = ref->linesize[p];
144  const int w = out->width;
145  const int h = out->height;
146 
147  const int is_chroma = p == 1 || p == 2;
148  const uint8_t def = is_chroma ? 128 : 0xFF;
149  const int has_ref = comps & (1 << p);
150  double sum = 0;
151  int count = 0;
152 
153  /* 4x4 SSIM */
154  for (int y = 0; y < (h & ~3); y += 4) {
155  for (int x = 0; x < (w & ~3); x += 4) {
156  const float c1 = .01 * .01 * 255 * 255 * 64;
157  const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
158  int s1 = 0, s2 = 0, ss = 0, s12 = 0, var, covar;
159 
160  for (int yy = 0; yy < 4; yy++) {
161  for (int xx = 0; xx < 4; xx++) {
162  int a = out->data[p][(y + yy) * stride_a + x + xx];
163  int b = has_ref ? ref->data[p][(y + yy) * stride_b + x + xx] : def;
164  s1 += a;
165  s2 += b;
166  ss += a * a + b * b;
167  s12 += a * b;
168  }
169  }
170 
171  var = ss * 64 - s1 * s1 - s2 * s2;
172  covar = s12 * 64 - s1 * s2;
173  sum += (2 * s1 * s2 + c1) * (2 * covar + c2) /
174  ((s1 * s1 + s2 * s2 + c1) * (var + c2));
175  count++;
176  }
177  }
178 
179  ssim[p] = count ? sum / count : 0.0;
180  }
181 }
182 
183 static float get_loss(const float ssim[4])
184 {
185  const float weights[3] = { 0.8, 0.1, 0.1 }; /* tuned for Y'CrCr */
186 
187  float sum = 0;
188  for (int i = 0; i < 3; i++)
189  sum += weights[i] * ssim[i];
190  sum *= ssim[3]; /* ensure alpha errors get caught */
191 
192  return 1.0 - sum;
193 }
194 
195 static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode,
196  struct options opts)
197 {
198  SwsContext *sws_legacy;
199  int ret;
200 
201  sws_legacy = sws_alloc_context();
202  if (!sws_legacy)
203  return -1;
204 
205  sws_legacy->src_w = src->width;
206  sws_legacy->src_h = src->height;
207  sws_legacy->src_format = src->format;
208  sws_legacy->dst_w = dst->width;
209  sws_legacy->dst_h = dst->height;
210  sws_legacy->dst_format = dst->format;
211  sws_legacy->flags = mode.flags;
212  sws_legacy->dither = mode.dither;
213  sws_legacy->threads = opts.threads;
214 
215  if ((ret = sws_init_context(sws_legacy, NULL, NULL)) < 0)
216  goto error;
217 
218  for (int i = 0; ret >= 0 && i < opts.iters; i++)
219  ret = sws_scale_frame(sws_legacy, dst, src);
220 
221 error:
222  sws_freeContext(sws_legacy);
223  return ret;
224 }
225 
226 /* Runs a series of ref -> src -> dst -> out, and compares out vs ref */
227 static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
228  int dst_w, int dst_h, struct mode mode, struct options opts,
229  const AVFrame *ref, const float ssim_ref[4])
230 {
231  AVFrame *src = NULL, *dst = NULL, *out = NULL;
232  float ssim[4], ssim_sws[4];
233  const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt);
234  int64_t time, time_ref = 0;
235  int ret = -1;
236 
237  /* Estimate the expected amount of loss from bit depth reduction */
238  const float c1 = 0.01 * 0.01; /* stabilization constant */
239  const float ref_var = 1.0 / 12.0; /* uniformly distributed signal */
240  const float src_var = estimate_quantization_noise(src_fmt);
241  const float dst_var = estimate_quantization_noise(dst_fmt);
242  const float out_var = estimate_quantization_noise(ref->format);
243  const float total_var = src_var + dst_var + out_var;
244  const float ssim_luma = (2 * ref_var + c1) / (2 * ref_var + total_var + c1);
245  const float ssim_expected[4] = { ssim_luma, 1, 1, 1 }; /* for simplicity */
246  const float expected_loss = get_loss(ssim_expected);
247  float loss;
248 
249  src = av_frame_alloc();
250  dst = av_frame_alloc();
251  out = av_frame_alloc();
252  if (!src || !dst || !out)
253  goto error;
254 
258  src->width = out->width = ref->width;
259  src->height = out->height = ref->height;
260  out->format = ref->format;
261  src->format = src_fmt;
262  dst->format = dst_fmt;
263  dst->width = dst_w;
264  dst->height = dst_h;
265 
266  if (sws_scale_frame(sws[0], src, ref) < 0) {
267  av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
268  av_get_pix_fmt_name(ref->format), av_get_pix_fmt_name(src->format));
269  goto error;
270  }
271 
272  sws[1]->flags = mode.flags;
273  sws[1]->dither = mode.dither;
274  sws[1]->threads = opts.threads;
275 
276  time = av_gettime_relative();
277 
278  for (int i = 0; i < opts.iters; i++) {
279  if (sws_scale_frame(sws[1], dst, src) < 0) {
280  av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
281  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
282  goto error;
283  }
284  }
285 
286  time = av_gettime_relative() - time;
287 
288  if (sws_scale_frame(sws[2], out, dst) < 0) {
289  av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
290  av_get_pix_fmt_name(dst->format), av_get_pix_fmt_name(out->format));
291  goto error;
292  }
293 
294  get_ssim(ssim, out, ref, comps);
295  av_log(NULL, AV_LOG_INFO, "%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u\n",
296  av_get_pix_fmt_name(src->format), src->width, src->height,
297  av_get_pix_fmt_name(dst->format), dst->width, dst->height,
298  mode.flags, mode.dither);
299 
300  av_log(NULL, AV_LOG_VERBOSE - 4, " SSIM {Y=%f U=%f V=%f A=%f}\n",
301  ssim[0], ssim[1], ssim[2], ssim[3]);
302 
303  loss = get_loss(ssim);
304  if (loss - expected_loss > 1e-4 && dst_w >= ref->width && dst_h >= ref->height) {
305  const int bad = loss - expected_loss > 1e-2;
306  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
307  av_log(NULL, level, "%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u\n",
308  av_get_pix_fmt_name(src->format), src->width, src->height,
309  av_get_pix_fmt_name(dst->format), dst->width, dst->height,
310  mode.flags, mode.dither);
311  av_log(NULL, level, " loss %g is %s by %g, expected loss %g\n",
312  loss, bad ? "WORSE" : "worse", loss - expected_loss, expected_loss);
313  if (bad)
314  goto error;
315  }
316 
317  if (!ssim_ref && sws_isSupportedInput(src->format) && sws_isSupportedOutput(dst->format)) {
318  /* Compare against the legacy swscale API as a reference */
319  time_ref = av_gettime_relative();
320  if (scale_legacy(dst, src, mode, opts) < 0) {
321  av_log(NULL, AV_LOG_ERROR, "Failed ref %s ---> %s\n",
322  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
323  goto error;
324  }
325  time_ref = av_gettime_relative() - time_ref;
326 
327  if (sws_scale_frame(sws[2], out, dst) < 0)
328  goto error;
329 
330  get_ssim(ssim_sws, out, ref, comps);
331 
332  /* Legacy swscale does not perform bit accurate upconversions of low
333  * bit depth RGB. This artificially improves the SSIM score because the
334  * resulting error deletes some of the input dither noise. This gives
335  * it an unfair advantage when compared against a bit exact reference.
336  * Work around this by ensuring that the reference SSIM score is not
337  * higher than it theoretically "should" be. */
338  if (src_var > dst_var) {
339  const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var + c1);
340  ssim_sws[0] = FFMIN(ssim_sws[0], src_loss);
341  }
342 
343  ssim_ref = ssim_sws;
344  }
345 
346  if (ssim_ref) {
347  const float loss_ref = get_loss(ssim_ref);
348  if (loss - loss_ref > 1e-4) {
349  int bad = loss - loss_ref > 1e-2;
351  " loss %g is %s by %g, ref loss %g, "
352  "SSIM {Y=%f U=%f V=%f A=%f}\n",
353  loss, bad ? "WORSE" : "worse", loss - loss_ref, loss_ref,
354  ssim_ref[0], ssim_ref[1], ssim_ref[2], ssim_ref[3]);
355  if (bad)
356  goto error;
357  }
358  }
359 
360  if (opts.bench && time_ref) {
361  double ratio = (double) time_ref / time;
362  if (FFMIN(time, time_ref) > 100 /* don't pollute stats with low precision */) {
363  speedup_min = FFMIN(speedup_min, ratio);
364  speedup_max = FFMAX(speedup_max, ratio);
365  speedup_logavg += log(ratio);
366  speedup_count++;
367  }
368 
369  if (av_log_get_level() >= AV_LOG_INFO) {
370  printf(" time=%"PRId64" us, ref=%"PRId64" us, speedup=%.3fx %s%s\033[0m\n",
371  time / opts.iters, time_ref / opts.iters, ratio,
372  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
373  }
374  } else if (opts.bench) {
375  av_log(NULL, AV_LOG_INFO, " time=%"PRId64" us\n", time / opts.iters);
376  }
377 
378  fflush(stdout);
379  ret = 0; /* fall through */
380  error:
381  av_frame_free(&src);
382  av_frame_free(&dst);
383  av_frame_free(&out);
384  return ret;
385 }
386 
387 static inline int fmt_is_subsampled(enum AVPixelFormat fmt)
388 {
389  return av_pix_fmt_desc_get(fmt)->log2_chroma_w != 0 ||
391 }
392 
393 static int run_self_tests(const AVFrame *ref, struct options opts)
394 {
395  const int dst_w[] = { opts.w, opts.w - opts.w / 3, opts.w + opts.w / 3 };
396  const int dst_h[] = { opts.h, opts.h - opts.h / 3, opts.h + opts.h / 3 };
397 
398  enum AVPixelFormat src_fmt, dst_fmt,
399  src_fmt_min = 0,
400  dst_fmt_min = 0,
401  src_fmt_max = AV_PIX_FMT_NB - 1,
402  dst_fmt_max = AV_PIX_FMT_NB - 1;
403 
404  if (opts.src_fmt != AV_PIX_FMT_NONE)
405  src_fmt_min = src_fmt_max = opts.src_fmt;
406  if (opts.dst_fmt != AV_PIX_FMT_NONE)
407  dst_fmt_min = dst_fmt_max = opts.dst_fmt;
408 
409  for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
410  if (opts.unscaled && fmt_is_subsampled(src_fmt))
411  continue;
412  if (!sws_test_format(src_fmt, 0) || !sws_test_format(src_fmt, 1))
413  continue;
414  for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
415  if (opts.unscaled && fmt_is_subsampled(dst_fmt))
416  continue;
417  if (!sws_test_format(dst_fmt, 0) || !sws_test_format(dst_fmt, 1))
418  continue;
419  for (int h = 0; h < FF_ARRAY_ELEMS(dst_h); h++) {
420  for (int w = 0; w < FF_ARRAY_ELEMS(dst_w); w++) {
421  for (int f = 0; f < FF_ARRAY_ELEMS(flags); f++) {
422  struct mode mode = {
423  .flags = opts.flags >= 0 ? opts.flags : flags[f],
424  .dither = opts.dither >= 0 ? opts.dither : SWS_DITHER_AUTO,
425  };
426 
427  if (ff_sfc64_get(&prng_state) > UINT64_MAX * opts.prob)
428  continue;
429 
430  if (run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h],
431  mode, opts, ref, NULL) < 0)
432  return -1;
433 
434  if (opts.flags >= 0 || opts.unscaled)
435  break;
436  }
437  if (opts.unscaled)
438  break;
439  }
440  if (opts.unscaled)
441  break;
442  }
443  }
444  }
445 
446  return 0;
447 }
448 
449 static int run_file_tests(const AVFrame *ref, FILE *fp, struct options opts)
450 {
451  char buf[256];
452  int ret;
453 
454  while (fgets(buf, sizeof(buf), fp)) {
455  char src_fmt_str[21], dst_fmt_str[21];
456  enum AVPixelFormat src_fmt;
457  enum AVPixelFormat dst_fmt;
458  int sw, sh, dw, dh;
459  float ssim[4];
460  struct mode mode;
461 
462  ret = sscanf(buf,
463  "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
464  "SSIM {Y=%f U=%f V=%f A=%f}\n",
465  src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
466  &mode.flags, &mode.dither,
467  &ssim[0], &ssim[1], &ssim[2], &ssim[3]);
468  if (ret != 12) {
469  printf("%s", buf);
470  continue;
471  }
472 
473  src_fmt = av_get_pix_fmt(src_fmt_str);
474  dst_fmt = av_get_pix_fmt(dst_fmt_str);
475  if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE ||
476  sw != ref->width || sh != ref->height || dw > 8192 || dh > 8192 ||
478  av_log(NULL, AV_LOG_FATAL, "malformed input file\n");
479  return -1;
480  }
481 
482  if (opts.src_fmt != AV_PIX_FMT_NONE && src_fmt != opts.src_fmt ||
483  opts.dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts.dst_fmt)
484  continue;
485 
486  if (run_test(src_fmt, dst_fmt, dw, dh, mode, opts, ref, ssim) < 0)
487  return -1;
488  }
489 
490  return 0;
491 }
492 
493 int main(int argc, char **argv)
494 {
495  struct options opts = {
496  .src_fmt = AV_PIX_FMT_NONE,
497  .dst_fmt = AV_PIX_FMT_NONE,
498  .w = 96,
499  .h = 96,
500  .threads = 1,
501  .iters = 1,
502  .prob = 1.0,
503  .flags = -1,
504  .dither = -1,
505  };
506 
507  AVFrame *rgb = NULL, *ref = NULL;
508  FILE *fp = NULL;
509  AVLFG rand;
510  int ret = -1;
511 
512  for (int i = 1; i < argc; i += 2) {
513  if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
514  fprintf(stderr,
515  "swscale [options...]\n"
516  " -help\n"
517  " This text\n"
518  " -ref <file>\n"
519  " Uses file as reference to compare tests againsts. Tests that have become worse will contain the string worse or WORSE\n"
520  " -p <number between 0.0 and 1.0>\n"
521  " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
522  " It is often convenient to perform a random subset\n"
523  " -dst <pixfmt>\n"
524  " Only test the specified destination pixel format\n"
525  " -src <pixfmt>\n"
526  " Only test the specified source pixel format\n"
527  " -bench <iters>\n"
528  " Run benchmarks with the specified number of iterations. This mode also increases the size of the test images\n"
529  " -flags <flags>\n"
530  " Test with a specific combination of flags\n"
531  " -dither <mode>\n"
532  " Test with a specific dither mode\n"
533  " -unscaled <1 or 0>\n"
534  " If 1, test only conversions that do not involve scaling\n"
535  " -threads <threads>\n"
536  " Use the specified number of threads\n"
537  " -cpuflags <cpuflags>\n"
538  " Uses the specified cpuflags in the tests\n"
539  " -v <level>\n"
540  " Enable log verbosity at given level\n"
541  );
542  return 0;
543  }
544  if (argv[i][0] != '-' || i + 1 == argc)
545  goto bad_option;
546  if (!strcmp(argv[i], "-ref")) {
547  fp = fopen(argv[i + 1], "r");
548  if (!fp) {
549  fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
550  goto error;
551  }
552  } else if (!strcmp(argv[i], "-cpuflags")) {
553  unsigned flags = av_get_cpu_flags();
554  int res = av_parse_cpu_caps(&flags, argv[i + 1]);
555  if (res < 0) {
556  fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]);
557  goto error;
558  }
560  } else if (!strcmp(argv[i], "-src")) {
561  opts.src_fmt = av_get_pix_fmt(argv[i + 1]);
562  if (opts.src_fmt == AV_PIX_FMT_NONE) {
563  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
564  goto error;
565  }
566  } else if (!strcmp(argv[i], "-dst")) {
567  opts.dst_fmt = av_get_pix_fmt(argv[i + 1]);
568  if (opts.dst_fmt == AV_PIX_FMT_NONE) {
569  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
570  goto error;
571  }
572  } else if (!strcmp(argv[i], "-bench")) {
573  opts.bench = 1;
574  opts.iters = atoi(argv[i + 1]);
575  opts.iters = FFMAX(opts.iters, 1);
576  opts.w = 1920;
577  opts.h = 1080;
578  } else if (!strcmp(argv[i], "-flags")) {
579  opts.flags = strtol(argv[i + 1], NULL, 0);
580  } else if (!strcmp(argv[i], "-dither")) {
581  opts.dither = atoi(argv[i + 1]);
582  } else if (!strcmp(argv[i], "-unscaled")) {
583  opts.unscaled = atoi(argv[i + 1]);
584  } else if (!strcmp(argv[i], "-threads")) {
585  opts.threads = atoi(argv[i + 1]);
586  } else if (!strcmp(argv[i], "-p")) {
587  opts.prob = atof(argv[i + 1]);
588  } else if (!strcmp(argv[i], "-v")) {
589  av_log_set_level(atoi(argv[i + 1]));
590  } else {
591 bad_option:
592  fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]);
593  goto error;
594  }
595  }
596 
597  ff_sfc64_init(&prng_state, 0, 0, 0, 12);
598  av_lfg_init(&rand, 1);
599  signal(SIGINT, exit_handler);
600 
601  for (int i = 0; i < 3; i++) {
602  sws[i] = sws_alloc_context();
603  if (!sws[i])
604  goto error;
605  sws[i]->flags = SWS_BILINEAR;
606  }
607 
608  rgb = av_frame_alloc();
609  if (!rgb)
610  goto error;
611  rgb->width = opts.w / 12;
612  rgb->height = opts.h / 12;
613  rgb->format = AV_PIX_FMT_RGBA;
614  if (av_frame_get_buffer(rgb, 32) < 0)
615  goto error;
616 
617  for (int y = 0; y < rgb->height; y++) {
618  for (int x = 0; x < rgb->width; x++) {
619  for (int c = 0; c < 4; c++)
620  rgb->data[0][y * rgb->linesize[0] + x * 4 + c] = av_lfg_get(&rand);
621  }
622  }
623 
624  ref = av_frame_alloc();
625  if (!ref)
626  goto error;
627  ref->width = opts.w;
628  ref->height = opts.h;
629  ref->format = AV_PIX_FMT_YUVA444P;
630 
631  if (sws_scale_frame(sws[0], ref, rgb) < 0)
632  goto error;
633 
634  ret = fp ? run_file_tests(ref, fp, opts)
635  : run_self_tests(ref, opts);
636 
637  /* fall through */
638 error:
639  for (int i = 0; i < 3; i++)
641  av_frame_free(&rgb);
642  av_frame_free(&ref);
643  if (fp)
644  fclose(fp);
645  exit_handler(ret);
646 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
flags
const SwsFlags flags[]
Definition: swscale.c:61
av_force_cpu_flags
void av_force_cpu_flags(int arg)
Disables cpu detection and forces the specified flags.
Definition: cpu.c:81
av_gettime_relative
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
level
uint8_t level
Definition: svq3.c:208
SWS_DITHER_AUTO
@ SWS_DITHER_AUTO
Definition: swscale.h:81
r
const char * r
Definition: vf_curves.c:127
printf
__device__ int printf(const char *,...)
opt.h
scale_legacy
static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode, struct options opts)
Definition: swscale.c:195
out
FILE * out
Definition: movenc.c:55
sws_isSupportedOutput
#define sws_isSupportedOutput(x)
av_frame_get_buffer
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:206
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
fmt_is_subsampled
static int fmt_is_subsampled(enum AVPixelFormat fmt)
Definition: swscale.c:387
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
SwsContext::src_w
int src_w
Deprecated frame property overrides, for the legacy API only.
Definition: swscale.h:235
estimate_quantization_noise
static float estimate_quantization_noise(enum AVPixelFormat fmt)
Definition: swscale.c:104
int64_t
long long int64_t
Definition: coverity.c:34
AV_PIX_FMT_FLAG_FLOAT
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
Definition: pixdesc.h:158
sws_freeContext
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2244
normalize.log
log
Definition: normalize.py:21
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
options::unscaled
int unscaled
Definition: swscale.c:53
mode
Definition: swscale.c:56
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
speedup_color
static const char * speedup_color(double ratio)
Definition: swscale.c:80
SWS_BILINEAR
@ SWS_BILINEAR
bilinear filtering
Definition: swscale.h:99
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:156
b
#define b
Definition: input.c:42
options::dither
int dither
Definition: swscale.c:52
ff_sfc64_init
static void ff_sfc64_init(FFSFC64 *s, uint64_t seeda, uint64_t seedb, uint64_t seedc, int rounds)
Initialize sfc64 with up to 3 seeds.
Definition: sfc64.h:75
SwsContext::flags
unsigned flags
Bitmask of SWS_*.
Definition: swscale.h:202
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:109
c1
static const uint64_t c1
Definition: murmur3.c:52
mode::dither
SwsDither dither
Definition: swscale.c:58
prng_state
static FFSFC64 prng_state
Definition: swscale.c:72
run_file_tests
static int run_file_tests(const AVFrame *ref, FILE *fp, struct options opts)
Definition: swscale.c:449
speedup_max
static double speedup_max
Definition: swscale.c:77
AV_PIX_FMT_NB
@ AV_PIX_FMT_NB
hardware decoding through openharmony
Definition: pixfmt.h:502
SWS_FAST_BILINEAR
@ SWS_FAST_BILINEAR
Scaler selection options.
Definition: swscale.h:98
rgb
Definition: rpzaenc.c:60
SWS_FULL_CHR_H_INP
@ SWS_FULL_CHR_H_INP
Perform full chroma interpolation when downscaling RGB sources.
Definition: swscale.h:145
macros.h
FFSFC64
Definition: sfc64.h:37
SwsDither
SwsDither
Definition: swscale.h:77
options::iters
int iters
Definition: swscale.c:49
av_parse_cpu_caps
int av_parse_cpu_caps(unsigned *flags, const char *s)
Parse CPU caps from a string and update the given AV_CPU_* flags based on that.
Definition: cpu.c:119
sws_init_context
av_warn_unused_result int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
Definition: utils.c:1879
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:202
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
avassert.h
options::dst_fmt
enum AVPixelFormat dst_fmt
Definition: swscale.c:45
options::w
int w
Definition: swscale.c:47
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
SWS_AREA
@ SWS_AREA
area averaging
Definition: swscale.h:103
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
speedup_min
static double speedup_min
Definition: swscale.c:76
SwsContext::dither
SwsDither dither
Dither mode.
Definition: swscale.h:217
options::h
int h
Definition: swscale.c:47
SwsFlags
SwsFlags
Definition: swscale.h:94
SwsContext::threads
int threads
How many threads to use for processing, or 0 for automatic selection.
Definition: swscale.h:212
av_lfg_get
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
g
const char * g
Definition: vf_curves.c:128
lfg.h
run_self_tests
static int run_self_tests(const AVFrame *ref, struct options opts)
Definition: swscale.c:393
AV_PIX_FMT_FLAG_ALPHA
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:147
sfc64.h
AVPixFmtDescriptor::log2_chroma_w
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:80
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:470
opts
AVDictionary * opts
Definition: movenc.c:51
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:599
SWS_BICUBIC
@ SWS_BICUBIC
2-tap cubic B-spline
Definition: swscale.h:100
options::threads
int threads
Definition: swscale.c:48
run_test
static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int dst_w, int dst_h, struct mode mode, struct options opts, const AVFrame *ref, const float ssim_ref[4])
Definition: swscale.c:227
options
Definition: swscale.c:43
sws_test_format
int sws_test_format(enum AVPixelFormat format, int output)
Test if a given pixel format is supported.
Definition: format.c:525
double
double
Definition: af_crystalizer.c:132
time.h
exp
int8_t exp
Definition: eval.c:73
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
options::src_fmt
enum AVPixelFormat src_fmt
Definition: swscale.c:44
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
f
f
Definition: af_crystalizer.c:122
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1018
AV_PIX_FMT_FLAG_RGB
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:136
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
cpu.h
mode::flags
SwsFlags flags
Definition: swscale.c:57
SWS_POINT
@ SWS_POINT
nearest neighbor
Definition: swscale.h:102
SwsContext::src_h
int src_h
Width and height of the source frame.
Definition: swscale.h:235
exit_handler
static void exit_handler(int sig)
Definition: swscale.c:91
frame.h
options::prob
double prob
Definition: swscale.c:46
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
get_loss
static float get_loss(const float ssim[4])
Definition: swscale.c:183
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:174
SWS_DITHER_NB
@ SWS_DITHER_NB
Definition: swscale.h:86
SwsContext::dst_format
int dst_format
Destination pixel format.
Definition: swscale.h:238
sws_isSupportedInput
#define sws_isSupportedInput(x)
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
options::flags
int flags
Definition: swscale.c:51
sws
static SwsContext * sws[3]
Definition: swscale.c:73
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:475
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
SWS_X
@ SWS_X
experimental
Definition: swscale.h:101
weights
static const int weights[]
Definition: hevc_pel.c:32
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:57
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
SwsContext::dst_h
int dst_h
Width and height of the destination frame.
Definition: swscale.h:236
ff_sfc64_get
static uint64_t ff_sfc64_get(FFSFC64 *s)
Definition: sfc64.h:41
ret
ret
Definition: filter_design.txt:187
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition: log.h:204
pixfmt.h
SWS_FULL_CHR_H_INT
@ SWS_FULL_CHR_H_INT
Perform full chroma upsampling when upscaling to RGB.
Definition: swscale.h:132
get_ssim
static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
Definition: swscale.c:135
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:3388
speedup_count
static int speedup_count
Definition: swscale.c:78
c2
static const uint64_t c2
Definition: murmur3.c:53
main
int main(int argc, char **argv)
Definition: swscale.c:493
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
bad
static int bad(InterplayACMContext *s, unsigned ind, unsigned col)
Definition: interplayacm.c:130
desc
const char * desc
Definition: libsvtav1.c:78
SwsContext::dst_w
int dst_w
Definition: swscale.h:236
SwsContext::src_format
int src_format
Source pixel format.
Definition: swscale.h:237
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
options::bench
int bench
Definition: swscale.c:50
sws_free_context
void sws_free_context(SwsContext **ctx)
Free the context and everything associated with it, and write NULL to the provided pointer.
Definition: utils.c:2326
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
sws_scale_frame
int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
Scale source data from src and write the output to dst.
Definition: swscale.c:1356
SWS_ACCURATE_RND
@ SWS_ACCURATE_RND
Force bit-exact output.
Definition: swscale.h:155
h
h
Definition: vp9dsp_template.c:2070
SwsContext
Main external API structure.
Definition: swscale.h:189
fmt_comps
static int fmt_comps(enum AVPixelFormat fmt)
Definition: swscale.c:126
AVPixFmtDescriptor::log2_chroma_h
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:89
src
#define src
Definition: vp8dsp.c:248
swscale.h
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:3376
speedup_logavg
static double speedup_logavg
Definition: swscale.c:75