linuxOS_AP06/buildroot/package/gstreamer1/gst1-plugins-bad/0041-kmssink-Support-HDR.patch
2025-06-03 12:28:32 +08:00

407 lines
14 KiB
Diff

From d8bced54dda87c7d6f390719c3ce1c2a6ea06f22 Mon Sep 17 00:00:00 2001
From: Jiajian Wu <jair.wu@rock-chips.com>
Date: Mon, 3 Jul 2023 15:26:53 +0800
Subject: [PATCH 41/48] kmssink: Support HDR
Signed-off-by: Jiajian Wu <jair.wu@rock-chips.com>
---
sys/kms/gstkmssink.c | 206 +++++++++++++++++++++++++++++++++++++++----
sys/kms/gstkmssink.h | 7 ++
2 files changed, 195 insertions(+), 18 deletions(-)
diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
index 5b2ae38..4883c3e 100644
--- a/sys/kms/gstkmssink.c
+++ b/sys/kms/gstkmssink.c
@@ -57,6 +57,7 @@
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include <string.h>
+#include <linux/videodev2.h>
#include "gstkmssink.h"
#include "gstkmsutils.h"
@@ -109,6 +110,8 @@ enum
PROP_FORCE_ASPECT_RATIO,
PROP_SYNC_MODE,
PROP_FULLSCREEN,
+ PROP_HDR_EN,
+ PROP_REQUIRED_CLL,
PROP_N,
};
@@ -128,6 +131,13 @@ enum hdmi_eotf
HDMI_EOTF_SMPTE_ST2084,
HDMI_EOTF_BT_2100_HLG,
};
+/* define in include/uapi/drm/rockchip_drm.h */
+enum rockchip_crtc_feture
+{
+ ROCKCHIP_DRM_CRTC_FEATURE_ALPHA_SCALE,
+ ROCKCHIP_DRM_CRTC_FEATURE_HDR10,
+ ROCKCHIP_DRM_CRTC_FEATURE_NEXT_HDR,
+};
static void
gst_kms_populate_infoframe (struct hdr_output_metadata *pinfo_frame,
@@ -178,11 +188,104 @@ gst_kms_populate_infoframe (struct hdr_output_metadata *pinfo_frame,
pinfo_frame->hdmi_metadata_type1.white_point.y = p_hdr_minfo->white_point.y;
}
+static void
+gst_kms_add_plane_properties (GstKMSSink * self, drmModeAtomicReq *req, gboolean clear_it_out)
+{
+ drmModeObjectPropertiesPtr props = NULL;
+ int zpos_idx = -1;
+ int eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
+ int colorspace = V4L2_COLORSPACE_DEFAULT;
+ int ret;
+
+ props =
+ drmModeObjectGetProperties (self->fd, self->plane_id, DRM_MODE_OBJECT_PLANE);
+ if (!props)
+ return;
+
+ for (int i = 0;
+ i < props->count_props && (self->eotfPropID == 0
+ || self->colorSpacePropID == 0
+ || self->zposPropID == 0); i++) {
+ drmModePropertyPtr pprop = drmModeGetProperty (self->fd, props->props[i]);
+
+ if (pprop) {
+ if(!strncmp ("EOTF", pprop->name, strlen ("EOTF"))) {
+ self->eotfPropID = pprop->prop_id;
+ } else if(!strncmp ("COLOR_SPACE", pprop->name, strlen ("COLOR_SPACE"))) {
+ self->colorSpacePropID = pprop->prop_id;
+ } else if(!strncmp ("zpos", pprop->name, strlen ("zpos"))
+ || !strncmp ("ZPOS", pprop->name, strlen ("ZPOS"))) {
+ self->zposPropID = pprop->prop_id;
+ zpos_idx = i;
+ }
+ }
+ drmModeFreeProperty (pprop);
+ }
+
+ if (self->eotfPropID == 0 || self->colorSpacePropID == 0
+ || self->zposPropID == 0) {
+ GST_ERROR_OBJECT (self, "cannot find eotf | colorspace | zpos");
+ goto out;
+ }
+
+ eotf = self->colorimetry;
+ colorspace = self->colorspace;
+
+ drmModeAtomicAddProperty(req, self->plane_id, self->eotfPropID,
+ clear_it_out ? HDMI_EOTF_TRADITIONAL_GAMMA_SDR : eotf);
+ drmModeAtomicAddProperty(req, self->plane_id, self->colorSpacePropID,
+ clear_it_out ? V4L2_COLORSPACE_DEFAULT : colorspace);
+
+ if (clear_it_out) {
+ if (self->saved_zpos >= 0)
+ drmModeAtomicAddProperty(req, self->plane_id, self->zposPropID,
+ self->saved_zpos);
+ } else {
+ if (self->saved_zpos < 0)
+ self->saved_zpos = props->prop_values[zpos_idx];
+ drmModeAtomicAddProperty(req, self->plane_id, self->zposPropID, 0);
+ }
+
+out:
+ drmModeFreeObjectProperties (props);
+}
+
+static int
+gst_kms_check_crtc_hdr_support (GstKMSSink * self)
+{
+ drmModeObjectPropertiesPtr props = NULL;
+ drmModePropertyPtr prop = NULL;
+ uint32_t val = 0;
+
+ props = drmModeObjectGetProperties (self->fd, self->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
+ if (!props)
+ return FALSE;
+
+ for (int i = 0; i < props->count_props; i++) {
+ prop = drmModeGetProperty (self->fd, props->props[i]);
+ if (prop) {
+ if (!strcmp (prop->name, "FEATURE")) {
+ val = props->prop_values[i];
+ break;
+ }
+ }
+ drmModeFreeProperty (prop);
+ prop = NULL;
+ }
+
+ drmModeFreeProperty (prop);
+ drmModeFreeObjectProperties (props);
+
+ return (val & (1 << ROCKCHIP_DRM_CRTC_FEATURE_HDR10));
+}
+
static void
gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
{
struct hdr_output_metadata info_frame;
drmModeObjectPropertiesPtr props;
+ drmModeAtomicReq *req;
uint32_t hdrBlobID;
int drm_fd = self->fd;
uint32_t conn_id = self->conn_id;
@@ -193,9 +296,19 @@ gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
return;
}
+ if (gst_kms_check_crtc_hdr_support (self) == FALSE) {
+ GST_WARNING_OBJECT (self, "No HDR support on CRTC %d", self->crtc_id);
+ self->has_sent_hdrif = TRUE;
+ return;
+ }
+
+ if (drmSetClientCap (drm_fd, DRM_CLIENT_CAP_ATOMIC, 1))
+ 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) {
+ if (self->hdrPropID == 0 || self->edidPropID == 0
+ || self->connColorSpacePropID == 0) {
props =
drmModeObjectGetProperties (drm_fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -208,7 +321,7 @@ gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
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++) {
+ || self->edidPropID == 0 || self->connColorSpacePropID == 0); i++) {
drmModePropertyPtr pprop = drmModeGetProperty (drm_fd, props->props[i]);
if (pprop) {
@@ -219,6 +332,12 @@ gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
GST_DEBUG_OBJECT (self, "HDR prop ID = %d", self->hdrPropID);
}
+ if (!strncmp ("Colorspace", pprop->name,
+ strlen ("Colorspace"))) {
+ self->connColorSpacePropID = pprop->prop_id;
+ GST_DEBUG_OBJECT (self, "Colorspace prop ID = %d", self->connColorSpacePropID);
+ }
+
if (!strncmp ("EDID", pprop->name, strlen ("EDID"))) {
self->edidPropID = pprop->prop_id;
@@ -251,6 +370,7 @@ gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
drmModeFreeObjectProperties (props);
if (self->hdrPropID == 0 || self->edidPropID == 0
+ || self->connColorSpacePropID == 0
|| hdr_edid_info.eotf == 0) {
GST_DEBUG_OBJECT (self, "No HDR support on target display");
self->no_infoframe = TRUE;
@@ -269,23 +389,33 @@ gst_kms_push_hdr_infoframe (GstKMSSink * self, gboolean clear_it_out)
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 {
+ if (ret) {
GST_ERROR_OBJECT (self, "Failed to drmModeCreatePropertyBlob %d %s", errno,
g_strerror (errno));
+ goto err_out;
}
+ req = drmModeAtomicAlloc();
+ if (!req) {
+ GST_ERROR_OBJECT (self, "drmModeAtomicAlloc failed");
+ drmModeDestroyPropertyBlob (drm_fd, hdrBlobID);
+ goto err_out;
+ }
+
+ drmModeAtomicAddProperty(req, conn_id, self->connColorSpacePropID,
+ clear_it_out ? 0 : self->colorspace);
+ drmModeAtomicAddProperty(req, conn_id, self->hdrPropID, hdrBlobID);
+ gst_kms_add_plane_properties(self, req, clear_it_out);
+ ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+ if (ret)
+ GST_WARNING_OBJECT (self, "drmModeAtomicCommit failed %d", ret);
+ drmModeAtomicFree(req);
+
+ drmModeDestroyPropertyBlob (drm_fd, hdrBlobID);
+
+err_out:
if (!ret) {
GST_INFO ("Set HDR Infoframe on connector %d", conn_id);
self->has_sent_hdrif = TRUE; // Hooray!
@@ -317,6 +447,7 @@ gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
switch (colorimetry.transfer) {
case GST_VIDEO_TRANSFER_SMPTE2084:
self->colorimetry = HDMI_EOTF_SMPTE_ST2084;
+ self->colorspace = V4L2_COLORSPACE_BT2020;
has_hdr_eotf = TRUE;
GST_DEBUG ("Got HDR transfer value GST_VIDEO_TRANSFER_SMPTE2084: %u",
self->colorimetry);
@@ -324,12 +455,14 @@ gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
case GST_VIDEO_TRANSFER_BT2020_10:
case GST_VIDEO_TRANSFER_ARIB_STD_B67:
self->colorimetry = HDMI_EOTF_BT_2100_HLG;
+ self->colorspace = V4L2_COLORSPACE_BT2020;
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;
+ self->colorspace = V4L2_COLORSPACE_DEFAULT;
GST_DEBUG ("Got HDR transfer value GST_VIDEO_TRANSFER_BT709, "
"not HDR: %u", self->colorimetry);
break;
@@ -337,6 +470,7 @@ gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
/* not an HDMI and/or HDR colorimetry, we will ignore */
GST_DEBUG ("Unsupported transfer function, no HDR: %u",
colorimetry.transfer);
+ self->colorspace = V4L2_COLORSPACE_DEFAULT;
self->no_infoframe = TRUE;
self->has_hdr_info = FALSE;
break;
@@ -396,8 +530,10 @@ gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
GST_WARNING ("Missing content light level info");
}
- self->no_infoframe = TRUE;
- self->has_hdr_info = FALSE;
+ if (self->required_cll) {
+ self->no_infoframe = TRUE;
+ self->has_hdr_info = FALSE;
+ }
}
/* need all caps set */
@@ -405,9 +541,10 @@ gst_kms_sink_set_hdr10_caps (GstKMSSink * self, GstCaps * caps)
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;
+ if (has_hdr_eotf && !has_cll && self->required_cll) {
+ self->no_infoframe = TRUE;
+ self->has_hdr_info = FALSE;
+ }
}
}
@@ -1533,6 +1670,10 @@ gst_kms_sink_stop (GstBaseSink * bsink)
self->saved_zpos = -1;
}
+#ifdef HAVE_DRM_HDR
+ /* Clear the HDR infoframes */
+ gst_kms_push_hdr_infoframe (self, TRUE);
+#endif
gst_buffer_replace (&self->last_buffer, NULL);
gst_caps_replace (&self->allowed_caps, NULL);
gst_object_replace ((GstObject **) & self->pool, NULL);
@@ -2600,6 +2741,12 @@ gst_kms_sink_set_property (GObject * object, guint prop_id,
case PROP_FULLSCREEN:
sink->fullscreen = g_value_get_boolean (value);
break;
+ case PROP_HDR_EN:
+ sink->hdr_en = g_value_get_boolean (value);
+ break;
+ case PROP_REQUIRED_CLL:
+ sink->required_cll = g_value_get_boolean (value);
+ break;
default:
if (!gst_video_overlay_set_property (object, PROP_N, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -2668,6 +2815,12 @@ gst_kms_sink_get_property (GObject * object, guint prop_id,
case PROP_FULLSCREEN:
g_value_set_boolean (value, sink->fullscreen);
break;
+ case PROP_HDR_EN:
+ g_value_set_boolean (value, sink->hdr_en);
+ break;
+ case PROP_REQUIRED_CLL:
+ g_value_set_boolean (value, sink->required_cll);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2710,12 +2863,19 @@ gst_kms_sink_init (GstKMSSink * sink)
sink->skip_vsync = TRUE;
#ifdef HAVE_DRM_HDR
+ sink->hdr_en = TRUE;
+ sink->required_cll = FALSE;
sink->no_infoframe = FALSE;
sink->has_hdr_info = FALSE;
sink->has_sent_hdrif = FALSE;
sink->edidPropID = 0;
sink->hdrPropID = 0;
+ sink->connColorSpacePropID = 0;
+ sink->eotfPropID = 0;
+ sink->colorSpacePropID = 0;
+ sink->zposPropID = 0;
sink->colorimetry = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
+ sink->colorspace = V4L2_COLORSPACE_DEFAULT;
gst_video_mastering_display_info_init (&sink->hdr_minfo);
gst_video_content_light_level_init (&sink->hdr_cll);
#endif
@@ -2947,6 +3107,16 @@ gst_kms_sink_class_init (GstKMSSinkClass * klass)
"Force showing fullscreen", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_properties[PROP_HDR_EN] =
+ g_param_spec_boolean ("hdr-enable", "HDR enable",
+ "Enable HDR", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_properties[PROP_REQUIRED_CLL] =
+ g_param_spec_boolean ("required-cll", "HDR cll is required",
+ "Content light level information is required", FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (gobject_class, PROP_N, g_properties);
gst_video_overlay_install_properties (gobject_class, PROP_N);
diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
index 5c4065a..80b5c3e 100644
--- a/sys/kms/gstkmssink.h
+++ b/sys/kms/gstkmssink.h
@@ -111,12 +111,19 @@ struct _GstKMSSink {
#ifdef HAVE_DRM_HDR
/* HDR mastering related structure */
+ gboolean hdr_en;
+ gboolean required_cll;
gboolean no_infoframe;
gboolean has_hdr_info;
gboolean has_sent_hdrif;
guint32 edidPropID;
guint32 hdrPropID;
+ guint32 connColorSpacePropID;
+ guint32 eotfPropID;
+ guint32 colorSpacePropID;
+ guint32 zposPropID;
gchar colorimetry;
+ gchar colorspace;
GstVideoMasteringDisplayInfo hdr_minfo;
GstVideoContentLightLevel hdr_cll;
#endif
--
2.20.1