GNOME Bugzilla – Bug 702840
queue2 does not work with use-buffering=true
Last modified: 2014-03-24 11:06:27 UTC
For some reason, uridecodebin does not work anymore for audio/video from an http source in the git version of gst 1.0. These for example do not work on 1.0 : gst-launch-1.0 uridecodebin uri="http://download.wavetlan.com/SVV/Media/HTTP/H264/Talkinghead_Media/H264_test1_Talkinghead_mp4_480x360.mp4" name=d ! videoconvert ! xvimagesink d. ! pulsesink gst-launch-1.0 uridecodebin uri="http://people.collabora.com/~kakaroto/MP3-320-CBR-NS/01 Rhiannon.mp3" ! pulsesink The same command works if I use gst-launch-0.10 instead of gst-launch-1.0. Also note that an HLS stream (http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8) works. If I use playbin instead of uridecodebin, it works, if I use 'souphttpsrc ! queue2 ! decodebin', it works as well, but if I use "souphttpsrc ! queue2 use-buffering=true ! decodebin" then it stops working. From my observations, it looks like queue2 sends the buffering 0% message then stops doing anything, blocking this way forever. If I also set ring-buffer-max-size to something like 1000000, it works, but setting it to the default of 0 will not work. This is weird though since it works with playbin and playbin also uses ring-buffer-max-size with a default of 0. This is a regression in git since with 1.0.7, it works, but it fails with the git version.
It's caused by adding support for serialized queries. * queue2 is blocked pushing a buffer downstream because the sink is blocking in preroll * The basesrc is doing an allocation query that blocks waiting for a reply that never comes because the pushing side it blocked. I think the best thing for now is to only forward the serialized query when: - The queue is empty, so you know nothing is blocking downstream - *or* The queue is not buffering
commit 2f78e962997725f734353ffe5c061f98b53903d8 Author: Wim Taymans <wim.taymans@collabora.co.uk> Date: Mon Jun 24 23:25:51 2013 +0200 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
Why is this not a problem in queue and multiqueue when they emit BUFFERING messages and are blocked downstream?
*** Bug 703354 has been marked as a duplicate of this bug. ***
commit 0dc232e1140be953e920388c54dd4cfa0d7637e0 Author: Sebastian Dröge <slomo@circular-chaos.org> Date: Tue Jul 16 11:36:50 2013 +0200 multiqueue: 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.. https://bugzilla.gnome.org/show_bug.cgi?id=702840
I think this might be not quite enough. I've been tracking down a deadlock in a situation where I have a souphttpsrc, queue2, then other stuff ending in a multiudpsink. Not always, I get a deadlock with: - one thread blocked in preroll, where queue2 has pushed a buffer, and multiudpsink is then blocked in preroll - one thread gets a sink query, checks if it's using queue (yes), if the queue is empty (yes), so enqueues the query and waits. What seems to be happening is that the qlock is released after dequeuing the buffer, so the queue will be empty while the buffer is making its way downstream, so the query can be pushed, and this blocks. A naive idea would be to only dequeue the buffer (or event, etc) after it's been pushed. Does this seem plausible/sane ?
Created attachment 272474 [details] [review] Fix event/preroll deadlock This "works for me". It avoids waiting on the event when downstream may block. It waits on all buffers and buffer lists, which may be a bit too much, and denies request then. This seems "violent", but this is also what the existing code does, so may be OK. Sane enough ?
Created attachment 272477 [details] [review] Fix event/preroll deadlock As discussed with Wim on IRC, new simpler version.
commit a6decb91ac2c035c381d59f1f1fabfeb2f869f95 Author: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Thu Mar 20 06:14:33 2014 -0400 queue2: fix event/preroll deadlock The qlock is released between popping a buffer from the queue and pushing it. When this buffer causes the sink to wait in preroll, this lets a query see that the queue is empty, and push the query then wait for it to be serviced. However, this will not be done till after peroll, and this will thus block. If upstream was waiting on buffering to reach 100% before switching to PLAYING, a deadlock would ensue. We fix it by refusing the query when buffering, as per Wim's recommendation on IRC.