gldownload: Fix renegotiation loop
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Mon, 11 Nov 2019 01:05:59 +0000 (20:05 -0500)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Mon, 11 Nov 2019 22:11:45 +0000 (17:11 -0500)
When DMABuf was tried, we would renegotiate back and fourth between
DMABuf and system memory if the export failed. This would happen for
every single frame.

This patch introduces try_dmabuf_exports boolean, which is unset when
an export failed. This boolean is then put back to TRUE when upstream
pushes new caps, or downstream pushes a reconfigure event.

ext/gl/gstgldownloadelement.c
ext/gl/gstgldownloadelement.h

index 4a87e94..ddd6ae2 100644 (file)
@@ -45,6 +45,8 @@ static gboolean gst_gl_download_element_get_unit_size (GstBaseTransform * trans,
     GstCaps * caps, gsize * size);
 static GstCaps *gst_gl_download_element_transform_caps (GstBaseTransform * bt,
     GstPadDirection direction, GstCaps * caps, GstCaps * filter);
+static GstCaps *gst_gl_download_element_fixate_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 static gboolean gst_gl_download_element_set_caps (GstBaseTransform * bt,
     GstCaps * in_caps, GstCaps * out_caps);
 static GstFlowReturn
@@ -89,12 +91,15 @@ gst_gl_download_element_class_init (GstGLDownloadElementClass * klass)
   bt_class->start = gst_gl_download_element_start;
   bt_class->stop = gst_gl_download_element_stop;
   bt_class->transform_caps = gst_gl_download_element_transform_caps;
+  bt_class->fixate_caps = gst_gl_download_element_fixate_caps;
   bt_class->set_caps = gst_gl_download_element_set_caps;
   bt_class->get_unit_size = gst_gl_download_element_get_unit_size;
   bt_class->prepare_output_buffer =
       gst_gl_download_element_prepare_output_buffer;
   bt_class->transform = gst_gl_download_element_transform;
   bt_class->decide_allocation = gst_gl_download_element_decide_allocation;
+  bt_class->sink_event = gst_gl_download_element_sink_event;
+  bt_class->src_event = gst_gl_download_element_src_event;
 
   bt_class->passthrough_on_same_caps = TRUE;
 
@@ -124,6 +129,7 @@ gst_gl_download_element_start (GstBaseTransform * bt)
   GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt);
 
   dl->dmabuf_allocator = gst_dmabuf_allocator_new ();
+  g_atomic_int_set (&dl->try_dmabuf_exports, TRUE);
 #endif
 
   return TRUE;
@@ -158,8 +164,8 @@ gst_gl_download_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps,
   if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) {
     dl->mode = GST_GL_DOWNLOAD_MODE_PASSTHROUGH;
 #if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF
-  } else if (gst_caps_features_contains (features,
-          GST_CAPS_FEATURE_MEMORY_DMABUF)) {
+  } else if (g_atomic_int_get (&dl->try_dmabuf_exports) &&
+      gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
     dl->mode = GST_GL_DOWNLOAD_MODE_DMABUF_EXPORTS;
 #endif
   } else {
@@ -232,6 +238,33 @@ gst_gl_download_element_transform_caps (GstBaseTransform * bt,
   return result;
 }
 
+static GstCaps *
+gst_gl_download_element_fixate_caps (GstBaseTransform * bt,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF
+  GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt);
+
+  /* Remove DMABuf features if try_dmabuf_exports is not set */
+  if (direction == GST_PAD_SINK && !g_atomic_int_get (&dl->try_dmabuf_exports)) {
+    gint i;
+
+    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+      GstCapsFeatures *features = gst_caps_get_features (othercaps, i);
+
+      if (features && gst_caps_features_contains (features,
+              GST_CAPS_FEATURE_MEMORY_DMABUF)) {
+        caps = gst_caps_make_writable (othercaps);
+        gst_caps_remove_structure (othercaps, i--);
+      }
+    }
+  }
+#endif
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->fixate_caps (bt, direction,
+      caps, othercaps);
+}
+
 static gboolean
 gst_gl_download_element_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
     gsize * size)
@@ -453,6 +486,7 @@ gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt,
       src_caps = gst_caps_make_writable (src_caps);
       features = gst_caps_get_features (src_caps, 0);
       gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_DMABUF);
+      g_atomic_int_set (&dl->try_dmabuf_exports, FALSE);
       dl->mode = GST_GL_DOWNLOAD_MODE_PBO_TRANSFERS;
 
       if (!gst_base_transform_update_src_caps (bt, src_caps)) {
@@ -500,6 +534,30 @@ gst_gl_download_element_decide_allocation (GstBaseTransform * trans,
       query);
 }
 
+static gboolean
+gst_gl_download_element_sink_event (GstBaseTransform * bt, GstEvent * event)
+{
+  GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt);
+
+  /* Retry exporting whenever we have new caps from upstream */
+  if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+    g_atomic_int_set (&dl->try_dmabuf_exports, TRUE);
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (bt, event);
+}
+
+static gboolean
+gst_gl_download_element_src_event (GstBaseTransform * bt, GstEvent * event)
+{
+  GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt);
+
+  /* Retry exporting whenever downstream have changed */
+  if (GST_EVENT_TYPE (event) == GST_EVENT_RECONFIGURE)
+    g_atomic_int_set (&dl->try_dmabuf_exports, TRUE);
+
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (bt, event);
+}
+
 static void
 gst_gl_download_element_finalize (GObject * object)
 {
index 8f4f8f1..93bfd50 100644 (file)
@@ -51,6 +51,7 @@ struct _GstGLDownloadElement
   GstGLBaseFilter  parent;
 
   GstGlDownloadMode mode;
+  gboolean try_dmabuf_exports;
   GstAllocator * dmabuf_allocator;
   gboolean add_videometa;
 };