GNOME Bugzilla – Bug 787621
adaptivedemux: Pre-rolling problem after seeks on HLS streams
Last modified: 2018-11-03 14:13:25 UTC
Created attachment 359702 [details] Reproduce unit test code gstplayer in pause state, seek to a specific point, will cause the pipeline to hangs. Attached unit_test will perform a seek to user specified position in PAUSED state, such as:./gst-play http://10.9.44.116/seek_issure/index.m3u8 90000 The HLS file for reproduction is here: https://drive.google.com/file/d/0B8t5E5lSOxhHOEo2akNZQW9MX2s/view?usp=sharing The seek location set to 90000, 100% will hangs, audio seems unable to preroll success, and the video has been preroll completed. backtrace: ---
+ Trace 237953
Thread 24 (Thread 0x7fff8ef7f700 (LWP 24629))
Thread 23 (Thread 0x7fff8fd9a700 (LWP 24628))
Thread 11 (Thread 0x7fffdcf11700 (LWP 24616))
Thread 10 (Thread 0x7fffdd953700 (LWP 24615))
Thread 9 (Thread 0x7fffde7fc700 (LWP 24614))
Thread 8 (Thread 0x7fffdeffd700 (LWP 24613))
Thread 7 (Thread 0x7fffdf7fe700 (LWP 24612))
Thread 6 (Thread 0x7fffdffff700 (LWP 24611))
Thread 3 (Thread 0x7fffee096700 (LWP 24608))
Both playbin2 and playbin3 fail. Anybody can help verify that this bug is the same as Bug https://bugzilla.gnome.org/show_bug.cgi?id=736655(basesink: preroll issue for some clips which audio is shorter than video)? I'm not sure because it was seeking to 90000 (1 minute 30 seconds), exactly fragment 8.ts , but 8.ts video duration = 10.680s, audio duration = 10.581s, their diff is really small.
I looked into it further and found that it seems that the queue behind the demux module has a relationship,the demux component pauses once the audio/video pipeline is filled up with data. This means that now the transport stream is no longer processed and required amount of a/v data is not passed on. The audio chain does not get a complete buffer so is stuck in prerolling. default queue size:5s,which filled up with < 1min25sec 'data,but we want > 1min30sec data(SEGMENT time segment start=0:01:30.000000000 ) default gstsegment.c:835:gst_segment_to_running_time: position(84600000000) < start(90000000000) default gstsegment.c:835:gst_segment_to_running_time: position(84600000000) < start(90000000000) ... So the situation is ,undecoded queue data filled with garbage data, and blocked the demux component, but vqueue / aqueue no valid data to complete preroll. I verified, if the queue is set to <(default_size=5s) + (1min30sec-1min25sec=5s)= 10s>, preroll ok. My question is, since we already have a new segment, why not drop most of data < newsegment.start to avoid the above situation? Such as queue max_size = 5s, we make sure that the new data enqueue meets following requirements: * newdata.position + 1s < segment.start ,drop (1s is just an example, perhaps a value between 1 and 5 s?) Above is only my personal understanding, please do not hesitate to correct me. -)
Your analysis sounds plausible, and this seems to be completely unrelated to GstPlayer indeed. It might be related to how adaptivedemux is doing things though, so let's move it there for now.
(In reply to Sebastian Dröge (slomo) from comment #3) > Your analysis sounds plausible, and this seems to be completely unrelated to > GstPlayer indeed. > Yes,just used to write the test code using Gstplayer. > It might be related to how adaptivedemux is doing things though, so let's > move it there for now. gstadaptivedemux.c gst_adaptive_demux_prepare_streams()'s code annotation, seems to have dealt with this situation? ----------------- /* The demuxer segment is just built from seek events, but for each stream * we have to adjust segments according to the current period and the * stream specific presentation time offset. * * For each period, buffer timestamps start again from 0. Additionally the * buffer timestamps are shifted by the stream specific presentation time * offset, so the first buffer timestamp of a period is 0 + presentation * time offset. If the stream contains timestamps itself, this is also * supposed to be the presentation time stored inside the stream. * * The stream time over periods is supposed to be continuous, that is the * buffer timestamp 0 + presentation time offset should map to the start * time of the current period. * * * The adjustment of the stream segments as such works the following. * * If the demuxer segment start is bigger than the period start, this * means that we have to drop some media at the beginning of the current * period, e.g. because a seek into the middle of the period has * happened. The amount of media to drop is the difference between the * period start and the demuxer segment start, and as each period starts * again from 0, this difference is going to be the actual stream's * segment start. As all timestamps of the stream are shifted by the * presentation time offset, we will also have to move the segment start * by that offset. * * Likewise, the demuxer segment stop value is adjusted in the same * fashion. * * Now the running time and stream time at the stream's segment start has * to be the one that is stored inside the demuxer's segment, which means * that segment.base and segment.time have to be copied over (done just * above) -----------------
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/609.