From cea53a90d48fa8215ad7979f1139b24bad4ca190 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 23 Jul 2021 17:35:22 +0300 Subject: [PATCH] libweston: add HDR metadata to weston_output This adds hdr_meta field in weston_output_color_outcome. This field is intended to be set by color manager modules, and read by backends which will send the information to the video sink in SMPTE ST 2084 mode a.k.a Perceptual Quantizer HDR system. Such metadata is essential in ST 2084 mode for the video sink to produce a good picture. The validation of the data and the group split is based on the HDR Static Metata Type 1 definition in CTA-861-G specification. Signed-off-by: Pekka Paalanen --- include/libweston/libweston.h | 60 +++++++++++++++++++++++ libweston/backend.h | 5 ++ libweston/color-lcms/color-lcms.c | 2 + libweston/color-noop.c | 2 + libweston/compositor.c | 80 ++++++++++++++++++++++++++++++- 5 files changed, 148 insertions(+), 1 deletion(-) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 01c4e4d7..ceaca6a9 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -247,6 +247,63 @@ struct weston_CIExy { float y; }; +enum weston_hdr_metadata_type1_groups { + /** weston_hdr_metadata_type1::primary is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES = 0x01, + + /** weston_hdr_metadata_type1::white is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_WHITE = 0x02, + + /** weston_hdr_metadata_type1::maxDML is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML = 0x04, + + /** weston_hdr_metadata_type1::minDML is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_MINDML = 0x08, + + /** weston_hdr_metadata_type1::maxCLL is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL = 0x10, + + /** weston_hdr_metadata_type1::maxFALL is set */ + WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL = 0x20, + + /** all valid bits */ + WESTON_HDR_METADATA_TYPE1_GROUP_ALL_MASK = 0x3f +}; + +/** HDR static metadata type 1 + * + * The fields are defined by CTA-861-G except here they use float encoding. + * + * In Weston used only with HDR display modes. + */ +struct weston_hdr_metadata_type1 { + /** Which fields are valid + * + * A bitmask of values from enum weston_hdr_metadata_type1_groups. + */ + uint32_t group_mask; + + /* EOTF is tracked externally with enum weston_eotf_mode */ + + /** Chromaticities of the primaries, in any order */ + struct weston_CIExy primary[3]; + + /** White point chromaticity */ + struct weston_CIExy white; + + /** Maximum display mastering luminance, 1 - 65535 cd/m² */ + float maxDML; + + /** Minimum display mastering luminance, 0.0001 - 6.5535 cd/m² */ + float minDML; + + /** Maximum content light level, 1 - 65535 cd/m² */ + float maxCLL; + + /** Maximum frame-average light level, 1 - 65535 cd/m² */ + float maxFALL; +}; + enum weston_color_characteristics_groups { /** weston_color_characteristics::primary is set */ WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01, @@ -358,6 +415,9 @@ struct weston_output_color_outcome { /** Blending to output color space transformation */ struct weston_color_transform *from_blend_to_output; + + /** HDR Static Metadata Type 1 for WESTON_EOTF_MODE_ST2084 */ + struct weston_hdr_metadata_type1 hdr_meta; }; /** Content producer for heads diff --git a/libweston/backend.h b/libweston/backend.h index 26624cf9..2374b17b 100644 --- a/libweston/backend.h +++ b/libweston/backend.h @@ -32,6 +32,8 @@ #ifndef LIBWESTON_BACKEND_INTERNAL_H #define LIBWESTON_BACKEND_INTERNAL_H +struct weston_hdr_metadata_type1; + struct weston_backend { void (*destroy)(struct weston_compositor *compositor); @@ -173,6 +175,9 @@ void weston_output_region_from_global(struct weston_output *output, pixman_region32_t *region); +const struct weston_hdr_metadata_type1 * +weston_output_get_hdr_metadata_type1(const struct weston_output *output); + /* weston_seat */ void diff --git a/libweston/color-lcms/color-lcms.c b/libweston/color-lcms/color-lcms.c index 005cbc9d..f8d44530 100644 --- a/libweston/color-lcms/color-lcms.c +++ b/libweston/color-lcms/color-lcms.c @@ -208,6 +208,8 @@ cmlcms_create_output_color_outcome(struct weston_color_manager *cm_base, &co->from_sRGB_to_output)) goto out_fail; + co->hdr_meta.group_mask = 0; + return co; out_fail: diff --git a/libweston/color-noop.c b/libweston/color-noop.c index 2e1461f3..4bd1e762 100644 --- a/libweston/color-noop.c +++ b/libweston/color-noop.c @@ -116,6 +116,8 @@ cmnoop_create_output_color_outcome(struct weston_color_manager *cm_base, co->from_sRGB_to_blend = NULL; co->from_sRGB_to_output = NULL; + co->hdr_meta.group_mask = 0; + return co; } diff --git a/libweston/compositor.c b/libweston/compositor.c index e5c4bc70..47cd4ff9 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -6449,6 +6449,57 @@ weston_output_transform_coordinate(struct weston_output *output, *y = p.f[1] / p.f[3]; } +static bool +validate_float_range(float val, float min, float max) +{ + return val >= min && val <= max; +} + +/* Based on CTA-861-G, HDR static metadata type 1 */ +static bool +weston_hdr_metadata_type1_validate(const struct weston_hdr_metadata_type1 *md) +{ + unsigned i; + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES) { + for (i = 0; i < ARRAY_LENGTH(md->primary); i++) { + if (!validate_float_range(md->primary[i].x, 0.0, 1.0)) + return false; + if (!validate_float_range(md->primary[i].y, 0.0, 1.0)) + return false; + } + } + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_WHITE) { + if (!validate_float_range(md->white.x, 0.0, 1.0)) + return false; + if (!validate_float_range(md->white.y, 0.0, 1.0)) + return false; + } + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML) { + if (!validate_float_range(md->maxDML, 1.0, 65535.0)) + return false; + } + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MINDML) { + if (!validate_float_range(md->minDML, 0.0001, 6.5535)) + return false; + } + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL) { + if (!validate_float_range(md->maxCLL, 1.0, 65535.0)) + return false; + } + + if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL) { + if (!validate_float_range(md->maxFALL, 1.0, 65535.0)) + return false; + } + + return true; +} + WL_EXPORT void weston_output_color_outcome_destroy(struct weston_output_color_outcome **pco) { @@ -6475,10 +6526,15 @@ weston_output_set_color_outcome(struct weston_output *output) if (!colorout) { weston_log("Creating color transformation for output \"%s\" failed.\n", output->name); - return false; } + if (!weston_hdr_metadata_type1_validate(&colorout->hdr_meta)) { + weston_log("Internal color manager error creating Metadata Type 1 for output \"%s\".\n", + output->name); + goto out_error; + } + weston_output_color_outcome_destroy(&output->color_outcome); output->color_outcome = colorout; @@ -6488,6 +6544,11 @@ weston_output_set_color_outcome(struct weston_output *output) weston_color_profile_get_description(output->color_profile)); return true; + +out_error: + weston_output_color_outcome_destroy(&colorout); + + return false; } /** Removes output from compositor's list of enabled outputs @@ -6764,6 +6825,23 @@ weston_output_get_eotf_mode(const struct weston_output *output) return output->eotf_mode; } +/** Get HDR static metadata type 1 + * + * \param output The output to query. + * \return Pointer to the metadata stored in weston_output. + * + * This function is meant to be used by libweston backends. + * + * \ingroup output + * \internal + */ +WL_EXPORT const struct weston_hdr_metadata_type1 * +weston_output_get_hdr_metadata_type1(const struct weston_output *output) +{ + assert(output->color_outcome); + return &output->color_outcome->hdr_meta; +} + /** Set display or monitor basic color characteristics * * \param output The output to modify, must be in disabled state.