basetextoverlay: Rewrite negotiation method
authorNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Tue, 12 May 2015 18:12:52 +0000 (14:12 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Fri, 12 Jun 2015 23:58:39 +0000 (19:58 -0400)
This cleanup the negotiation function by properly splitting the probe
and the decisions. This allow handling correctly pipeline where upstream
caps have special memory type. An example pipeline is:

  gltestsrc ! textoverlay text=bla ! fakesink

The upstream caps will be memory:GLMemory, which isn't supported by the
blitter.

https://bugzilla.gnome.org/show_bug.cgi?id=749243

ext/pango/gstbasetextoverlay.c

index e76e2d21fa1c5eeeef7a5a29ed23deacad87f399..9c7aba7a920d703e3843198429d6d0e944b08b11 100644 (file)
@@ -669,14 +669,13 @@ gst_base_text_overlay_setcaps_txt (GstBaseTextOverlay * overlay, GstCaps * caps)
 static gboolean
 gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps)
 {
-  GstQuery *query;
+  gboolean upstream_has_meta = FALSE;
+  gboolean caps_has_meta = FALSE;
+  gboolean alloc_has_meta = FALSE;
   gboolean attach = FALSE;
-  gboolean caps_has_meta = TRUE;
-  gboolean ret;
+  gboolean ret = TRUE;
   GstCapsFeatures *f;
-  GstCaps *original_caps;
-  gboolean original_has_meta = FALSE;
-  gboolean allocation_ret = TRUE;
+  GstCaps *overlay_caps;
 
   GST_DEBUG_OBJECT (overlay, "performing negotiation");
 
@@ -688,76 +687,77 @@ gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps)
   if (!caps || gst_caps_is_empty (caps))
     goto no_format;
 
-  original_caps = caps;
-
-  /* Try to use the overlay meta if possible */
-  f = gst_caps_get_features (caps, 0);
-
-  /* if the caps doesn't have the overlay meta, we query if downstream
-   * accepts it before trying the version without the meta
-   * If upstream already is using the meta then we can only use it */
-  if (!f
-      || !gst_caps_features_contains (f,
-          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) {
-    GstCaps *overlay_caps;
-
-    /* In this case we added the meta, but we can work without it
-     * so preserve the original caps so we can use it as a fallback */
-    overlay_caps = gst_caps_copy (caps);
-
-    f = gst_caps_get_features (overlay_caps, 0);
-    gst_caps_features_add (f,
+  /* Check if upstream caps have meta */
+  if ((f = gst_caps_get_features (caps, 0))) {
+    caps_has_meta = gst_caps_features_contains (f,
         GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
+  }
 
-    ret = gst_pad_peer_query_accept_caps (overlay->srcpad, overlay_caps);
-    GST_DEBUG_OBJECT (overlay, "Downstream accepts the overlay meta: %d", ret);
-    if (ret) {
-      gst_caps_unref (caps);
-      caps = overlay_caps;
-
-    } else {
-      /* fallback to the original */
-      gst_caps_unref (overlay_caps);
-      caps_has_meta = FALSE;
-    }
+  if (upstream_has_meta) {
+    overlay_caps = gst_caps_ref (caps);
   } else {
-    original_has_meta = TRUE;
-  }
-  GST_DEBUG_OBJECT (overlay, "Using caps %" GST_PTR_FORMAT, caps);
-  ret = gst_pad_set_caps (overlay->srcpad, caps);
+    GstQuery *query;
 
-  if (ret) {
-    /* find supported meta */
+    /* First check if the allocation meta has compositon */
     query = gst_query_new_allocation (caps, FALSE);
 
     if (!gst_pad_peer_query (overlay->srcpad, query)) {
       /* no problem, we use the query defaults */
       GST_DEBUG_OBJECT (overlay, "ALLOCATION query failed");
-      allocation_ret = FALSE;
+
+      /* In case we were flushing, mark reconfigure and fail this method,
+       * will make it retry */
+      if (overlay->video_flushing)
+        ret = FALSE;
     }
 
-    if (caps_has_meta && gst_query_find_allocation_meta (query,
-            GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL))
-      attach = TRUE;
+    alloc_has_meta = gst_query_find_allocation_meta (query,
+        GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
 
     gst_query_unref (query);
+
+    /* Then check if downstream accept overlay composition in caps */
+    overlay_caps = gst_caps_copy (caps);
+
+    f = gst_caps_get_features (overlay_caps, 0);
+    gst_caps_features_add (f,
+        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
+
+    caps_has_meta = gst_pad_peer_query_accept_caps (overlay->srcpad,
+        overlay_caps);
   }
 
-  overlay->attach_compo_to_buffer = attach;
+  /* For backward compatbility, we will prefer bliting if downstream
+   * allocation does not support the meta. In other case we will prefer
+   * attaching, and will fail the negotiation in the unlikely case we are
+   * force to blit, but format isn't supported. */
 
-  if (!allocation_ret && overlay->video_flushing) {
-    ret = FALSE;
-  } else if (original_caps && !original_has_meta && !attach) {
-    if (caps_has_meta) {
-      /* Some elements (fakesink) claim to accept the meta on caps but won't
-         put it in the allocation query result, this leads below
-         check to fail. Prevent this by removing the meta from caps */
-      gst_caps_unref (caps);
-      caps = gst_caps_ref (original_caps);
-      ret = gst_pad_set_caps (overlay->srcpad, caps);
-      if (ret && !gst_base_text_overlay_can_handle_caps (caps))
-        ret = FALSE;
+  if (upstream_has_meta) {
+    attach = TRUE;
+  } else if (caps_has_meta) {
+    if (alloc_has_meta) {
+      attach = TRUE;
+    } else {
+      /* Don't attach unless we cannot handle the format */
+      attach = !gst_base_text_overlay_can_handle_caps (caps);
     }
+  } else {
+    ret = gst_base_text_overlay_can_handle_caps (caps);
+  }
+
+  /* If we attach, then pick the overlay caps */
+  if (attach) {
+    gst_caps_unref (caps);
+    caps = overlay_caps;
+  } else {
+    gst_caps_unref (overlay_caps);
+  }
+
+  /* If negotiation worked, set the caps and remember to attach */
+  if (ret) {
+    GST_DEBUG_OBJECT (overlay, "Using caps %" GST_PTR_FORMAT, caps);
+    overlay->attach_compo_to_buffer = attach;
+    ret = gst_pad_set_caps (overlay->srcpad, caps);
   }
 
   if (!ret) {