plugins/elements/: Fix queue negotiation. If acceptcaps unconditionally returns TRUE...
authorWim Taymans <wim.taymans@gmail.com>
Mon, 15 Oct 2007 11:36:37 +0000 (11:36 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 15 Oct 2007 11:36:37 +0000 (11:36 +0000)
Original commit message from CVS:
* plugins/elements/gstmultiqueue.c: (gst_single_queue_push_one),
(gst_single_queue_new):
* plugins/elements/gstqueue.c: (gst_queue_init),
(gst_queue_push_one):
Fix queue negotiation. If acceptcaps unconditionally returns TRUE,
upstream is tricked into thinking it can suggest a format downstream
while downstream does not support that format. The real problem is that
core calls acceptcaps when pushing a buffer with new caps, for which we
do a little workaround by setting the caps on the srcpad ourselves
before pushing the buffer (until this is figured out). Fixes #486758.

ChangeLog
plugins/elements/gstmultiqueue.c
plugins/elements/gstqueue.c

index 8ebd4b8..207b8f2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-10-15  Wim Taymans  <wim.taymans@gmail.com>
+
+       * plugins/elements/gstmultiqueue.c: (gst_single_queue_push_one),
+       (gst_single_queue_new):
+       * plugins/elements/gstqueue.c: (gst_queue_init),
+       (gst_queue_push_one):
+       Fix queue negotiation. If acceptcaps unconditionally returns TRUE,
+       upstream is tricked into thinking it can suggest a format downstream
+       while downstream does not support that format. The real problem is that
+       core calls acceptcaps when pushing a buffer with new caps, for which we
+       do a little workaround by setting the caps on the srcpad ourselves
+       before pushing the buffer (until this is figured out). Fixes #486758.
+
 2007-10-15  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/gststructure.c:
index f80863b..be2808e 100644 (file)
@@ -601,10 +601,12 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
   if (GST_IS_BUFFER (object)) {
     GstBuffer *buffer;
     GstClockTime timestamp, duration;
+    GstCaps *caps;
 
     buffer = GST_BUFFER_CAST (object);
     timestamp = GST_BUFFER_TIMESTAMP (buffer);
     duration = GST_BUFFER_DURATION (buffer);
+    caps = GST_BUFFER_CAPS (buffer);
 
     apply_buffer (mq, sq, timestamp, duration, &sq->src_segment);
 
@@ -615,6 +617,12 @@ gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
         "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT,
         sq->id, buffer, GST_TIME_ARGS (timestamp));
 
+    /* Set caps on pad before pushing, this avoids core calling the accpetcaps
+     * function on the srcpad, which will call acceptcaps upstream, which might
+     * not accept these caps (anymore). */
+    if (caps && caps != GST_PAD_CAPS (sq->srcpad))
+      gst_pad_set_caps (sq->srcpad, caps);
+
     result = gst_pad_push (sq->srcpad, buffer);
   } else if (GST_IS_EVENT (object)) {
     GstEvent *event;
@@ -1031,12 +1039,6 @@ gst_multi_queue_src_activate_push (GstPad * pad, gboolean active)
 }
 
 static gboolean
-gst_multi_queue_acceptcaps (GstPad * pad, GstCaps * caps)
-{
-  return TRUE;
-}
-
-static gboolean
 gst_multi_queue_src_event (GstPad * pad, GstEvent * event)
 {
   GstSingleQueue *sq = gst_pad_get_element_private (pad);
@@ -1345,8 +1347,6 @@ gst_single_queue_new (GstMultiQueue * mqueue)
 
   gst_pad_set_activatepush_function (sq->srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push));
-  gst_pad_set_acceptcaps_function (sq->srcpad,
-      GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps));
   gst_pad_set_getcaps_function (sq->srcpad,
       GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
   gst_pad_set_event_function (sq->srcpad,
index 567c266..f86678e 100644 (file)
@@ -189,7 +189,6 @@ static void gst_queue_get_property (GObject * object,
 static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
 static GstFlowReturn gst_queue_bufferalloc (GstPad * pad, guint64 offset,
     guint size, GstCaps * caps, GstBuffer ** buf);
-static gboolean gst_queue_acceptcaps (GstPad * pad, GstCaps * caps);
 static GstFlowReturn gst_queue_push_one (GstQueue * queue);
 static void gst_queue_loop (GstPad * pad);
 
@@ -383,8 +382,6 @@ gst_queue_init (GstQueue * queue, GstQueueClass * g_class)
       GST_DEBUG_FUNCPTR (gst_queue_src_activate_push));
   gst_pad_set_link_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue_link_src));
-  gst_pad_set_acceptcaps_function (queue->srcpad,
-      GST_DEBUG_FUNCPTR (gst_queue_acceptcaps));
   gst_pad_set_getcaps_function (queue->srcpad,
       GST_DEBUG_FUNCPTR (gst_queue_getcaps));
   gst_pad_set_event_function (queue->srcpad,
@@ -503,14 +500,6 @@ gst_queue_bufferalloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps,
   return result;
 }
 
-static gboolean
-gst_queue_acceptcaps (GstPad * pad, GstCaps * caps)
-{
-  /* The only time our acceptcaps method should be called is on the srcpad
-   * when we push a buffer, in which case we always accept those caps */
-  return TRUE;
-}
-
 /* calculate the diff between running time on the sink and src of the queue.
  * This is the total amount of time in the queue. */
 static void
@@ -984,9 +973,20 @@ gst_queue_push_one (GstQueue * queue)
 
 next:
   if (GST_IS_BUFFER (data)) {
-    GstBuffer *buffer = GST_BUFFER_CAST (data);
+    GstBuffer *buffer;
+    GstCaps *caps;
+
+    buffer = GST_BUFFER_CAST (data);
+    caps = GST_BUFFER_CAPS (buffer);
 
     GST_QUEUE_MUTEX_UNLOCK (queue);
+    /* set the right caps on the pad now. We do this before pushing the buffer
+     * because the pad_push call will check (using acceptcaps) if the buffer can
+     * be set on the pad, which might fail because this will be propagated
+     * upstream. Also note that if the buffer has NULL caps, it means that the
+     * caps did not change, so we don't have to change caps on the pad. */
+    if (caps && caps != GST_PAD_CAPS (queue->srcpad))
+      gst_pad_set_caps (queue->srcpad, caps);
 
     result = gst_pad_push (queue->srcpad, buffer);