basetransform: Try suggesting caps on bad caps pad_alloc
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>
Mon, 29 Mar 2010 21:05:40 +0000 (18:05 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Mon, 26 Jul 2010 17:49:14 +0000 (14:49 -0300)
When basetransform received an unsupported caps on pad_alloc
it just returned not-negotiated. This patch makes it query
the allowed caps between his sinkpad and upstream's srcpad
to find a caps to suggest.

This happens when dinamically switching pipeline elements
and upstream pad_allocs with the previous caps that was
being used.

Fixes #614296

libs/gst/base/gstbasetransform.c
tests/check/libs/transform1.c

index f6f7ab8..8f49737 100644 (file)
@@ -1341,6 +1341,7 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
   /* check if we got different caps on this new output buffer */
   newcaps = GST_BUFFER_CAPS (*out_buf);
   newsize = GST_BUFFER_SIZE (*out_buf);
+
   if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) {
     GstCaps *othercaps;
     gboolean can_convert;
@@ -1619,6 +1620,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
 {
   GstBaseTransform *trans;
+  GstBaseTransformClass *klass;
   GstBaseTransformPrivate *priv;
   GstFlowReturn res;
   gboolean proxy, suggest, same_caps;
@@ -1626,6 +1628,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
   guint size_suggest;
 
   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   priv = trans->priv;
 
   GST_DEBUG_OBJECT (pad, "alloc with caps %p %" GST_PTR_FORMAT ", size %u",
@@ -1707,15 +1710,51 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
           sink_suggest = NULL;
         }
 
-        GST_DEBUG_OBJECT (trans, "Caps fixated to now: %" GST_PTR_FORMAT,
+        GST_DEBUG_OBJECT (trans, "Caps fixed to: %" GST_PTR_FORMAT,
             sink_suggest);
       }
 
       if (sink_suggest) {
         templ = gst_pad_get_pad_template_caps (pad);
 
-        if (!gst_caps_can_intersect (sink_suggest, templ))
-          goto not_supported;
+        if (!gst_caps_can_intersect (sink_suggest, templ)) {
+          GstCaps *allowed;
+          GstCaps *peercaps;
+
+          /* the requested pad alloc caps are not supported, so let's try
+           * picking something allowed between the pads (they are linked,
+           * there must be something) */
+
+          allowed = gst_pad_get_allowed_caps (pad);
+          if (allowed && !gst_caps_is_empty (allowed)) {
+            GST_DEBUG_OBJECT (trans, "Requested pad alloc caps is not "
+                "supported, but pads could agree on one of the following caps: "
+                "%" GST_PTR_FORMAT, allowed);
+            allowed = gst_caps_make_writable (allowed);
+
+            if (klass->fixate_caps) {
+              peercaps =
+                  gst_pad_get_allowed_caps (GST_BASE_TRANSFORM_SRC_PAD (trans));
+              klass->fixate_caps (trans, GST_PAD_SRC, peercaps, allowed);
+              gst_caps_unref (peercaps);
+            }
+
+            /* Fixate them to be safe if the subclass didn't do it */
+            gst_caps_truncate (allowed);
+            gst_pad_fixate_caps (pad, allowed);
+            gst_caps_replace (&sink_suggest, allowed);
+            gst_caps_unref (allowed);
+
+            suggest = TRUE;
+
+            GST_DEBUG_OBJECT (trans, "Fixated suggestion caps to %"
+                GST_PTR_FORMAT, sink_suggest);
+          } else {
+            if (allowed)
+              gst_caps_unref (allowed);
+            goto not_supported;
+          }
+        }
       }
     }
 
@@ -1757,7 +1796,8 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
   GST_OBJECT_UNLOCK (pad);
 
   proxy = priv->proxy_alloc;
-  GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d", proxy);
+  GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d, suggest %d", proxy,
+      suggest);
 
   /* we only want to proxy if we have no suggestion pending, FIXME */
   if (proxy && !suggest) {
index afd09a7..55b316c 100644 (file)
@@ -642,7 +642,10 @@ GST_START_TEST (basetransform_chain_ct1)
 
   buffer_alloc_ct1_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* FIXME, why would this call the alloc function? we try to alloc something
    * with caps that are not supported on the sinkpad */
   fail_unless (buffer_alloc_ct1_called == FALSE);
@@ -743,7 +746,10 @@ GST_START_TEST (basetransform_chain_ct1)
 
   buffer_alloc_ct1_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* should not call the pad-alloc function */
   fail_unless (buffer_alloc_ct1_called == FALSE);
 
@@ -933,7 +939,10 @@ GST_START_TEST (basetransform_chain_ct2)
   buffer_alloc_ct2_case = 2;
   buffer_alloc_ct2_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* should not call pad-alloc because the caps and sizes are different */
   fail_unless (buffer_alloc_ct2_called == FALSE);
 
@@ -1024,7 +1033,10 @@ GST_START_TEST (basetransform_chain_ct2)
   buffer_alloc_ct2_case = 2;
   buffer_alloc_ct2_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* should not call the pad-alloc function */
   fail_unless (buffer_alloc_ct2_called == FALSE);
 
@@ -1086,7 +1098,10 @@ GST_START_TEST (basetransform_chain_ct3)
   buffer_alloc_ct2_case = 2;
   buffer_alloc_ct2_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* should not call pad-alloc because the caps and sizes are different */
   fail_unless (buffer_alloc_ct2_called == FALSE);
 
@@ -1173,7 +1188,10 @@ GST_START_TEST (basetransform_chain_ct3)
   buffer_alloc_ct2_case = 2;
   buffer_alloc_ct2_called = FALSE;
   res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer);
-  fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
+  fail_unless (res == GST_FLOW_OK);
+  fail_if (buffer == NULL);
+  fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+  gst_buffer_unref (buffer);
   /* FIXME should not call the pad-alloc function but it currently does */
   fail_unless (buffer_alloc_ct2_called == FALSE);