GNOME Bugzilla – Bug 455808
rtspsrc deadlocks on pause
Last modified: 2007-08-17 17:02:55 UTC
Please describe the problem: When RTSP streaming is paused during playback, it just deadlocks. State change (PLAYING -> PAUSED) never returns. This happens when using "rtpdec" session manager that comes along with rtspsrc element. With "gstrtpbin" session manager pause succeeds. Steps to reproduce: Actual results: Expected results: Does this happen every time? Other information:
I forgot to mention that transport protocol was TCP. I got following warning from rtspsrc in the beginning of playback: "warning: Could not receive any UDP packets for 5.0000 seconds, maybe your firewall is blocking it. Retrying using a TCP connection"
Forgot to mention that I used playbin (+decodebin2) to test this. I made some debugging and it looks like gst_rtspsrc_loop_interleaved() blocks in gst_pad_push() call. This happens because multiqueue in decodebin2 gets full and blocks in gst_multi_queue_chain::gst_data_queue_push() call: gstmultiqueue.c:624:gst_multi_queue_chain:<multiqueue1> SingleQueue 0 : about to push buffer with id 209 gstmultiqueue.c:923:single_queue_overrun_cb:<multiqueue1> Single Queue 0 is full After this everything stops. gst_rtspsrc_pause() gets stuck in GST_RTSP_STREAM_LOCK() that never happens --> deadlock
rtpdec really should not be used, it does not do the right thing and was just an intermediate element to make the transition to the new rtpbin. The warning is a normal thing when the udp transport times out, if you know udp is not possible, you can disable it as a valid transport in rtspsrc with protocols=4. The locking can however be made a little more fine grained. It currently takes the stream lock to make sure that the streaming thread is not receiving data from the server while we send the PAUSE command.
If rtpdec shouldn't be used, then what we should use to make RTSP to work? RTPManager from plugins-bad? About that locking thing. Isn't there quite an obvious deadlock possibility in interleaved mode when pad_push() blocks (when downstream has already been paused and queue is full?) and statechange wants to call gst_rtspsrc_pause() ? In this case the STREAM_LOCK is held by GstTask and _pause() starts waiting for it.
Yes, the plugins from -bad are fully functional for RTSP. I'm currently fixing the obvious deadlock you describe.
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init), (gst_rtspsrc_finalize), (gst_rtspsrc_connection_send), (gst_rtspsrc_connection_receive), (gst_rtspsrc_sink_chain), (gst_rtspsrc_handle_request), (gst_rtspsrc_send_keep_alive), (gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp), (gst_rtspsrc_try_send), (gst_rtspsrc_pause): * gst/rtsp/gstrtspsrc.h: Protect connection activity with a new lock, avoids deadlocks when going to PAUSED. Fixes #455808.