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).
This commit is contained in:
Niklas Haas 2017-09-10 18:18:31 +02:00
parent b19b0869d6
commit d0c87dd579
No known key found for this signature in database
GPG Key ID: 9A09076581B27402
5 changed files with 24 additions and 4 deletions

View File

@ -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 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. 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`` ``--use-embedded-icc-profile``
Load the embedded ICC profile contained in media files such as PNG images. 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 (Default: yes). Note that this option only works when also using a display

View File

@ -363,6 +363,7 @@ const struct m_sub_options gl_video_conf = {
OPT_FLAG("hdr-compute-peak", compute_hdr_peak, 0), OPT_FLAG("hdr-compute-peak", compute_hdr_peak, 0),
OPT_FLOAT("tone-mapping-param", tone_mapping_param, 0), OPT_FLOAT("tone-mapping-param", tone_mapping_param, 0),
OPT_FLOAT("tone-mapping-desaturate", tone_mapping_desat, 0), OPT_FLOAT("tone-mapping-desaturate", tone_mapping_desat, 0),
OPT_FLAG("gamut-warning", gamut_warning, 0),
OPT_FLAG("opengl-pbo", pbo, 0), OPT_FLAG("opengl-pbo", pbo, 0),
SCALER_OPTS("scale", SCALER_SCALE), SCALER_OPTS("scale", SCALER_SCALE),
SCALER_OPTS("dscale", SCALER_DSCALE), 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 // Adapt from src to dst as necessary
pass_color_map(p->sc, src, dst, p->opts.tone_mapping, pass_color_map(p->sc, src, dst, p->opts.tone_mapping,
p->opts.tone_mapping_param, p->opts.tone_mapping_desat, 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) { if (p->use_lut_3d) {
gl_sc_uniform_texture(p->sc, "lut_3d", p->lut_3d_texture); gl_sc_uniform_texture(p->sc, "lut_3d", p->lut_3d_texture);

View File

@ -115,6 +115,7 @@ struct gl_video_opts {
int compute_hdr_peak; int compute_hdr_peak;
float tone_mapping_param; float tone_mapping_param;
float tone_mapping_desat; float tone_mapping_desat;
int gamut_warning;
int linear_scaling; int linear_scaling;
int correct_downscaling; int correct_downscaling;
int sigmoid_upscaling; int sigmoid_upscaling;

View File

@ -616,7 +616,7 @@ static void pass_tone_map(struct gl_shader_cache *sc, float ref_peak,
switch (algo) { switch (algo) {
case TONE_MAPPING_CLIP: 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; break;
case TONE_MAPPING_MOBIUS: 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, struct mp_colorspace src, struct mp_colorspace dst,
enum tone_mapping algo, float tone_mapping_param, enum tone_mapping algo, float tone_mapping_param,
float tone_mapping_desat, bool detect_peak, float tone_mapping_desat, bool detect_peak,
bool is_linear) bool gamut_warning, bool is_linear)
{ {
GLSLF("// color mapping\n"); GLSLF("// color mapping\n");
@ -748,6 +748,12 @@ void pass_color_map(struct gl_shader_cache *sc,
if (src.light != dst.light) if (src.light != dst.light)
pass_inverse_ootf(sc, dst.light, mp_trc_nom_peak(dst.gamma)); 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) if (is_linear)
pass_delinearize(sc, dst.gamma); pass_delinearize(sc, dst.gamma);
} }

View File

@ -46,7 +46,7 @@ void pass_color_map(struct gl_shader_cache *sc,
struct mp_colorspace src, struct mp_colorspace dst, struct mp_colorspace src, struct mp_colorspace dst,
enum tone_mapping algo, float tone_mapping_param, enum tone_mapping algo, float tone_mapping_param,
float tone_mapping_desat, bool use_detected_peak, 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, void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
AVLFG *lfg, enum mp_csp_trc trc); AVLFG *lfg, enum mp_csp_trc trc);