git » pipewire.git » main » tree

[main] / 0002-gst-Sanitize-caps-before-translating.patch

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Sun, 25 Feb 2024 17:36:08 +0100
Subject: [PATCH] gst: Sanitize caps before translating

DMABuf caps without concrete formats and modifiers don't map well to the
Pipewire negotiation process.
Introduce a new gst_caps_sanitize() helper function, where such cases
can be handled.
---
 src/gst/gstpipewireformat.c | 40 +++++++++++++++++++++++++++++++++++++
 src/gst/gstpipewireformat.h |  2 ++
 src/gst/gstpipewiresrc.c    |  6 +++++-
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c
index ff1752a06565..6830de234a8d 100644
--- a/src/gst/gstpipewireformat.c
+++ b/src/gst/gstpipewireformat.c
@@ -1176,3 +1176,43 @@ gst_caps_from_format (const struct spa_pod *format)
   }
   return res;
 }
+
+static gboolean
+filter_dmabuf_caps (GstCapsFeatures *features,
+                    GstStructure    *structure,
+                    gpointer         user_data)
+{
+  const GValue *value;
+  const char *v;
+
+  if (!gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF))
+    return TRUE;
+
+  if (!(value = gst_structure_get_value (structure, "format")) ||
+      !(v = get_nth_string (value, 0)))
+    return FALSE;
+
+#ifdef HAVE_GSTREAMER_DMA_DRM
+  {
+    int idx;
+
+    idx = gst_video_format_from_string (v);
+    if (idx == GST_VIDEO_FORMAT_UNKNOWN)
+      return FALSE;
+
+    if (idx == GST_VIDEO_FORMAT_DMA_DRM &&
+        !gst_structure_get_value (structure, "drm-format"))
+      return FALSE;
+  }
+#endif
+
+  return TRUE;
+}
+
+GstCaps *
+gst_caps_sanitize (GstCaps *caps)
+{
+  caps = gst_caps_make_writable (caps);
+  gst_caps_filter_and_map_in_place (caps, filter_dmabuf_caps, NULL);
+  return caps;
+}
diff --git a/src/gst/gstpipewireformat.h b/src/gst/gstpipewireformat.h
index abd45c4e9bbb..ca76b70c2f06 100644
--- a/src/gst/gstpipewireformat.h
+++ b/src/gst/gstpipewireformat.h
@@ -15,6 +15,8 @@ GPtrArray *      gst_caps_to_format_all  (GstCaps *caps);
 
 GstCaps *        gst_caps_from_format    (const struct spa_pod *format);
 
+GstCaps *        gst_caps_sanitize       (GstCaps *caps);
+
 G_END_DECLS
 
 #endif
diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c
index f96da74ba3d0..a9ef7d1b2430 100644
--- a/src/gst/gstpipewiresrc.c
+++ b/src/gst/gstpipewiresrc.c
@@ -847,10 +847,14 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
     /* no peer, work with our own caps then */
     possible_caps = g_steal_pointer (&thiscaps);
   }
+
+  GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, possible_caps);
+  gst_caps_sanitize (possible_caps);
+
   if (gst_caps_is_empty (possible_caps))
     goto no_common_caps;
 
-  GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, possible_caps);
+  GST_DEBUG_OBJECT (basesrc, "have common caps (sanitized): %" GST_PTR_FORMAT, possible_caps);
 
   if (pw_stream_get_state(pwsrc->stream, NULL) == PW_STREAM_STATE_STREAMING) {
     g_autoptr (GstCaps) current_caps = NULL;