Go to the documentation of this file.
29 #undef HAVE_AV_CONFIG_H
82 return ratio > 10.00 ?
"\033[1;94m" :
83 ratio > 2.00 ?
"\033[1;32m" :
84 ratio > 1.02 ?
"\033[32m" :
86 ratio > 0.90 ?
"\033[33m" :
87 ratio > 0.75 ?
"\033[31m" :
95 printf(
"Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
107 float variance = 1.0 / 12;
108 if (
desc->comp[0].depth < 8) {
110 variance *= (8 -
desc->comp[0].depth);
116 const float r = 0.299 / (1 <<
desc->comp[0].depth);
117 const float g = 0.587 / (1 <<
desc->comp[1].depth);
118 const float b = 0.114 / (1 <<
desc->comp[2].depth);
119 return (
r *
r +
g *
g +
b *
b) * variance;
121 const float y = 1.0 / (1 <<
desc->comp[0].depth);
122 return y * y * variance;
129 int comps =
desc->nb_components >= 3 ? 0b111 : 0
b1;
141 for (
int p = 0; p < 4; p++) {
142 const int stride_a =
out->linesize[p];
143 const int stride_b =
ref->linesize[p];
144 const int w =
out->width;
145 const int h =
out->height;
147 const int is_chroma = p == 1 || p == 2;
148 const uint8_t def = is_chroma ? 128 : 0xFF;
149 const int has_ref = comps & (1 << p);
154 for (
int y = 0; y < (
h & ~3); y += 4) {
155 for (
int x = 0; x < (
w & ~3); x += 4) {
156 const float c1 = .01 * .01 * 255 * 255 * 64;
157 const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
158 int s1 = 0, s2 = 0,
ss = 0, s12 = 0, var, covar;
160 for (
int yy = 0; yy < 4; yy++) {
161 for (
int xx = 0; xx < 4; xx++) {
162 int a =
out->data[p][(y + yy) * stride_a + x + xx];
163 int b = has_ref ?
ref->data[p][(y + yy) * stride_b + x + xx] : def;
171 var =
ss * 64 - s1 * s1 - s2 * s2;
172 covar = s12 * 64 - s1 * s2;
173 sum += (2 * s1 * s2 +
c1) * (2 * covar +
c2) /
174 ((s1 * s1 + s2 * s2 +
c1) * (var +
c2));
179 ssim[p] = count ? sum / count : 0.0;
185 const float weights[3] = { 0.8, 0.1, 0.1 };
188 for (
int i = 0;
i < 3;
i++)
218 for (
int i = 0;
ret >= 0 &&
i <
opts.iters;
i++)
232 float ssim[4], ssim_sws[4];
238 const float c1 = 0.01 * 0.01;
239 const float ref_var = 1.0 / 12.0;
243 const float total_var = src_var + dst_var + out_var;
244 const float ssim_luma = (2 * ref_var +
c1) / (2 * ref_var + total_var +
c1);
245 const float ssim_expected[4] = { ssim_luma, 1, 1, 1 };
246 const float expected_loss =
get_loss(ssim_expected);
260 out->format =
ref->format;
261 src->format = src_fmt;
262 dst->format = dst_fmt;
278 for (
int i = 0;
i <
opts.iters;
i++) {
295 printf(
"%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u, "
296 "SSIM {Y=%f U=%f V=%f A=%f}\n",
300 ssim[0], ssim[1], ssim[2], ssim[3]);
303 if (loss - expected_loss > 1e-4 && dst_w >=
ref->width && dst_h >=
ref->height) {
304 int bad = loss - expected_loss > 1e-2;
305 printf(
"\033[1;31m loss %g is %s by %g, expected loss %g\033[0m\n",
306 loss,
bad ?
"WORSE" :
"worse", loss - expected_loss, expected_loss);
332 if (src_var > dst_var) {
333 const float src_loss = (2 * ref_var +
c1) / (2 * ref_var + src_var +
c1);
334 ssim_sws[0] =
FFMIN(ssim_sws[0], src_loss);
341 const float loss_ref =
get_loss(ssim_ref);
342 if (loss - loss_ref > 1e-4) {
343 int bad = loss - loss_ref > 1e-2;
344 printf(
"\033[1;31m loss %g is %s by %g, ref loss %g, "
345 "SSIM {Y=%f U=%f V=%f A=%f}\033[0m\n",
346 loss,
bad ?
"WORSE" :
"worse", loss - loss_ref, loss_ref,
347 ssim_ref[0], ssim_ref[1], ssim_ref[2], ssim_ref[3]);
353 if (
opts.bench && time_ref) {
354 double ratio = (
double) time_ref / time;
355 if (
FFMIN(time, time_ref) > 100 ) {
362 printf(
" time=%"PRId64
" us, ref=%"PRId64
" us, speedup=%.3fx %s%s\033[0m\n",
363 time /
opts.iters, time_ref /
opts.iters, ratio,
365 }
else if (
opts.bench) {
366 printf(
" time=%"PRId64
" us\n", time /
opts.iters);
396 src_fmt_min = src_fmt_max =
opts.src_fmt;
398 dst_fmt_min = dst_fmt_max =
opts.dst_fmt;
400 for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
405 for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
421 if (
run_test(src_fmt, dst_fmt, dst_w[
w], dst_h[
h],
425 if (
opts.flags >= 0 ||
opts.unscaled)
445 while (fgets(buf,
sizeof(buf), fp)) {
446 char src_fmt_str[21], dst_fmt_str[21];
454 "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
455 "SSIM {Y=%f U=%f V=%f A=%f}\n",
456 src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
458 &ssim[0], &ssim[1], &ssim[2], &ssim[3]);
467 sw !=
ref->width || sh !=
ref->height || dw > 8192 || dh > 8192 ||
469 fprintf(stderr,
"malformed input file\n");
484 int main(
int argc,
char **argv)
503 for (
int i = 1;
i < argc;
i += 2) {
504 if (!strcmp(argv[
i],
"-help") || !strcmp(argv[
i],
"--help")) {
506 "swscale [options...]\n"
510 " Uses file as reference to compare tests againsts. Tests that have become worse will contain the string worse or WORSE\n"
511 " -p <number between 0.0 and 1.0>\n"
512 " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
513 " It is often convenient to perform a random subset\n"
515 " Only test the specified destination pixel format\n"
517 " Only test the specified source pixel format\n"
519 " Run benchmarks with the specified number of iterations. This mode also increases the size of the test images\n"
521 " Test with a specific combination of flags\n"
523 " Test with a specific dither mode\n"
524 " -unscaled <1 or 0>\n"
525 " If 1, test only conversions that do not involve scaling\n"
526 " -threads <threads>\n"
527 " Use the specified number of threads\n"
528 " -cpuflags <cpuflags>\n"
529 " Uses the specified cpuflags in the tests\n"
531 " Enable log verbosity at given level\n"
535 if (argv[
i][0] !=
'-' ||
i + 1 == argc)
537 if (!strcmp(argv[
i],
"-ref")) {
538 fp = fopen(argv[
i + 1],
"r");
540 fprintf(stderr,
"could not open '%s'\n", argv[
i + 1]);
543 }
else if (!strcmp(argv[
i],
"-cpuflags")) {
547 fprintf(stderr,
"invalid cpu flags %s\n", argv[
i + 1]);
551 }
else if (!strcmp(argv[
i],
"-src")) {
554 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
557 }
else if (!strcmp(argv[
i],
"-dst")) {
560 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
563 }
else if (!strcmp(argv[
i],
"-bench")) {
565 opts.iters = atoi(argv[
i + 1]);
569 }
else if (!strcmp(argv[
i],
"-flags")) {
570 opts.flags = strtol(argv[
i + 1],
NULL, 0);
571 }
else if (!strcmp(argv[
i],
"-dither")) {
572 opts.dither = atoi(argv[
i + 1]);
573 }
else if (!strcmp(argv[
i],
"-unscaled")) {
574 opts.unscaled = atoi(argv[
i + 1]);
575 }
else if (!strcmp(argv[
i],
"-threads")) {
576 opts.threads = atoi(argv[
i + 1]);
577 }
else if (!strcmp(argv[
i],
"-p")) {
578 opts.prob = atof(argv[
i + 1]);
579 }
else if (!strcmp(argv[
i],
"-v")) {
583 fprintf(stderr,
"bad option or argument missing (%s) see -help\n", argv[
i]);
592 for (
int i = 0;
i < 3;
i++) {
608 for (
int y = 0; y <
rgb->height; y++) {
609 for (
int x = 0; x <
rgb->width; x++) {
610 for (
int c = 0;
c < 4;
c++)
630 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.
__device__ int printf(const char *,...)
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)
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