From d0c87dd57918cab1afc4d5968355b6253377c0b1 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 10 Sep 2017 18:18:31 +0200 Subject: vo_opengl: add a gamut warning feature This clearly highlights all out-of-gamut/clipped pixels. (Either too bright or too saturated) Has some (documented) caveats. Also make TONE_MAPPING_CLIP stop actually clamping the value range (it's unnecessary and breaks this feature). --- DOCS/man/options.rst | 12 ++++++++++++ video/out/opengl/video.c | 3 ++- video/out/opengl/video.h | 1 + video/out/opengl/video_shaders.c | 10 ++++++++-- video/out/opengl/video_shaders.h | 2 +- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index dd9a51e807..ce14d3e92a 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -4865,6 +4865,18 @@ The following video options are currently all specific to ``--vo=opengl`` and The default of 2.0 is somewhat conservative and will mostly just apply to skies or directly sunlit surfaces. A setting of 0.0 disables this option. +``--gamut-warning`` + If enabled, mpv will mark all clipped/out-of-gamut pixels that exceed a + given threshold (currently hard-coded to 101%). The affected pixels will be + inverted to make them stand out. Note: This option applies after the + effects of all of mpv's color space transformation / tone mapping options, + so it's a good idea to combine this with ``--tone-mapping=clip`` and use + ``--target-gamut`` to set the gamut to simulate. For example, + ``--target-gamut=bt.709`` would make mpv highlight all pixels that exceed the + gamut of a standard gamut (sRGB) display. This option also does not work + well with ICC profiles, since the 3DLUTs are always generated against the + source color space and have chromatically-accurate clipping built in. + ``--use-embedded-icc-profile`` Load the embedded ICC profile contained in media files such as PNG images. (Default: yes). Note that this option only works when also using a display diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 8d90c2bcaa..3362381eff 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -363,6 +363,7 @@ const struct m_sub_options gl_video_conf = { OPT_FLAG("hdr-compute-peak", compute_hdr_peak, 0), OPT_FLOAT("tone-mapping-param", tone_mapping_param, 0), OPT_FLOAT("tone-mapping-desaturate", tone_mapping_desat, 0), + OPT_FLAG("gamut-warning", gamut_warning, 0), OPT_FLAG("opengl-pbo", pbo, 0), SCALER_OPTS("scale", SCALER_SCALE), SCALER_OPTS("dscale", SCALER_DSCALE), @@ -2460,7 +2461,7 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool // Adapt from src to dst as necessary pass_color_map(p->sc, src, dst, p->opts.tone_mapping, p->opts.tone_mapping_param, p->opts.tone_mapping_desat, - detect_peak, p->use_linear && !osd); + detect_peak, p->opts.gamut_warning, p->use_linear && !osd); if (p->use_lut_3d) { gl_sc_uniform_texture(p->sc, "lut_3d", p->lut_3d_texture); diff --git a/video/out/opengl/video.h b/video/out/opengl/video.h index e5e7ae70ec..e20af90643 100644 --- a/video/out/opengl/video.h +++ b/video/out/opengl/video.h @@ -115,6 +115,7 @@ struct gl_video_opts { int compute_hdr_peak; float tone_mapping_param; float tone_mapping_desat; + int gamut_warning; int linear_scaling; int correct_downscaling; int sigmoid_upscaling; diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c index 10edc0563d..60c5ce82ac 100644 --- a/video/out/opengl/video_shaders.c +++ b/video/out/opengl/video_shaders.c @@ -616,7 +616,7 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak, switch (algo) { case TONE_MAPPING_CLIP: - GLSLF("sig = clamp(%f * sig, 0.0, 1.0);\n", isnan(param) ? 1.0 : param); + GLSLF("sig = %f * sig;\n", isnan(param) ? 1.0 : param); break; case TONE_MAPPING_MOBIUS: @@ -683,7 +683,7 @@ void pass_color_map(struct gl_shader_cache *sc, struct mp_colorspace src, struct mp_colorspace dst, enum tone_mapping algo, float tone_mapping_param, float tone_mapping_desat, bool detect_peak, - bool is_linear) + bool gamut_warning, bool is_linear) { GLSLF("// color mapping\n"); @@ -748,6 +748,12 @@ void pass_color_map(struct gl_shader_cache *sc, if (src.light != dst.light) pass_inverse_ootf(sc, dst.light, mp_trc_nom_peak(dst.gamma)); + // Warn for remaining out-of-gamut colors is enabled + if (gamut_warning) { + GLSL(if (any(greaterThan(color.rgb, vec3(1.01))))) + GLSL(color.rgb = vec3(1.0) - color.rgb;) // invert + } + if (is_linear) pass_delinearize(sc, dst.gamma); } diff --git a/video/out/opengl/video_shaders.h b/video/out/opengl/video_shaders.h index 1fae830720..8345e4c598 100644 --- a/video/out/opengl/video_shaders.h +++ b/video/out/opengl/video_shaders.h @@ -46,7 +46,7 @@ void pass_color_map(struct gl_shader_cache *sc, struct mp_colorspace src, struct mp_colorspace dst, enum tone_mapping algo, float tone_mapping_param, float tone_mapping_desat, bool use_detected_peak, - bool is_linear); + bool gamut_warning, bool is_linear); void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts, AVLFG *lfg, enum mp_csp_trc trc); -- cgit v1.2.3