Go to the documentation of this file.
29 #undef HAVE_AV_CONFIG_H
82 return ratio > 1.10 ?
"\033[1;32m" :
83 ratio > 1.02 ?
"\033[32m" :
85 ratio > 0.95 ?
"\033[33m" :
86 ratio > 0.90 ?
"\033[31m" :
94 printf(
"Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
106 float variance = 1.0 / 12;
107 if (
desc->comp[0].depth < 8) {
109 variance *= (8 -
desc->comp[0].depth);
115 const float r = 0.299 / (1 <<
desc->comp[0].depth);
116 const float g = 0.587 / (1 <<
desc->comp[1].depth);
117 const float b = 0.114 / (1 <<
desc->comp[2].depth);
118 return (
r *
r +
g *
g +
b *
b) * variance;
120 const float y = 1.0 / (1 <<
desc->comp[0].depth);
121 return y * y * variance;
128 int comps =
desc->nb_components >= 3 ? 0b111 : 0
b1;
140 for (
int p = 0; p < 4; p++) {
141 const int stride_a =
out->linesize[p];
142 const int stride_b =
ref->linesize[p];
143 const int w =
out->width;
144 const int h =
out->height;
146 const int is_chroma = p == 1 || p == 2;
147 const uint8_t def = is_chroma ? 128 : 0xFF;
148 const int has_ref = comps & (1 << p);
153 for (
int y = 0; y < (
h & ~3); y += 4) {
154 for (
int x = 0; x < (
w & ~3); x += 4) {
155 const float c1 = .01 * .01 * 255 * 255 * 64;
156 const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
157 int s1 = 0, s2 = 0,
ss = 0, s12 = 0, var, covar;
159 for (
int yy = 0; yy < 4; yy++) {
160 for (
int xx = 0; xx < 4; xx++) {
161 int a =
out->data[p][(y + yy) * stride_a + x + xx];
162 int b = has_ref ?
ref->data[p][(y + yy) * stride_b + x + xx] : def;
170 var =
ss * 64 - s1 * s1 - s2 * s2;
171 covar = s12 * 64 - s1 * s2;
172 sum += (2 * s1 * s2 +
c1) * (2 * covar +
c2) /
173 ((s1 * s1 + s2 * s2 +
c1) * (var +
c2));
178 ssim[p] = count ? sum / count : 0.0;
184 const float weights[3] = { 0.8, 0.1, 0.1 };
187 for (
int i = 0;
i < 3;
i++)
217 for (
int i = 0;
ret >= 0 &&
i <
opts.iters;
i++)
231 float ssim[4], ssim_sws[4];
237 const float c1 = 0.01 * 0.01;
238 const float ref_var = 1.0 / 12.0;
242 const float total_var = src_var + dst_var + out_var;
243 const float ssim_luma = (2 * ref_var +
c1) / (2 * ref_var + total_var +
c1);
244 const float ssim_expected[4] = { ssim_luma, 1, 1, 1 };
245 const float expected_loss =
get_loss(ssim_expected);
259 out->format =
ref->format;
260 src->format = src_fmt;
261 dst->format = dst_fmt;
277 for (
int i = 0;
i <
opts.iters;
i++) {
294 printf(
"%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u, "
295 "SSIM {Y=%f U=%f V=%f A=%f}\n",
299 ssim[0], ssim[1], ssim[2], ssim[3]);
302 if (loss - expected_loss > 1e-4 && dst_w >=
ref->width && dst_h >=
ref->height) {
303 int bad = loss - expected_loss > 1e-2;
304 printf(
"\033[1;31m loss %g is %s by %g, expected loss %g\033[0m\n",
305 loss,
bad ?
"WORSE" :
"worse", loss - expected_loss, expected_loss);
331 if (src_var > dst_var) {
332 const float src_loss = (2 * ref_var +
c1) / (2 * ref_var + src_var +
c1);
333 ssim_sws[0] =
FFMIN(ssim_sws[0], src_loss);
340 const float loss_ref =
get_loss(ssim_ref);
341 if (loss - loss_ref > 1e-4) {
342 int bad = loss - loss_ref > 1e-2;
343 printf(
"\033[1;31m loss %g is %s by %g, ref loss %g, "
344 "SSIM {Y=%f U=%f V=%f A=%f}\033[0m\n",
345 loss,
bad ?
"WORSE" :
"worse", loss - loss_ref, loss_ref,
346 ssim_ref[0], ssim_ref[1], ssim_ref[2], ssim_ref[3]);
352 if (
opts.bench && time_ref) {
353 double ratio = (
double) time_ref / time;
354 if (
FFMIN(time, time_ref) > 100 ) {
361 printf(
" time=%"PRId64
" us, ref=%"PRId64
" us, speedup=%.3fx %s%s\033[0m\n",
362 time /
opts.iters, time_ref /
opts.iters, ratio,
364 }
else if (
opts.bench) {
365 printf(
" time=%"PRId64
" us\n", time /
opts.iters);
395 src_fmt_min = src_fmt_max =
opts.src_fmt;
397 dst_fmt_min = dst_fmt_max =
opts.dst_fmt;
399 for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
404 for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
420 if (
run_test(src_fmt, dst_fmt, dst_w[
w], dst_h[
h],
424 if (
opts.flags >= 0 ||
opts.unscaled)
444 while (fgets(buf,
sizeof(buf), fp)) {
445 char src_fmt_str[21], dst_fmt_str[21];
453 "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
454 "SSIM {Y=%f U=%f V=%f A=%f}\n",
455 src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
457 &ssim[0], &ssim[1], &ssim[2], &ssim[3]);
466 sw !=
ref->width || sh !=
ref->height || dw > 8192 || dh > 8192 ||
468 fprintf(stderr,
"malformed input file\n");
483 int main(
int argc,
char **argv)
502 for (
int i = 1;
i < argc;
i += 2) {
503 if (!strcmp(argv[
i],
"-help") || !strcmp(argv[
i],
"--help")) {
505 "swscale [options...]\n"
509 " Uses file as reference to compare tests againsts. Tests that have become worse will contain the string worse or WORSE\n"
510 " -p <number between 0.0 and 1.0>\n"
511 " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
512 " It is often convenient to perform a random subset\n"
514 " Only test the specified destination pixel format\n"
516 " Only test the specified source pixel format\n"
518 " Run benchmarks with the specified number of iterations. This mode also increases the size of the test images\n"
520 " Test with a specific combination of flags\n"
522 " Test with a specific dither mode\n"
523 " -unscaled <1 or 0>\n"
524 " If 1, test only conversions that do not involve scaling\n"
525 " -threads <threads>\n"
526 " Use the specified number of threads\n"
527 " -cpuflags <cpuflags>\n"
528 " Uses the specified cpuflags in the tests\n"
530 " Enable log verbosity at given level\n"
534 if (argv[
i][0] !=
'-' ||
i + 1 == argc)
536 if (!strcmp(argv[
i],
"-ref")) {
537 fp = fopen(argv[
i + 1],
"r");
539 fprintf(stderr,
"could not open '%s'\n", argv[
i + 1]);
542 }
else if (!strcmp(argv[
i],
"-cpuflags")) {
546 fprintf(stderr,
"invalid cpu flags %s\n", argv[
i + 1]);
550 }
else if (!strcmp(argv[
i],
"-src")) {
553 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
556 }
else if (!strcmp(argv[
i],
"-dst")) {
559 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
562 }
else if (!strcmp(argv[
i],
"-bench")) {
564 opts.iters = atoi(argv[
i + 1]);
568 }
else if (!strcmp(argv[
i],
"-flags")) {
569 opts.flags = strtol(argv[
i + 1],
NULL, 0);
570 }
else if (!strcmp(argv[
i],
"-dither")) {
571 opts.dither = atoi(argv[
i + 1]);
572 }
else if (!strcmp(argv[
i],
"-unscaled")) {
573 opts.unscaled = atoi(argv[
i + 1]);
574 }
else if (!strcmp(argv[
i],
"-threads")) {
575 opts.threads = atoi(argv[
i + 1]);
576 }
else if (!strcmp(argv[
i],
"-p")) {
577 opts.prob = atof(argv[
i + 1]);
578 }
else if (!strcmp(argv[
i],
"-v")) {
582 fprintf(stderr,
"bad option or argument missing (%s) see -help\n", argv[
i]);
591 for (
int i = 0;
i < 3;
i++) {
607 for (
int y = 0; y <
rgb->height; y++) {
608 for (
int x = 0; x <
rgb->width; x++) {
609 for (
int c = 0;
c < 4;
c++)
629 for (
int i = 0;
i < 3;
i++)
static void error(const char *err)
void av_force_cpu_flags(int arg)
Disables cpu detection and forces the specified flags.
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
AVPixelFormat
Pixel format.
static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode, struct options opts)
#define sws_isSupportedOutput(x)
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
static int fmt_is_subsampled(enum AVPixelFormat fmt)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
int src_w
Deprecated frame property overrides, for the legacy API only.
static float estimate_quantization_noise(enum AVPixelFormat fmt)
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
This structure describes decoded (raw) audio or video data.
static const char * speedup_color(double ratio)
@ SWS_BILINEAR
bilinear filtering
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.
unsigned flags
Bitmask of SWS_*.
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
static FFSFC64 prng_state
static int run_file_tests(const AVFrame *ref, FILE *fp, struct options opts)
static double speedup_max
@ AV_PIX_FMT_NB
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
@ SWS_FAST_BILINEAR
Scaler selection options.
static double b1(void *priv, double x, double y)
@ SWS_FULL_CHR_H_INP
Perform full chroma interpolation when downscaling RGB sources.
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.
av_warn_unused_result int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
#define ss(width, name, subs,...)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
enum AVPixelFormat dst_fmt
#define FF_ARRAY_ELEMS(a)
static double speedup_min
SwsDither dither
Dither mode.
int threads
How many threads to use for processing, or 0 for automatic selection.
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
static int run_self_tests(const AVFrame *ref, struct options opts)
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
@ SWS_BICUBIC
2-tap cubic B-spline
static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int dst_w, int dst_h, struct mode mode, struct options opts, const AVFrame *ref, const float ssim_ref[4])
int sws_test_format(enum AVPixelFormat format, int output)
Test if a given pixel format is supported.
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
enum AVPixelFormat src_fmt
Context structure for the Lagged Fibonacci PRNG.
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
@ SWS_POINT
nearest neighbor
int src_h
Width and height of the source frame.
static void exit_handler(int sig)
printf("static const uint8_t my_array[100] = {\n")
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
static float get_loss(const float ssim[4])
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
int dst_format
Destination pixel format.
#define sws_isSupportedInput(x)
static SwsContext * sws[3]
void av_log_set_level(int level)
Set the log level.
#define i(width, name, range_min, range_max)
static const int weights[]
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
int dst_h
Width and height of the destination frame.
static uint64_t ff_sfc64_get(FFSFC64 *s)
@ SWS_FULL_CHR_H_INT
Perform full chroma upsampling when upscaling to RGB.
static void get_ssim(float ssim[4], const AVFrame *out, const AVFrame *ref, int comps)
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
int main(int argc, char **argv)
static int ref[MAX_W *MAX_W]
static int bad(InterplayACMContext *s, unsigned ind, unsigned col)
int src_format
Source pixel format.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
void sws_free_context(SwsContext **ctx)
Free the context and everything associated with it, and write NULL to the provided pointer.
int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
Scale source data from src and write the output to dst.
@ SWS_ACCURATE_RND
Force bit-exact output.
Main external API structure.
static int fmt_comps(enum AVPixelFormat fmt)
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
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.
static double speedup_logavg