kmssink: add fd property
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Wed, 6 Jul 2022 13:08:17 +0000 (09:08 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 18 Aug 2022 18:31:59 +0000 (18:31 +0000)
This allows an application to provide their own opened DRM device
fd handle to kmssink.  For example, an application can lease
multiple fd's from a DRM master to display on different CRTC
outputs at the same time with multiple kmssink instances.

Specifying the fd property is not allowed when driver-name
and/or bus-id properties are specified.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2807>

subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json
subprojects/gst-plugins-bad/sys/kms/gstkmssink.c
subprojects/gst-plugins-bad/sys/kms/gstkmssink.h

index d10018b..10a5c65 100644 (file)
                         "type": "gchararray",
                         "writable": true
                     },
+                    "fd": {
+                        "blurb": "DRM file descriptor",
+                        "conditionally-available": false,
+                        "construct": true,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "-1",
+                        "max": "2147483647",
+                        "min": "-1",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gint",
+                        "writable": true
+                    },
                     "force-modesetting": {
                         "blurb": "When enabled, the sink try to configure the display mode",
                         "conditionally-available": false,
index 788cefc..cba6a36 100644 (file)
@@ -97,6 +97,7 @@ enum
   PROP_DISPLAY_HEIGHT,
   PROP_CONNECTOR_PROPS,
   PROP_PLANE_PROPS,
+  PROP_FD,
   PROP_N,
 };
 
@@ -729,10 +730,14 @@ gst_kms_sink_start (GstBaseSink * bsink)
   pres = NULL;
   plane = NULL;
 
-  if (self->devname || self->bus_id)
-    self->fd = drmOpen (self->devname, self->bus_id);
-  else
-    self->fd = kms_open (&self->devname);
+  /* open our own internal device fd if application did not supply its own */
+  if (self->is_internal_fd) {
+    if (self->devname || self->bus_id)
+      self->fd = drmOpen (self->devname, self->bus_id);
+    else
+      self->fd = kms_open (&self->devname);
+  }
+
   if (self->fd < 0)
     goto open_failed;
 
@@ -838,7 +843,8 @@ bail:
     drmModeFreeResources (res);
 
   if (!ret && self->fd >= 0) {
-    drmClose (self->fd);
+    if (self->is_internal_fd)
+      drmClose (self->fd);
     self->fd = -1;
   }
 
@@ -945,7 +951,8 @@ gst_kms_sink_stop (GstBaseSink * bsink)
   }
 
   if (self->fd >= 0) {
-    drmClose (self->fd);
+    if (self->is_internal_fd)
+      drmClose (self->fd);
     self->fd = -1;
   }
 
@@ -1776,6 +1783,51 @@ gst_kms_sink_query (GstBaseSink * bsink, GstQuery * query)
 }
 
 static void
+_validate_and_set_external_fd (GstKMSSink * self, gint fd)
+{
+  if (self->devname) {
+    GST_WARNING_OBJECT (self, "Can't set fd... %s already set.",
+        g_param_spec_get_name (g_properties[PROP_DRIVER_NAME]));
+    return;
+  }
+
+  if (self->bus_id) {
+    GST_WARNING_OBJECT (self, "Can't set fd... %s already set.",
+        g_param_spec_get_name (g_properties[PROP_BUS_ID]));
+    return;
+  }
+
+  if (self->fd >= 0) {
+    GST_WARNING_OBJECT (self, "Can't set fd... it is already set.");
+    return;
+  }
+
+  if (fd >= 0) {
+    self->devname = drmGetDeviceNameFromFd (fd);
+    if (!self->devname) {
+      GST_WARNING_OBJECT (self, "Failed to verify fd is a DRM fd.");
+      return;
+    }
+
+    self->fd = fd;
+    self->is_internal_fd = FALSE;
+  }
+}
+
+static void
+_invalidate_external_fd (GstKMSSink * self, GParamSpec * pspec)
+{
+  if (self->is_internal_fd)
+    return;
+
+  GST_WARNING_OBJECT (self, "Unsetting fd... %s has priority.",
+      g_param_spec_get_name (pspec));
+
+  self->fd = -1;
+  self->is_internal_fd = TRUE;
+}
+
+static void
 gst_kms_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
@@ -1785,10 +1837,12 @@ gst_kms_sink_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case PROP_DRIVER_NAME:
+      _invalidate_external_fd (sink, pspec);
       g_free (sink->devname);
       sink->devname = g_value_dup_string (value);
       break;
     case PROP_BUS_ID:
+      _invalidate_external_fd (sink, pspec);
       g_free (sink->bus_id);
       sink->bus_id = g_value_dup_string (value);
       break;
@@ -1827,6 +1881,9 @@ gst_kms_sink_set_property (GObject * object, guint prop_id,
 
       break;
     }
+    case PROP_FD:
+      _validate_and_set_external_fd (sink, g_value_get_int (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);
@@ -1880,6 +1937,9 @@ gst_kms_sink_get_property (GObject * object, guint prop_id,
     case PROP_PLANE_PROPS:
       gst_value_set_structure (value, sink->plane_props);
       break;
+    case PROP_FD:
+      g_value_set_int (value, sink->fd);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1906,6 +1966,7 @@ static void
 gst_kms_sink_init (GstKMSSink * sink)
 {
   sink->fd = -1;
+  sink->is_internal_fd = TRUE;
   sink->conn_id = -1;
   sink->plane_id = -1;
   sink->can_scale = TRUE;
@@ -2078,6 +2139,19 @@ gst_kms_sink_class_init (GstKMSSinkClass * klass)
       "Additional properties for the plane",
       GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * kmssink:fd:
+   *
+   * You can supply your own DRM file descriptor.  By default, the sink will
+   * open its own DRM file descriptor.
+   *
+   * Since: 1.22
+   */
+  g_properties[PROP_FD] =
+      g_param_spec_int ("fd", "File Descriptor",
+      "DRM file descriptor", -1, G_MAXINT, -1,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
+
   g_object_class_install_properties (gobject_class, PROP_N, g_properties);
 
   gst_video_overlay_install_properties (gobject_class, PROP_N);
index 428c057..536b0a7 100644 (file)
@@ -93,6 +93,8 @@ struct _GstKMSSink {
   /* reconfigure info if driver doesn't scale */
   GstVideoRectangle pending_rect;
   gboolean reconfigure;
+
+  gboolean is_internal_fd;
 };
 
 struct _GstKMSSinkClass {