basetransform: fix reverse negotiation
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 28 Oct 2010 12:29:31 +0000 (13:29 +0100)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 29 Oct 2010 11:03:48 +0000 (12:03 +0100)
When the downstream element suggests a new format, pass the suggestion
upstream if we can't convert to it.

Fixes #633147

libs/gst/base/gstbasetransform.c

index 0e225bc..b4f6c42 100644 (file)
@@ -1214,8 +1214,8 @@ gst_base_transform_query (GstPad * pad, GstQuery * query)
         gst_query_set_position (query, format,
             gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
                 (pad ==
-                    trans->sinkpad) ? trans->segment.last_stop : trans->
-                priv->last_stop_out));
+                    trans->sinkpad) ? trans->segment.last_stop : trans->priv->
+                last_stop_out));
       } else {
         ret = gst_pad_peer_query (otherpad, query);
       }
@@ -1241,6 +1241,51 @@ gst_base_transform_query_type (GstPad * pad)
   return types;
 }
 
+static void
+compute_upstream_suggestion (GstBaseTransform * trans, guint expsize,
+    GstCaps * caps)
+{
+  GstCaps *othercaps;
+  GstBaseTransformPrivate *priv = trans->priv;
+
+  GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
+
+  /* we cannot convert the current buffer but we might be able to suggest a
+   * new format upstream, try to find what the best format is. */
+  othercaps = gst_base_transform_find_transform (trans, trans->srcpad, caps);
+
+  if (!othercaps) {
+    GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
+    /* we received caps that we cannot transform. Upstream is behaving badly
+     * because it should have checked if we could handle these caps. We can
+     * simply ignore these caps and produce a buffer with our original caps. */
+  } else {
+    guint size_suggest;
+
+    GST_DEBUG_OBJECT (trans, "getting size of suggestion");
+
+    /* not a subset, we have a new upstream suggestion, remember it and
+     * allocate a default buffer. First we try to convert the size */
+    if (gst_base_transform_transform_size (trans,
+            GST_PAD_SRC, caps, expsize, othercaps, &size_suggest)) {
+
+      /* ok, remember the suggestions now */
+      GST_DEBUG_OBJECT (trans,
+          "storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
+          size_suggest, othercaps);
+
+      GST_OBJECT_LOCK (trans->sinkpad);
+      if (priv->sink_suggest)
+        gst_caps_unref (priv->sink_suggest);
+      priv->sink_suggest = gst_caps_ref (othercaps);
+      priv->size_suggest = size_suggest;
+      trans->priv->suggest_pending = TRUE;
+      GST_OBJECT_UNLOCK (trans->sinkpad);
+    }
+    gst_caps_unref (othercaps);
+  }
+}
+
 /* Allocate a buffer using gst_pad_alloc_buffer
  *
  * This function can do renegotiation on the source pad
@@ -1363,6 +1408,12 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
 
     if (!can_convert) {
       GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
+
+      gst_base_transform_transform_size (trans,
+          GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
+
+      compute_upstream_suggestion (trans, expsize, newcaps);
+
       /* we got a suggested caps but we can't transform to it. See if there is
        * another downstream format that we can transform to */
       othercaps =
@@ -1426,43 +1477,8 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
       }
       outsize = expsize;
     } else {
-      GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
-
-      /* we cannot convert the current buffer but we might be able to suggest a
-       * new format upstream, try to find what the best format is. */
-      othercaps =
-          gst_base_transform_find_transform (trans, trans->srcpad, newcaps);
-
-      if (!othercaps) {
-        GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
-        /* we received caps that we cannot transform. Upstream is behaving badly
-         * because it should have checked if we could handle these caps. We can
-         * simply ignore these caps and produce a buffer with our original caps. */
-      } else {
-        guint size_suggest;
+      compute_upstream_suggestion (trans, expsize, newcaps);
 
-        GST_DEBUG_OBJECT (trans, "getting size of suggestion");
-
-        /* not a subset, we have a new upstream suggestion, remember it and
-         * allocate a default buffer. First we try to convert the size */
-        if (gst_base_transform_transform_size (trans,
-                GST_PAD_SRC, newcaps, expsize, othercaps, &size_suggest)) {
-
-          /* ok, remember the suggestions now */
-          GST_DEBUG_OBJECT (trans,
-              "storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
-              size_suggest, othercaps);
-
-          GST_OBJECT_LOCK (trans->sinkpad);
-          if (priv->sink_suggest)
-            gst_caps_unref (priv->sink_suggest);
-          priv->sink_suggest = gst_caps_ref (othercaps);
-          priv->size_suggest = size_suggest;
-          trans->priv->suggest_pending = TRUE;
-          GST_OBJECT_UNLOCK (trans->sinkpad);
-        }
-        gst_caps_unref (othercaps);
-      }
       if (in_buf != *out_buf)
         gst_buffer_unref (*out_buf);
       *out_buf = NULL;