Go to the documentation of this file.
29 #undef HAVE_AV_CONFIG_H
100 return ratio > 10.00 ?
"\033[1;94m" :
101 ratio > 2.00 ?
"\033[1;32m" :
102 ratio > 1.02 ?
"\033[32m" :
104 ratio > 0.90 ?
"\033[33m" :
105 ratio > 0.75 ?
"\033[31m" :
113 fprintf(stderr,
"Overall speedup=%.3fx %s%s\033[0m, min=%.3fx max=%.3fx\n", ratio,
125 float variance = 1.0 / 12;
126 if (
desc->comp[0].depth < 8) {
128 variance *= (8 -
desc->comp[0].depth);
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;
139 const float y = 1.0 / (1 <<
desc->comp[0].depth);
140 return y * y * variance;
147 int comps =
desc->nb_components >= 3 ? 0x7 : 0x1;
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;
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);
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;
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;
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));
197 ssim[
p] = count ? sum / count : 0.0;
203 const float weights[3] = { 0.8, 0.1, 0.1 };
206 for (
int i = 0;
i < 3;
i++)
222 memset(
frame->linesize, 0,
sizeof(
frame->linesize));
251 for (
int i = 0;
ret >= 0 &&
i <
opts->iters;
i++) {
294 for (
int i = 0;
ret >= 0 &&
i <
opts->iters;
i++)
316 if (
src->format ==
dst->format)
401 for (
int i = 0;
ret >= 0 &&
i <
opts->iters;
i++) {
430 int dst_w,
int dst_h,
437 printf(
"%-*s %*dx%*d -> %-*s %*dx%*d, flags=0x%0*x dither=%u",
439 opts->pretty ? 4 : 0,
src->width,
440 opts->pretty ? 4 : 0,
src->height,
442 opts->pretty ? 4 : 0,
dst->width,
443 opts->pretty ? 4 : 0,
dst->height,
447 if (!
opts->bench || !ref_r) {
448 printf(
", SSIM={Y=%f U=%f V=%f A=%f} loss=%e",
449 r->ssim[0],
r->ssim[1],
r->ssim[2],
r->ssim[3],
456 printf(
", time=%*"PRId64
"/%u us",
457 opts->pretty ? 7 : 0,
r->time,
opts->iters);
468 printf(
" (ref=%*"PRId64
"/%u us), speedup=%*.3fx %s%s\033[0m",
470 opts->pretty ? 6 : 0, ratio,
479 if (
r->loss - expected_loss > 1e-4 && dst_w >=
ref->width && dst_h >=
ref->height) {
480 const int bad =
r->loss - expected_loss > 1e-2;
482 const char *worse_str =
bad ?
"WORSE" :
"worse";
484 " loss %e is %s by %e, expected loss %e\n",
485 r->loss, worse_str,
r->loss - expected_loss, expected_loss);
488 if (ref_r &&
r->loss - ref_r->
loss > 1e-4) {
498 const int bad =
r->loss - ref_r->
loss > 1e-2 && dst_bits > 1;
500 const char *worse_str =
bad ?
"WORSE" :
"worse";
502 " loss %e is %s by %e, ref loss %e SSIM={Y=%f U=%f V=%f A=%f}\n",
503 r->loss, worse_str,
r->loss - ref_r->
loss, ref_r->
loss,
524 int dst_w,
int dst_h,
534 const float c1 = 0.01 * 0.01;
535 const float ref_var = 1.0 / 12.0;
539 const float total_var = src_var + dst_var + out_var;
540 const float ssim_luma = (2 * ref_var +
c1) / (2 * ref_var + total_var +
c1);
541 const float ssim_expected[4] = { ssim_luma, 1, 1, 1 };
542 const float expected_loss =
get_loss(ssim_expected);
546 if (
src->format != src_fmt) {
550 src->height =
ref->height;
551 src->format = src_fmt;
587 if (src_var > dst_var) {
588 const float src_loss = (2 * ref_var +
c1) / (2 * ref_var + src_var +
c1);
589 r.ssim[0] =
FFMIN(
r.ssim[0], src_loss);
594 if (!
opts->legacy &&
r.loss - expected_loss > 1e-2 && dst_w >=
ref->width && dst_h >=
ref->height) {
599 if (ref_r &&
r.loss - ref_r->
loss > 1e-2) {
661 src_fmt_min = src_fmt_max =
opts->src_fmt;
663 dst_fmt_min = dst_fmt_max =
opts->dst_fmt;
665 for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) {
671 for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) {
693 if (
opts->flags >= 0 ||
opts->unscaled)
721 for (
int line = 1; fgets(buf,
sizeof(buf), fp);
line++) {
722 char src_fmt_str[21], dst_fmt_str[21];
731 "%20s %dx%d -> %20s %dx%d, flags=0x%x dither=%u, "
732 "SSIM={Y=%f U=%f V=%f A=%f} loss=%e%n",
733 src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh,
735 &
r.ssim[0], &
r.ssim[1], &
r.ssim[2], &
r.ssim[3],
739 "Malformed reference file in line %d\n",
line);
743 ret = sscanf(buf + n,
744 ", time=%"PRId64
"/%u us",
748 "Missing benchmarks from reference file in line %d\n",
758 "Unknown pixel formats (%s and/or %s) in line %d\n",
759 src_fmt_str, dst_fmt_str,
line);
763 if (sw !=
ref->width || sh !=
ref->height) {
765 "Mismatching dimensions %dx%d (ref is %dx%d) in line %d\n",
804 for (
int y = 0; y <
rgb->height; y++) {
805 for (
int x = 0; x <
rgb->width; x++) {
806 for (
int c = 0;
c < 4;
c++)
822 for (
int i = 1;
i < argc;
i += 2) {
823 if (!strcmp(argv[
i],
"-help") || !strcmp(argv[
i],
"--help")) {
825 "swscale [options...]\n"
829 " Uses file as reference to compare tests against. Tests that have become worse will contain the string worse or WORSE\n"
830 " -p <number between 0.0 and 1.0>\n"
831 " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n"
832 " It is often convenient to perform a random subset\n"
834 " Only test the specified destination pixel format\n"
836 " Only test the specified source pixel format\n"
838 " Set frame size (WxH or abbreviation)\n"
840 " Run benchmarks with the specified number of iterations. This mode also sets the frame size to 1920x1080 (unless -s is specified)\n"
842 " Test with a specific combination of flags\n"
844 " Test with a specific dither mode\n"
845 " -unscaled <1 or 0>\n"
846 " If 1, test only conversions that do not involve scaling\n"
847 " -legacy <1 or 0>\n"
848 " If 1, force using legacy swscale for the main conversion\n"
850 " Use Vulkan hardware acceleration on the specified device for the main conversion\n"
851 " -threads <threads>\n"
852 " Use the specified number of threads\n"
853 " -cpuflags <cpuflags>\n"
854 " Uses the specified cpuflags in the tests\n"
855 " -pretty <1 or 0>\n"
856 " Align fields while printing results\n"
858 " Enable log verbosity at given level\n"
862 if (argv[
i][0] !=
'-' ||
i + 1 == argc)
864 if (!strcmp(argv[
i],
"-ref")) {
865 *fp = fopen(argv[
i + 1],
"r");
867 fprintf(stderr,
"could not open '%s'\n", argv[
i + 1]);
870 }
else if (!strcmp(argv[
i],
"-cpuflags")) {
874 fprintf(stderr,
"invalid cpu flags %s\n", argv[
i + 1]);
878 }
else if (!strcmp(argv[
i],
"-src")) {
881 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
884 }
else if (!strcmp(argv[
i],
"-dst")) {
887 fprintf(stderr,
"invalid pixel format %s\n", argv[
i + 1]);
890 }
else if (!strcmp(argv[
i],
"-s")) {
892 fprintf(stderr,
"invalid frame size %s\n", argv[
i + 1]);
895 }
else if (!strcmp(argv[
i],
"-bench")) {
896 int iters = atoi(argv[
i + 1]);
904 }
else if (!strcmp(argv[
i],
"-flags")) {
910 fprintf(stderr,
"invalid flags %s\n", argv[
i + 1]);
913 }
else if (!strcmp(argv[
i],
"-dither")) {
914 opts->dither = atoi(argv[
i + 1]);
915 }
else if (!strcmp(argv[
i],
"-unscaled")) {
916 opts->unscaled = atoi(argv[
i + 1]);
917 }
else if (!strcmp(argv[
i],
"-legacy")) {
918 opts->legacy = atoi(argv[
i + 1]);
919 }
else if (!strcmp(argv[
i],
"-hw")) {
922 argv[
i + 1],
NULL, 0);
924 fprintf(stderr,
"Failed to create Vulkan device '%s'\n",
931 fprintf(stderr,
"Failed to retrieve Vulkan device constraints '%s'\n",
935 }
else if (!strcmp(argv[
i],
"-threads")) {
936 opts->threads = atoi(argv[
i + 1]);
937 }
else if (!strcmp(argv[
i],
"-p")) {
938 opts->prob = atof(argv[
i + 1]);
939 }
else if (!strcmp(argv[
i],
"-pretty")) {
940 opts->pretty = atoi(argv[
i + 1]);
941 }
else if (!strcmp(argv[
i],
"-v")) {
945 fprintf(stderr,
"bad option or argument missing (%s) see -help\n", argv[
i]);
958 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.
uint8_t * data
The data buffer.
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)
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
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.
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
This structure describes decoded (raw) audio or video data.
static const char * speedup_color(double ratio)
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
int depth
Number of bits in the component.
@ 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.
int width
The allocated dimensions of the frames in this pool.
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...
static FFSFC64 prng_state
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
@ AV_HWDEVICE_TYPE_VULKAN
static double speedup_max
static int run_self_tests(const AVFrame *ref, const struct options *opts)
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
@ 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.
static int scale_hw(AVFrame *dst, const AVFrame *src, const struct mode *mode, const struct options *opts, int64_t *out_time)
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
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
SwsDither dither
Dither mode.
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
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
static AVBufferRef * hw_device_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...
static int fmt_is_supported_by_hw(enum AVPixelFormat fmt)
int av_log_get_level(void)
Get the current log level.
static AVDictionary * opts
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
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)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
static AVHWFramesConstraints * hw_device_constr
@ 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)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
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[]
@ 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...
#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)
This struct describes a set or pool of "hardware" frames (i.e.
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
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.
@ 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)
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
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]
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static int bad(InterplayACMContext *s, unsigned ind, unsigned col)
static SwsContext * sws_dst_out
A reference to a data buffer.
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.
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
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