Skip to content

Commit b5c4cdd

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 b5c4cdd

2 files changed

Lines changed: 50 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: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,32 @@ 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+
if (!pl_color_transfer_is_hdr(csp->transfer))
713+
return true;
714+
#if PL_API_VER >= 362
715+
if (csp->transfer == PL_COLOR_TRC_SCRGB && target_csp && !pl_color_transfer_is_hdr(target_csp->transfer))
716+
return true;
717+
#endif
718+
return false;
719+
}
720+
695721
static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
696722
struct pl_frame *frame)
697723
{
@@ -729,9 +755,11 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
729755
};
730756

731757
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-
758+
float ref_luma;
759+
if (!pl_color_transfer_is_hdr(frame->color.transfer) && (ref_luma = get_ref_luma(p))) {
760+
MP_ERR(vo, "ref: %f\n", ref_luma);
761+
frame->color.hdr.max_luma = ref_luma;
762+
}
735763

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

944972
static void apply_target_options(struct priv *p, struct pl_frame *target,
945-
float min_luma, bool hint)
973+
float min_luma, bool hint, float target_ref_luma,
974+
const struct pl_color_space *target_csp)
946975
{
947976
update_lut(p, &p->next_opts->target_lut);
948977
target->lut = p->next_opts->target_lut.lut;
@@ -959,9 +988,9 @@ static void apply_target_options(struct priv *p, struct pl_frame *target,
959988
target->color.transfer = opts->target_trc;
960989
if (opts->target_peak && (!target->color.hdr.max_luma || !hint))
961990
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;
991+
if (target_ref_luma && (!target->color.hdr.max_luma || !hint) &&
992+
use_ref_luma(&target->color, target_csp)) {
993+
target->color.hdr.max_luma = target_ref_luma;
965994
}
966995
if ((!target->color.hdr.min_luma || !hint))
967996
apply_target_contrast(p, &target->color, min_luma);
@@ -1179,9 +1208,12 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
11791208
// Assume HDR is supported, if target_csp() is not available
11801209
// TODO: Remove this fallback when all backends support target_csp()
11811210
bool target_unknown = target_csp.transfer == PL_COLOR_TRC_UNKNOWN;
1211+
float target_ref_luma = 0;
11821212
if (target_unknown) {
11831213
target_csp = (struct pl_color_space){
11841214
.transfer = opts->target_trc ? opts->target_trc : pl_color_space_hdr10.transfer };
1215+
} else {
1216+
target_ref_luma = get_ref_luma(p);
11851217
}
11861218
bool external_params = false;
11871219
if (target_hint && frame->current) {
@@ -1246,8 +1278,8 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
12461278
hint.transfer = opts->target_trc;
12471279
if (opts->target_peak)
12481280
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;
1281+
if (target_ref_luma && use_ref_luma(&hint, &target_csp))
1282+
hint.hdr.max_luma = target_ref_luma;
12511283
// Always set maxCLL, display uses this metadata and we shouldn't let it
12521284
// fallback to default value.
12531285
if (!hint.hdr.max_cll)
@@ -1311,7 +1343,8 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
13111343
if (external_params)
13121344
target.color = hint;
13131345
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);
1346+
apply_target_options(p, &target, hint.hdr.min_luma, strict_sw_params,
1347+
target_ref_luma, &target_csp);
13151348
bool clip_gamut = pl_primaries_valid(&target.color.hdr.prim);
13161349
#if PL_API_VER >= 362
13171350
clip_gamut = clip_gamut && target.color.transfer != PL_COLOR_TRC_SCRGB;
@@ -1736,7 +1769,7 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
17361769
const struct gl_video_opts *opts = p->opts_cache->opts;
17371770
if (args->scaled) {
17381771
// Apply target LUT, ICC profile and CSP override only in window mode
1739-
apply_target_options(p, &target, 0, false);
1772+
apply_target_options(p, &target, 0, false, 0, NULL);
17401773
} else if (args->native_csp) {
17411774
target.color = image.color;
17421775
} else {

0 commit comments

Comments
 (0)