FFmpeg
swscale.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Niklas 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/parseutils.h"
32 #include "libavutil/pixdesc.h"
33 #include "libavutil/lfg.h"
34 #include "libavutil/sfc64.h"
35 #include "libavutil/frame.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/time.h"
38 #include "libavutil/pixfmt.h"
39 #include "libavutil/avassert.h"
40 #include "libavutil/macros.h"
41 
42 #include "libswscale/swscale.h"
43 
44 struct options {
47  double prob;
48  int w, h;
49  int threads;
50  int iters;
51  int bench;
52  int flags;
53  int dither;
54  int unscaled;
55  int legacy;
56  int pretty;
57 };
58 
59 struct mode {
62 };
63 
64 struct test_results {
65  float ssim[4];
66  float loss;
68  int iters;
69 };
70 
71 const SwsFlags flags[] = {
72  0, // test defaults
77  SWS_POINT,
80 };
81 
83 
84 /* reused between tests for efficiency */
88 
89 static double speedup_logavg;
90 static double speedup_min = 1e10;
91 static double speedup_max = 0;
92 static int speedup_count;
93 
94 static const char *speedup_color(double ratio)
95 {
96  return ratio > 10.00 ? "\033[1;94m" : /* bold blue */
97  ratio > 2.00 ? "\033[1;32m" : /* bold green */
98  ratio > 1.02 ? "\033[32m" : /* green */
99  ratio > 0.98 ? "" : /* default */
100  ratio > 0.90 ? "\033[33m" : /* yellow */
101  ratio > 0.75 ? "\033[31m" : /* red */
102  "\033[1;31m"; /* bold red */
103 }
104 
105 static void exit_handler(int sig)
106 {
107  if (speedup_count) {
108  double ratio = exp(speedup_logavg / speedup_count);
109  fprintf(stderr, "Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
110  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower",
112  }
113 
114  exit(sig);
115 }
116 
117 /* Estimate luma variance assuming uniform dither noise distribution */
119 {
121  float variance = 1.0 / 12;
122  if (desc->comp[0].depth < 8) {
123  /* Extra headroom for very low bit depth output */
124  variance *= (8 - desc->comp[0].depth);
125  }
126 
127  if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
128  return 0.0;
129  } else if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
130  const float r = 0.299 / (1 << desc->comp[0].depth);
131  const float g = 0.587 / (1 << desc->comp[1].depth);
132  const float b = 0.114 / (1 << desc->comp[2].depth);
133  return (r * r + g * g + b * b) * variance;
134  } else {
135  const float y = 1.0 / (1 << desc->comp[0].depth);
136  return y * y * variance;
137  }
138 }
139 
140 static int fmt_comps(enum AVPixelFormat fmt)
141 {
143  int comps = desc->nb_components >= 3 ? 0x7 : 0x1;
144  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
145  comps |= 0x8;
146  return comps;
147 }
148 
149 static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
150 {
151  av_assert1(out->format == AV_PIX_FMT_YUVA444P);
152  av_assert1(ref->format == out->format);
153  av_assert1(ref->width == out->width && ref->height == out->height);
154 
155  for (int p = 0; p < 4; p++) {
156  const int stride_a = out->linesize[p];
157  const int stride_b = ref->linesize[p];
158  const int w = out->width;
159  const int h = out->height;
160 
161  const int is_chroma = p == 1 || p == 2;
162  const uint8_t def = is_chroma ? 128 : 0xFF;
163  const int has_ref = comps & (1 << p);
164  double sum = 0;
165  int count = 0;
166 
167  /* 4x4 SSIM */
168  for (int y = 0; y < (h & ~3); y += 4) {
169  for (int x = 0; x < (w & ~3); x += 4) {
170  const float c1 = .01 * .01 * 255 * 255 * 64;
171  const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
172  int s1 = 0, s2 = 0, ss = 0, s12 = 0, var, covar;
173 
174  for (int yy = 0; yy < 4; yy++) {
175  for (int xx = 0; xx < 4; xx++) {
176  int a = out->data[p][(y + yy) * stride_a + x + xx];
177  int b = has_ref ? ref->data[p][(y + yy) * stride_b + x + xx] : def;
178  s1 += a;
179  s2 += b;
180  ss += a * a + b * b;
181  s12 += a * b;
182  }
183  }
184 
185  var = ss * 64 - s1 * s1 - s2 * s2;
186  covar = s12 * 64 - s1 * s2;
187  sum += (2 * s1 * s2 + c1) * (2 * covar + c2) /
188  ((s1 * s1 + s2 * s2 + c1) * (var + c2));
189  count++;
190  }
191  }
192 
193  ssim[p] = count ? sum / count : 0.0;
194  }
195 }
196 
197 static float get_loss(const float ssim[4])
198 {
199  const float weights[3] = { 0.8, 0.1, 0.1 }; /* tuned for Y'CbCr */
200 
201  float sum = 0;
202  for (int i = 0; i < 3; i++)
203  sum += weights[i] * ssim[i];
204  sum *= ssim[3]; /* ensure alpha errors get caught */
205 
206  return 1.0 - sum;
207 }
208 
210 {
211  for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) {
212  if (!frame->buf[i])
213  break;
214  av_buffer_unref(&frame->buf[i]);
215  }
216 
217  memset(frame->data, 0, sizeof(frame->data));
218  memset(frame->linesize, 0, sizeof(frame->linesize));
219 }
220 
222 {
223  int ret = sws_scale_frame(c, dst, src);
224  if (ret < 0) {
225  av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
226  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
227  }
228  return ret;
229 }
230 
231 static int scale_new(AVFrame *dst, const AVFrame *src,
232  const struct mode *mode, const struct options *opts,
233  int64_t *out_time)
234 {
237  sws_src_dst->threads = opts->threads;
238 
240  if (ret < 0) {
241  av_log(NULL, AV_LOG_ERROR, "Failed to setup %s ---> %s\n",
242  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
243  return ret;
244  }
245 
246  int64_t time = av_gettime_relative();
247  for (int i = 0; ret >= 0 && i < opts->iters; i++) {
250  }
251  *out_time = av_gettime_relative() - time;
252 
253  return ret;
254 }
255 
256 static int scale_legacy(AVFrame *dst, const AVFrame *src,
257  const struct mode *mode, const struct options *opts,
258  int64_t *out_time)
259 {
260  SwsContext *sws_legacy;
261  int ret;
262 
263  sws_legacy = sws_alloc_context();
264  if (!sws_legacy)
265  return -1;
266 
267  sws_legacy->src_w = src->width;
268  sws_legacy->src_h = src->height;
269  sws_legacy->src_format = src->format;
270  sws_legacy->dst_w = dst->width;
271  sws_legacy->dst_h = dst->height;
272  sws_legacy->dst_format = dst->format;
273  sws_legacy->flags = mode->flags;
274  sws_legacy->dither = mode->dither;
275  sws_legacy->threads = opts->threads;
276 
278  dst->width = sws_legacy->dst_w;
279  dst->height = sws_legacy->dst_h;
280  dst->format = sws_legacy->dst_format;
282  if (ret < 0)
283  goto error;
284 
285  ret = sws_init_context(sws_legacy, NULL, NULL);
286  if (ret < 0)
287  goto error;
288 
289  int64_t time = av_gettime_relative();
290  for (int i = 0; ret >= 0 && i < opts->iters; i++)
291  ret = checked_sws_scale_frame(sws_legacy, dst, src);
292  *out_time = av_gettime_relative() - time;
293 
294 error:
295  sws_freeContext(sws_legacy);
296  return ret;
297 }
298 
299 static void print_results(const AVFrame *ref, const AVFrame *src, const AVFrame *dst,
300  int dst_w, int dst_h,
301  const struct mode *mode, const struct options *opts,
302  const struct test_results *r,
303  const struct test_results *ref_r,
304  float expected_loss)
305 {
306  if (av_log_get_level() >= AV_LOG_INFO) {
307  printf("%-*s %*dx%*d -> %-*s %*dx%*d, flags=0x%0*x dither=%u",
308  opts->pretty ? 14 : 0, av_get_pix_fmt_name(src->format),
309  opts->pretty ? 4 : 0, src->width,
310  opts->pretty ? 4 : 0, src->height,
311  opts->pretty ? 14 : 0, av_get_pix_fmt_name(dst->format),
312  opts->pretty ? 4 : 0, dst->width,
313  opts->pretty ? 4 : 0, dst->height,
314  opts->pretty ? 8 : 0, mode->flags,
315  mode->dither);
316 
317  if (!opts->bench || !ref_r) {
318  printf(", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
319  r->ssim[0], r->ssim[1], r->ssim[2], r->ssim[3],
320  r->loss);
321  if (ref_r)
322  printf(" (ref=%e)", ref_r->loss);
323  }
324 
325  if (opts->bench) {
326  printf(", time=%*"PRId64"/%u us",
327  opts->pretty ? 7 : 0, r->time, opts->iters);
328  if (ref_r) {
329  double ratio = ((double) ref_r->time / ref_r->iters)
330  / ((double) r->time / opts->iters);
331  if (FFMIN(r->time, ref_r->time) > 100 /* don't pollute stats with low precision */) {
332  speedup_min = FFMIN(speedup_min, ratio);
333  speedup_max = FFMAX(speedup_max, ratio);
334  speedup_logavg += log(ratio);
335  speedup_count++;
336  }
337 
338  printf(" (ref=%*"PRId64"/%u us), speedup=%*.3fx %s%s\033[0m",
339  opts->pretty ? 7 : 0, ref_r->time, ref_r->iters,
340  opts->pretty ? 6 : 0, ratio,
341  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
342  }
343  }
344  printf("\n");
345 
346  fflush(stdout);
347  }
348 
349  if (r->loss - expected_loss > 1e-4 && dst_w >= ref->width && dst_h >= ref->height) {
350  const int bad = r->loss - expected_loss > 1e-2;
351  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
352  const char *worse_str = bad ? "WORSE" : "worse";
353  av_log(NULL, level,
354  " loss %e is %s by %e, expected loss %e\n",
355  r->loss, worse_str, r->loss - expected_loss, expected_loss);
356  }
357 
358  if (ref_r && r->loss - ref_r->loss > 1e-4) {
359  /**
360  * The new scaling code does not (yet) perform error diffusion for
361  * low bit depth output, which impacts the SSIM score slightly for
362  * very low bit-depth formats (e.g. monow, monob). Since this is an
363  * expected result, drop the badness from an error to a warning for
364  * such cases. This can be removed again once error diffusion is
365  * implemented in the new ops code.
366  */
367  const int dst_bits = av_pix_fmt_desc_get(dst->format)->comp[0].depth;
368  const int bad = r->loss - ref_r->loss > 1e-2 && dst_bits > 1;
369  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
370  const char *worse_str = bad ? "WORSE" : "worse";
371  av_log(NULL, level,
372  " loss %e is %s by %e, ref loss %e SSIM={Y=%f U=%f V=%f A=%f}\n",
373  r->loss, worse_str, r->loss - ref_r->loss, ref_r->loss,
374  ref_r->ssim[0], ref_r->ssim[1], ref_r->ssim[2], ref_r->ssim[3]);
375  }
376 }
377 
378 static int init_frame(AVFrame **pframe, const AVFrame *ref,
379  int width, int height, enum AVPixelFormat format)
380 {
382  if (!frame)
383  return AVERROR(ENOMEM);
385  frame->width = width;
386  frame->height = height;
387  frame->format = format;
388  *pframe = frame;
389  return 0;
390 }
391 
392 /* Runs a series of ref -> src -> dst -> out, and compares out vs ref */
393 static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
394  int dst_w, int dst_h,
395  const struct mode *mode, const struct options *opts,
396  const AVFrame *ref, AVFrame *src,
397  const struct test_results *ref_r)
398 {
399  AVFrame *dst = NULL, *out = NULL;
400  const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt);
401  int ret;
402 
403  /* Estimate the expected amount of loss from bit depth reduction */
404  const float c1 = 0.01 * 0.01; /* stabilization constant */
405  const float ref_var = 1.0 / 12.0; /* uniformly distributed signal */
406  const float src_var = estimate_quantization_noise(src_fmt);
407  const float dst_var = estimate_quantization_noise(dst_fmt);
408  const float out_var = estimate_quantization_noise(ref->format);
409  const float total_var = src_var + dst_var + out_var;
410  const float ssim_luma = (2 * ref_var + c1) / (2 * ref_var + total_var + c1);
411  const float ssim_expected[4] = { ssim_luma, 1, 1, 1 }; /* for simplicity */
412  const float expected_loss = get_loss(ssim_expected);
413 
414  struct test_results r = { 0 };
415 
416  if (src->format != src_fmt) {
419  src->width = ref->width;
420  src->height = ref->height;
421  src->format = src_fmt;
423  if (ret < 0)
424  goto error;
425  }
426 
427  ret = init_frame(&dst, ref, dst_w, dst_h, dst_fmt);
428  if (ret < 0)
429  goto error;
430 
431  ret = opts->legacy ? scale_legacy(dst, src, mode, opts, &r.time)
432  : scale_new(dst, src, mode, opts, &r.time);
433  if (ret < 0)
434  goto error;
435 
436  ret = init_frame(&out, ref, ref->width, ref->height, ref->format);
437  if (ret < 0)
438  goto error;
439 
441  if (ret < 0)
442  goto error;
443 
444  get_ssim(r.ssim, out, ref, comps);
445 
446  if (opts->legacy) {
447  /* Legacy swscale does not perform bit accurate upconversions of low
448  * bit depth RGB. This artificially improves the SSIM score because the
449  * resulting error deletes some of the input dither noise. This gives
450  * it an unfair advantage when compared against a bit exact reference.
451  * Work around this by ensuring that the resulting SSIM score is not
452  * higher than it theoretically "should" be. */
453  if (src_var > dst_var) {
454  const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var + c1);
455  r.ssim[0] = FFMIN(r.ssim[0], src_loss);
456  }
457  }
458 
459  r.loss = get_loss(r.ssim);
460  if (!opts->legacy && r.loss - expected_loss > 1e-2 && dst_w >= ref->width && dst_h >= ref->height) {
461  ret = -1;
462  goto bad_loss;
463  }
464 
465  if (ref_r && r.loss - ref_r->loss > 1e-2) {
466  ret = -1;
467  goto bad_loss;
468  }
469 
470  ret = 0; /* fall through */
471 
472 bad_loss:
474  dst_w, dst_h,
475  mode, opts,
476  &r, ref_r,
477  expected_loss);
478 
479  error:
480  av_frame_free(&dst);
481  av_frame_free(&out);
482  return ret;
483 }
484 
485 static inline int fmt_is_subsampled(enum AVPixelFormat fmt)
486 {
487  return av_pix_fmt_desc_get(fmt)->log2_chroma_w != 0 ||
489 }
490 
491 static int run_self_tests(const AVFrame *ref, const struct options *opts)
492 {
493  const int dst_w[] = { opts->w, opts->w - opts->w / 3, opts->w + opts->w / 3 };
494  const int dst_h[] = { opts->h, opts->h - opts->h / 3, opts->h + opts->h / 3 };
495 
496  enum AVPixelFormat src_fmt, dst_fmt,
497  src_fmt_min = 0,
498  dst_fmt_min = 0,
499  src_fmt_max = AV_PIX_FMT_NB - 1,
500  dst_fmt_max = AV_PIX_FMT_NB - 1;
501 
503  if (!src)
504  return AVERROR(ENOMEM);
505 
506  int ret = 0;
507 
508  if (opts->src_fmt != AV_PIX_FMT_NONE)
509  src_fmt_min = src_fmt_max = opts->src_fmt;
510  if (opts->dst_fmt != AV_PIX_FMT_NONE)
511  dst_fmt_min = dst_fmt_max = opts->dst_fmt;
512 
513  for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
514  if (opts->unscaled && fmt_is_subsampled(src_fmt))
515  continue;
516  if (!sws_test_format(src_fmt, 0) || !sws_test_format(src_fmt, 1))
517  continue;
518  for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
519  if (opts->unscaled && fmt_is_subsampled(dst_fmt))
520  continue;
521  if (!sws_test_format(dst_fmt, 0) || !sws_test_format(dst_fmt, 1))
522  continue;
523  for (int h = 0; h < FF_ARRAY_ELEMS(dst_h); h++) {
524  for (int w = 0; w < FF_ARRAY_ELEMS(dst_w); w++) {
525  for (int f = 0; f < FF_ARRAY_ELEMS(flags); f++) {
526  struct mode mode = {
527  .flags = opts->flags >= 0 ? opts->flags : flags[f],
528  .dither = opts->dither >= 0 ? opts->dither : SWS_DITHER_AUTO,
529  };
530 
531  if (ff_sfc64_get(&prng_state) > UINT64_MAX * opts->prob)
532  continue;
533 
534  ret = run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h],
535  &mode, opts, ref, src, NULL);
536  if (ret < 0)
537  goto error;
538 
539  if (opts->flags >= 0 || opts->unscaled)
540  break;
541  }
542  if (opts->unscaled)
543  break;
544  }
545  if (opts->unscaled)
546  break;
547  }
548  }
549  }
550 
551  ret = 0;
552 
553 error:
554  av_frame_free(&src);
555  return ret;
556 }
557 
558 static int run_file_tests(const AVFrame *ref, FILE *fp, const struct options *opts)
559 {
560  char buf[256];
561  int ret = 0;
562 
564  if (!src)
565  return AVERROR(ENOMEM);
566 
567  for (int line = 1; fgets(buf, sizeof(buf), fp); line++) {
568  char src_fmt_str[21], dst_fmt_str[21];
569  enum AVPixelFormat src_fmt;
570  enum AVPixelFormat dst_fmt;
571  int sw, sh, dw, dh;
572  struct test_results r = { 0 };
573  struct mode mode;
574  int n = 0;
575 
576  ret = sscanf(buf,
577  "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
578  "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
579  src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
580  &mode.flags, &mode.dither,
581  &r.ssim[0], &r.ssim[1], &r.ssim[2], &r.ssim[3],
582  &r.loss, &n);
583  if (ret != 13) {
585  "Malformed reference file in line %d\n", line);
586  goto error;
587  }
588  if (opts->bench) {
589  ret = sscanf(buf + n,
590  ", time=%"PRId64"/%u us",
591  &r.time, &r.iters);
592  if (ret != 2) {
594  "Missing benchmarks from reference file in line %d\n",
595  line);
596  goto error;
597  }
598  }
599 
600  src_fmt = av_get_pix_fmt(src_fmt_str);
601  dst_fmt = av_get_pix_fmt(dst_fmt_str);
602  if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE) {
604  "Unknown pixel formats (%s and/or %s) in line %d\n",
605  src_fmt_str, dst_fmt_str, line);
606  goto error;
607  }
608 
609  if (sw != ref->width || sh != ref->height) {
611  "Mismatching dimensions %dx%d (ref is %dx%d) in line %d\n",
612  sw, sh, ref->width, ref->height, line);
613  goto error;
614  }
615 
616  if (opts->src_fmt != AV_PIX_FMT_NONE && src_fmt != opts->src_fmt ||
617  opts->dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts->dst_fmt)
618  continue;
619 
620  ret = run_test(src_fmt, dst_fmt, dw, dh, &mode, opts, ref, src, &r);
621  if (ret < 0)
622  goto error;
623  }
624 
625  ret = 0;
626 
627 error:
628  av_frame_free(&src);
629  return ret;
630 }
631 
632 static int init_ref(AVFrame *ref, const struct options *opts)
633 {
636  AVLFG rand;
637  int ret = -1;
638 
639  if (!ctx || !rgb)
640  goto error;
641 
642  rgb->width = opts->w / 12;
643  rgb->height = opts->h / 12;
644  rgb->format = AV_PIX_FMT_RGBA;
645  ret = av_frame_get_buffer(rgb, 32);
646  if (ret < 0)
647  goto error;
648 
649  av_lfg_init(&rand, 1);
650  for (int y = 0; y < rgb->height; y++) {
651  for (int x = 0; x < rgb->width; x++) {
652  for (int c = 0; c < 4; c++)
653  rgb->data[0][y * rgb->linesize[0] + x * 4 + c] = av_lfg_get(&rand);
654  }
655  }
656 
659 
660 error:
662  av_frame_free(&rgb);
663  return ret;
664 }
665 
666 static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
667 {
668  for (int i = 1; i < argc; i += 2) {
669  if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
670  fprintf(stderr,
671  "swscale [options...]\n"
672  " -help\n"
673  " This text\n"
674  " -ref <file>\n"
675  " Uses file as reference to compare tests against. Tests that have become worse will contain the string worse or WORSE\n"
676  " -p <number between 0.0 and 1.0>\n"
677  " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
678  " It is often convenient to perform a random subset\n"
679  " -dst <pixfmt>\n"
680  " Only test the specified destination pixel format\n"
681  " -src <pixfmt>\n"
682  " Only test the specified source pixel format\n"
683  " -s <size>\n"
684  " Set frame size (WxH or abbreviation)\n"
685  " -bench <iters>\n"
686  " Run benchmarks with the specified number of iterations. This mode also sets the frame size to 1920x1080 (unless -s is specified)\n"
687  " -flags <flags>\n"
688  " Test with a specific combination of flags\n"
689  " -dither <mode>\n"
690  " Test with a specific dither mode\n"
691  " -unscaled <1 or 0>\n"
692  " If 1, test only conversions that do not involve scaling\n"
693  " -legacy <1 or 0>\n"
694  " If 1, force using legacy swscale for the main conversion\n"
695  " -threads <threads>\n"
696  " Use the specified number of threads\n"
697  " -cpuflags <cpuflags>\n"
698  " Uses the specified cpuflags in the tests\n"
699  " -pretty <1 or 0>\n"
700  " Align fields while printing results\n"
701  " -v <level>\n"
702  " Enable log verbosity at given level\n"
703  );
704  exit(0);
705  }
706  if (argv[i][0] != '-' || i + 1 == argc)
707  goto bad_option;
708  if (!strcmp(argv[i], "-ref")) {
709  *fp = fopen(argv[i + 1], "r");
710  if (!*fp) {
711  fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
712  return -1;
713  }
714  } else if (!strcmp(argv[i], "-cpuflags")) {
715  unsigned flags = av_get_cpu_flags();
716  int res = av_parse_cpu_caps(&flags, argv[i + 1]);
717  if (res < 0) {
718  fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]);
719  return -1;
720  }
722  } else if (!strcmp(argv[i], "-src")) {
723  opts->src_fmt = av_get_pix_fmt(argv[i + 1]);
724  if (opts->src_fmt == AV_PIX_FMT_NONE) {
725  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
726  return -1;
727  }
728  } else if (!strcmp(argv[i], "-dst")) {
729  opts->dst_fmt = av_get_pix_fmt(argv[i + 1]);
730  if (opts->dst_fmt == AV_PIX_FMT_NONE) {
731  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
732  return -1;
733  }
734  } else if (!strcmp(argv[i], "-s")) {
735  if (av_parse_video_size(&opts->w, &opts->h, argv[i + 1]) < 0) {
736  fprintf(stderr, "invalid frame size %s\n", argv[i + 1]);
737  return -1;
738  }
739  } else if (!strcmp(argv[i], "-bench")) {
740  int iters = atoi(argv[i + 1]);
741  if (iters <= 0) {
742  opts->bench = 0;
743  opts->iters = 1;
744  } else {
745  opts->bench = 1;
746  opts->iters = iters;
747  }
748  } else if (!strcmp(argv[i], "-flags")) {
750  const AVOption *flags_opt = av_opt_find(dummy, "sws_flags", NULL, 0, 0);
751  int ret = av_opt_eval_flags(dummy, flags_opt, argv[i + 1], &opts->flags);
753  if (ret < 0) {
754  fprintf(stderr, "invalid flags %s\n", argv[i + 1]);
755  return -1;
756  }
757  } else if (!strcmp(argv[i], "-dither")) {
758  opts->dither = atoi(argv[i + 1]);
759  } else if (!strcmp(argv[i], "-unscaled")) {
760  opts->unscaled = atoi(argv[i + 1]);
761  } else if (!strcmp(argv[i], "-legacy")) {
762  opts->legacy = atoi(argv[i + 1]);
763  } else if (!strcmp(argv[i], "-threads")) {
764  opts->threads = atoi(argv[i + 1]);
765  } else if (!strcmp(argv[i], "-p")) {
766  opts->prob = atof(argv[i + 1]);
767  } else if (!strcmp(argv[i], "-pretty")) {
768  opts->pretty = atoi(argv[i + 1]);
769  } else if (!strcmp(argv[i], "-v")) {
770  av_log_set_level(atoi(argv[i + 1]));
771  } else {
772 bad_option:
773  fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]);
774  return -1;
775  }
776  }
777 
778  if (opts->w < 0 || opts->h < 0) {
779  opts->w = opts->bench ? 1920 : 96;
780  opts->h = opts->bench ? 1080 : 96;
781  }
782 
783  return 0;
784 }
785 
786 int main(int argc, char **argv)
787 {
788  struct options opts = {
789  .src_fmt = AV_PIX_FMT_NONE,
790  .dst_fmt = AV_PIX_FMT_NONE,
791  .w = -1,
792  .h = -1,
793  .threads = 1,
794  .iters = 1,
795  .prob = 1.0,
796  .flags = -1,
797  .dither = -1,
798  };
799 
800  AVFrame *ref = NULL;
801  FILE *fp = NULL;
802  int ret = -1;
803 
804  if (parse_options(argc, argv, &opts, &fp) < 0)
805  goto error;
806 
807  ff_sfc64_init(&prng_state, 0, 0, 0, 12);
808  signal(SIGINT, exit_handler);
809 
813  if (!sws_ref_src || !sws_src_dst || !sws_dst_out)
814  goto error;
817 
818  ref = av_frame_alloc();
819  if (!ref)
820  goto error;
821  ref->width = opts.w;
822  ref->height = opts.h;
823  ref->format = AV_PIX_FMT_YUVA444P;
824 
825  ret = init_ref(ref, &opts);
826  if (ret < 0)
827  goto error;
828 
829  ret = fp ? run_file_tests(ref, fp, &opts)
830  : run_self_tests(ref, &opts);
831 
832  /* fall through */
833 error:
837  av_frame_free(&ref);
838  if (fp)
839  fclose(fp);
840  exit_handler(ret);
841 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
flags
const SwsFlags flags[]
Definition: swscale.c:71
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
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
printf
__device__ int printf(const char *,...)
opt.h
checked_sws_scale_frame
static int checked_sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src)
Definition: swscale.c:221
out
static FILE * out
Definition: movenc.c:55
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:485
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:253
print_results
static void print_results(const AVFrame *ref, const AVFrame *src, const AVFrame *dst, int dst_w, int dst_h, const struct mode *mode, const struct options *opts, const struct test_results *r, const struct test_results *ref_r, float expected_loss)
Definition: swscale.c:299
estimate_quantization_noise
static float estimate_quantization_noise(enum AVPixelFormat fmt)
Definition: swscale.c:118
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:2285
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:54
mode
Definition: swscale.c:59
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
pixdesc.h
speedup_color
static const char * speedup_color(double ratio)
Definition: swscale.c:94
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:57
SWS_BILINEAR
@ SWS_BILINEAR
bilinear filtering
Definition: swscale.h:177
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:157
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:42
options::pretty
int pretty
Definition: swscale.c:56
options::dither
int dither
Definition: swscale.c:53
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:219
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:61
prng_state
static FFSFC64 prng_state
Definition: swscale.c:82
dummy
static int dummy
Definition: ffplay.c:3751
speedup_max
static double speedup_max
Definition: swscale.c:91
run_self_tests
static int run_self_tests(const AVFrame *ref, const struct options *opts)
Definition: swscale.c:491
AV_PIX_FMT_NB
@ AV_PIX_FMT_NB
hardware decoding through openharmony
Definition: pixfmt.h:502
run_file_tests
static int run_file_tests(const AVFrame *ref, FILE *fp, const struct options *opts)
Definition: swscale.c:558
SWS_FAST_BILINEAR
@ SWS_FAST_BILINEAR
Scaler selection options.
Definition: swscale.h:176
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:146
macros.h
FFSFC64
Definition: sfc64.h:37
SwsDither
SwsDither
Definition: swscale.h:77
options::iters
int iters
Definition: swscale.c:50
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:1919
sws_frame_setup
int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src)
Like sws_scale_frame, but without actually scaling.
Definition: swscale.c:1422
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:202
test_results::ssim
float ssim[4]
Definition: swscale.c:65
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:46
options::w
int w
Definition: swscale.c:48
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:181
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
speedup_min
static double speedup_min
Definition: swscale.c:90
SwsContext::dither
SwsDither dither
Dither mode.
Definition: swscale.h:235
options::h
int h
Definition: swscale.c:48
SwsFlags
SwsFlags
Definition: swscale.h:110
SwsContext::threads
int threads
How many threads to use for processing, or 0 for automatic selection.
Definition: swscale.h:230
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
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1414
g
const char * g
Definition: vf_curves.c:128
lfg.h
AV_PIX_FMT_FLAG_ALPHA
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:147
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
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
options::legacy
int legacy
Definition: swscale.c:55
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:472
opts
static 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
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
SWS_BICUBIC
@ SWS_BICUBIC
2-tap cubic B-spline
Definition: swscale.h:178
options::threads
int threads
Definition: swscale.c:49
parseutils.h
options
Definition: swscale.c:44
sws_test_format
int sws_test_format(enum AVPixelFormat format, int output)
Test if a given (software) pixel format is supported.
Definition: format.c:556
double
double
Definition: af_crystalizer.c:132
time.h
run_test
static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int dst_w, int dst_h, const struct mode *mode, const struct options *opts, const AVFrame *ref, AVFrame *src, const struct test_results *ref_r)
Definition: swscale.c:393
exp
int8_t exp
Definition: eval.c:76
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:45
av_opt_find
const AVOption * av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
Look for an option in an object.
Definition: opt.c:1985
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
f
f
Definition: af_crystalizer.c:122
height
#define height
Definition: dsp.h:89
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1031
sws_ref_src
static SwsContext * sws_ref_src
Definition: swscale.c:85
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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
mode::flags
SwsFlags flags
Definition: swscale.c:60
SWS_POINT
@ SWS_POINT
nearest neighbor
Definition: swscale.h:180
SwsContext::src_h
int src_h
Width and height of the source frame.
Definition: swscale.h:253
sws_src_dst
static SwsContext * sws_src_dst
Definition: swscale.c:86
exit_handler
static void exit_handler(int sig)
Definition: swscale.c:105
scale_legacy
static int scale_legacy(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
Definition: swscale.c:256
frame.h
options::prob
double prob
Definition: swscale.c:47
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:197
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
line
Definition: graph2dot.c:48
unref_buffers
static void unref_buffers(AVFrame *frame)
Definition: swscale.c:209
SwsContext::dst_format
int dst_format
Destination pixel format.
Definition: swscale.h:256
av_parse_video_size
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
Definition: parseutils.c:150
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
options::flags
int flags
Definition: swscale.c:52
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:477
test_results::loss
float loss
Definition: swscale.c:66
SWS_X
@ SWS_X
experimental
Definition: swscale.h:179
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:58
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
test_results
Definition: swscale.c:64
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:496
SwsContext::dst_h
int dst_h
Width and height of the destination frame.
Definition: swscale.h:254
ff_sfc64_get
static uint64_t ff_sfc64_get(FFSFC64 *s)
Definition: sfc64.h:41
av_opt_eval_flags
int av_opt_eval_flags(void *obj, const AVOption *o, const char *val, int *flags_out)
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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
test_results::time
int64_t time
Definition: swscale.c:67
SWS_FULL_CHR_H_INT
@ SWS_FULL_CHR_H_INT
Perform full chroma upsampling when upscaling to RGB.
Definition: swscale.h:133
get_ssim
static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
Definition: swscale.c:149
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:92
c2
static const uint64_t c2
Definition: murmur3.c:53
main
int main(int argc, char **argv)
Definition: swscale.c:786
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
init_ref
static int init_ref(AVFrame *ref, const struct options *opts)
Definition: swscale.c:632
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
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:82
sws_dst_out
static SwsContext * sws_dst_out
Definition: swscale.c:87
SwsContext::dst_w
int dst_w
Definition: swscale.h:254
SwsContext::src_format
int src_format
Source pixel format.
Definition: swscale.h:255
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
w
uint8_t w
Definition: llvidencdsp.c:39
options::bench
int bench
Definition: swscale.c:51
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:2368
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:1349
SWS_ACCURATE_RND
@ SWS_ACCURATE_RND
Force bit-exact output.
Definition: swscale.h:156
h
h
Definition: vp9dsp_template.c:2070
width
#define width
Definition: dsp.h:89
SwsContext
Main external API structure.
Definition: swscale.h:206
scale_new
static int scale_new(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
Definition: swscale.c:231
fmt_comps
static int fmt_comps(enum AVPixelFormat fmt)
Definition: swscale.c:140
test_results::iters
int iters
Definition: swscale.c:68
parse_options
static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
Definition: swscale.c:666
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
init_frame
static int init_frame(AVFrame **pframe, const AVFrame *ref, int width, int height, enum AVPixelFormat format)
Definition: swscale.c:378
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:89