1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-27 01:22:30 +00:00

vo_gpu_next: implement HDR passthrough

Completely untested, since Linux still can't into HDR in 2021. Somebody
please make sure it works.

Technically covers #8219, since gpu-context=drm can be combined with
vo=gpu-next.
This commit is contained in:
Niklas Haas 2021-11-07 23:47:55 +01:00 committed by Niklas Haas
parent 3cf6147368
commit 4470eaf5e5
3 changed files with 66 additions and 0 deletions

View File

@ -31,6 +31,7 @@ Interface changes
`--allow-delayed-peak-detect`, `--builtin-scalers`,
`--interpolation-preserve` `--lut`, `--lut-type`, `--image-lut`,
`--image-lut-type` and `--target-lut` along with it.
- add `--target-colorspace-hint`
--- mpv 0.34.0 ---
- deprecate selecting by card number with `--drm-connector`, add
`--drm-device` which can be used instead

View File

@ -6172,6 +6172,11 @@ 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```
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``.
``--target-prim=<value>``
Specifies the primaries of the display. Video colors will be adapted to
this colorspace when ICC color management is not being used. Valid values

View File

@ -127,6 +127,7 @@ struct priv {
int delayed_peak;
int inter_preserve;
int target_hint;
};
static void update_render_options(struct priv *p);
@ -486,6 +487,57 @@ static void discard_frame(const struct pl_source_frame *src)
talloc_free(mpi);
}
static struct pl_swapchain_colors get_csp_hint(struct vo *vo, struct mp_image *mpi)
{
struct priv *p = vo->priv;
const struct gl_video_opts *opts = p->opts_cache->opts;
struct pl_swapchain_colors hint = {
.primaries = mp_prim_to_pl(mpi->params.color.primaries),
.transfer = mp_trc_to_pl(mpi->params.color.gamma),
};
// Respect target color space overrides
if (opts->target_prim)
hint.primaries = mp_prim_to_pl(opts->target_prim);
if (opts->target_trc)
hint.transfer = mp_prim_to_pl(opts->target_trc);
for (int i = 0; i < mpi->num_ff_side_data; i++) {
void *data = mpi->ff_side_data[i].buf->data;
switch (mpi->ff_side_data[i].type) {
case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: {
const AVContentLightMetadata *clm = data;
hint.hdr.max_cll = clm->MaxCLL;
hint.hdr.max_fall = clm->MaxFALL;
break;
}
case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: {
const AVMasteringDisplayMetadata *mdm = data;
if (mdm->has_luminance) {
hint.hdr.min_luma = av_q2d(mdm->min_luminance);
hint.hdr.max_luma = av_q2d(mdm->max_luminance);
}
if (mdm->has_primaries) {
hint.hdr.prim.red.x = av_q2d(mdm->display_primaries[0][0]);
hint.hdr.prim.red.y = av_q2d(mdm->display_primaries[0][1]);
hint.hdr.prim.green.x = av_q2d(mdm->display_primaries[1][0]);
hint.hdr.prim.green.y = av_q2d(mdm->display_primaries[1][1]);
hint.hdr.prim.blue.x = av_q2d(mdm->display_primaries[2][0]);
hint.hdr.prim.blue.y = av_q2d(mdm->display_primaries[2][1]);
hint.hdr.prim.white.x = av_q2d(mdm->white_point[0]);
hint.hdr.prim.white.y = av_q2d(mdm->white_point[1]);
}
break;
}
default: break;
}
}
return hint;
}
static void info_callback(void *priv, const struct pl_render_info *info)
{
struct vo *vo = priv;
@ -580,6 +632,13 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
if (!should_draw)
return;
if (p->target_hint && frame->current) {
struct pl_swapchain_colors hint = get_csp_hint(vo, frame->current);
pl_swapchain_colorspace_hint(p->sw, &hint);
} else if (!p->target_hint) {
pl_swapchain_colorspace_hint(p->sw, NULL);
}
struct pl_swapchain_frame swframe;
if (!pl_swapchain_start_frame(p->sw, &swframe)) {
// Advance the queue state to the current PTS to discard unused frames
@ -1275,6 +1334,7 @@ const struct vo_driver video_out_gpu_next = {
{"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_FLAG(target_hint)},
// No `target-lut-type` because we don't support non-RGB targets
{0}
},