mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
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
This commit is contained in:
parent
626a8f0a74
commit
548ed60e86
1 changed files with 43 additions and 21 deletions
|
@ -122,6 +122,7 @@ struct _GstAdaptiveDemuxPrivate
|
||||||
gint64 next_update;
|
gint64 next_update;
|
||||||
|
|
||||||
gboolean exposing;
|
gboolean exposing;
|
||||||
|
guint32 segment_seqnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstBinClass *parent_class = NULL;
|
static GstBinClass *parent_class = NULL;
|
||||||
|
@ -332,6 +333,9 @@ gst_adaptive_demux_init (GstAdaptiveDemux * demux,
|
||||||
demux->priv->input_adapter = gst_adapter_new ();
|
demux->priv->input_adapter = gst_adapter_new ();
|
||||||
demux->downloader = gst_uri_downloader_new ();
|
demux->downloader = gst_uri_downloader_new ();
|
||||||
demux->stream_struct_size = sizeof (GstAdaptiveDemuxStream);
|
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);
|
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
@ -592,6 +596,7 @@ gst_adaptive_demux_reset (GstAdaptiveDemux * demux)
|
||||||
demux->have_group_id = FALSE;
|
demux->have_group_id = FALSE;
|
||||||
demux->group_id = G_MAXUINT;
|
demux->group_id = G_MAXUINT;
|
||||||
demux->priv->exposing = FALSE;
|
demux->priv->exposing = FALSE;
|
||||||
|
demux->priv->segment_seqnum = gst_util_seqnum_next ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -762,14 +767,19 @@ gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux,
|
||||||
|
|
||||||
offset = gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
|
offset = gst_adaptive_demux_stream_get_presentation_offset (demux, stream);
|
||||||
stream->segment = demux->segment;
|
stream->segment = demux->segment;
|
||||||
stream->segment.start = stream->segment.position = stream->segment.time =
|
|
||||||
stream->fragment.timestamp + offset;
|
|
||||||
|
|
||||||
stream->segment.base =
|
if (first_segment)
|
||||||
gst_segment_to_running_time (&demux->segment, GST_FORMAT_TIME,
|
demux->segment.start = demux->segment.position = demux->segment.time =
|
||||||
stream->segment.start);
|
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);
|
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));
|
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;
|
GstSeekType start_type, stop_type;
|
||||||
gint64 start, stop;
|
gint64 start, stop;
|
||||||
guint32 seqnum;
|
guint32 seqnum;
|
||||||
GList *iter;
|
|
||||||
gboolean update;
|
gboolean update;
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
GstSegment oldsegment;
|
GstSegment oldsegment;
|
||||||
|
@ -1005,20 +1014,11 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent,
|
||||||
GST_MANIFEST_LOCK (demux);
|
GST_MANIFEST_LOCK (demux);
|
||||||
ret = demux_class->seek (demux, event);
|
ret = demux_class->seek (demux, event);
|
||||||
|
|
||||||
if (ret) {
|
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 {
|
|
||||||
/* Is there anything else we can do if it fails? */
|
/* Is there anything else we can do if it fails? */
|
||||||
gst_segment_copy_into (&oldsegment, &demux->segment);
|
gst_segment_copy_into (&oldsegment, &demux->segment);
|
||||||
|
} else {
|
||||||
|
demux->priv->segment_seqnum = seqnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & GST_SEEK_FLAG_FLUSH) {
|
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_event_set_seqnum (fevent, seqnum);
|
||||||
gst_adaptive_demux_push_src_event (demux, fevent);
|
gst_adaptive_demux_push_src_event (demux, fevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demux->next_streams) {
|
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 */
|
/* Restart the demux */
|
||||||
|
@ -1987,7 +2005,7 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
|
||||||
if (G_UNLIKELY (stream->restart_download)) {
|
if (G_UNLIKELY (stream->restart_download)) {
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
GstEvent *seg_event;
|
GstEvent *seg_event;
|
||||||
GstClockTime cur, ts;
|
GstClockTime cur, ts, offset;
|
||||||
gint64 pos;
|
gint64 pos;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (stream->pad,
|
GST_DEBUG_OBJECT (stream->pad,
|
||||||
|
@ -2034,7 +2052,11 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
|
||||||
segment.position = ts;
|
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_DEBUG_OBJECT (stream->pad, "Sending restart segment: %"
|
||||||
GST_PTR_FORMAT, seg_event);
|
GST_PTR_FORMAT, seg_event);
|
||||||
gst_pad_push_event (stream->pad, seg_event);
|
gst_pad_push_event (stream->pad, seg_event);
|
||||||
|
|
Loading…
Reference in a new issue