Skip to content

Commit d6756a8

Browse files
committed
vo_gpu_next: follow reference white system setting
This is mostly useful for SDR mode where previously we would output 203 nits, which on Windows is considered HDR, because reference white is fixed at 80 nits in SDR mode. Which in turn causes additional tone-mapping when using scRGB output. Note that for SDR transfers this doesn't change the luminance, but instead causes more aggressive tone-mapping, might not be fully expected. But maybe we should follow system setting for better of for worse. Fixes: #17850 Not fully, because when ICC profile is embeded in content, libplacebo will override our luminance, this will be fixed separately.
1 parent 37041f9 commit d6756a8

2 files changed

Lines changed: 45 additions & 13 deletions

File tree

DOCS/man/options.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7534,11 +7534,15 @@ them.
75347534
encoding into the target colorspace, so after the application of
75357535
``--target-trc``. (Only for ``--vo=gpu-next``)
75367536

7537-
``--hdr-reference-white=<auto|10-1000000>``
7537+
``--hdr-reference-white=<auto|10-10000>``
75387538
Specifies the assumed peak brightness of the mastering display for SDR
75397539
content, in cd/m² (nits). This is used as HDR diffuse white level for SDR
75407540
content. Essentially this is the SDR brightness in HDR container.
7541-
Default is 203 cd/m². (Only for ``--vo=gpu-next``)
7541+
(Only for ``--vo=gpu-next``)
7542+
7543+
In ``auto`` mode (default), the reference white luminance is queried from
7544+
the system. This is currently only supported on Windows. If the system does
7545+
not provide a value, 203 cd/m² is assumed.
75427546

75437547
.. note::
75447548

video/out/vo_gpu_next.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,27 @@ static bool format_supported(struct vo *vo, int format, bool use_uint)
692692
return true;
693693
}
694694

695+
// Effective reference white luminance in nits to assume for SDR content.
696+
static float get_ref_luma(struct priv *p)
697+
{
698+
const struct gl_video_opts *opts = p->opts_cache->opts;
699+
if (opts->hdr_reference_white)
700+
return opts->hdr_reference_white;
701+
702+
// auto: follow the system reference white, if available
703+
struct ra_swapchain *sw = p->ra_ctx->swapchain;
704+
if (sw->fns->target_ref_luma)
705+
return sw->fns->target_ref_luma(sw);
706+
707+
return 0;
708+
}
709+
710+
static bool use_ref_luma(const struct pl_color_space *csp, const struct pl_color_space *target_csp)
711+
{
712+
return !pl_color_transfer_is_hdr(csp->transfer) ||
713+
(csp->transfer == PL_COLOR_TRC_SCRGB && target_csp && !pl_color_transfer_is_hdr(target_csp->transfer));
714+
}
715+
695716
static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
696717
struct pl_frame *frame)
697718
{
@@ -729,9 +750,11 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
729750
};
730751

731752
const struct gl_video_opts *opts = p->opts_cache->opts;
732-
if (opts->hdr_reference_white && !pl_color_transfer_is_hdr(frame->color.transfer))
733-
frame->color.hdr.max_luma = opts->hdr_reference_white;
734-
753+
float ref_luma;
754+
if (!pl_color_transfer_is_hdr(frame->color.transfer) && (ref_luma = get_ref_luma(p))) {
755+
MP_ERR(vo, "ref: %f\n", ref_luma);
756+
frame->color.hdr.max_luma = ref_luma;
757+
}
735758

736759
if (opts->treat_srgb_as_power22 & 1 && frame->color.transfer == PL_COLOR_TRC_SRGB) {
737760
// The sRGB EOTF is a pure gamma 2.2 function. See reference display in
@@ -942,7 +965,8 @@ static void apply_target_contrast(struct priv *p, struct pl_color_space *color,
942965
}
943966

944967
static void apply_target_options(struct priv *p, struct pl_frame *target,
945-
float min_luma, bool hint)
968+
float min_luma, bool hint, float target_ref_luma,
969+
const struct pl_color_space *target_csp)
946970
{
947971
update_lut(p, &p->next_opts->target_lut);
948972
target->lut = p->next_opts->target_lut.lut;
@@ -959,9 +983,9 @@ static void apply_target_options(struct priv *p, struct pl_frame *target,
959983
target->color.transfer = opts->target_trc;
960984
if (opts->target_peak && (!target->color.hdr.max_luma || !hint))
961985
target->color.hdr.max_luma = opts->target_peak;
962-
if (opts->hdr_reference_white && (!target->color.hdr.max_luma || !hint) &&
963-
!pl_color_transfer_is_hdr(target->color.transfer)) {
964-
target->color.hdr.max_luma = opts->hdr_reference_white;
986+
if (target_ref_luma && (!target->color.hdr.max_luma || !hint) &&
987+
use_ref_luma(&target->color, target_csp)) {
988+
target->color.hdr.max_luma = target_ref_luma;
965989
}
966990
if ((!target->color.hdr.min_luma || !hint))
967991
apply_target_contrast(p, &target->color, min_luma);
@@ -1179,9 +1203,12 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
11791203
// Assume HDR is supported, if target_csp() is not available
11801204
// TODO: Remove this fallback when all backends support target_csp()
11811205
bool target_unknown = target_csp.transfer == PL_COLOR_TRC_UNKNOWN;
1206+
float target_ref_luma = 0;
11821207
if (target_unknown) {
11831208
target_csp = (struct pl_color_space){
11841209
.transfer = opts->target_trc ? opts->target_trc : pl_color_space_hdr10.transfer };
1210+
} else {
1211+
target_ref_luma = get_ref_luma(p);
11851212
}
11861213
bool external_params = false;
11871214
if (target_hint && frame->current) {
@@ -1246,8 +1273,8 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
12461273
hint.transfer = opts->target_trc;
12471274
if (opts->target_peak)
12481275
hint.hdr.max_luma = opts->target_peak;
1249-
if (opts->hdr_reference_white && !pl_color_transfer_is_hdr(hint.transfer))
1250-
hint.hdr.max_luma = opts->hdr_reference_white;
1276+
if (target_ref_luma && use_ref_luma(&hint, &target_csp))
1277+
hint.hdr.max_luma = target_ref_luma;
12511278
// Always set maxCLL, display uses this metadata and we shouldn't let it
12521279
// fallback to default value.
12531280
if (!hint.hdr.max_cll)
@@ -1311,7 +1338,8 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
13111338
if (external_params)
13121339
target.color = hint;
13131340
bool strict_sw_params = target_hint && p->next_opts->target_hint_strict;
1314-
apply_target_options(p, &target, hint.hdr.min_luma, strict_sw_params);
1341+
apply_target_options(p, &target, hint.hdr.min_luma, strict_sw_params,
1342+
target_ref_luma, &target_csp);
13151343
bool clip_gamut = pl_primaries_valid(&target.color.hdr.prim);
13161344
#if PL_API_VER >= 362
13171345
clip_gamut = clip_gamut && target.color.transfer != PL_COLOR_TRC_SCRGB;
@@ -1736,7 +1764,7 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
17361764
const struct gl_video_opts *opts = p->opts_cache->opts;
17371765
if (args->scaled) {
17381766
// Apply target LUT, ICC profile and CSP override only in window mode
1739-
apply_target_options(p, &target, 0, false);
1767+
apply_target_options(p, &target, 0, false, 0, NULL);
17401768
} else if (args->native_csp) {
17411769
target.color = image.color;
17421770
} else {

0 commit comments

Comments
 (0)