GNOME Bugzilla – Bug 655790
Hang when playing MPEG TS from disk with buffering
Last modified: 2014-06-12 12:20:15 UTC
Created attachment 193044 [details] For each thread a bit of strace output and back trace from gdb. I realize MPEG TS plugins come from the bad package, however I am not sure this is not a core bug of some sort. I am seeing a reproducible hang where gst-launch pauses the pipeline and starts buffering never to get out of that state. Test command is: gst-launch-0.10 -v playbin2 uri=file:///home/storage/bbc-end2.ts flags=0x103 audio-sink=alsasink It only happens when buffering (0x100 in flags to playbin2) is turned on. It happens most of the time but not always - I suspect it is timing related so some sort of a race condition. Because I was seeing it 100% of the time at first and it went away when I turned on verbose debug to console. Redirecting that to a file and hang was there again. I have looked at back traces of all gst-launch threads (attached). But since I am quite new to GStreamer I am not quite there yet to untangle and make sense of it all. It looks a lot of interesting threads are blocking in synchronization primitives - which would indeed suggest a race condition. Demuxer is sitting in gst_data_queue_push, two threads in gst_queue_chain and another two in gst_base_sink_wait_preroll. I will attach stack traces and strace snippets from all threads which show the state when hanging. Also a GST_DEBUG=5 log file of it.
Debug output is 5Mb compressed which Bugzilla won't let me upload. I am happy to email it to interested parties or upload it somewhere if suggested.
I have just rebuilt all packages from today's git and the hang is still there.
I have tried to manually build the pipeline as similar to the one playbin2 creates. It goes like this: /usr/local/bin/gst-launch-0.10 -v filesrc location=/home/storage/bbc-end2.ts ! typefind ! mpegtsdemux name=demux multiqueue max-size-buffers=0 max-size-time=2000000000 max-size-bytes=2097152 use-buffering=true name=mq demux. ! mq.sink0 mq.src0 ! mpegaudioparse ! mad ! input-selector ! tee ! queue ! audioconvert ! audioresample ! alsasink demux. ! mq.sink1 mq.src1 ! mpeg2dec ! input-selector ! queue ! videoscale ! xvimagesink Only difference I can see is that there is no way to insert that GstStreamSynchronizer element, but otherwise pipelines are pretty close. Crucial thing is playbin2 hangs while the manual pipeline does not. Can someone please look at the pipelines and see if I got it right? If I have, what could be causing the hang? I see that streamsynchronizer is made running in pass-through mode by default - but would it make sense to actually attempt to remove it from the playbin2 pipeline to see what happens?
My possibly silly and misguided attempt to remove streamsynchronizer out of the picture did not really work. I assumed multiqueue could do the job but with default it would not play, and when I set queueing properties to zero then it plays full speed (decode+render speed) for a while and then it magically locks into sync. It does pass over the spot where it hangs with streamsynchronizer, but I kind of suspect that might not mean anything considering above described behaviour. diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index b36ab1b..7afb640 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -138,7 +138,7 @@ struct _GstPlaySink GstPlayFlags flags; - GstStreamSynchronizer *stream_synchronizer; + GstElement *stream_synchronizer; /* chains */ GstPlayAudioChain *audiochain; @@ -461,7 +461,10 @@ gst_play_sink_init (GstPlaySink * playsink) playsink->flags = DEFAULT_FLAGS; playsink->stream_synchronizer = - g_object_new (GST_TYPE_STREAM_SYNCHRONIZER, NULL); + gst_element_factory_make ("multiqueue", NULL); + g_object_set (playsink->stream_synchronizer, "max-size-bytes", 0, NULL); + g_object_set (playsink->stream_synchronizer, "max-size-buffers", 0, NULL); + g_object_set (playsink->stream_synchronizer, "max-size-time", 0, NULL); gst_bin_add (GST_BIN_CAST (playsink), GST_ELEMENT_CAST (playsink->stream_synchronizer)); @@ -2201,7 +2204,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) playsink->video_sinkpad_stream_synchronizer = gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); + (playsink->stream_synchronizer), "sink%d"); it = gst_pad_iterate_internal_links (playsink->video_sinkpad_stream_synchronizer); g_assert (it); @@ -2357,7 +2360,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) playsink->audio_sinkpad_stream_synchronizer = gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); + (playsink->stream_synchronizer), "sink%d"); it = gst_pad_iterate_internal_links (playsink->audio_sinkpad_stream_synchronizer); g_assert (it); @@ -2474,7 +2477,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) if (!playsink->text_sinkpad_stream_synchronizer) { playsink->text_sinkpad_stream_synchronizer = gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); + (playsink->stream_synchronizer), "sink%d"); it = gst_pad_iterate_internal_links (playsink->text_sinkpad_stream_synchronizer); g_assert (it);
I've confirmed that it's synchronisation causing the problem; if I set flags to 0x101 or 0x102 (video-only or audio-only), the file plays through in full. If I use flags 0x103, it jams.
I can see this issue, using this command line and a random sample. It goes away if I disable the logic in gst-launch that switches the pipeline between PAUSED and PLAYING when it gets BUFFERING messages. This logic is also disabled for live pipelines - which file:// URIs will not cause. Does the following patch fix this for you ? If so, the issue is probably a red herring. If not, could I get the sample file ? diff --git a/tools/gst-launch.c b/tools/gst-launch.c index ea99b8f..8930bd2 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -70,7 +70,7 @@ static EventLoopResult caught_error = ELR_NO_ERROR; static gboolean quiet = FALSE; static gboolean tags = FALSE; static gboolean messages = FALSE; -static gboolean is_live = FALSE; +static gboolean is_live = TRUE; //FALSE; static gboolean waiting_eos = FALSE; /* convenience macro so we don't have to litter the code with if(!quiet) */
I can confirm that the patch fixes it.
*** Bug 663263 has been marked as a duplicate of this bug. ***
Does this still cause issue with current git ?
Closing this bug report as no further information has been provided. Please feel free to reopen this bug if you can provide the information asked for. Thanks!
A similar, but not quite identical, issue still happens on master. See https://bugzilla.gnome.org/show_bug.cgi?id=731474 I recalled having seen something like this, tried the switch, it worked, so I looked in BZ to see what the fix was - and there wasn't any. Not 100% sure it's the same thing since 731474 works when playing audio and video, but does not work when playing only audio, so the other way around than this bug.