mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 01:22:30 +00:00
vo_gpu: add --tone-mapping-mode
This merges the old desaturation control options into a single enumeration, with the goal of both simplifying how these options work and also making this list more extensible (including, notably, new options only supported by vo_gpu_next). For the hybrid option, I decided to port the (slightly tweaked) values from libplacebo's pre-refactor defaults, rather than the old values we had in mpv, to more visually match the look of the vo_gpu_next hybrid.
This commit is contained in:
parent
f3fccfc395
commit
d09c73c7b2
@ -36,6 +36,8 @@ Interface changes
|
||||
- add `--tone-mapping` options `auto`, `spline` and `bt.2446a`
|
||||
- add `--inverse-tone-mapping`
|
||||
- add `--gamut-mapping-mode`, replacing `--gamut-clipping` and `--gamut-warning`
|
||||
- add `--tone-mapping-mode`, replacing `--tone-mapping-desaturate` and
|
||||
`--tone-mapping-desaturate-exponent`.
|
||||
--- mpv 0.34.0 ---
|
||||
- deprecate selecting by card number with `--drm-connector`, add
|
||||
`--drm-device` which can be used instead
|
||||
|
@ -6385,6 +6385,28 @@ them.
|
||||
it too high will make dark scenes appear unnaturally bright. (``-vo=gpu``
|
||||
only)
|
||||
|
||||
``--tone-mapping-mode``
|
||||
Controls how the tone mapping function is applied to colors.
|
||||
|
||||
auto
|
||||
Choose the best mode automatically. (Default)
|
||||
rgb
|
||||
Tone-map per-channel (RGB). Has a tendency to severely distort colors,
|
||||
desaturate highlights, and is generally not very recommended. However,
|
||||
this is the mode used in many displays and TVs (especially early ones),
|
||||
and so sometimes it's needed to reproduce the artistic intent a film
|
||||
was mastered with.
|
||||
max
|
||||
Tone-map on the brightest component in the video. Has a tendency to
|
||||
lead to weirdly oversaturated colors, and loss of dark details.
|
||||
hybrid
|
||||
A hybrid approach that uses linear tone-mapping for midtones and
|
||||
per-channel tone mapping for highlights.
|
||||
luma
|
||||
Luminance-based method from ITU-R BT.2446a, including fixed gamut
|
||||
reductions to account for brightness-related perceptual nonuniformity.
|
||||
(``--vo=gpu-next`` only)
|
||||
|
||||
``--gamut-mapping-mode``
|
||||
Specifies the algorithm used for reducing the gamut of images for the
|
||||
target display, after any tone mapping is done.
|
||||
@ -6445,27 +6467,6 @@ them.
|
||||
aggressive, up to the limit of the high threshold (at which point the
|
||||
filter becomes instant).
|
||||
|
||||
``--tone-mapping-desaturate=<0.0..1.0>``
|
||||
Apply desaturation for highlights (default: 0.75). The parameter controls
|
||||
the strength of the desaturation curve. A value of 0.0 completely disables
|
||||
it, while a value of 1.0 means that overly bright colors will tend towards
|
||||
white. This is not always the case, especially not for highlights that are
|
||||
near primary colors. (``--vo=gpu`` only)
|
||||
|
||||
Values in between apply progressively more/less aggressive desaturation.
|
||||
This setting helps prevent unnaturally oversaturated colors for
|
||||
super-highlights, by (smoothly) turning them into less saturated (per
|
||||
channel tone mapped) colors instead. This makes images feel more natural,
|
||||
at the cost of chromatic distortions for out-of-range colors. The default
|
||||
value of 0.75 provides a good balance. Setting this to 0.0 preserves the
|
||||
chromatic accuracy of the tone mapping process.
|
||||
|
||||
``--tone-mapping-desaturate-exponent=<0.0..20.0>``
|
||||
This setting controls the exponent of the desaturation curve, which
|
||||
controls how bright a color needs to be in order to start being
|
||||
desaturated. The default of 1.5 provides a reasonable balance. Decreasing
|
||||
this exponent makes the curve more aggressive.
|
||||
|
||||
``--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
|
||||
|
@ -329,8 +329,6 @@ static const struct gl_video_opts gl_video_opts_def = {
|
||||
.decay_rate = 100.0,
|
||||
.scene_threshold_low = 5.5,
|
||||
.scene_threshold_high = 10.0,
|
||||
.desat = 0.75,
|
||||
.desat_exp = 1.5,
|
||||
},
|
||||
.early_flush = -1,
|
||||
.hwdec_interop = "auto",
|
||||
@ -394,9 +392,12 @@ const struct m_sub_options gl_video_conf = {
|
||||
M_RANGE(0.0, 0.3)},
|
||||
{"tone-mapping-max-boost", OPT_FLOAT(tone_map.max_boost),
|
||||
M_RANGE(1.0, 10.0)},
|
||||
{"tone-mapping-desaturate", OPT_FLOAT(tone_map.desat)},
|
||||
{"tone-mapping-desaturate-exponent", OPT_FLOAT(tone_map.desat_exp),
|
||||
M_RANGE(0.0, 20.0)},
|
||||
{"tone-mapping-mode", OPT_CHOICE(tone_map.mode,
|
||||
{"auto", TONE_MAP_MODE_AUTO},
|
||||
{"rgb", TONE_MAP_MODE_RGB},
|
||||
{"max", TONE_MAP_MODE_MAX},
|
||||
{"hybrid", TONE_MAP_MODE_HYBRID},
|
||||
{"luma", TONE_MAP_MODE_LUMA})},
|
||||
{"gamut-mapping-mode", OPT_CHOICE(tone_map.gamut_mode,
|
||||
{"auto", GAMUT_AUTO},
|
||||
{"clip", GAMUT_CLIP},
|
||||
@ -479,6 +480,8 @@ const struct m_sub_options gl_video_conf = {
|
||||
"--linear-downscaling")},
|
||||
{"gamut-warning", OPT_REMOVED("Replaced by --gamut-mapping-mode=warn")},
|
||||
{"gamut-clipping", OPT_REMOVED("Replaced by --gamut-mapping-mode=desaturate")},
|
||||
{"tone-mapping-desaturate", OPT_REMOVED("Replaced by --tone-mapping-mode")},
|
||||
{"tone-mapping-desaturate-exponent", OPT_REMOVED("Replaced by --tone-mapping-mode")},
|
||||
{0}
|
||||
},
|
||||
.size = sizeof(struct gl_video_opts),
|
||||
@ -2644,6 +2647,18 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p->opts.tone_map.mode) {
|
||||
case TONE_MAP_MODE_AUTO:
|
||||
case TONE_MAP_MODE_RGB:
|
||||
case TONE_MAP_MODE_MAX:
|
||||
case TONE_MAP_MODE_HYBRID:
|
||||
break;
|
||||
default:
|
||||
MP_WARN(p, "Tone mapping mode unsupported by vo_gpu, falling back.\n");
|
||||
p->opts.tone_map.mode = TONE_MAP_MODE_AUTO;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p->opts.tone_map.gamut_mode) {
|
||||
case GAMUT_AUTO:
|
||||
case GAMUT_WARN:
|
||||
|
@ -100,6 +100,14 @@ enum tone_mapping {
|
||||
TONE_MAPPING_BT_2446A,
|
||||
};
|
||||
|
||||
enum tone_mapping_mode {
|
||||
TONE_MAP_MODE_AUTO,
|
||||
TONE_MAP_MODE_RGB,
|
||||
TONE_MAP_MODE_MAX,
|
||||
TONE_MAP_MODE_HYBRID,
|
||||
TONE_MAP_MODE_LUMA,
|
||||
};
|
||||
|
||||
enum gamut_mode {
|
||||
GAMUT_AUTO,
|
||||
GAMUT_CLIP,
|
||||
@ -114,12 +122,11 @@ struct gl_tone_map_opts {
|
||||
float max_boost;
|
||||
int inverse;
|
||||
float crosstalk;
|
||||
int mode;
|
||||
int compute_peak;
|
||||
float decay_rate;
|
||||
float scene_threshold_low;
|
||||
float scene_threshold_high;
|
||||
float desat;
|
||||
float desat_exp;
|
||||
int gamut_mode;
|
||||
};
|
||||
|
||||
|
@ -809,18 +809,24 @@ static void pass_tone_map(struct gl_shader_cache *sc,
|
||||
abort();
|
||||
}
|
||||
|
||||
GLSL(vec3 sig_lin = color.rgb * (sig[sig_idx] / sig_orig);)
|
||||
|
||||
// Mix between the per-channel tone mapped and the linear tone mapped
|
||||
// signal based on the desaturation strength
|
||||
if (opts->desat > 0) {
|
||||
float base = 0.18 * dst_scale;
|
||||
GLSLF("float coeff = max(sig[sig_idx] - %f, 1e-6) / "
|
||||
" max(sig[sig_idx], 1.0);\n", base);
|
||||
GLSLF("coeff = %f * pow(coeff, %f);\n", opts->desat, opts->desat_exp);
|
||||
GLSLF("color.rgb = mix(sig_lin, %f * sig, coeff);\n", dst_scale);
|
||||
} else {
|
||||
GLSL(color.rgb = sig_lin;)
|
||||
switch (opts->mode) {
|
||||
case TONE_MAP_MODE_RGB:
|
||||
GLSL(color.rgb = sig;)
|
||||
break;
|
||||
case TONE_MAP_MODE_MAX:
|
||||
GLSL(color.rgb *= sig[sig_idx] / sig_orig;)
|
||||
break;
|
||||
case TONE_MAP_MODE_AUTO:
|
||||
case TONE_MAP_MODE_HYBRID:
|
||||
GLSLF("float coeff = max(sig[sig_idx] - %f, 1e-6) / \n"
|
||||
" max(sig[sig_idx], 1.0); \n"
|
||||
"coeff = %f * pow(coeff / %f, %f); \n"
|
||||
"color.rgb *= sig[sig_idx] / sig_orig; \n"
|
||||
"color.rgb = mix(color.rgb, %f * sig, coeff); \n",
|
||||
0.18 / dst_scale, 0.90, dst_scale, 0.20, dst_scale);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1406,12 +1406,21 @@ static void update_render_options(struct priv *p)
|
||||
[GAMUT_DARKEN] = PL_GAMUT_DARKEN,
|
||||
};
|
||||
|
||||
static const enum pl_tone_map_mode tone_map_modes[] = {
|
||||
[TONE_MAP_MODE_AUTO] = PL_TONE_MAP_AUTO,
|
||||
[TONE_MAP_MODE_RGB] = PL_TONE_MAP_RGB,
|
||||
[TONE_MAP_MODE_MAX] = PL_TONE_MAP_MAX,
|
||||
[TONE_MAP_MODE_HYBRID] = PL_TONE_MAP_HYBRID,
|
||||
[TONE_MAP_MODE_LUMA] = PL_TONE_MAP_LUMA,
|
||||
};
|
||||
|
||||
p->color_map = pl_color_map_default_params;
|
||||
p->color_map.intent = opts->icc_opts->intent;
|
||||
p->color_map.tone_mapping_function = tone_map_funs[opts->tone_map.curve];
|
||||
p->color_map.tone_mapping_param = opts->tone_map.curve_param;
|
||||
p->color_map.inverse_tone_mapping = opts->tone_map.inverse;
|
||||
p->color_map.tone_mapping_crosstalk = opts->tone_map.crosstalk;
|
||||
p->color_map.tone_mapping_mode = tone_map_modes[opts->tone_map.mode];
|
||||
if (isnan(p->color_map.tone_mapping_param)) // vo_gpu compatibility
|
||||
p->color_map.tone_mapping_param = 0.0;
|
||||
if (opts->tone_map.gamut_mode != GAMUT_AUTO)
|
||||
|
Loading…
Reference in New Issue
Block a user