Go to the documentation of this file.
29 #undef HAVE_AV_CONFIG_H
96 return ratio > 10.00 ?
"\033[1;94m" :
97 ratio > 2.00 ?
"\033[1;32m" :
98 ratio > 1.02 ?
"\033[32m" :
100 ratio > 0.90 ?
"\033[33m" :
101 ratio > 0.75 ?
"\033[31m" :
109 fprintf(stderr,
"Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
121 float variance = 1.0 / 12;
122 if (
desc->comp[0].depth < 8) {
124 variance *= (8 -
desc->comp[0].depth);
130 const float r = 0.299 / (1 <<
desc->comp[0].depth);
131 const float g = 0.587 / (1 <<
desc->comp[1].depth);
132 const float b = 0.114 / (1 <<
desc->comp[2].depth);
133 return (
r *
r +
g *
g +
b *
b) * variance;
135 const float y = 1.0 / (1 <<
desc->comp[0].depth);
136 return y * y * variance;
143 int comps =
desc->nb_components >= 3 ? 0x7 : 0x1;
155 for (
int p = 0;
p < 4;
p++) {
156 const int stride_a =
out->linesize[
p];
157 const int stride_b =
ref->linesize[
p];
158 const int w =
out->width;
159 const int h =
out->height;
161 const int is_chroma =
p == 1 ||
p == 2;
162 const uint8_t def = is_chroma ? 128 : 0xFF;
163 const int has_ref = comps & (1 <<
p);
168 for (
int y = 0; y < (
h & ~3); y += 4) {
169 for (
int x = 0; x < (
w & ~3); x += 4) {
170 const float c1 = .01 * .01 * 255 * 255 * 64;
171 const float c2 = .03 * .03 * 255 * 255 * 64 * 63;
172 int s1 = 0, s2 = 0,
ss = 0, s12 = 0, var, covar;
174 for (
int yy = 0; yy < 4; yy++) {
175 for (
int xx = 0; xx < 4; xx++) {
176 int a =
out->data[
p][(y + yy) * stride_a + x + xx];
177 int b = has_ref ?
ref->data[
p][(y + yy) * stride_b + x + xx] : def;
185 var =
ss * 64 - s1 * s1 - s2 * s2;
186 covar = s12 * 64 - s1 * s2;
187 sum += (2 * s1 * s2 +
c1) * (2 * covar +
c2) /
188 ((s1 * s1 + s2 * s2 +
c1) * (var +
c2));
193 ssim[
p] = count ? sum / count : 0.0;
199 const float weights[3] = { 0.8, 0.1, 0.1 };
202 for (
int i = 0;
i < 3;
i++)
218 memset(
frame->linesize, 0,
sizeof(
frame->linesize));
247 for (
int i = 0;
ret >= 0 &&
i <
opts->iters;
i++) {
290 for (
int i = 0;
ret >= 0 &&
i <
opts->iters;
i++)
300 int dst_w,
int dst_h,
307 printf(
"%-*s %*dx%*d -> %-*s %*dx%*d, flags=0x%0*x dither=%u",
309 opts->pretty ? 4 : 0,
src->width,
310 opts->pretty ? 4 : 0,
src->height,
312 opts->pretty ? 4 : 0,
dst->width,
313 opts->pretty ? 4 : 0,
dst->height,
317 if (!
opts->bench || !ref_r) {
318 printf(
", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
319 r->ssim[0],
r->ssim[1],
r->ssim[2],
r->ssim[3],
326 printf(
", time=%*"PRId64
"/%u us",
327 opts->pretty ? 7 : 0,
r->time,
opts->iters);
338 printf(
" (ref=%*"PRId64
"/%u us), speedup=%*.3fx %s%s\033[0m",
340 opts->pretty ? 6 : 0, ratio,
349 if (
r->loss - expected_loss > 1e-4 && dst_w >=
ref->width && dst_h >=
ref->height) {
350 const int bad =
r->loss - expected_loss > 1e-2;
352 const char *worse_str =
bad ?
"WORSE" :
"worse";
354 " loss %e is %s by %e, expected loss %e\n",
355 r->loss, worse_str,
r->loss - expected_loss, expected_loss);
358 if (ref_r &&
r->loss - ref_r->
loss > 1e-4) {
359 const int bad =
r->loss - ref_r->
loss > 1e-2;
361 const char *worse_str =
bad ?
"WORSE" :
"worse";
363 " loss %e is %s by %e, ref loss %e SSIM={Y=%f U=%f V=%f A=%f}\n",
364 r->loss, worse_str,
r->loss - ref_r->
loss, ref_r->
loss,
385 int dst_w,
int dst_h,
395 const float c1 = 0.01 * 0.01;
396 const float ref_var = 1.0 / 12.0;
400 const float total_var = src_var + dst_var + out_var;
401 const float ssim_luma = (2 * ref_var +
c1) / (2 * ref_var + total_var +
c1);
402 const float ssim_expected[4] = { ssim_luma, 1, 1, 1 };
403 const float expected_loss =
get_loss(ssim_expected);
407 if (
src->format != src_fmt) {
411 src->height =
ref->height;
412 src->format = src_fmt;
444 if (src_var > dst_var) {
445 const float src_loss = (2 * ref_var +
c1) / (2 * ref_var + src_var +
c1);
446 r.ssim[0] =
FFMIN(
r.ssim[0], src_loss);
451 if (!
opts->legacy &&
r.loss - expected_loss > 1e-2 && dst_w >=
ref->width && dst_h >=
ref->height) {
456 if (ref_r &&
r.loss - ref_r->
loss > 1e-2) {
500 src_fmt_min = src_fmt_max =
opts->src_fmt;
502 dst_fmt_min = dst_fmt_max =
opts->dst_fmt;
504 for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
509 for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
530 if (
opts->flags >= 0 ||
opts->unscaled)
558 for (
int line = 1; fgets(buf,
sizeof(buf), fp);
line++) {
559 char src_fmt_str[21], dst_fmt_str[21];
568 "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
569 "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
570 src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
572 &
r.ssim[0], &
r.ssim[1], &
r.ssim[2], &
r.ssim[3],
576 "Malformed reference file in line %d\n",
line);
580 ret = sscanf(buf + n,
581 ", time=%"PRId64
"/%u us",
585 "Missing benchmarks from reference file in line %d\n",
595 "Unknown pixel formats (%s and/or %s) in line %d\n",
596 src_fmt_str, dst_fmt_str,
line);
600 if (sw !=
ref->width || sh !=
ref->height) {
602 "Mismatching dimensions %dx%d (ref is %dx%d) in line %d\n",
641 for (
int y = 0; y <
rgb->height; y++) {
642 for (
int x = 0; x <
rgb->width; x++) {
643 for (
int c = 0;
c < 4;
c++)
659 for (
int i = 1;
i < argc;
i += 2) {
660 if (!strcmp(argv[
i],
"-help") || !strcmp(argv[
i],
"--help")) {
662 "swscale [options...]\n"
666 " Uses file as reference to compare tests against. Tests that have become worse will contain the string worse or WORSE\n"
667 " -p <number between 0.0 and 1.0>\n"
668 " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
669 " It is often convenient to perform a random subset\n"
671 " Only test the specified destination pixel format\n"
673 " Only test the specified source pixel format\n"
675 " Set frame size (WxH or abbreviation)\n"
677 " Run benchmarks with the specified number of iterations. This mode also sets the frame size to 1920x1080 (unless -s is specified)\n"
679 " Test with a specific combination of flags\n"
681 " Test with a specific dither mode\n"
682 " -unscaled <1 or 0>\n"
683 " If 1, test only conversions that do not involve scaling\n"
684 " -legacy <1 or 0>\n"
685 " If 1, force using legacy swscale for the main conversion\n"
686 " -threads <threads>\n"
687 " Use the specified number of threads\n"
688 " -cpuflags <cpuflags>\n"
689 " Uses the specified cpuflags in the tests\n"
690 " -pretty <1 or 0>\n"
691 " Align fields while printing results\n"
693 " Enable log verbosity at given level\n"
697 if (argv[
i][0] !=
'-' ||
i + 1 == argc)
699 if (!strcmp(argv[
i],
"-ref")) {
700 *fp = fopen(argv[
i + 1],
"r");
702 fprintf(stderr,
"could not open '%s'\n", argv[
i + 1]);
705 }
else if (!strcmp(argv[
i],
"-cpuflags")) {
709 fprintf(stderr,
"invalid cpu flags %s\n", argv[
i + 1]);
713 }
else if (!strcmp(argv[
i],
"-src")) {
716 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
719 }
else if (!strcmp(argv[
i],
"-dst")) {
722 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
725 }
else if (!strcmp(argv[
i],
"-s")) {
727 fprintf(stderr,
"invalid frame size %s\n", argv[
i + 1]);
730 }
else if (!strcmp(argv[
i],
"-bench")) {
731 int iters = atoi(argv[
i + 1]);
739 }
else if (!strcmp(argv[
i],
"-flags")) {
745 fprintf(stderr,
"invalid flags %s\n", argv[
i + 1]);
748 }
else if (!strcmp(argv[
i],
"-dither")) {
749 opts->dither = atoi(argv[
i + 1]);
750 }
else if (!strcmp(argv[
i],
"-unscaled")) {
751 opts->unscaled = atoi(argv[
i + 1]);
752 }
else if (!strcmp(argv[
i],
"-legacy")) {
753 opts->legacy = atoi(argv[
i + 1]);
754 }
else if (!strcmp(argv[
i],
"-threads")) {
755 opts->threads = atoi(argv[
i + 1]);
756 }
else if (!strcmp(argv[
i],
"-p")) {
757 opts->prob = atof(argv[
i + 1]);
758 }
else if (!strcmp(argv[
i],
"-pretty")) {
759 opts->pretty = atoi(argv[
i + 1]);
760 }
else if (!strcmp(argv[
i],
"-v")) {
764 fprintf(stderr,
"bad option or argument missing (%s) see -help\n", argv[
i]);
777 int main(
int argc,
char **argv)
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.
#define AV_LOG_WARNING
Something somehow does not look correct.
AVPixelFormat
Pixel format.
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
__device__ int printf(const char *,...)
static int checked_sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src)
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 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)
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 double speedup_max
static int run_self_tests(const AVFrame *ref, const struct options *opts)
@ AV_PIX_FMT_NB
hardware decoding through openharmony
static int run_file_tests(const AVFrame *ref, FILE *fp, const struct options *opts)
@ SWS_FAST_BILINEAR
Scaler selection options.
@ 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.
int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src)
Like sws_scale_frame, but without actually scaling.
#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 AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#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.
int flags
Flags modifying the (de)muxer behaviour.
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
static AVFormatContext * ctx
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_log_get_level(void)
Get the current log level.
static AVDictionary * opts
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
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
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
@ SWS_BICUBIC
2-tap cubic B-spline
int sws_test_format(enum AVPixelFormat format, int output)
Test if a given (software) pixel format is supported.
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)
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
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.
Context structure for the Lagged Fibonacci PRNG.
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
static SwsContext * sws_ref_src
#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
#define i(width, name, range_min, range_max)
@ SWS_POINT
nearest neighbor
int src_h
Width and height of the source frame.
static SwsContext * sws_src_dst
static void exit_handler(int sig)
static int scale_legacy(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
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)
static void unref_buffers(AVFrame *frame)
int dst_format
Destination pixel format.
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.
#define AV_LOG_INFO
Standard information.
void av_log_set_level(int level)
Set the log level.
static const int weights[]
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
int dst_h
Width and height of the destination frame.
static uint64_t ff_sfc64_get(FFSFC64 *s)
int av_opt_eval_flags(void *obj, const AVOption *o, const char *val, int *flags_out)
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
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
@ 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 init_ref(AVFrame *ref, const struct options *opts)
static int ref[MAX_W *MAX_W]
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static int bad(InterplayACMContext *s, unsigned ind, unsigned col)
static SwsContext * sws_dst_out
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 scale_new(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
static int fmt_comps(enum AVPixelFormat fmt)
static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
static int init_frame(AVFrame **pframe, const AVFrame *ref, int width, int height, enum AVPixelFormat format)
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