mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
kmssink: add HDR10 infoframe support
If stream has HDR10 metadata and HDMI device EDID supports it, this patch will set the DRM properties accordingly. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3303>
This commit is contained in:
parent
daecbd1ff0
commit
afb18e0e31
5 changed files with 514 additions and 1 deletions
111
subprojects/gst-plugins-bad/sys/kms/gstkmsedid.c
Normal file
111
subprojects/gst-plugins-bad/sys/kms/gstkmsedid.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2017, 2018 Collabora, Ltd.
|
||||
* Copyright © 2017, 2018 General Electric Company
|
||||
* Copyright (c) 2018 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "gstkmsedid.h"
|
||||
|
||||
/* from libweston/backend-drm/modes.c unaccepted merge, modified slightly to
|
||||
remove non HDR stuff, return -1 if no HDR in EDID.
|
||||
https://gitlab.freedesktop.org/jcline/weston/-/commit/b3fa65d19ca60a45d0cc0fc1bfa68eea970344ee
|
||||
*/
|
||||
#define EDID_OFFSET_EXT_COUNT 0x7E
|
||||
#define EDID_EXTENSION_SIZE 0x80
|
||||
// Indicates the EDID extension is a CTA extension
|
||||
#define EDID_CTA_EXTENSION_TAG 0x02
|
||||
// Indicates the data block uses the extended tag field
|
||||
#define EDID_CTA_EXTENDED_TAG 0x07
|
||||
// Value of the extended tag field for HDR static metadata blocks
|
||||
#define EDID_CTA_STATIC_HDR_TAG 0x06
|
||||
|
||||
/* Extract the HDR static metadata from a CTA EDID extension. */
|
||||
static int
|
||||
gst_kms_parse_hdr_metadata (const uint8_t * cta_ext_data,
|
||||
struct gst_kms_hdr_static_metadata *metadata)
|
||||
{
|
||||
int i, block_len;
|
||||
uint8_t cta_revision = cta_ext_data[1];
|
||||
uint8_t dtd_offset = cta_ext_data[2];
|
||||
const uint8_t *data_blocks = cta_ext_data + 4;
|
||||
|
||||
if (cta_revision != 3) {
|
||||
return -1;
|
||||
}
|
||||
// The data block collection ranges from byte 4 to the dtd_offset; each
|
||||
// block begins with the block size (in bytes) in bits 0-4 of the first byte.
|
||||
for (i = 0; i < dtd_offset; i += (data_blocks[i] & 0x1f) + 1) {
|
||||
if ((data_blocks[i] & 0xe0) >> 5 == EDID_CTA_EXTENDED_TAG) {
|
||||
block_len = data_blocks[i] & 0x1f;
|
||||
|
||||
if (data_blocks[i + 1] == EDID_CTA_STATIC_HDR_TAG) {
|
||||
if (block_len < 2)
|
||||
continue;
|
||||
|
||||
metadata->eotf = data_blocks[i + 2];
|
||||
metadata->metadata_type = data_blocks[i + 3];
|
||||
|
||||
if (block_len > 3 && data_blocks[i + 4])
|
||||
metadata->max_cll = 50.0 * pow (2, data_blocks[i + 4] / 32.0);
|
||||
if (block_len > 4 && data_blocks[i + 5])
|
||||
metadata->max_fall = 50.0 * pow (2, data_blocks[i + 5] / 32.0);
|
||||
if (block_len > 5)
|
||||
metadata->min_cll =
|
||||
metadata->max_cll * pow (data_blocks[i + 6] / 255.0, 2) / 100.0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
gst_kms_edid_parse (struct gst_kms_hdr_static_metadata *metadata,
|
||||
const uint8_t * data, size_t length)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *edid_extension;
|
||||
|
||||
/* check header */
|
||||
if (length < 128 || length < ((size_t) data[EDID_OFFSET_EXT_COUNT] + 1) * 128)
|
||||
return -1;
|
||||
if (data[0] != 0x00 || data[1] != 0xff)
|
||||
return -1;
|
||||
|
||||
edid_extension = data + 128;
|
||||
for (i = 0; i < data[EDID_OFFSET_EXT_COUNT]; i++) {
|
||||
switch (edid_extension[0]) {
|
||||
case EDID_CTA_EXTENSION_TAG:
|
||||
return gst_kms_parse_hdr_metadata (edid_extension, metadata);
|
||||
}
|
||||
edid_extension += 128;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* END from libweston/backend-drm/modes.c unaccepted merge */
|
55
subprojects/gst-plugins-bad/sys/kms/gstkmsedid.h
Normal file
55
subprojects/gst-plugins-bad/sys/kms/gstkmsedid.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2017, 2018 Collabora, Ltd.
|
||||
* Copyright © 2017, 2018 General Electric Company
|
||||
* Copyright (c) 2018 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __GST_KMS_EDID_H__
|
||||
#define __GST_KMS_EDID_H__
|
||||
|
||||
/* from libweston/backend-drm/modes.c unaccepted merge, modified slightly to
|
||||
remove non HDR stuff, return -1 if no HDR in EDID.
|
||||
https://gitlab.freedesktop.org/jcline/weston/-/commit/b3fa65d19ca60a45d0cc0fc1bfa68eea970344ee
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* HDR Metadata as per 861.G spec from linux/hdmi.h, modified for stdint.h */
|
||||
struct gst_kms_hdr_static_metadata
|
||||
{
|
||||
uint8_t eotf;
|
||||
uint8_t metadata_type;
|
||||
uint16_t max_cll;
|
||||
uint16_t max_fall;
|
||||
uint16_t min_cll;
|
||||
};
|
||||
|
||||
int
|
||||
gst_kms_edid_parse (struct gst_kms_hdr_static_metadata *metadata, const uint8_t * data,
|
||||
size_t length);
|
||||
|
||||
#endif /* __GST_KMS_EDID_H__ */
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/videooverlay.h>
|
||||
#include <gst/video/video-color.h>
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#include <drm.h>
|
||||
|
@ -62,6 +63,11 @@
|
|||
#include "gstkmsbufferpool.h"
|
||||
#include "gstkmsallocator.h"
|
||||
|
||||
#ifdef HAVE_DRM_HDR
|
||||
#include <math.h>
|
||||
#include "gstkmsedid.h"
|
||||
#endif
|
||||
|
||||
#define GST_PLUGIN_NAME "kmssink"
|
||||
#define GST_PLUGIN_DESC "Video sink using the Linux kernel mode setting API"
|
||||
|
||||
|
@ -104,6 +110,303 @@ enum
|
|||
|
||||
static GParamSpec *g_properties[PROP_N] = { NULL, };
|
||||
|
||||
#ifdef HAVE_DRM_HDR
|
||||
enum hdmi_metadata_type
|
||||
{
|
||||
HDMI_STATIC_METADATA_TYPE1 = 0,
|
||||
};
|
||||
enum hdmi_eotf
|
||||
{
|
||||
HDMI_EOTF_TRADITIONAL_GAMMA_SDR = 0,
|
||||
HDMI_EOTF_TRADITIONAL_GAMMA_HDR,
|
||||
HDMI_EOTF_SMPTE_ST2084,
|
||||
HDMI_EOTF_BT_2100_HLG,
|
||||
};
|
||||
|
||||
static void
|
||||
gst_kms_populate_infoframe (struct hdr_output_metadata *pinfo_frame,
|
||||
GstVideoMasteringDisplayInfo * p_hdr_minfo,
|
||||
GstVideoContentLightLevel * p_hdr_cll,
|
||||
gchar colorimetry, gboolean clear_it_out)
|
||||
{
|
||||
/* From CTA-861.3:
|
||||
* When a source is transmitting the Dynamic Range and Mastering InfoFrame,
|
||||
* it shall signal the end of Dynamic Range... by sending a ... InfoFrame with
|
||||
* the EOTF field to '0', the Static_Metadata_Descriptor_ID field set to '0',
|
||||
* and the fields of the Static_Metadata_Descriptor set to unknown (0)...
|
||||
*
|
||||
* See also https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html
|
||||
*/
|
||||
if (clear_it_out) {
|
||||
/* Static_Metadata_Descriptor_ID */
|
||||
pinfo_frame->metadata_type = 0;
|
||||
(void) memset ((void *) &pinfo_frame->hdmi_metadata_type1, 0,
|
||||
sizeof (pinfo_frame->hdmi_metadata_type1));
|
||||
return;
|
||||
} else {
|
||||
pinfo_frame->metadata_type = HDMI_STATIC_METADATA_TYPE1;
|
||||
pinfo_frame->hdmi_metadata_type1.eotf = colorimetry;
|
||||
pinfo_frame->hdmi_metadata_type1.metadata_type = HDMI_STATIC_METADATA_TYPE1;
|
||||
}
|
||||
|
||||
/* For HDR Infoframe see CTA-861-G, Section 6.9.1
|
||||
* SEI message is in units of 0.0001 cd/m2, HDMI is units of 1 cd/m2 - see
|
||||
* x265 specs */
|
||||
pinfo_frame->hdmi_metadata_type1.max_display_mastering_luminance =
|
||||
round (p_hdr_minfo->max_display_mastering_luminance / 10000.0);
|
||||
pinfo_frame->hdmi_metadata_type1.min_display_mastering_luminance =
|
||||
p_hdr_minfo->min_display_mastering_luminance;
|
||||
|
||||
pinfo_frame->hdmi_metadata_type1.max_cll = p_hdr_cll->max_content_light_level;
|
||||
pinfo_frame->hdmi_metadata_type1.max_fall =
|
||||
p_hdr_cll->max_frame_average_light_level;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
pinfo_frame->hdmi_metadata_type1.display_primaries[i].x =
|
||||
p_hdr_minfo->display_primaries[i].x;
|
||||
pinfo_frame->hdmi_metadata_type1.display_primaries[i].y =
|
||||
p_hdr_minfo->display_primaries[i].y;
|
||||
}
|
||||
|
||||
pinfo_frame->hdmi_metadata_type1.white_point.x = p_hdr_minfo->white_point.x;
|
||||
pinfo_frame->hdmi_metadata_type1.white_point.y = p_hdr_minfo->white_point.y;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
|
||||
{
|
||||
struct hdr_output_metadata info_frame;
|
||||
drmModeObjectPropertiesPtr props;
|
||||
uint32_t hdrBlobID;
|
||||
int drm_fd = self->fd;
|
||||
uint32_t conn_id = self->conn_id;
|
||||
int ret = 0;
|
||||
|
||||
if (self->no_infoframe || !self->has_hdr_info || (!clear_it_out
|
||||
&& self->has_sent_hdrif)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check to see if the connection has the HDR_OUTPUT_METADATA property if
|
||||
* we haven't already found it */
|
||||
if (self->hdrPropID == 0 || self->edidPropID == 0) {
|
||||
props =
|
||||
drmModeObjectGetProperties (drm_fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
|
||||
|
||||
if (!props) {
|
||||
GST_ERROR_OBJECT (self, "Error on drmModeObjectGetProperties %d %s",
|
||||
errno, g_strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
struct gst_kms_hdr_static_metadata hdr_edid_info = { 0, 0, 0, 0, 0 };
|
||||
for (uint32_t i = 0;
|
||||
i < props->count_props && (self->hdrPropID == 0
|
||||
|| self->edidPropID == 0); i++) {
|
||||
drmModePropertyPtr pprop = drmModeGetProperty (drm_fd, props->props[i]);
|
||||
|
||||
if (pprop) {
|
||||
/* 7 16 DRM_MODE_PROP_BLOB HDR_OUTPUT_METADATA */
|
||||
if (!strncmp ("HDR_OUTPUT_METADATA", pprop->name,
|
||||
strlen ("HDR_OUTPUT_METADATA"))) {
|
||||
self->hdrPropID = pprop->prop_id;
|
||||
GST_DEBUG_OBJECT (self, "HDR prop ID = %d", self->hdrPropID);
|
||||
}
|
||||
|
||||
if (!strncmp ("EDID", pprop->name, strlen ("EDID"))) {
|
||||
self->edidPropID = pprop->prop_id;
|
||||
|
||||
/* Check if EDID indicates device supports HDR */
|
||||
drmModePropertyBlobPtr blob;
|
||||
blob = drmModeGetPropertyBlob (drm_fd, props->prop_values[i]);
|
||||
if (blob) {
|
||||
int res =
|
||||
gst_kms_edid_parse (&hdr_edid_info, blob->data, blob->length);
|
||||
if (res != 0) {
|
||||
hdr_edid_info.eotf = 0;
|
||||
hdr_edid_info.metadata_type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreePropertyBlob (blob);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "EDID prop ID = %d", self->edidPropID);
|
||||
/* only these two values are guaranteed to be populated for HDR */
|
||||
GST_DEBUG_OBJECT (self, "EDID EOTF = %u, metadata type = %u",
|
||||
hdr_edid_info.eotf, hdr_edid_info.metadata_type);
|
||||
}
|
||||
|
||||
drmModeFreeProperty (pprop);
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Error on drmModeGetProperty(%d)", i);
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreeObjectProperties (props);
|
||||
|
||||
if (self->hdrPropID == 0 || self->edidPropID == 0
|
||||
|| hdr_edid_info.eotf == 0) {
|
||||
GST_DEBUG_OBJECT (self, "No HDR support on target display");
|
||||
self->no_infoframe = TRUE;
|
||||
/* FIXME: maybe not the right flag here... */
|
||||
self->has_sent_hdrif = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (clear_it_out)
|
||||
GST_INFO ("Clearing HDR Infoframe on connector %d", self->conn_id);
|
||||
else
|
||||
GST_INFO ("Setting HDR Infoframe, if available on connector %d",
|
||||
self->conn_id);
|
||||
|
||||
gst_kms_populate_infoframe (&info_frame, &self->hdr_minfo, &self->hdr_cll,
|
||||
self->colorimetry, clear_it_out);
|
||||
|
||||
/* Use non-atomic property setting */
|
||||
ret = drmModeCreatePropertyBlob (drm_fd, &info_frame,
|
||||
sizeof (struct hdr_output_metadata), &hdrBlobID);
|
||||
if (!ret) {
|
||||
ret =
|
||||
drmModeObjectSetProperty (drm_fd, conn_id, DRM_MODE_OBJECT_CONNECTOR,
|
||||
self->hdrPropID, hdrBlobID);
|
||||
if (ret) {
|
||||
GST_ERROR_OBJECT (self, "drmModeObjectSetProperty result %d %d %s", ret,
|
||||
errno, g_strerror (errno));
|
||||
}
|
||||
drmModeDestroyPropertyBlob (drm_fd, hdrBlobID);
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Failed to drmModeCreatePropertyBlob %d %s", errno,
|
||||
g_strerror (errno));
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
GST_INFO ("Set HDR Infoframe on connector %d", conn_id);
|
||||
self->has_sent_hdrif = TRUE; // Hooray!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* From an HDR10 stream caps:
|
||||
*
|
||||
* colorimetry=(string)bt2100-pq
|
||||
* content-light-level=(string)10000:166
|
||||
* mastering-display-info=(string)35400:14600:8500:39850:6550:2300:15635:16450:10000000:1
|
||||
*/
|
||||
static void
|
||||
gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
|
||||
{
|
||||
GstVideoMasteringDisplayInfo hdr_minfo;
|
||||
GstVideoContentLightLevel hdr_cll;
|
||||
GstStructure *structure;
|
||||
const gchar *colorimetry_s;
|
||||
GstVideoColorimetry colorimetry;
|
||||
gboolean has_hdr_eotf = FALSE;
|
||||
gboolean has_cll = FALSE;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
if ((colorimetry_s = gst_structure_get_string (structure,
|
||||
"colorimetry")) != NULL &&
|
||||
gst_video_colorimetry_from_string (&colorimetry, colorimetry_s)) {
|
||||
switch (colorimetry.transfer) {
|
||||
case GST_VIDEO_TRANSFER_SMPTE2084:
|
||||
self->colorimetry = HDMI_EOTF_SMPTE_ST2084;
|
||||
has_hdr_eotf = TRUE;
|
||||
GST_DEBUG ("Got HDR transfer value GST_VIDEO_TRANSFER_SMPTE2084: %u",
|
||||
self->colorimetry);
|
||||
break;
|
||||
case GST_VIDEO_TRANSFER_BT2020_10:
|
||||
case GST_VIDEO_TRANSFER_ARIB_STD_B67:
|
||||
self->colorimetry = HDMI_EOTF_BT_2100_HLG;
|
||||
has_hdr_eotf = TRUE;
|
||||
GST_DEBUG ("Got HDR transfer value HDMI_EOTF_BT_2100_HLG: %u",
|
||||
self->colorimetry);
|
||||
break;
|
||||
case GST_VIDEO_TRANSFER_BT709:
|
||||
self->colorimetry = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
|
||||
GST_DEBUG ("Got HDR transfer value GST_VIDEO_TRANSFER_BT709, "
|
||||
"not HDR: %u", self->colorimetry);
|
||||
break;
|
||||
default:
|
||||
/* not an HDMI and/or HDR colorimetry, we will ignore */
|
||||
GST_DEBUG ("Unsupported transfer function, no HDR: %u",
|
||||
colorimetry.transfer);
|
||||
self->no_infoframe = TRUE;
|
||||
self->has_hdr_info = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gst_video_mastering_display_info_from_caps (&hdr_minfo, caps)) {
|
||||
if (!gst_video_mastering_display_info_is_equal (&hdr_minfo,
|
||||
&self->hdr_minfo)) {
|
||||
self->hdr_minfo = hdr_minfo;
|
||||
self->no_infoframe = FALSE;
|
||||
self->has_hdr_info = TRUE;
|
||||
/* to send again */
|
||||
self->has_sent_hdrif = FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG ("Got mastering info: "
|
||||
"min %u max %u wp %u %u dp[0] %u %u dp[1] %u %u dp[2] %u %u",
|
||||
self->hdr_minfo.min_display_mastering_luminance,
|
||||
self->hdr_minfo.max_display_mastering_luminance,
|
||||
self->hdr_minfo.white_point.x, self->hdr_minfo.white_point.y,
|
||||
self->hdr_minfo.display_primaries[0].x,
|
||||
self->hdr_minfo.display_primaries[0].y,
|
||||
self->hdr_minfo.display_primaries[1].x,
|
||||
self->hdr_minfo.display_primaries[1].y,
|
||||
self->hdr_minfo.display_primaries[2].x,
|
||||
self->hdr_minfo.display_primaries[2].y);
|
||||
|
||||
} else {
|
||||
if (self->has_hdr_info == TRUE) {
|
||||
GST_WARNING ("Missing mastering display info");
|
||||
} else {
|
||||
self->no_infoframe = TRUE;
|
||||
self->has_hdr_info = FALSE;
|
||||
}
|
||||
|
||||
gst_video_mastering_display_info_init (&self->hdr_minfo);
|
||||
}
|
||||
|
||||
if (gst_video_content_light_level_from_caps (&hdr_cll, caps)) {
|
||||
GST_DEBUG ("Got content light level information: Max CLL: %u Max FALL: %u",
|
||||
hdr_cll.max_content_light_level, hdr_cll.max_frame_average_light_level);
|
||||
|
||||
if (!gst_video_content_light_level_is_equal (&hdr_cll, &self->hdr_cll)) {
|
||||
self->hdr_cll = hdr_cll;
|
||||
self->no_infoframe = FALSE;
|
||||
self->has_hdr_info = TRUE;
|
||||
/* to send again */
|
||||
self->has_sent_hdrif = FALSE;
|
||||
}
|
||||
|
||||
has_cll = TRUE;
|
||||
} else {
|
||||
gst_video_content_light_level_init (&self->hdr_cll);
|
||||
|
||||
if (self->has_hdr_info == TRUE) {
|
||||
GST_WARNING ("Missing content light level info");
|
||||
}
|
||||
|
||||
self->no_infoframe = TRUE;
|
||||
self->has_hdr_info = FALSE;
|
||||
}
|
||||
|
||||
/* need all caps set */
|
||||
if ((has_hdr_eotf || has_cll) && !(has_hdr_eotf && has_cll)) {
|
||||
GST_ELEMENT_WARNING (self, STREAM, FORMAT,
|
||||
("Stream doesn't have all HDR components needed"),
|
||||
("Check stream caps"));
|
||||
|
||||
self->no_infoframe = TRUE;
|
||||
self->has_hdr_info = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_DRM_HDR */
|
||||
|
||||
static void
|
||||
gst_kms_sink_set_render_rectangle (GstVideoOverlay * overlay,
|
||||
gint x, gint y, gint width, gint height)
|
||||
|
@ -1148,6 +1451,10 @@ gst_kms_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
if (GST_VIDEO_SINK_WIDTH (self) <= 0 || GST_VIDEO_SINK_HEIGHT (self) <= 0)
|
||||
goto invalid_size;
|
||||
|
||||
#ifdef HAVE_DRM_HDR
|
||||
gst_kms_sink_set_hdr10_caps (self, caps);
|
||||
#endif
|
||||
|
||||
/* discard dumb buffer pool */
|
||||
if (self->pool) {
|
||||
gst_buffer_pool_set_active (self->pool, FALSE);
|
||||
|
@ -1665,6 +1972,10 @@ retry_set_plane:
|
|||
src.w = result.w;
|
||||
src.h = result.h;
|
||||
}
|
||||
#ifdef HAVE_DRM_HDR
|
||||
/* Send the HDR infoframes if appropriate */
|
||||
gst_kms_push_hdr_infoframe (self, FALSE);
|
||||
#endif
|
||||
|
||||
GST_TRACE_OBJECT (self,
|
||||
"drmModeSetPlane at (%i,%i) %ix%i sourcing at (%i,%i) %ix%i",
|
||||
|
@ -1981,6 +2292,17 @@ gst_kms_sink_init (GstKMSSink * sink)
|
|||
sink->poll = gst_poll_new (TRUE);
|
||||
gst_video_info_init (&sink->vinfo);
|
||||
sink->skip_vsync = FALSE;
|
||||
|
||||
#ifdef HAVE_DRM_HDR
|
||||
sink->no_infoframe = FALSE;
|
||||
sink->has_hdr_info = FALSE;
|
||||
sink->has_sent_hdrif = FALSE;
|
||||
sink->edidPropID = 0;
|
||||
sink->hdrPropID = 0;
|
||||
sink->colorimetry = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
|
||||
gst_video_mastering_display_info_init (&sink->hdr_minfo);
|
||||
gst_video_content_light_level_init (&sink->hdr_cll);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define __GST_KMS_SINK_H__
|
||||
|
||||
#include <gst/video/gstvideosink.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <gst/video/video-hdr.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -96,6 +98,18 @@ struct _GstKMSSink {
|
|||
|
||||
gboolean is_internal_fd;
|
||||
gboolean skip_vsync;
|
||||
|
||||
#ifdef HAVE_DRM_HDR
|
||||
/* HDR mastering related structure */
|
||||
gboolean no_infoframe;
|
||||
gboolean has_hdr_info;
|
||||
gboolean has_sent_hdrif;
|
||||
guint32 edidPropID;
|
||||
guint32 hdrPropID;
|
||||
gchar colorimetry;
|
||||
GstVideoMasteringDisplayInfo hdr_minfo;
|
||||
GstVideoContentLightLevel hdr_cll;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GstKMSSinkClass {
|
||||
|
|
|
@ -4,6 +4,7 @@ kmssink_sources = [
|
|||
'gstkmssink.c',
|
||||
'gstkmsutils.c',
|
||||
]
|
||||
extra_deps = []
|
||||
|
||||
if host_system != 'linux'
|
||||
subdir_done()
|
||||
|
@ -12,12 +13,22 @@ endif
|
|||
libdrm_dep = dependency('libdrm', version : '>= 2.4.98',
|
||||
required : get_option('kms'),
|
||||
fallback: ['libdrm', 'ext_libdrm'])
|
||||
libdrm_hdr_dep = dependency('libdrm', version : '>= 2.4.104',
|
||||
required : false,
|
||||
fallback: ['libdrm', 'ext_libdrm'])
|
||||
mathlib = cc.find_library('m', required : false)
|
||||
|
||||
if libdrm_hdr_dep.found() and mathlib.found()
|
||||
cdata.set('HAVE_DRM_HDR', 1)
|
||||
kmssink_sources += 'gstkmsedid.c'
|
||||
endif
|
||||
|
||||
if libdrm_dep.found()
|
||||
gstkmssink = library('gstkms',
|
||||
kmssink_sources,
|
||||
c_args : gst_plugins_bad_args,
|
||||
include_directories : [configinc],
|
||||
dependencies : [gstbase_dep, gstvideo_dep, gstallocators_dep, libdrm_dep],
|
||||
dependencies : [gstbase_dep, gstvideo_dep, gstallocators_dep, libdrm_dep, mathlib],
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue