diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index a8eca8d629..c2543b4e1d 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -27,6 +27,8 @@ Interface changes --- mpv 0.31.0 --- - add `--d3d11-output-csp` to enable explicit selection of a D3D11 swap chain color space. + - add an builtin "sw-fast" profile, which restores performance settings + that were switched to higher quality since mpv 0.30.0 --- mpv 0.30.0 --- - add `--d3d11-output-format` to enable explicit selection of a D3D11 swap chain format. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index c8af27bcb7..76f39dc29f 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -3833,6 +3833,21 @@ Software Scaler ``--sws-cvs=`` Software scaler chroma vertical shifting. See ``--sws-scaler``. +``--sws-bitexact=`` + Unknown functionality (default: no). Consult libswscale source code. The + primary purpose of this, as far as libswscale API goes), is to produce + exactly the same output for the same input on all platforms (output has the + same "bits" everywhere, thus "bitexact"). Typically disables optimizations. + +``--sws-fast=`` + Allow optimizations that help with performance, but reduce quality (default: + no). + + VOs like ``drm`` and ``x11`` will benefit a lot from using ``--sws-fast``. + You may need to set other options, like ``--sws-scaler``. The builtin + ``sws-fast`` profile sets this option and some others to gain performance + for reduced quality. + ``--sws-allow-zimg=`` Allow using zimg (if the component using the internal swscale wrapper explicitly allows so). In this case, zimg *may* be used, if the internal @@ -3846,14 +3861,34 @@ Software Scaler correctly, a verbose priority log message will indicate whether zimg is being used. - Currently, barely anything uses this. + Most things which need software conversion can make use of this. -``--zimg--scaler=`` +``--zimg--scaler=`` Zimg luma scaler to use (default: bilinear). +``--zimg-scaler-param-a=``, ``--zimg-scaler-param-b=`` + Set scaler parameters. By default, these are set to the special string + ``default``, which maps to a scaler-specific default value. Ignored if the + scaler is not tunable. + + ``lanczos`` + ``--zimg-scaler-param-a`` is the number of taps. + + ``bicubic`` + a and b are the bicubic b and c parameters. + +``--zimg-scaler-chroma=...`` + Same as ``--zimg--scaler``, for for chroma interpolation. + +``--zimg-scaler-chroma-param-a``, ``--zimg-scaler-chroma-param-b`` + Same as ``--zimg-scaler-param-a`` / ``--zimg-scaler-param-b``, for chroma. + +``--zimg-dither=`` + Dithering (default: random). + ``--zimg-fast=`` Allow optimizations that help with performance, but reduce quality (default: - yes). Currently, this may simplify gamma conversion operations. + no). Currently, this may simplify gamma conversion operations. Audio Resampler diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index ea2d3ee645..50db983f06 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -71,6 +71,9 @@ Available video output drivers are: Shared memory video output driver without hardware acceleration that works whenever X11 is present. + Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent + performance. + .. note:: This is a fallback only, and should not be normally used. ``vdpau`` (X11 only) @@ -383,6 +386,9 @@ Available video output drivers are: Depends on support of true color by modern terminals to display the images at full color range. On Windows it requires an ansi terminal such as mintty. + Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent + performance. + ``--vo-tct-algo=`` Select how to write the pixels to the terminal. @@ -482,6 +488,9 @@ Available video output drivers are: environment (e.g. no X). Does not support hardware acceleration (if you need this, check the ``drm`` backend for ``gpu`` VO). + Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent + performance. + The following global options are supported by this video output: ``--drm-connector=[.]`` @@ -583,4 +592,7 @@ Available video output drivers are: Shared memory video output driver without hardware acceleration that works whenever Wayland is present. + Since mpv 0.30.0, you may need to use ``--profile=sw-fast`` to get decent + performance. + .. note:: This is a fallback only, and should not be normally used. diff --git a/etc/builtin.conf b/etc/builtin.conf index 28788c9598..f00f5e3515 100644 --- a/etc/builtin.conf +++ b/etc/builtin.conf @@ -62,6 +62,15 @@ video-sync=audio # DS currently requires reading ahead a frame interpolation=no # requires reference frames (more buffering) video-latency-hacks=yes # typically 1 or 2 video frame less latency +[sw-fast] +# For VOs which use software scalers, also affects screenshots and others. +sws-scaler=bilinear +sws-fast=yes +sws-allow-zimg=yes +zimg-scaler=bilinear +zimg-dither=no +zimg-fast=yes + # Compatibility alias (deprecated) [opengl-hq] profile=gpu-hq diff --git a/video/filter/vf_fingerprint.c b/video/filter/vf_fingerprint.c index 79273622b7..471d995f4f 100644 --- a/video/filter/vf_fingerprint.c +++ b/video/filter/vf_fingerprint.c @@ -15,6 +15,8 @@ * License along with mpv. If not, see . */ +#include + #include "common/common.h" #include "common/tags.h" #include "filters/filter.h" @@ -204,6 +206,14 @@ static struct mp_filter *f_create(struct mp_filter *parent, void *options) MP_HANDLE_OOM(p->sws); p->zimg = mp_zimg_alloc(); talloc_steal(p, p->zimg); + p->zimg->opts = (struct zimg_opts){ + .scaler = ZIMG_RESIZE_BILINEAR, + .scaler_params = {NAN, NAN}, + .scaler_chroma_params = {NAN, NAN}, + .scaler_chroma = ZIMG_RESIZE_BILINEAR, + .dither = ZIMG_DITHER_NONE, + .fast = 1, + }; return f; } diff --git a/video/sws_utils.c b/video/sws_utils.c index a41d4c6e76..47af77ca50 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -49,6 +49,8 @@ struct sws_opts { int chr_hshift; float chr_sharpen; float lum_sharpen; + int fast; + int bitexact; int zimg; }; @@ -73,19 +75,20 @@ const struct m_sub_options sws_conf = { OPT_INT("chs", chr_hshift, 0), OPT_FLOATRANGE("ls", lum_sharpen, 0, -100.0, 100.0), OPT_FLOATRANGE("cs", chr_sharpen, 0, -100.0, 100.0), + OPT_FLAG("fast", fast, 0), + OPT_FLAG("bitexact", bitexact, 0), OPT_FLAG("allow-zimg", zimg, 0), {0} }, .size = sizeof(struct sws_opts), .defaults = &(const struct sws_opts){ - .scaler = SWS_BICUBIC, + .scaler = SWS_LANCZOS, }, }; // Highest quality, but also slowest. -const int mp_sws_hq_flags = SWS_LANCZOS | SWS_FULL_CHR_H_INT | - SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | - SWS_BITEXACT; +static const int mp_sws_hq_flags = SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | + SWS_ACCURATE_RND; // Fast, lossy. const int mp_sws_fast_flags = SWS_BILINEAR; @@ -104,6 +107,10 @@ static void mp_sws_update_from_cmdline(struct mp_sws_context *ctx) ctx->flags = SWS_PRINT_INFO; ctx->flags |= opts->scaler; + if (!opts->fast) + ctx->flags |= mp_sws_hq_flags; + if (opts->bitexact) + ctx->flags |= SWS_BITEXACT; ctx->allow_zimg = opts->zimg; } @@ -357,7 +364,7 @@ int mp_image_sw_blur_scale(struct mp_image *dst, struct mp_image *src, float gblur) { struct mp_sws_context *ctx = mp_sws_alloc(NULL); - ctx->flags = mp_sws_hq_flags; + ctx->flags = SWS_LANCZOS | mp_sws_hq_flags; ctx->src_filter = sws_getDefaultFilter(gblur, gblur, 0, 0, 0, 0, 0); ctx->force_reload = true; int res = mp_sws_scale(ctx, dst, src); diff --git a/video/sws_utils.h b/video/sws_utils.h index de6a023524..ddf628cf23 100644 --- a/video/sws_utils.h +++ b/video/sws_utils.h @@ -13,7 +13,6 @@ struct mpv_global; // Guaranteed to be a power of 2 and > 1. #define SWS_MIN_BYTE_ALIGN MP_IMAGE_BYTE_ALIGN -extern const int mp_sws_hq_flags; extern const int mp_sws_fast_flags; bool mp_sws_supported_format(int imgfmt); diff --git a/video/zimg.c b/video/zimg.c index 7ea60531e1..b568a6bbec 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -27,27 +27,43 @@ static_assert(MP_IMAGE_BYTE_ALIGN >= ZIMG_ALIGN, ""); -struct zimg_opts { - int scaler; - int fast; +static const struct m_opt_choice_alternatives mp_zimg_scalers[] = { + {"point", ZIMG_RESIZE_POINT}, + {"bilinear", ZIMG_RESIZE_BILINEAR}, + {"bicubic", ZIMG_RESIZE_BICUBIC}, + {"spline16", ZIMG_RESIZE_SPLINE16}, + {"spline36", ZIMG_RESIZE_SPLINE36}, + {"lanczos", ZIMG_RESIZE_LANCZOS}, + {0} }; +#define OPT_PARAM(name, var, flags) \ + OPT_DOUBLE(name, var, (flags) | M_OPT_DEFAULT_NAN) + #define OPT_BASE_STRUCT struct zimg_opts const struct m_sub_options zimg_conf = { .opts = (struct m_option[]) { - OPT_CHOICE("scaler", scaler, 0, - ({"point", ZIMG_RESIZE_POINT}, - {"bilinear", ZIMG_RESIZE_BILINEAR}, - {"bicubic", ZIMG_RESIZE_BICUBIC}, - {"spline16", ZIMG_RESIZE_SPLINE16}, - {"lanczos", ZIMG_RESIZE_LANCZOS})), + OPT_CHOICE_C("scaler", scaler, 0, mp_zimg_scalers), + OPT_PARAM("scaler-param-a", scaler_params[0], 0), + OPT_PARAM("scaler-param-b", scaler_params[1], 0), + OPT_CHOICE_C("scaler-chroma", scaler_chroma, 0, mp_zimg_scalers), + OPT_PARAM("scaler-chroma-param-a", scaler_chroma_params[0], 0), + OPT_PARAM("scaler-chroma-param-b", scaler_chroma_params[1], 0), + OPT_CHOICE("dither", dither, 0, + ({"no", ZIMG_DITHER_NONE}, + {"ordered", ZIMG_DITHER_ORDERED}, + {"random", ZIMG_DITHER_RANDOM}, + {"error-diffusion", ZIMG_DITHER_ERROR_DIFFUSION})), OPT_FLAG("fast", fast, 0), {0} }, .size = sizeof(struct zimg_opts), .defaults = &(const struct zimg_opts){ - .scaler = ZIMG_RESIZE_BILINEAR, - .fast = 1, + .scaler = ZIMG_RESIZE_LANCZOS, + .scaler_params = {NAN, NAN}, + .scaler_chroma_params = {NAN, NAN}, + .scaler_chroma = ZIMG_RESIZE_BILINEAR, + .dither = ZIMG_DITHER_RANDOM, }, }; @@ -90,9 +106,7 @@ static void mp_zimg_update_from_cmdline(struct mp_zimg_context *ctx) m_config_cache_update(ctx->opts_cache); struct zimg_opts *opts = ctx->opts_cache->opts; - - ctx->scaler = opts->scaler; - ctx->fast = opts->fast; + ctx->opts = *opts; } static zimg_chroma_location_e mp_to_z_chroma(enum mp_chroma_location cl) @@ -183,13 +197,8 @@ struct mp_zimg_context *mp_zimg_alloc(void) struct mp_zimg_context *ctx = talloc_ptrtype(NULL, ctx); *ctx = (struct mp_zimg_context) { .log = mp_null_log, - .scaler = ZIMG_RESIZE_BILINEAR, - .scaler_params = {NAN, NAN}, - .scaler_chroma = ZIMG_RESIZE_BILINEAR, - .scaler_chroma_params = {NAN, NAN}, - .dither = ZIMG_DITHER_NONE, - .fast = true, }; + ctx->opts = *(struct zimg_opts *)zimg_conf.defaults; talloc_set_destructor(ctx, free_mp_zimg); return ctx; } @@ -504,7 +513,7 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r, zfmt->color_primaries = mp_to_z_prim(fmt.color.primaries); zfmt->chroma_location = mp_to_z_chroma(fmt.chroma_location); - if (ctx && ctx->fast) { + if (ctx && ctx->opts.fast) { // mpv's default for RGB output slows down zimg significantly. if (zfmt->transfer_characteristics == ZIMG_TRANSFER_IEC_61966_2_1 && zfmt->color_family == ZIMG_COLOR_RGB) @@ -547,6 +556,8 @@ static bool allocate_buffer(struct mp_zimg_context *ctx, bool mp_zimg_config(struct mp_zimg_context *ctx) { + struct zimg_opts *opts = &ctx->opts; + destroy_zimg(ctx); if (ctx->opts_cache) @@ -569,19 +580,19 @@ bool mp_zimg_config(struct mp_zimg_context *ctx) zimg_graph_builder_params params; zimg_graph_builder_params_default(¶ms, ZIMG_API_VERSION); - params.resample_filter = ctx->scaler; - params.filter_param_a = ctx->scaler_params[0]; - params.filter_param_b = ctx->scaler_params[1]; + params.resample_filter = opts->scaler; + params.filter_param_a = opts->scaler_params[0]; + params.filter_param_b = opts->scaler_params[1]; - params.resample_filter_uv = ctx->scaler_chroma; - params.filter_param_a_uv = ctx->scaler_chroma_params[0]; - params.filter_param_b_uv = ctx->scaler_chroma_params[1]; + params.resample_filter_uv = opts->scaler_chroma; + params.filter_param_a_uv = opts->scaler_chroma_params[0]; + params.filter_param_b_uv = opts->scaler_chroma_params[1]; - params.dither_type = ctx->dither; + params.dither_type = opts->dither; params.cpu_type = ZIMG_CPU_AUTO_64B; - if (ctx->fast) + if (opts->fast) params.allow_approximate_gamma = 1; if (ctx->src.color.sig_peak > 0) diff --git a/video/zimg.h b/video/zimg.h index 9fa247d061..0ef9c5a3a0 100644 --- a/video/zimg.h +++ b/video/zimg.h @@ -13,6 +13,15 @@ struct mpv_global; bool mp_zimg_supports_in_format(int imgfmt); bool mp_zimg_supports_out_format(int imgfmt); +struct zimg_opts { + int scaler; + double scaler_params[2]; + int scaler_chroma; + double scaler_chroma_params[2]; + int dither; + int fast; +}; + struct mp_zimg_context { // Can be set for verbose error printing. struct mp_log *log; @@ -20,12 +29,7 @@ struct mp_zimg_context { // User configuration. Note: changing these requires calling mp_zimg_config() // to update the filter graph. The first mp_zimg_convert() call (or if the // image format changes) will do this automatically. - zimg_resample_filter_e scaler; - double scaler_params[2]; - zimg_resample_filter_e scaler_chroma; - double scaler_chroma_params[2]; - zimg_dither_type_e dither; - bool fast; // reduce quality for better performance + struct zimg_opts opts; // Input/output parameters. Note: if these mismatch with the // mp_zimg_convert() parameters, mp_zimg_config() will be called