summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <edward@centricular.com>2017-05-09 11:41:49 +0200
committerEdward Hervey <bilboed@bilboed.com>2017-07-13 11:15:38 +0200
commitb80b11cce97b8e5432c0ca5a4f50b432b82dd130 (patch)
tree52f48ecf9ed5fe956104c39dbdaf1cdec609195a
parentdfbf187073a82288c6b51f591b3b82c37b2ffade (diff)
downloadgstreamer-plugins-bad-b80b11cce97b8e5432c0ca5a4f50b432b82dd130.tar.gz
adaptivedemux: Handle prepared streams on seeks
This is a race that was exposed by the {hls|dash}.scrub_forward_seeking validate test. The "race" is that a subclass might want to change format, causing a new stream to be created (but not exposed/switched yet) and put on the prepared_streams list. That stream will have values (including pending segment) from the pre-seek state. Before the stream is exposed/switched, a new seek comes in and the stream values get updated ... but the ones that will be changed don't get updated causing them to push out wrong segments once they are exposed. https://bugzilla.gnome.org/show_bug.cgi?id=773159
-rw-r--r--gst-libs/gst/adaptivedemux/gstadaptivedemux.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
index 3c98eac12..ddcc8126f 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
@@ -1702,6 +1702,35 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux, GstPad * pad,
seg_evt = gst_event_new_segment (&stream->segment);
gst_event_set_seqnum (seg_evt, demux->priv->segment_seqnum);
gst_event_replace (&stream->pending_segment, seg_evt);
+ GST_DEBUG_OBJECT (stream->pad, "Pending segment now %" GST_SEGMENT_FORMAT,
+ &stream->pending_segment);
+ gst_event_unref (seg_evt);
+ /* Make sure the first buffer after a seek has the discont flag */
+ stream->discont = TRUE;
+ }
+ /* Same thing but for prepared streams that haven't been exposed yet */
+ for (iter = demux->prepared_streams; iter; iter = g_list_next (iter)) {
+ GstAdaptiveDemuxStream *stream = iter->data;
+ GstEvent *seg_evt;
+ GstClockTime offset;
+
+ /* See comments in gst_adaptive_demux_get_period_start_time() for
+ * an explanation of the segment modifications */
+ stream->segment = demux->segment;
+ offset =
+ gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
+ stream->segment.start += offset - period_start;
+ if (GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
+ stream->segment.stop += offset - period_start;
+ if (demux->segment.rate > 0 && start_type != GST_SEEK_TYPE_NONE)
+ stream->segment.position = stream->segment.start;
+ else if (demux->segment.rate < 0 && stop_type != GST_SEEK_TYPE_NONE)
+ stream->segment.position = stream->segment.stop;
+ seg_evt = gst_event_new_segment (&stream->segment);
+ gst_event_set_seqnum (seg_evt, demux->priv->segment_seqnum);
+ gst_event_replace (&stream->pending_segment, seg_evt);
+ GST_DEBUG_OBJECT (stream->pad, "Pending segment now %" GST_SEGMENT_FORMAT,
+ &stream->pending_segment);
gst_event_unref (seg_evt);
/* Make sure the first buffer after a seek has the discont flag */
stream->discont = TRUE;