kmssink: add 'connector-properties' prop

Can be used to pass custom connector properties to DRM. Properties can
be enumerated using modetest tool. These properties can then be applied
with the following gst-launch-1.0 syntax. Note that the name of the
structure is ignored.

  ... ! kmssink connector-properties="s,props1=value,props2=value"

https://bugzilla.gnome.org/show_bug.cgi?id=797027
This commit is contained in:
Guillaume Desmottes 2018-08-23 14:29:37 +02:00 committed by Nicolas Dufresne
parent 4af7637012
commit 71ab97cba6
2 changed files with 114 additions and 0 deletions

View file

@ -88,6 +88,7 @@ enum
PROP_CAN_SCALE,
PROP_DISPLAY_WIDTH,
PROP_DISPLAY_HEIGHT,
PROP_CONNECTOR_PROPS,
PROP_N
};
@ -559,6 +560,89 @@ ensure_allowed_caps (GstKMSSink * self, drmModeConnector * conn,
return (self->allowed_caps && !gst_caps_is_empty (self->allowed_caps));
}
static gboolean
set_drm_property (gint fd, guint32 object, guint32 object_type,
drmModeObjectPropertiesPtr properties, const gchar * prop_name,
guint64 value)
{
guint i;
gboolean ret = FALSE;
for (i = 0; i < properties->count_props && !ret; i++) {
drmModePropertyPtr property;
property = drmModeGetProperty (fd, properties->props[i]);
if (!strcmp (property->name, prop_name)) {
drmModeObjectSetProperty (fd, object, object_type,
property->prop_id, value);
ret = TRUE;
}
drmModeFreeProperty (property);
}
return ret;
}
typedef struct
{
GstKMSSink *self;
drmModeObjectPropertiesPtr properties;
} SetPropsIter;
static gboolean
set_connector_prop (GQuark field_id, const GValue * value, gpointer user_data)
{
SetPropsIter *iter = user_data;
GstKMSSink *self = iter->self;
const gchar *name;
guint64 v;
name = g_quark_to_string (field_id);
if (G_VALUE_HOLDS (value, G_TYPE_INT))
v = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
v = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64))
v = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64))
v = g_value_get_uint64 (value);
else {
GST_WARNING_OBJECT (self,
"'uint64' value expected for control '%s'.", name);
return TRUE;
}
if (set_drm_property (self->fd, self->conn_id, DRM_MODE_OBJECT_CONNECTOR,
iter->properties, name, v)) {
GST_DEBUG_OBJECT (self,
"Set connector property '%s' to %" G_GUINT64_FORMAT, name, v);
} else {
GST_WARNING_OBJECT (self,
"Failed to set connector property '%s' to %" G_GUINT64_FORMAT, name, v);
}
return TRUE;
}
static void
gst_kms_sink_update_connector_properties (GstKMSSink * self)
{
SetPropsIter iter;
if (!self->connector_props)
return;
iter.self = self;
iter.properties =
drmModeObjectGetProperties (self->fd, self->conn_id,
DRM_MODE_OBJECT_CONNECTOR);
gst_structure_foreach (self->connector_props, set_connector_prop, &iter);
drmModeFreeObjectProperties (iter.properties);
}
static gboolean
gst_kms_sink_start (GstBaseSink * bsink)
{
@ -667,6 +751,8 @@ retry_find_plane:
g_object_notify_by_pspec (G_OBJECT (self), g_properties[PROP_DISPLAY_WIDTH]);
g_object_notify_by_pspec (G_OBJECT (self), g_properties[PROP_DISPLAY_HEIGHT]);
gst_kms_sink_update_connector_properties (self);
ret = TRUE;
bail:
@ -1595,6 +1681,16 @@ gst_kms_sink_set_property (GObject * object, guint prop_id,
case PROP_CAN_SCALE:
sink->can_scale = g_value_get_boolean (value);
break;
case PROP_CONNECTOR_PROPS:{
const GstStructure *s = gst_value_get_structure (value);
g_clear_pointer (&sink->connector_props, gst_structure_free);
if (s)
sink->connector_props = gst_structure_copy (s);
break;
}
default:
if (!gst_video_overlay_set_property (object, PROP_N, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -1639,6 +1735,9 @@ gst_kms_sink_get_property (GObject * object, guint prop_id,
g_value_set_int (value, sink->vdisplay);
GST_OBJECT_UNLOCK (sink);
break;
case PROP_CONNECTOR_PROPS:
gst_value_set_structure (value, sink->connector_props);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1654,6 +1753,7 @@ gst_kms_sink_finalize (GObject * object)
g_clear_pointer (&sink->devname, g_free);
g_clear_pointer (&sink->bus_id, g_free);
gst_poll_free (sink->poll);
g_clear_pointer (&sink->connector_props, gst_structure_free);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -1795,6 +1895,19 @@ gst_kms_sink_class_init (GstKMSSinkClass * klass)
"Height of the display surface in pixels", 0, G_MAXINT, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* kmssink:connector-properties:
*
* Additional properties for the connector. Keys are strings and values
* unsigned 64 bits integers.
*
* Since: 1.16
*/
g_properties[PROP_CONNECTOR_PROPS] =
g_param_spec_boxed ("connector-properties", "Connector Properties",
"Additionnal properties for the connector",
GST_TYPE_STRUCTURE, 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);

View file

@ -65,6 +65,7 @@ struct _GstKMSSink {
gboolean can_scale;
gboolean modesetting_enabled;
GstStructure *connector_props;
GstVideoInfo vinfo;
GstCaps *allowed_caps;