From 5363f86bb12d604013baeef01e3eb55aa9c90e2c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 15 Oct 2007 11:36:37 +0000 Subject: [PATCH] plugins/elements/: Fix queue negotiation. If acceptcaps unconditionally returns TRUE, upstream is tricked into thinki... 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 | 13 +++++++++++++ plugins/elements/gstmultiqueue.c | 16 ++++++++-------- plugins/elements/gstqueue.c | 24 ++++++++++++------------ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ebd4b8734..207b8f27dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-10-15 Wim Taymans + + * 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 * gst/gststructure.c: diff --git a/plugins/elements/gstmultiqueue.c b/plugins/elements/gstmultiqueue.c index f80863b124..be2808e3f9 100644 --- a/plugins/elements/gstmultiqueue.c +++ b/plugins/elements/gstmultiqueue.c @@ -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; @@ -1030,12 +1038,6 @@ gst_multi_queue_src_activate_push (GstPad * pad, gboolean active) return result; } -static gboolean -gst_multi_queue_acceptcaps (GstPad * pad, GstCaps * caps) -{ - return TRUE; -} - static gboolean gst_multi_queue_src_event (GstPad * pad, GstEvent * event) { @@ -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, diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 567c2660c4..f86678e456 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -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);