Commit 548ed60e authored by Sebastian Dröge's avatar Sebastian Dröge 🍵
Browse files

adaptivedemux: Properly handle presentationTimeOffset for seeking and multi-period streams

Segment start/time/position/base should only be modified if this is the first
time we send a segment, otherwise we will override values from the seek
segment if new streams have to be exposed as part of the seek.

Segment base should be calculated from the segment start based on the stream's
own segment, not the demuxer's segment. Both might differ slightly because of
the presentationTimeOffset.

Always add the presentationTimeOffset (relative to the period start, not
timestamp 0) to the segment start after resetting the stream's segment based
on the demuxer's segment (i.e. after seeks or stream restart). Also make sure
to keep the stream's segment up to date and not just send a new segment event
without storing the segment in the stream.

https://bugzilla.gnome.org/show_bug.cgi?id=745455
parent 626a8f0a
......@@ -122,6 +122,7 @@ struct _GstAdaptiveDemuxPrivate
gint64 next_update;
gboolean exposing;
guint32 segment_seqnum;
};
static GstBinClass *parent_class = NULL;
......@@ -332,6 +333,9 @@ gst_adaptive_demux_init (GstAdaptiveDemux * demux,
demux->priv->input_adapter = gst_adapter_new ();
demux->downloader = gst_uri_downloader_new ();
demux->stream_struct_size = sizeof (GstAdaptiveDemuxStream);
demux->priv->segment_seqnum = gst_util_seqnum_next ();
demux->have_group_id = FALSE;
demux->group_id = G_MAXUINT;
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
......@@ -592,6 +596,7 @@ gst_adaptive_demux_reset (GstAdaptiveDemux * demux)
demux->have_group_id = FALSE;
demux->group_id = G_MAXUINT;
demux->priv->exposing = FALSE;
demux->priv->segment_seqnum = gst_util_seqnum_next ();
}
static void
......@@ -762,14 +767,19 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
offset = gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
stream->segment = demux->segment;
stream->segment.start = stream->segment.position = stream->segment.time =
stream->fragment.timestamp + offset;
stream->segment.base =
gst_segment_to_running_time (&demux->segment, GST_FORMAT_TIME,
stream->segment.start);
if (first_segment)
demux->segment.start = demux->segment.position = demux->segment.time =
stream->fragment.timestamp;
stream->segment.start += offset;
if (first_segment)
stream->segment.base =
gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME,
stream->segment.start);
stream->pending_segment = gst_event_new_segment (&stream->segment);
gst_event_set_seqnum (stream->pending_segment, demux->priv->segment_seqnum);
}
gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
......@@ -940,7 +950,6 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent,
GstSeekType start_type, stop_type;
gint64 start, stop;
guint32 seqnum;
GList *iter;
gboolean update;
gboolean ret = TRUE;
GstSegment oldsegment;
......@@ -1005,20 +1014,11 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent,
GST_MANIFEST_LOCK (demux);
ret = demux_class->seek (demux, event);
if (ret) {
GstEvent *seg_evt;
seg_evt = gst_event_new_segment (&demux->segment);
gst_event_set_seqnum (seg_evt, seqnum);
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
GstAdaptiveDemuxStream *stream = iter->data;
gst_event_replace (&stream->pending_segment, seg_evt);
}
gst_event_unref (seg_evt);
} else {
if (!ret) {
/* Is there anything else we can do if it fails? */
gst_segment_copy_into (&oldsegment, &demux->segment);
} else {
demux->priv->segment_seqnum = seqnum;
}
if (flags & GST_SEEK_FLAG_FLUSH) {
......@@ -1029,8 +1029,26 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent,
gst_event_set_seqnum (fevent, seqnum);
gst_adaptive_demux_push_src_event (demux, fevent);
}
if (demux->next_streams) {
gst_adaptive_demux_expose_streams (demux, TRUE);
gst_adaptive_demux_expose_streams (demux, FALSE);
} else {
GstEvent *seg_evt;
GList *iter;
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
GstAdaptiveDemuxStream *stream = iter->data;
GstClockTime offset;
stream->segment = demux->segment;
offset =
gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
stream->segment.start += offset;
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_event_unref (seg_evt);
}
/* Restart the demux */
......@@ -1987,7 +2005,7 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
if (G_UNLIKELY (stream->restart_download)) {
GstSegment segment;
GstEvent *seg_event;
GstClockTime cur, ts;
GstClockTime cur, ts, offset;
gint64 pos;
GST_DEBUG_OBJECT (stream->pad,
......@@ -2034,7 +2052,11 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
segment.position = ts;
}
}
seg_event = gst_event_new_segment (&segment);
stream->segment = segment;
offset = gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
stream->segment.start += offset;
seg_event = gst_event_new_segment (&stream->segment);
gst_event_set_seqnum (seg_event, demux->priv->segment_seqnum);
GST_DEBUG_OBJECT (stream->pad, "Sending restart segment: %"
GST_PTR_FORMAT, seg_event);
gst_pad_push_event (stream->pad, seg_event);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment