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 #include "libavutil/hwcontext.h"
42 
43 #include "libswscale/swscale.h"
44 
45 struct options {
48  double prob;
49  int w, h;
50  int threads;
51  int iters;
52  int bench;
53  int flags;
54  int dither;
55  int unscaled;
56  int legacy;
57  int pretty;
58 };
59 
60 struct mode {
63 };
64 
65 struct test_results {
66  float ssim[4];
67  float loss;
69  int iters;
70 };
71 
72 const SwsFlags flags[] = {
73  0, // test defaults
78  SWS_POINT,
81 };
82 
84 
85 /* reused between tests for efficiency */
89 
92 
93 static double speedup_logavg;
94 static double speedup_min = 1e10;
95 static double speedup_max = 0;
96 static int speedup_count;
97 
98 static const char *speedup_color(double ratio)
99 {
100  return ratio > 10.00 ? "\033[1;94m" : /* bold blue */
101  ratio > 2.00 ? "\033[1;32m" : /* bold green */
102  ratio > 1.02 ? "\033[32m" : /* green */
103  ratio > 0.98 ? "" : /* default */
104  ratio > 0.90 ? "\033[33m" : /* yellow */
105  ratio > 0.75 ? "\033[31m" : /* red */
106  "\033[1;31m"; /* bold red */
107 }
108 
109 static void exit_handler(int sig)
110 {
111  if (speedup_count) {
112  double ratio = exp(speedup_logavg / speedup_count);
113  fprintf(stderr, "Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
114  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower",
116  }
117 
118  exit(sig);
119 }
120 
121 /* Estimate luma variance assuming uniform dither noise distribution */
123 {
125  float variance = 1.0 / 12;
126  if (desc->comp[0].depth < 8) {
127  /* Extra headroom for very low bit depth output */
128  variance *= (8 - desc->comp[0].depth);
129  }
130 
131  if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
132  return 0.0;
133  } else if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
134  const float r = 0.299 / (1 << desc->comp[0].depth);
135  const float g = 0.587 / (1 << desc->comp[1].depth);
136  const float b = 0.114 / (1 << desc->comp[2].depth);
137  return (r * r + g * g + b * b) * variance;
138  } else {
139  const float y = 1.0 / (1 << desc->comp[0].depth);
140  return y * y * variance;
141  }
142 }
143 
144 static int fmt_comps(enum AVPixelFormat fmt)
145 {
147  int comps = desc->nb_components >= 3 ? 0x7 : 0x1;
148  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
149  comps |= 0x8;
150  return comps;
151 }
152 
153 static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
154 {
155  av_assert1(out->format == AV_PIX_FMT_YUVA444P);
156  av_assert1(ref->format == out->format);
157  av_assert1(ref->width == out->width && ref->height == out->height);
158 
159  for (int p = 0; p < 4; p++) {
160  const int stride_a = out->linesize[p];
161  const int stride_b = ref->linesize[p];
162  const int w = out->width;
163  const int h = out->height;
164 
165  const int is_chroma = p == 1 || p == 2;
166  const uint8_t def = is_chroma ? 128 : 0xFF;
167  const int has_ref = comps & (1 << p);
168  double sum = 0;
169  int count = 0;
170 
171  /* 4x4 SSIM */
172  for (int y = 0; y < (h & ~3); y += 4) {
173  for (int x = 0; x < (w & ~3); x += 4) {
174  const float c1 = .01 * .01 * 255 * 255 * 64;
175  const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
176  int s1 = 0, s2 = 0, ss = 0, s12 = 0, var, covar;
177 
178  for (int yy = 0; yy < 4; yy++) {
179  for (int xx = 0; xx < 4; xx++) {
180  int a = out->data[p][(y + yy) * stride_a + x + xx];
181  int b = has_ref ? ref->data[p][(y + yy) * stride_b + x + xx] : def;
182  s1 += a;
183  s2 += b;
184  ss += a * a + b * b;
185  s12 += a * b;
186  }
187  }
188 
189  var = ss * 64 - s1 * s1 - s2 * s2;
190  covar = s12 * 64 - s1 * s2;
191  sum += (2 * s1 * s2 + c1) * (2 * covar + c2) /
192  ((s1 * s1 + s2 * s2 + c1) * (var + c2));
193  count++;
194  }
195  }
196 
197  ssim[p] = count ? sum / count : 0.0;
198  }
199 }
200 
201 static float get_loss(const float ssim[4])
202 {
203  const float weights[3] = { 0.8, 0.1, 0.1 }; /* tuned for Y'CbCr */
204 
205  float sum = 0;
206  for (int i = 0; i < 3; i++)
207  sum += weights[i] * ssim[i];
208  sum *= ssim[3]; /* ensure alpha errors get caught */
209 
210  return 1.0 - sum;
211 }
212 
214 {
215  for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) {
216  if (!frame->buf[i])
217  break;
218  av_buffer_unref(&frame->buf[i]);
219  }
220 
221  memset(frame->data, 0, sizeof(frame->data));
222  memset(frame->linesize, 0, sizeof(frame->linesize));
223 }
224 
226 {
227  int ret = sws_scale_frame(c, dst, src);
228  if (ret < 0) {
229  av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
230  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
231  }
232  return ret;
233 }
234 
235 static int scale_new(AVFrame *dst, const AVFrame *src,
236  const struct mode *mode, const struct options *opts,
237  int64_t *out_time)
238 {
241  sws_src_dst->threads = opts->threads;
242 
244  if (ret < 0) {
245  av_log(NULL, AV_LOG_ERROR, "Failed to setup %s ---> %s\n",
246  av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
247  return ret;
248  }
249 
250  int64_t time = av_gettime_relative();
251  for (int i = 0; ret >= 0 && i < opts->iters; i++) {
254  }
255  *out_time = av_gettime_relative() - time;
256 
257  return ret;
258 }
259 
260 static int scale_legacy(AVFrame *dst, const AVFrame *src,
261  const struct mode *mode, const struct options *opts,
262  int64_t *out_time)
263 {
264  SwsContext *sws_legacy;
265  int ret;
266 
267  sws_legacy = sws_alloc_context();
268  if (!sws_legacy)
269  return -1;
270 
271  sws_legacy->src_w = src->width;
272  sws_legacy->src_h = src->height;
273  sws_legacy->src_format = src->format;
274  sws_legacy->dst_w = dst->width;
275  sws_legacy->dst_h = dst->height;
276  sws_legacy->dst_format = dst->format;
277  sws_legacy->flags = mode->flags;
278  sws_legacy->dither = mode->dither;
279  sws_legacy->threads = opts->threads;
280 
282  dst->width = sws_legacy->dst_w;
283  dst->height = sws_legacy->dst_h;
284  dst->format = sws_legacy->dst_format;
286  if (ret < 0)
287  goto error;
288 
289  ret = sws_init_context(sws_legacy, NULL, NULL);
290  if (ret < 0)
291  goto error;
292 
293  int64_t time = av_gettime_relative();
294  for (int i = 0; ret >= 0 && i < opts->iters; i++)
295  ret = checked_sws_scale_frame(sws_legacy, dst, src);
296  *out_time = av_gettime_relative() - time;
297 
298 error:
299  sws_freeContext(sws_legacy);
300  return ret;
301 }
302 
303 static int scale_hw(AVFrame *dst, const AVFrame *src,
304  const struct mode *mode, const struct options *opts,
305  int64_t *out_time)
306 {
307  SwsContext *sws_hw = NULL;
308  AVBufferRef *in_ref = NULL;
309  AVBufferRef *out_ref = NULL;
310  AVHWFramesContext *in_ctx = NULL;
311  AVHWFramesContext *out_ctx = NULL;
312  AVFrame *in_f = NULL;
313  AVFrame *out_f = NULL;
314  int ret;
315 
316  if (src->format == dst->format)
317  return AVERROR(ENOTSUP);
318 
319  sws_hw = sws_alloc_context();
320  if (!sws_hw) {
321  ret = AVERROR(ENOMEM);
322  goto error;
323  }
324 
325  sws_hw->flags = mode->flags;
326  sws_hw->dither = mode->dither;
327 
329  if (!in_ref) {
330  ret = AVERROR(ENOMEM);
331  goto error;
332  }
333 
334  in_ctx = (AVHWFramesContext *)in_ref->data;
335  in_ctx->format = AV_PIX_FMT_VULKAN;
336  in_ctx->sw_format = src->format;
337  in_ctx->width = src->width;
338  in_ctx->height = src->height;
339  ret = av_hwframe_ctx_init(in_ref);
340  if (ret < 0) {
341  if (ret != AVERROR(ENOTSUP))
342  av_log(NULL, AV_LOG_ERROR, "Failed to create input HW context: %s\n",
343  av_err2str(ret));
344  goto error;
345  }
346 
348  if (!out_ref) {
349  ret = AVERROR(ENOMEM);
350  goto error;
351  }
352 
353  out_ctx = (AVHWFramesContext *) out_ref->data;
354  out_ctx->format = AV_PIX_FMT_VULKAN;
355  out_ctx->sw_format = dst->format;
356  out_ctx->width = dst->width;
357  out_ctx->height = dst->height;
358  ret = av_hwframe_ctx_init(out_ref);
359  if (ret < 0) {
360  if (ret != AVERROR(ENOTSUP))
361  av_log(NULL, AV_LOG_ERROR, "Failed to create output HW context: %s\n",
362  av_err2str(ret));
363  goto error;
364  }
365 
366  in_f = av_frame_alloc();
367  if (!in_f) {
368  ret = AVERROR(ENOMEM);
369  goto error;
370  }
371  in_f->width = src->width;
372  in_f->height = src->height;
373  in_f->format = AV_PIX_FMT_VULKAN;
374  ret = av_hwframe_get_buffer(in_ref, in_f, 0);
375  if (ret < 0) {
376  av_log(NULL, AV_LOG_ERROR, "Failed to allocate input HW frame\n");
377  goto error;
378  }
379 
380  ret = av_hwframe_transfer_data(in_f, src, 0);
381  if (ret < 0) {
382  av_log(NULL, AV_LOG_ERROR, "Failed to upload HW frame\n");
383  goto error;
384  }
385 
386  out_f = av_frame_alloc();
387  if (!out_f) {
388  ret = AVERROR(ENOMEM);
389  goto error;
390  }
391  out_f->width = dst->width;
392  out_f->height = dst->height;
393  out_f->format = AV_PIX_FMT_VULKAN;
394  ret = av_hwframe_get_buffer(out_ref, out_f, 0);
395  if (ret < 0) {
396  av_log(NULL, AV_LOG_ERROR, "Failed to allocate output HW frame\n");
397  goto error;
398  }
399 
400  int64_t time = av_gettime_relative();
401  for (int i = 0; ret >= 0 && i < opts->iters; i++) {
402  ret = checked_sws_scale_frame(sws_hw, out_f, in_f);
403  if (ret < 0)
404  goto error;
405  }
406  *out_time = av_gettime_relative() - time;
407 
409  if (ret < 0)
410  goto error;
411 
412  ret = av_hwframe_transfer_data(dst, out_f, 0);
413  if (ret < 0) {
414  av_log(NULL, AV_LOG_ERROR, "Failed to download HW frame\n");
415  goto error;
416  }
417 
418  ret = 0;
419 
420 error:
421  av_frame_free(&in_f);
422  av_frame_free(&out_f);
423  av_buffer_unref(&in_ref);
424  av_buffer_unref(&out_ref);
425  sws_free_context(&sws_hw);
426  return ret;
427 }
428 
429 static void print_results(const AVFrame *ref, const AVFrame *src, const AVFrame *dst,
430  int dst_w, int dst_h,
431  const struct mode *mode, const struct options *opts,
432  const struct test_results *r,
433  const struct test_results *ref_r,
434  float expected_loss)
435 {
436  if (av_log_get_level() >= AV_LOG_INFO) {
437  printf("%-*s %*dx%*d -> %-*s %*dx%*d, flags=0x%0*x dither=%u",
438  opts->pretty ? 14 : 0, av_get_pix_fmt_name(src->format),
439  opts->pretty ? 4 : 0, src->width,
440  opts->pretty ? 4 : 0, src->height,
441  opts->pretty ? 14 : 0, av_get_pix_fmt_name(dst->format),
442  opts->pretty ? 4 : 0, dst->width,
443  opts->pretty ? 4 : 0, dst->height,
444  opts->pretty ? 8 : 0, mode->flags,
445  mode->dither);
446 
447  if (!opts->bench || !ref_r) {
448  printf(", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
449  r->ssim[0], r->ssim[1], r->ssim[2], r->ssim[3],
450  r->loss);
451  if (ref_r)
452  printf(" (ref=%e)", ref_r->loss);
453  }
454 
455  if (opts->bench) {
456  printf(", time=%*"PRId64"/%u us",
457  opts->pretty ? 7 : 0, r->time, opts->iters);
458  if (ref_r) {
459  double ratio = ((double) ref_r->time / ref_r->iters)
460  / ((double) r->time / opts->iters);
461  if (FFMIN(r->time, ref_r->time) > 100 /* don't pollute stats with low precision */) {
462  speedup_min = FFMIN(speedup_min, ratio);
463  speedup_max = FFMAX(speedup_max, ratio);
464  speedup_logavg += log(ratio);
465  speedup_count++;
466  }
467 
468  printf(" (ref=%*"PRId64"/%u us), speedup=%*.3fx %s%s\033[0m",
469  opts->pretty ? 7 : 0, ref_r->time, ref_r->iters,
470  opts->pretty ? 6 : 0, ratio,
471  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
472  }
473  }
474  printf("\n");
475 
476  fflush(stdout);
477  }
478 
479  if (r->loss - expected_loss > 1e-4 && dst_w >= ref->width && dst_h >= ref->height) {
480  const int bad = r->loss - expected_loss > 1e-2;
481  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
482  const char *worse_str = bad ? "WORSE" : "worse";
483  av_log(NULL, level,
484  " loss %e is %s by %e, expected loss %e\n",
485  r->loss, worse_str, r->loss - expected_loss, expected_loss);
486  }
487 
488  if (ref_r && r->loss - ref_r->loss > 1e-4) {
489  /**
490  * The new scaling code does not (yet) perform error diffusion for
491  * low bit depth output, which impacts the SSIM score slightly for
492  * very low bit-depth formats (e.g. monow, monob). Since this is an
493  * expected result, drop the badness from an error to a warning for
494  * such cases. This can be removed again once error diffusion is
495  * implemented in the new ops code.
496  */
497  const int dst_bits = av_pix_fmt_desc_get(dst->format)->comp[0].depth;
498  const int bad = r->loss - ref_r->loss > 1e-2 && dst_bits > 1;
499  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
500  const char *worse_str = bad ? "WORSE" : "worse";
501  av_log(NULL, level,
502  " loss %e is %s by %e, ref loss %e SSIM={Y=%f U=%f V=%f A=%f}\n",
503  r->loss, worse_str, r->loss - ref_r->loss, ref_r->loss,
504  ref_r->ssim[0], ref_r->ssim[1], ref_r->ssim[2], ref_r->ssim[3]);
505  }
506 }
507 
508 static int init_frame(AVFrame **pframe, const AVFrame *ref,
509  int width, int height, enum AVPixelFormat format)
510 {
512  if (!frame)
513  return AVERROR(ENOMEM);
515  frame->width = width;
516  frame->height = height;
517  frame->format = format;
518  *pframe = frame;
519  return 0;
520 }
521 
522 /* Runs a series of ref -> src -> dst -> out, and compares out vs ref */
523 static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
524  int dst_w, int dst_h,
525  const struct mode *mode, const struct options *opts,
526  const AVFrame *ref, AVFrame *src,
527  const struct test_results *ref_r)
528 {
529  AVFrame *dst = NULL, *out = NULL;
530  const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt);
531  int ret;
532 
533  /* Estimate the expected amount of loss from bit depth reduction */
534  const float c1 = 0.01 * 0.01; /* stabilization constant */
535  const float ref_var = 1.0 / 12.0; /* uniformly distributed signal */
536  const float src_var = estimate_quantization_noise(src_fmt);
537  const float dst_var = estimate_quantization_noise(dst_fmt);
538  const float out_var = estimate_quantization_noise(ref->format);
539  const float total_var = src_var + dst_var + out_var;
540  const float ssim_luma = (2 * ref_var + c1) / (2 * ref_var + total_var + c1);
541  const float ssim_expected[4] = { ssim_luma, 1, 1, 1 }; /* for simplicity */
542  const float expected_loss = get_loss(ssim_expected);
543 
544  struct test_results r = { 0 };
545 
546  if (src->format != src_fmt) {
549  src->width = ref->width;
550  src->height = ref->height;
551  src->format = src_fmt;
553  if (ret < 0)
554  goto error;
555  }
556 
557  ret = init_frame(&dst, ref, dst_w, dst_h, dst_fmt);
558  if (ret < 0)
559  goto error;
560 
561  ret = opts->legacy ? scale_legacy(dst, src, mode, opts, &r.time)
562  : hw_device_ctx ? scale_hw(dst, src, mode, opts, &r.time)
563  : scale_new(dst, src, mode, opts, &r.time);
564  if (ret < 0) {
565  if (ret == AVERROR(ENOTSUP))
566  ret = 0;
567  goto error;
568  }
569 
570  ret = init_frame(&out, ref, ref->width, ref->height, ref->format);
571  if (ret < 0)
572  goto error;
573 
575  if (ret < 0)
576  goto error;
577 
578  get_ssim(r.ssim, out, ref, comps);
579 
580  if (opts->legacy) {
581  /* Legacy swscale does not perform bit accurate upconversions of low
582  * bit depth RGB. This artificially improves the SSIM score because the
583  * resulting error deletes some of the input dither noise. This gives
584  * it an unfair advantage when compared against a bit exact reference.
585  * Work around this by ensuring that the resulting SSIM score is not
586  * higher than it theoretically "should" be. */
587  if (src_var > dst_var) {
588  const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var + c1);
589  r.ssim[0] = FFMIN(r.ssim[0], src_loss);
590  }
591  }
592 
593  r.loss = get_loss(r.ssim);
594  if (!opts->legacy && r.loss - expected_loss > 1e-2 && dst_w >= ref->width && dst_h >= ref->height) {
595  ret = -1;
596  goto bad_loss;
597  }
598 
599  if (ref_r && r.loss - ref_r->loss > 1e-2) {
600  ret = -1;
601  goto bad_loss;
602  }
603 
604  ret = 0; /* fall through */
605 
606 bad_loss:
608  dst_w, dst_h,
609  mode, opts,
610  &r, ref_r,
611  expected_loss);
612 
613  error:
614  av_frame_free(&dst);
615  av_frame_free(&out);
616  return ret;
617 }
618 
619 static inline int fmt_is_subsampled(enum AVPixelFormat fmt)
620 {
621  return av_pix_fmt_desc_get(fmt)->log2_chroma_w != 0 ||
623 }
624 
625 static inline int fmt_is_supported_by_hw(enum AVPixelFormat fmt)
626 {
627  if (!hw_device_constr)
628  return 1;
629 
630  /* Semi-planar formats are only supported by the legacy path, which
631  * does not support hardware frames. */
632  if (fmt == AV_PIX_FMT_NV24 || fmt == AV_PIX_FMT_P410 ||
633  fmt == AV_PIX_FMT_P412 || fmt == AV_PIX_FMT_P416)
634  return 0;
635  for (int i = 0;
637  if (hw_device_constr->valid_sw_formats[i] == fmt)
638  return 1;
639  }
640  return 0;
641 }
642 
643 static int run_self_tests(const AVFrame *ref, const struct options *opts)
644 {
645  const int dst_w[] = { opts->w, opts->w - opts->w / 3, opts->w + opts->w / 3 };
646  const int dst_h[] = { opts->h, opts->h - opts->h / 3, opts->h + opts->h / 3 };
647 
648  enum AVPixelFormat src_fmt, dst_fmt,
649  src_fmt_min = 0,
650  dst_fmt_min = 0,
651  src_fmt_max = AV_PIX_FMT_NB - 1,
652  dst_fmt_max = AV_PIX_FMT_NB - 1;
653 
655  if (!src)
656  return AVERROR(ENOMEM);
657 
658  int ret = 0;
659 
660  if (opts->src_fmt != AV_PIX_FMT_NONE)
661  src_fmt_min = src_fmt_max = opts->src_fmt;
662  if (opts->dst_fmt != AV_PIX_FMT_NONE)
663  dst_fmt_min = dst_fmt_max = opts->dst_fmt;
664 
665  for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
666  if ((!fmt_is_supported_by_hw(src_fmt)) ||
667  (opts->unscaled && fmt_is_subsampled(src_fmt)))
668  continue;
669  if (!sws_test_format(src_fmt, 0) || !sws_test_format(src_fmt, 1))
670  continue;
671  for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
672  if ((!fmt_is_supported_by_hw(dst_fmt)) ||
673  (opts->unscaled && fmt_is_subsampled(dst_fmt)))
674  continue;
675  if (!sws_test_format(dst_fmt, 0) || !sws_test_format(dst_fmt, 1))
676  continue;
677  for (int h = 0; h < FF_ARRAY_ELEMS(dst_h); h++) {
678  for (int w = 0; w < FF_ARRAY_ELEMS(dst_w); w++) {
679  for (int f = 0; f < FF_ARRAY_ELEMS(flags); f++) {
680  struct mode mode = {
681  .flags = opts->flags >= 0 ? opts->flags : flags[f],
682  .dither = opts->dither >= 0 ? opts->dither : SWS_DITHER_AUTO,
683  };
684 
685  if (ff_sfc64_get(&prng_state) > UINT64_MAX * opts->prob)
686  continue;
687 
688  ret = run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h],
689  &mode, opts, ref, src, NULL);
690  if (ret < 0)
691  goto error;
692 
693  if (opts->flags >= 0 || opts->unscaled)
694  break;
695  }
696  if (opts->unscaled)
697  break;
698  }
699  if (opts->unscaled)
700  break;
701  }
702  }
703  }
704 
705  ret = 0;
706 
707 error:
708  av_frame_free(&src);
709  return ret;
710 }
711 
712 static int run_file_tests(const AVFrame *ref, FILE *fp, const struct options *opts)
713 {
714  char buf[256];
715  int ret = 0;
716 
718  if (!src)
719  return AVERROR(ENOMEM);
720 
721  for (int line = 1; fgets(buf, sizeof(buf), fp); line++) {
722  char src_fmt_str[21], dst_fmt_str[21];
723  enum AVPixelFormat src_fmt;
724  enum AVPixelFormat dst_fmt;
725  int sw, sh, dw, dh;
726  struct test_results r = { 0 };
727  struct mode mode;
728  int n = 0;
729 
730  ret = sscanf(buf,
731  "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
732  "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
733  src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
734  &mode.flags, &mode.dither,
735  &r.ssim[0], &r.ssim[1], &r.ssim[2], &r.ssim[3],
736  &r.loss, &n);
737  if (ret != 13) {
739  "Malformed reference file in line %d\n", line);
740  goto error;
741  }
742  if (opts->bench) {
743  ret = sscanf(buf + n,
744  ", time=%"PRId64"/%u us",
745  &r.time, &r.iters);
746  if (ret != 2) {
748  "Missing benchmarks from reference file in line %d\n",
749  line);
750  goto error;
751  }
752  }
753 
754  src_fmt = av_get_pix_fmt(src_fmt_str);
755  dst_fmt = av_get_pix_fmt(dst_fmt_str);
756  if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE) {
758  "Unknown pixel formats (%s and/or %s) in line %d\n",
759  src_fmt_str, dst_fmt_str, line);
760  goto error;
761  }
762 
763  if (sw != ref->width || sh != ref->height) {
765  "Mismatching dimensions %dx%d (ref is %dx%d) in line %d\n",
766  sw, sh, ref->width, ref->height, line);
767  goto error;
768  }
769 
770  if (opts->src_fmt != AV_PIX_FMT_NONE && src_fmt != opts->src_fmt ||
771  opts->dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts->dst_fmt)
772  continue;
773 
774  ret = run_test(src_fmt, dst_fmt, dw, dh, &mode, opts, ref, src, &r);
775  if (ret < 0)
776  goto error;
777  }
778 
779  ret = 0;
780 
781 error:
782  av_frame_free(&src);
783  return ret;
784 }
785 
786 static int init_ref(AVFrame *ref, const struct options *opts)
787 {
790  AVLFG rand;
791  int ret = -1;
792 
793  if (!ctx || !rgb)
794  goto error;
795 
796  rgb->width = opts->w / 12;
797  rgb->height = opts->h / 12;
798  rgb->format = AV_PIX_FMT_RGBA;
799  ret = av_frame_get_buffer(rgb, 32);
800  if (ret < 0)
801  goto error;
802 
803  av_lfg_init(&rand, 1);
804  for (int y = 0; y < rgb->height; y++) {
805  for (int x = 0; x < rgb->width; x++) {
806  for (int c = 0; c < 4; c++)
807  rgb->data[0][y * rgb->linesize[0] + x * 4 + c] = av_lfg_get(&rand);
808  }
809  }
810 
813 
814 error:
816  av_frame_free(&rgb);
817  return ret;
818 }
819 
820 static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
821 {
822  for (int i = 1; i < argc; i += 2) {
823  if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
824  fprintf(stderr,
825  "swscale [options...]\n"
826  " -help\n"
827  " This text\n"
828  " -ref <file>\n"
829  " Uses file as reference to compare tests against. Tests that have become worse will contain the string worse or WORSE\n"
830  " -p <number between 0.0 and 1.0>\n"
831  " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
832  " It is often convenient to perform a random subset\n"
833  " -dst <pixfmt>\n"
834  " Only test the specified destination pixel format\n"
835  " -src <pixfmt>\n"
836  " Only test the specified source pixel format\n"
837  " -s <size>\n"
838  " Set frame size (WxH or abbreviation)\n"
839  " -bench <iters>\n"
840  " Run benchmarks with the specified number of iterations. This mode also sets the frame size to 1920x1080 (unless -s is specified)\n"
841  " -flags <flags>\n"
842  " Test with a specific combination of flags\n"
843  " -dither <mode>\n"
844  " Test with a specific dither mode\n"
845  " -unscaled <1 or 0>\n"
846  " If 1, test only conversions that do not involve scaling\n"
847  " -legacy <1 or 0>\n"
848  " If 1, force using legacy swscale for the main conversion\n"
849  " -hw <device>\n"
850  " Use Vulkan hardware acceleration on the specified device for the main conversion\n"
851  " -threads <threads>\n"
852  " Use the specified number of threads\n"
853  " -cpuflags <cpuflags>\n"
854  " Uses the specified cpuflags in the tests\n"
855  " -pretty <1 or 0>\n"
856  " Align fields while printing results\n"
857  " -v <level>\n"
858  " Enable log verbosity at given level\n"
859  );
860  exit(0);
861  }
862  if (argv[i][0] != '-' || i + 1 == argc)
863  goto bad_option;
864  if (!strcmp(argv[i], "-ref")) {
865  *fp = fopen(argv[i + 1], "r");
866  if (!*fp) {
867  fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
868  return -1;
869  }
870  } else if (!strcmp(argv[i], "-cpuflags")) {
871  unsigned flags = av_get_cpu_flags();
872  int res = av_parse_cpu_caps(&flags, argv[i + 1]);
873  if (res < 0) {
874  fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]);
875  return -1;
876  }
878  } else if (!strcmp(argv[i], "-src")) {
879  opts->src_fmt = av_get_pix_fmt(argv[i + 1]);
880  if (opts->src_fmt == AV_PIX_FMT_NONE) {
881  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
882  return -1;
883  }
884  } else if (!strcmp(argv[i], "-dst")) {
885  opts->dst_fmt = av_get_pix_fmt(argv[i + 1]);
886  if (opts->dst_fmt == AV_PIX_FMT_NONE) {
887  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
888  return -1;
889  }
890  } else if (!strcmp(argv[i], "-s")) {
891  if (av_parse_video_size(&opts->w, &opts->h, argv[i + 1]) < 0) {
892  fprintf(stderr, "invalid frame size %s\n", argv[i + 1]);
893  return -1;
894  }
895  } else if (!strcmp(argv[i], "-bench")) {
896  int iters = atoi(argv[i + 1]);
897  if (iters <= 0) {
898  opts->bench = 0;
899  opts->iters = 1;
900  } else {
901  opts->bench = 1;
902  opts->iters = iters;
903  }
904  } else if (!strcmp(argv[i], "-flags")) {
906  const AVOption *flags_opt = av_opt_find(dummy, "sws_flags", NULL, 0, 0);
907  int ret = av_opt_eval_flags(dummy, flags_opt, argv[i + 1], &opts->flags);
909  if (ret < 0) {
910  fprintf(stderr, "invalid flags %s\n", argv[i + 1]);
911  return -1;
912  }
913  } else if (!strcmp(argv[i], "-dither")) {
914  opts->dither = atoi(argv[i + 1]);
915  } else if (!strcmp(argv[i], "-unscaled")) {
916  opts->unscaled = atoi(argv[i + 1]);
917  } else if (!strcmp(argv[i], "-legacy")) {
918  opts->legacy = atoi(argv[i + 1]);
919  } else if (!strcmp(argv[i], "-hw")) {
922  argv[i + 1], NULL, 0);
923  if (ret < 0) {
924  fprintf(stderr, "Failed to create Vulkan device '%s'\n",
925  argv[i + 1]);
926  return -1;
927  }
929  NULL);
930  if (!hw_device_constr) {
931  fprintf(stderr, "Failed to retrieve Vulkan device constraints '%s'\n",
932  argv[i + 1]);
933  return -1;
934  }
935  } else if (!strcmp(argv[i], "-threads")) {
936  opts->threads = atoi(argv[i + 1]);
937  } else if (!strcmp(argv[i], "-p")) {
938  opts->prob = atof(argv[i + 1]);
939  } else if (!strcmp(argv[i], "-pretty")) {
940  opts->pretty = atoi(argv[i + 1]);
941  } else if (!strcmp(argv[i], "-v")) {
942  av_log_set_level(atoi(argv[i + 1]));
943  } else {
944 bad_option:
945  fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]);
946  return -1;
947  }
948  }
949 
950  if (opts->w < 0 || opts->h < 0) {
951  opts->w = opts->bench ? 1920 : 96;
952  opts->h = opts->bench ? 1080 : 96;
953  }
954 
955  return 0;
956 }
957 
958 int main(int argc, char **argv)
959 {
960  struct options opts = {
961  .src_fmt = AV_PIX_FMT_NONE,
962  .dst_fmt = AV_PIX_FMT_NONE,
963  .w = -1,
964  .h = -1,
965  .threads = 1,
966  .iters = 1,
967  .prob = 1.0,
968  .flags = -1,
969  .dither = -1,
970  };
971 
972  AVFrame *ref = NULL;
973  FILE *fp = NULL;
974  int ret = -1;
975 
976  if (parse_options(argc, argv, &opts, &fp) < 0)
977  goto error;
978 
979  ff_sfc64_init(&prng_state, 0, 0, 0, 12);
980  signal(SIGINT, exit_handler);
981 
985  if (!sws_ref_src || !sws_src_dst || !sws_dst_out)
986  goto error;
989 
990  ref = av_frame_alloc();
991  if (!ref)
992  goto error;
993  ref->width = opts.w;
994  ref->height = opts.h;
995  ref->format = AV_PIX_FMT_YUVA444P;
996 
997  ret = init_ref(ref, &opts);
998  if (ret < 0)
999  goto error;
1000 
1001  ret = fp ? run_file_tests(ref, fp, &opts)
1002  : run_self_tests(ref, &opts);
1003 
1004  /* fall through */
1005 error:
1011  av_frame_free(&ref);
1012  if (fp)
1013  fclose(fp);
1014  exit_handler(ret);
1015 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
flags
const SwsFlags flags[]
Definition: swscale.c:72
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:225
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:619
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
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
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:429
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
estimate_quantization_noise
static float estimate_quantization_noise(enum AVPixelFormat fmt)
Definition: swscale.c:122
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:55
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
mode
Definition: swscale.c:60
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
pixdesc.h
AVFrame::width
int width
Definition: frame.h:499
speedup_color
static const char * speedup_color(double ratio)
Definition: swscale.c:98
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:263
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:57
options::dither
int dither
Definition: swscale.c:54
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
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
mode::dither
SwsDither dither
Definition: swscale.c:62
av_hwdevice_get_hwframe_constraints
AVHWFramesConstraints * av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig)
Get the constraints on HW frames given a device and the HW-specific configuration to be used with tha...
Definition: hwcontext.c:581
prng_state
static FFSFC64 prng_state
Definition: swscale.c:83
dummy
static int dummy
Definition: ffplay.c:3751
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
AV_HWDEVICE_TYPE_VULKAN
@ AV_HWDEVICE_TYPE_VULKAN
Definition: hwcontext.h:39
speedup_max
static double speedup_max
Definition: swscale.c:95
run_self_tests
static int run_self_tests(const AVFrame *ref, const struct options *opts)
Definition: swscale.c:643
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:444
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:712
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
scale_hw
static int scale_hw(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
Definition: swscale.c:303
macros.h
FFSFC64
Definition: sfc64.h:37
SwsDither
SwsDither
Definition: swscale.h:77
options::iters
int iters
Definition: swscale.c:51
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:66
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:47
options::w
int w
Definition: swscale.c:49
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:94
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
AVHWFramesConstraints::valid_sw_formats
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:456
SwsContext::dither
SwsDither dither
Dither mode.
Definition: swscale.h:235
av_hwframe_constraints_free
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:606
options::h
int h
Definition: swscale.c:49
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
hw_device_ctx
static AVBufferRef * hw_device_ctx
Definition: swscale.c:90
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:56
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
fmt_is_supported_by_hw
static int fmt_is_supported_by_hw(enum AVPixelFormat fmt)
Definition: swscale.c:625
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
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
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:50
AV_PIX_FMT_P410
#define AV_PIX_FMT_P410
Definition: pixfmt.h:617
parseutils.h
options
Definition: swscale.c:45
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:523
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:46
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:86
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
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
mode::flags
SwsFlags flags
Definition: swscale.c:61
hw_device_constr
static AVHWFramesConstraints * hw_device_constr
Definition: swscale.c:91
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:87
exit_handler
static void exit_handler(int sig)
Definition: swscale.c:109
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:514
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:260
frame.h
options::prob
double prob
Definition: swscale.c:48
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:201
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:213
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:53
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:67
SWS_X
@ SWS_X
experimental
Definition: swscale.h:179
weights
static const int weights[]
Definition: hevc_pel.c:32
AV_PIX_FMT_NV24
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:371
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:65
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
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
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
av_hwdevice_ctx_create
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition: hwcontext.c:615
test_results::time
int64_t time
Definition: swscale.c:68
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:153
av_hwframe_transfer_data
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:448
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:96
AVFrame::height
int height
Definition: frame.h:499
c2
static const uint64_t c2
Definition: murmur3.c:53
main
int main(int argc, char **argv)
Definition: swscale.c:958
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:786
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:88
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
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
AV_PIX_FMT_P416
#define AV_PIX_FMT_P416
Definition: pixfmt.h:621
options::bench
int bench
Definition: swscale.c:52
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
hwcontext.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AV_PIX_FMT_P412
#define AV_PIX_FMT_P412
Definition: pixfmt.h:619
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
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:506
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:235
fmt_comps
static int fmt_comps(enum AVPixelFormat fmt)
Definition: swscale.c:144
test_results::iters
int iters
Definition: swscale.c:69
parse_options
static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
Definition: swscale.c:820
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:508
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:93