basetransform fix for upstream caps-renegotiation
authorRob Clark <rob@ti.com>
Sat, 22 May 2010 21:33:11 +0000 (16:33 -0500)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 27 Jul 2010 15:34:49 +0000 (17:34 +0200)
If initially pass-through caps are negotiated between a transform element's
sink and src pads, but then the downstream element returns different caps
on a buffer from pad_alloc(), basetransform gets stuck with proxy_alloc=TRUE
even though the upstream peer doesn't accept the caps, causing
gst_pad_peer_accept_caps() to be called on each buffer in _buffer_alloc():

    if (!gst_caps_is_equal (newcaps, caps)) {
      GST_DEBUG_OBJECT (trans, "caps are new");
      /* we have new caps, see if we can proxy downstream */
>>    if (gst_pad_peer_accept_caps (pad, newcaps)) {
        /* peer accepts the caps, return a buffer in this format */
        GST_DEBUG_OBJECT (trans, "peer accepted new caps");

which is taking ~40ms/frame.

This patch does two things.  (1) if the buffer returned from pad_alloc() has
new caps, trigger the decision whether to proxy the buffer-alloc to be
revisited, and (2) disable proxy if peer does not accept new caps.  (The first
part may not be strictly needed, but seemed like a good idea.)

Note that this issue would not arise except in case of downstream elements
who have on their template-caps, some that would be suitable for pass-through,
but at runtime pick more restrictive caps (for ex, after querying a driver for
what formats it actually supports).

libs/gst/base/gstbasetransform.c

index 8f49737674db6f8221a194b011cda0a4ff65ac77..1d159a06514cde859b440d23938ccce5590f1ee9 100644 (file)
@@ -1389,6 +1389,9 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
       /* new format configure, and use the new output buffer */
       gst_pad_set_caps (trans->srcpad, newcaps);
       discard = FALSE;
+      /* clear previous cached sink-pad caps, so buffer_alloc knows that
+       * it needs to revisit the decision about whether to proxy or not: */
+      gst_caps_replace (&priv->sink_alloc, NULL);
       /* if we got a buffer of the wrong size, discard it now and make sure we
        * allocate a propertly sized buffer later. */
       if (newsize != expsize) {
@@ -1829,8 +1832,11 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
         GST_OBJECT_UNLOCK (pad);
       } else {
         GST_DEBUG_OBJECT (trans, "peer did not accept new caps");
-        /* peer does not accept the caps, free the buffer we received and
-         * create a buffer of the requested format by the default handler. */
+        /* peer does not accept the caps, disable proxy_alloc, free the
+         * buffer we received and create a buffer of the requested format
+         * by the default handler. */
+        GST_DEBUG_OBJECT (trans, "disabling proxy");
+        priv->proxy_alloc = FALSE;
         gst_buffer_unref (*buf);
         *buf = NULL;
       }