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_test_params(char *buf, size_t buf_size,
430  const AVFrame *src, const AVFrame *dst,
431  const struct mode *mode, const struct options *opts)
432 {
433  snprintf(buf, buf_size,
434  "%-*s %*dx%*d -> %-*s %*dx%*d, flags=0x%0*x dither=%u",
435  opts->pretty ? 14 : 0, av_get_pix_fmt_name(src->format),
436  opts->pretty ? 4 : 0, src->width,
437  opts->pretty ? 4 : 0, src->height,
438  opts->pretty ? 14 : 0, av_get_pix_fmt_name(dst->format),
439  opts->pretty ? 4 : 0, dst->width,
440  opts->pretty ? 4 : 0, dst->height,
441  opts->pretty ? 8 : 0, mode->flags,
442  mode->dither);
443 }
444 
445 static void print_results(const AVFrame *ref, const AVFrame *src, const AVFrame *dst,
446  int dst_w, int dst_h,
447  const struct mode *mode, const struct options *opts,
448  const struct test_results *r,
449  const struct test_results *ref_r,
450  float expected_loss)
451 {
452  char buf[128];
453 
454  if (av_log_get_level() >= AV_LOG_INFO) {
455  print_test_params(buf, sizeof(buf), src, dst, mode, opts);
456  printf("%s", buf);
457 
458  if (!opts->bench || !ref_r) {
459  printf(", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
460  r->ssim[0], r->ssim[1], r->ssim[2], r->ssim[3],
461  r->loss);
462  if (ref_r)
463  printf(" (ref=%e)", ref_r->loss);
464  }
465 
466  if (opts->bench) {
467  printf(", time=%*"PRId64"/%u us",
468  opts->pretty ? 7 : 0, r->time, opts->iters);
469  if (ref_r) {
470  double ratio = ((double) ref_r->time / ref_r->iters)
471  / ((double) r->time / opts->iters);
472  if (FFMIN(r->time, ref_r->time) > 100 /* don't pollute stats with low precision */) {
473  speedup_min = FFMIN(speedup_min, ratio);
474  speedup_max = FFMAX(speedup_max, ratio);
475  speedup_logavg += log(ratio);
476  speedup_count++;
477  }
478 
479  printf(" (ref=%*"PRId64"/%u us), speedup=%*.3fx %s%s\033[0m",
480  opts->pretty ? 7 : 0, ref_r->time, ref_r->iters,
481  opts->pretty ? 6 : 0, ratio,
482  speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
483  }
484  }
485  printf("\n");
486 
487  fflush(stdout);
488  }
489 
490  if (r->loss - expected_loss > 1e-4 && dst_w >= ref->width && dst_h >= ref->height) {
491  const int bad = r->loss - expected_loss > 1e-2;
492  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
493  const char *worse_str = bad ? "WORSE" : "worse";
494  if (bad) {
495  print_test_params(buf, sizeof(buf), src, dst, mode, opts);
496  av_log(NULL, level, "%s\n", buf);
497  }
498  av_log(NULL, level,
499  " loss %e is %s by %e, expected loss %e\n",
500  r->loss, worse_str, r->loss - expected_loss, expected_loss);
501  }
502 
503  if (ref_r && r->loss - ref_r->loss > 1e-4) {
504  /**
505  * The new scaling code does not (yet) perform error diffusion for
506  * low bit depth output, which impacts the SSIM score slightly for
507  * very low bit-depth formats (e.g. monow, monob). Since this is an
508  * expected result, drop the badness from an error to a warning for
509  * such cases. This can be removed again once error diffusion is
510  * implemented in the new ops code.
511  */
512  const int dst_bits = av_pix_fmt_desc_get(dst->format)->comp[0].depth;
513  const int bad = r->loss - ref_r->loss > 1e-2 && dst_bits > 1;
514  const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
515  const char *worse_str = bad ? "WORSE" : "worse";
516  if (bad) {
517  print_test_params(buf, sizeof(buf), src, dst, mode, opts);
518  av_log(NULL, level, "%s\n", buf);
519  }
520  av_log(NULL, level,
521  " loss %e is %s by %e, ref loss %e SSIM={Y=%f U=%f V=%f A=%f}\n",
522  r->loss, worse_str, r->loss - ref_r->loss, ref_r->loss,
523  ref_r->ssim[0], ref_r->ssim[1], ref_r->ssim[2], ref_r->ssim[3]);
524  }
525 }
526 
527 static int init_frame(AVFrame **pframe, const AVFrame *ref,
528  int width, int height, enum AVPixelFormat format)
529 {
531  if (!frame)
532  return AVERROR(ENOMEM);
534  frame->width = width;
535  frame->height = height;
536  frame->format = format;
537  *pframe = frame;
538  return 0;
539 }
540 
541 /* Runs a series of ref -> src -> dst -> out, and compares out vs ref */
542 static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
543  int dst_w, int dst_h,
544  const struct mode *mode, const struct options *opts,
545  const AVFrame *ref, AVFrame *src,
546  const struct test_results *ref_r)
547 {
548  AVFrame *dst = NULL, *out = NULL;
549  const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt);
550  int ret;
551 
552  /* Estimate the expected amount of loss from bit depth reduction */
553  const float c1 = 0.01 * 0.01; /* stabilization constant */
554  const float ref_var = 1.0 / 12.0; /* uniformly distributed signal */
555  const float src_var = estimate_quantization_noise(src_fmt);
556  const float dst_var = estimate_quantization_noise(dst_fmt);
557  const float out_var = estimate_quantization_noise(ref->format);
558  const float total_var = src_var + dst_var + out_var;
559  const float ssim_luma = (2 * ref_var + c1) / (2 * ref_var + total_var + c1);
560  const float ssim_expected[4] = { ssim_luma, 1, 1, 1 }; /* for simplicity */
561  const float expected_loss = get_loss(ssim_expected);
562 
563  struct test_results r = { 0 };
564 
565  if (src->format != src_fmt) {
568  src->width = ref->width;
569  src->height = ref->height;
570  src->format = src_fmt;
572  if (ret < 0)
573  goto error;
574  }
575 
576  ret = init_frame(&dst, ref, dst_w, dst_h, dst_fmt);
577  if (ret < 0)
578  goto error;
579 
580  ret = opts->legacy ? scale_legacy(dst, src, mode, opts, &r.time)
581  : hw_device_ctx ? scale_hw(dst, src, mode, opts, &r.time)
582  : scale_new(dst, src, mode, opts, &r.time);
583  if (ret < 0) {
584  if (ret == AVERROR(ENOTSUP))
585  ret = 0;
586  goto error;
587  }
588 
589  ret = init_frame(&out, ref, ref->width, ref->height, ref->format);
590  if (ret < 0)
591  goto error;
592 
594  if (ret < 0)
595  goto error;
596 
597  get_ssim(r.ssim, out, ref, comps);
598 
599  if (opts->legacy) {
600  /* Legacy swscale does not perform bit accurate upconversions of low
601  * bit depth RGB. This artificially improves the SSIM score because the
602  * resulting error deletes some of the input dither noise. This gives
603  * it an unfair advantage when compared against a bit exact reference.
604  * Work around this by ensuring that the resulting SSIM score is not
605  * higher than it theoretically "should" be. */
606  if (src_var > dst_var) {
607  const float src_loss = (2 * ref_var + c1) / (2 * ref_var + src_var + c1);
608  r.ssim[0] = FFMIN(r.ssim[0], src_loss);
609  }
610  }
611 
612  r.loss = get_loss(r.ssim);
613  if (!opts->legacy && r.loss - expected_loss > 1e-2 && dst_w >= ref->width && dst_h >= ref->height) {
614  ret = -1;
615  goto bad_loss;
616  }
617 
618  if (ref_r && r.loss - ref_r->loss > 1e-2) {
619  ret = -1;
620  goto bad_loss;
621  }
622 
623  ret = 0; /* fall through */
624 
625 bad_loss:
627  dst_w, dst_h,
628  mode, opts,
629  &r, ref_r,
630  expected_loss);
631 
632  error:
633  av_frame_free(&dst);
634  av_frame_free(&out);
635  return ret;
636 }
637 
638 static inline int fmt_is_subsampled(enum AVPixelFormat fmt)
639 {
640  return av_pix_fmt_desc_get(fmt)->log2_chroma_w != 0 ||
642 }
643 
644 static inline int fmt_is_supported_by_hw(enum AVPixelFormat fmt)
645 {
646  if (!hw_device_constr)
647  return 1;
648 
649  /* Semi-planar formats are only supported by the legacy path, which
650  * does not support hardware frames. */
651  if (fmt == AV_PIX_FMT_NV24 || fmt == AV_PIX_FMT_P410 ||
652  fmt == AV_PIX_FMT_P412 || fmt == AV_PIX_FMT_P416)
653  return 0;
654  for (int i = 0;
656  if (hw_device_constr->valid_sw_formats[i] == fmt)
657  return 1;
658  }
659  return 0;
660 }
661 
662 static int run_self_tests(const AVFrame *ref, const struct options *opts)
663 {
664  const int dst_w[] = { opts->w, opts->w - opts->w / 3, opts->w + opts->w / 3 };
665  const int dst_h[] = { opts->h, opts->h - opts->h / 3, opts->h + opts->h / 3 };
666 
667  enum AVPixelFormat src_fmt, dst_fmt,
668  src_fmt_min = 0,
669  dst_fmt_min = 0,
670  src_fmt_max = AV_PIX_FMT_NB - 1,
671  dst_fmt_max = AV_PIX_FMT_NB - 1;
672 
674  if (!src)
675  return AVERROR(ENOMEM);
676 
677  int ret = 0;
678 
679  if (opts->src_fmt != AV_PIX_FMT_NONE)
680  src_fmt_min = src_fmt_max = opts->src_fmt;
681  if (opts->dst_fmt != AV_PIX_FMT_NONE)
682  dst_fmt_min = dst_fmt_max = opts->dst_fmt;
683 
684  for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
685  if ((!fmt_is_supported_by_hw(src_fmt)) ||
686  (opts->unscaled && fmt_is_subsampled(src_fmt)))
687  continue;
688  if (!sws_test_format(src_fmt, 0) || !sws_test_format(src_fmt, 1))
689  continue;
690  for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
691  if ((!fmt_is_supported_by_hw(dst_fmt)) ||
692  (opts->unscaled && fmt_is_subsampled(dst_fmt)))
693  continue;
694  if (!sws_test_format(dst_fmt, 0) || !sws_test_format(dst_fmt, 1))
695  continue;
696  for (int h = 0; h < FF_ARRAY_ELEMS(dst_h); h++) {
697  for (int w = 0; w < FF_ARRAY_ELEMS(dst_w); w++) {
698  for (int f = 0; f < FF_ARRAY_ELEMS(flags); f++) {
699  struct mode mode = {
700  .flags = opts->flags >= 0 ? opts->flags : flags[f],
701  .dither = opts->dither >= 0 ? opts->dither : SWS_DITHER_AUTO,
702  };
703 
704  if (ff_sfc64_get(&prng_state) <= UINT64_MAX * opts->prob) {
705  ret = run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h],
706  &mode, opts, ref, src, NULL);
707  if (ret < 0)
708  goto error;
709  }
710 
711  if (opts->flags >= 0 || opts->unscaled)
712  break;
713  }
714  if (opts->unscaled)
715  break;
716  }
717  if (opts->unscaled)
718  break;
719  }
720  }
721  }
722 
723  ret = 0;
724 
725 error:
726  av_frame_free(&src);
727  return ret;
728 }
729 
730 static int run_file_tests(const AVFrame *ref, FILE *fp, const struct options *opts)
731 {
732  char buf[256];
733  int ret = 0;
734 
736  if (!src)
737  return AVERROR(ENOMEM);
738 
739  for (int line = 1; fgets(buf, sizeof(buf), fp); line++) {
740  char src_fmt_str[21], dst_fmt_str[21];
741  enum AVPixelFormat src_fmt;
742  enum AVPixelFormat dst_fmt;
743  int sw, sh, dw, dh;
744  struct test_results r = { 0 };
745  struct mode mode;
746  int n = 0;
747 
748  ret = sscanf(buf,
749  "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
750  "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
751  src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
752  &mode.flags, &mode.dither,
753  &r.ssim[0], &r.ssim[1], &r.ssim[2], &r.ssim[3],
754  &r.loss, &n);
755  if (ret != 13) {
757  "Malformed reference file in line %d\n", line);
758  goto error;
759  }
760  if (opts->bench) {
761  ret = sscanf(buf + n,
762  ", time=%"PRId64"/%u us",
763  &r.time, &r.iters);
764  if (ret != 2) {
766  "Missing benchmarks from reference file in line %d\n",
767  line);
768  goto error;
769  }
770  }
771 
772  src_fmt = av_get_pix_fmt(src_fmt_str);
773  dst_fmt = av_get_pix_fmt(dst_fmt_str);
774  if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE) {
776  "Unknown pixel formats (%s and/or %s) in line %d\n",
777  src_fmt_str, dst_fmt_str, line);
778  goto error;
779  }
780 
781  if (sw != ref->width || sh != ref->height) {
783  "Mismatching dimensions %dx%d (ref is %dx%d) in line %d\n",
784  sw, sh, ref->width, ref->height, line);
785  goto error;
786  }
787 
788  if (opts->src_fmt != AV_PIX_FMT_NONE && src_fmt != opts->src_fmt ||
789  opts->dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts->dst_fmt)
790  continue;
791 
792  ret = run_test(src_fmt, dst_fmt, dw, dh, &mode, opts, ref, src, &r);
793  if (ret < 0)
794  goto error;
795  }
796 
797  ret = 0;
798 
799 error:
800  av_frame_free(&src);
801  return ret;
802 }
803 
804 static int init_ref(AVFrame *ref, const struct options *opts)
805 {
808  AVLFG rand;
809  int ret = -1;
810 
811  if (!ctx || !rgb)
812  goto error;
813 
814  rgb->width = opts->w > 32 ? opts->w / 12 : opts->w;
815  rgb->height = opts->h > 32 ? opts->h / 12 : opts->h;
816  rgb->format = AV_PIX_FMT_RGBA;
817  ret = av_frame_get_buffer(rgb, 32);
818  if (ret < 0)
819  goto error;
820 
821  av_lfg_init(&rand, 1);
822  for (int y = 0; y < rgb->height; y++) {
823  for (int x = 0; x < rgb->width; x++) {
824  for (int c = 0; c < 4; c++)
825  rgb->data[0][y * rgb->linesize[0] + x * 4 + c] = av_lfg_get(&rand);
826  }
827  }
828 
831 
832 error:
834  av_frame_free(&rgb);
835  return ret;
836 }
837 
838 static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
839 {
840  for (int i = 1; i < argc; i += 2) {
841  if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
842  fprintf(stderr,
843  "swscale [options...]\n"
844  " -help\n"
845  " This text\n"
846  " -ref <file>\n"
847  " Uses file as reference to compare tests against. Tests that have become worse will contain the string worse or WORSE\n"
848  " -p <number between 0.0 and 1.0>\n"
849  " The proportion of tests or comparisons to perform.\n"
850  " It is often convenient to perform a random subset\n"
851  " -dst <pixfmt>\n"
852  " Only test the specified destination pixel format\n"
853  " -src <pixfmt>\n"
854  " Only test the specified source pixel format\n"
855  " -s <size>\n"
856  " Set frame size (WxH or abbreviation)\n"
857  " -bench <iters>\n"
858  " Run benchmarks with the specified number of iterations. This mode also sets the frame size to 1920x1080 (unless -s is specified)\n"
859  " -flags <flags>\n"
860  " Test with a specific combination of flags\n"
861  " -dither <mode>\n"
862  " Test with a specific dither mode\n"
863  " -unscaled <1 or 0>\n"
864  " If 1, test only conversions that do not involve scaling\n"
865  " -legacy <1 or 0>\n"
866  " If 1, force using legacy swscale for the main conversion\n"
867  " -hw <device>\n"
868  " Use Vulkan hardware acceleration on the specified device for the main conversion\n"
869  " -threads <threads>\n"
870  " Use the specified number of threads\n"
871  " -cpuflags <cpuflags>\n"
872  " Uses the specified cpuflags in the tests\n"
873  " -pretty <1 or 0>\n"
874  " Align fields while printing results\n"
875  " -v <level>\n"
876  " Enable log verbosity at given level\n"
877  );
878  exit(0);
879  }
880  if (argv[i][0] != '-' || i + 1 == argc)
881  goto bad_option;
882  if (!strcmp(argv[i], "-ref")) {
883  *fp = fopen(argv[i + 1], "r");
884  if (!*fp) {
885  fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
886  return -1;
887  }
888  } else if (!strcmp(argv[i], "-cpuflags")) {
889  unsigned flags = av_get_cpu_flags();
890  int res = av_parse_cpu_caps(&flags, argv[i + 1]);
891  if (res < 0) {
892  fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]);
893  return -1;
894  }
896  } else if (!strcmp(argv[i], "-src")) {
897  opts->src_fmt = av_get_pix_fmt(argv[i + 1]);
898  if (opts->src_fmt == AV_PIX_FMT_NONE) {
899  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
900  return -1;
901  }
902  } else if (!strcmp(argv[i], "-dst")) {
903  opts->dst_fmt = av_get_pix_fmt(argv[i + 1]);
904  if (opts->dst_fmt == AV_PIX_FMT_NONE) {
905  fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
906  return -1;
907  }
908  } else if (!strcmp(argv[i], "-s")) {
909  if (av_parse_video_size(&opts->w, &opts->h, argv[i + 1]) < 0) {
910  fprintf(stderr, "invalid frame size %s\n", argv[i + 1]);
911  return -1;
912  }
913  } else if (!strcmp(argv[i], "-bench")) {
914  int iters = atoi(argv[i + 1]);
915  if (iters <= 0) {
916  opts->bench = 0;
917  opts->iters = 1;
918  } else {
919  opts->bench = 1;
920  opts->iters = iters;
921  }
922  } else if (!strcmp(argv[i], "-flags")) {
924  const AVOption *flags_opt = av_opt_find(dummy, "sws_flags", NULL, 0, 0);
925  int ret = av_opt_eval_flags(dummy, flags_opt, argv[i + 1], &opts->flags);
927  if (ret < 0) {
928  fprintf(stderr, "invalid flags %s\n", argv[i + 1]);
929  return -1;
930  }
931  } else if (!strcmp(argv[i], "-dither")) {
932  opts->dither = atoi(argv[i + 1]);
933  } else if (!strcmp(argv[i], "-unscaled")) {
934  opts->unscaled = atoi(argv[i + 1]);
935  } else if (!strcmp(argv[i], "-legacy")) {
936  opts->legacy = atoi(argv[i + 1]);
937  } else if (!strcmp(argv[i], "-hw")) {
940  argv[i + 1], NULL, 0);
941  if (ret < 0) {
942  fprintf(stderr, "Failed to create Vulkan device '%s'\n",
943  argv[i + 1]);
944  return -1;
945  }
947  NULL);
948  if (!hw_device_constr) {
949  fprintf(stderr, "Failed to retrieve Vulkan device constraints '%s'\n",
950  argv[i + 1]);
951  return -1;
952  }
953  } else if (!strcmp(argv[i], "-threads")) {
954  opts->threads = atoi(argv[i + 1]);
955  } else if (!strcmp(argv[i], "-p")) {
956  opts->prob = atof(argv[i + 1]);
957  } else if (!strcmp(argv[i], "-pretty")) {
958  opts->pretty = atoi(argv[i + 1]);
959  } else if (!strcmp(argv[i], "-v")) {
960  av_log_set_level(atoi(argv[i + 1]));
961  } else {
962 bad_option:
963  fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]);
964  return -1;
965  }
966  }
967 
968  if (opts->w < 0 || opts->h < 0) {
969  opts->w = opts->bench ? 1920 : 96;
970  opts->h = opts->bench ? 1080 : 96;
971  }
972 
973  return 0;
974 }
975 
976 int main(int argc, char **argv)
977 {
978  struct options opts = {
979  .src_fmt = AV_PIX_FMT_NONE,
980  .dst_fmt = AV_PIX_FMT_NONE,
981  .w = -1,
982  .h = -1,
983  .threads = 1,
984  .iters = 1,
985  .prob = 1.0,
986  .flags = -1,
987  .dither = -1,
988  };
989 
990  AVFrame *ref = NULL;
991  FILE *fp = NULL;
992  int ret = -1;
993 
994  if (parse_options(argc, argv, &opts, &fp) < 0)
995  goto error;
996 
997  ff_sfc64_init(&prng_state, 0, 0, 0, 12);
998  signal(SIGINT, exit_handler);
999 
1003  if (!sws_ref_src || !sws_src_dst || !sws_dst_out)
1004  goto error;
1007 
1008  ref = av_frame_alloc();
1009  if (!ref)
1010  goto error;
1011  ref->width = opts.w;
1012  ref->height = opts.h;
1013  ref->format = AV_PIX_FMT_YUVA444P;
1014 
1015  ret = init_ref(ref, &opts);
1016  if (ret < 0)
1017  goto error;
1018 
1019  ret = fp ? run_file_tests(ref, fp, &opts)
1020  : run_self_tests(ref, &opts);
1021 
1022  /* fall through */
1023 error:
1029  av_frame_free(&ref);
1030  if (fp)
1031  fclose(fp);
1032  exit_handler(ret);
1033 }
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:638
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:445
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:459
pixdesc.h
AVFrame::width
int width
Definition: frame.h:531
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:43
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:662
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:730
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:1447
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:202
test_results::ssim
float ssim[4]
Definition: swscale.c:66
print_test_params
static void print_test_params(char *buf, size_t buf_size, const AVFrame *src, const AVFrame *dst, const struct mode *mode, const struct options *opts)
Definition: swscale.c:429
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:1415
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:644
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:557
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:542
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:546
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:531
c2
static const uint64_t c2
Definition: murmur3.c:53
main
int main(int argc, char **argv)
Definition: swscale.c:976
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:804
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:83
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:2369
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:1370
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
snprintf
#define snprintf
Definition: snprintf.h:34
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:838
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:527
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