queue2: only block serialized query when it's safe

We must be certain that we don't cause a deadlock when blocking the serialized
queries. One such deadlock can happen when we are buffering and downstream is
blocked in preroll and a serialized query arrives. Downstream will not unblock
(and allow our query to execute) until we complete buffering and buffering will
not complete until we can answer the query..

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=702840
This commit is contained in:
Wim Taymans 2013-06-24 23:25:51 +02:00
parent 1815e6067a
commit 2f78e96299

View file

@ -2300,9 +2300,16 @@ gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent,
default: default:
if (GST_QUERY_IS_SERIALIZED (query)) { if (GST_QUERY_IS_SERIALIZED (query)) {
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received query %p", query); GST_CAT_LOG_OBJECT (queue_dataflow, queue, "received query %p", query);
/* serialized events go in the queue */ /* serialized events go in the queue. We need to be certain that we
* don't cause deadlocks waiting for the query return value. We check if
* the queue is empty (nothing is blocking downstream and the query can
* be pushed for sure) or we are not buffering. If we are buffering,
* the pipeline waits to unblock downstream until our queue fills up
* completely, which can not happen if we block on the query..
* Therefore we only potentially block when we are not buffering. */
GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing); GST_QUEUE2_MUTEX_LOCK_CHECK (queue, queue->sinkresult, out_flushing);
if (QUEUE_IS_USING_QUEUE (queue)) { if (QUEUE_IS_USING_QUEUE (queue) && (gst_queue2_is_empty (queue)
|| !queue->use_buffering)) {
gst_queue2_locked_enqueue (queue, query, GST_QUEUE2_ITEM_TYPE_QUERY); gst_queue2_locked_enqueue (queue, query, GST_QUEUE2_ITEM_TYPE_QUERY);
STATUS (queue, queue->sinkpad, "wait for QUERY"); STATUS (queue, queue->sinkpad, "wait for QUERY");