Skip to content

Commit

Permalink
vo_gpu_next: add target-colorspace-hint=auto
Browse files Browse the repository at this point in the history
  • Loading branch information
kasper93 committed Nov 23, 2024
1 parent a132b46 commit 102dcec
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 19 deletions.
2 changes: 1 addition & 1 deletion DOCS/interface-changes/target-hint.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
change `target-colorspace-hint` default to `yes`
change `target-colorspace-hint` default to `auto`
10 changes: 6 additions & 4 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6826,11 +6826,12 @@ them.
Fully replaces the color decoding. A LUT of this type should ingest the
image's native colorspace and output normalized non-linear RGB.

``--target-colorspace-hint``
``--target-colorspace-hint=<auto|yes|no>``
Automatically configure the output colorspace of the display to pass
through the input values of the stream (e.g. for HDR passthrough), if
possible. Requires a supporting driver and ``--vo=gpu-next``.
(Default: ``yes``)
possible. In ``auto`` mode (the default), the target colorspace is only set,
if the display signals support for HDR colorspace.
Requires a supporting driver and ``--vo=gpu-next``. (Default: ``auto``)

``--target-prim=<value>``
Specifies the primaries of the display. Video colors will be adapted to
Expand Down Expand Up @@ -6928,7 +6929,8 @@ them.

In ``auto`` mode (the default), the chosen peak is an appropriate value
based on the TRC in use. For SDR curves, it uses 203. For HDR curves, it
uses 203 * the transfer function's nominal peak.
uses 203 * the transfer function's nominal peak. If available, it will use
the target display's peak brightness as reported by the display.

.. note::

Expand Down
42 changes: 28 additions & 14 deletions video/out/vo_gpu_next.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ struct gl_next_opts {
struct user_lut lut;
struct user_lut image_lut;
struct user_lut target_lut;
bool target_hint;
int target_hint;
char **raw_opts;
};

Expand All @@ -197,15 +197,15 @@ const struct m_sub_options gl_next_conf = {
{"image-lut", OPT_STRING(image_lut.opt), .flags = M_OPT_FILE},
{"image-lut-type", OPT_CHOICE_C(image_lut.type, lut_types)},
{"target-lut", OPT_STRING(target_lut.opt), .flags = M_OPT_FILE},
{"target-colorspace-hint", OPT_BOOL(target_hint)},
{"target-colorspace-hint", OPT_CHOICE(target_hint, {"auto", -1}, {"no", 0}, {"yes", 1})},
// No `target-lut-type` because we don't support non-RGB targets
{"libplacebo-opts", OPT_KEYVALUELIST(raw_opts)},
{0},
},
.defaults = &(struct gl_next_opts) {
.border_background = BACKGROUND_COLOR,
.inter_preserve = true,
.target_hint = true,
.target_hint = -1,
},
.size = sizeof(struct gl_next_opts),
.change_flags = UPDATE_VIDEO,
Expand Down Expand Up @@ -798,7 +798,7 @@ static void apply_target_contrast(struct priv *p, struct pl_color_space *color)
color->hdr.min_luma = color->hdr.max_luma / opts->target_contrast;
}

static void apply_target_options(struct priv *p, struct pl_frame *target)
static void apply_target_options(struct priv *p, struct pl_frame *target, float target_peak)
{
update_lut(p, &p->next_opts->target_lut);
target->lut = p->next_opts->target_lut.lut;
Expand All @@ -813,8 +813,8 @@ static void apply_target_options(struct priv *p, struct pl_frame *target)
if (opts->target_trc)
target->color.transfer = opts->target_trc;
// If swapchain returned a value use this, override is used in hint
if (opts->target_peak && !target->color.hdr.max_luma)
target->color.hdr.max_luma = opts->target_peak;
if (target_peak && !target->color.hdr.max_luma)
target->color.hdr.max_luma = target_peak;
if (!target->color.hdr.min_luma)
apply_target_contrast(p, &target->color);
if (opts->target_gamut) {
Expand Down Expand Up @@ -975,27 +975,41 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
p->last_id = id;
}

struct ra_swapchain *sw = p->ra_ctx->swapchain;

bool pass_colorspace = false;
struct pl_color_space target_csp;
// Assume HDR is supported, if query is not available
// TODO: Implement this for all backends
target_csp = sw->fns->target_csp
? sw->fns->target_csp(sw)
: (struct pl_color_space){ .transfer = PL_COLOR_TRC_PQ };
if (!pl_color_transfer_is_hdr(target_csp.transfer))
target_csp.hdr.max_luma = 0;

float target_peak = opts->target_peak ? opts->target_peak : target_csp.hdr.max_luma;
struct pl_color_space hint;
if (p->next_opts->target_hint && frame->current) {
bool target_hint = p->next_opts->target_hint == 1 ||
(p->next_opts->target_hint == -1 &&
pl_color_transfer_is_hdr(target_csp.transfer));
if (target_hint && frame->current) {
hint = frame->current->params.color;
if (p->ra_ctx->fns->pass_colorspace && p->ra_ctx->fns->pass_colorspace(p->ra_ctx))
pass_colorspace = true;
if (opts->target_prim)
hint.primaries = opts->target_prim;
if (opts->target_trc)
hint.transfer = opts->target_trc;
if (opts->target_peak)
hint.hdr.max_luma = opts->target_peak;
if (target_peak)
hint.hdr.max_luma = target_peak;
apply_target_contrast(p, &hint);
if (!pass_colorspace)
pl_swapchain_colorspace_hint(p->sw, &hint);
} else if (!p->next_opts->target_hint) {
} else if (!target_hint) {
pl_swapchain_colorspace_hint(p->sw, NULL);
}

struct pl_swapchain_frame swframe;
struct ra_swapchain *sw = p->ra_ctx->swapchain;
bool should_draw = sw->fns->start_frame(sw, NULL); // for wayland logic
if (!should_draw || !pl_swapchain_start_frame(p->sw, &swframe)) {
if (frame->current) {
Expand All @@ -1019,7 +1033,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
// Calculate target
struct pl_frame target;
pl_frame_from_swapchain(&target, &swframe);
apply_target_options(p, &target);
apply_target_options(p, &target, target_peak);
update_overlays(vo, p->osd_res,
(frame->current && opts->blend_subs) ? OSD_DRAW_OSD_ONLY : 0,
PL_OVERLAY_COORDS_DST_FRAME, &p->osd_state, &target, frame->current);
Expand Down Expand Up @@ -1391,9 +1405,10 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
},
};

const struct gl_video_opts *opts = p->opts_cache->opts;
if (args->scaled) {
// Apply target LUT, ICC profile and CSP override only in window mode
apply_target_options(p, &target);
apply_target_options(p, &target, opts->target_peak);
} else if (args->native_csp) {
target.color = image.color;
} else {
Expand All @@ -1410,7 +1425,6 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args)
if (!args->osd)
osd_flags |= OSD_DRAW_SUB_ONLY;

const struct gl_video_opts *opts = p->opts_cache->opts;
struct frame_priv *fp = mpi->priv;
if (opts->blend_subs) {
float rx = pl_rect_w(dst) / pl_rect_w(image.crop);
Expand Down

0 comments on commit 102dcec

Please sign in to comment.