summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2021-11-07 23:47:55 +0100
committerNiklas Haas <github-daiK1o@haasn.dev>2021-11-08 20:57:54 +0100
commit4470eaf5e5caefc5c68440babb9b4e5b23c4627a (patch)
treed55c53dd8f8955e9bdbb54b04c8adf267463f252
parent3cf614736802695b47b7691ec25dccfd869c47fb (diff)
downloadmpv-4470eaf5e5caefc5c68440babb9b4e5b23c4627a.tar.bz2
mpv-4470eaf5e5caefc5c68440babb9b4e5b23c4627a.tar.xz
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.
-rw-r--r--DOCS/interface-changes.rst1
-rw-r--r--DOCS/man/options.rst5
-rw-r--r--video/out/vo_gpu_next.c60
3 files changed, 66 insertions, 0 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 6aa6fd907d..e8ad97cd55 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -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
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 254321d6ce..d03ec08f0d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -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
diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c
index 64ff4eb1da..c260af8865 100644
--- a/video/out/vo_gpu_next.c
+++ b/video/out/vo_gpu_next.c
@@ -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}
},