diff options
author | Thiago Santos <thiagoss@osg.samsung.com> | 2016-01-27 13:31:10 -0300 |
---|---|---|
committer | Thiago Santos <thiagoss@osg.samsung.com> | 2016-02-04 14:05:08 -0300 |
commit | 731ab94cc3ffc7dd906423a008ceca94962ab992 (patch) | |
tree | b78eb5fbc0af4a07259cec8234add88555fe1089 /gst-libs | |
parent | f16916f7e7e29c145c9fc99ca53b66f71acf5f1b (diff) |
adaptivedemux: handle snap seeks
Adaptive demuxers need to start downloading from specific positions
(fragments) for every stream, this means that all streams can snap-seek
to a different position when requested. Snap seeking in this case will
be done in 2 steps:
1) do the snap seeking on the pad that received the seek event and
get the final position
2) use this position to do a regular seek on the other streams to
make sure they all start from the same position
More arguments were added to the stream_seek function, allowing better control
of how seeking is done. Knowing the flags and the playback direction allows
subclasses to handle snap-seeking.
And also adds a new return parameter to inform of the final
selected seeking position that is used to align the other streams.
https://bugzilla.gnome.org/show_bug.cgi?id=759158
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/adaptivedemux/gstadaptivedemux.c | 71 | ||||
-rw-r--r-- | gst-libs/gst/adaptivedemux/gstadaptivedemux.h | 2 |
2 files changed, 64 insertions, 9 deletions
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c index c21584f6f..c1658bf60 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c @@ -230,7 +230,8 @@ static gboolean gst_adaptive_demux_expose_streams (GstAdaptiveDemux * demux, gboolean first_and_live); static gboolean gst_adaptive_demux_is_live (GstAdaptiveDemux * demux); static GstFlowReturn gst_adaptive_demux_stream_seek (GstAdaptiveDemux * demux, - GstAdaptiveDemuxStream * stream, GstClockTime ts); + GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags, + GstClockTime ts, GstClockTime * final_ts); static gboolean gst_adaptive_demux_stream_has_next_fragment (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream); static gboolean gst_adaptive_demux_stream_select_bitrate (GstAdaptiveDemux * @@ -1205,6 +1206,13 @@ gst_adaptive_demux_can_seek (GstAdaptiveDemux * demux) return klass->seek != NULL; } +#define IS_SNAP_SEEK(f) (f & (GST_SEEK_FLAG_SNAP_BEFORE | \ + GST_SEEK_FLAG_SNAP_AFTER | \ + GST_SEEK_FLAG_SNAP_NEAREST)) +#define REMOVE_SNAP_FLAGS(f) (f & !(GST_SEEK_FLAG_SNAP_BEFORE | \ + GST_SEEK_FLAG_SNAP_AFTER | \ + GST_SEEK_FLAG_SNAP_NEAREST)) + static gboolean gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event) @@ -1215,6 +1223,8 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent, demux = GST_ADAPTIVE_DEMUX_CAST (parent); demux_class = GST_ADAPTIVE_DEMUX_GET_CLASS (demux); + /* FIXME handle events received on pads that are to be removed */ + switch (event->type) { case GST_EVENT_SEEK: { @@ -1270,10 +1280,7 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent, seqnum = gst_event_get_seqnum (event); - GST_DEBUG_OBJECT (demux, - "seek event, rate: %f type: %d start: %" GST_TIME_FORMAT " stop: %" - GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start), - GST_TIME_ARGS (stop)); + GST_DEBUG_OBJECT (demux, "seek event, %" GST_PTR_FORMAT, event); /* have a backup in case seek fails */ gst_segment_copy_into (&demux->segment, &oldsegment); @@ -1309,6 +1316,52 @@ gst_adaptive_demux_src_event (GstPad * pad, GstObject * parent, GST_DEBUG_OBJECT (demux, "Seeking to segment %" GST_SEGMENT_FORMAT, &demux->segment); + /* + * Handle snap seeks as follows: + * 1) do the snap seeking on the stream that received + * the event + * 2) use the final position on this stream to seek + * on the other streams to the same position + * + * We can't snap at all streams at the same time as + * they might end in different positions, so just + * use the one that received the event as the 'leading' + * one to do the snap seek. + */ + if (IS_SNAP_SEEK (flags) && demux_class->stream_seek) { + GstAdaptiveDemuxStream *stream = + gst_adaptive_demux_find_stream_for_pad (demux, pad); + GstClockTime ts; + GstSeekFlags stream_seek_flags = flags; + + /* snap-seek on the stream that received the event and then + * use the resulting position to seek on all streams */ + + if (rate >= 0 && start_type != GST_SEEK_TYPE_NONE) { + ts = start; + } else if (rate < 0 && stop_type != GST_SEEK_TYPE_NONE) { + ts = stop; + } + + ret = + demux_class->stream_seek (stream, rate >= 0, stream_seek_flags, ts, + &ts); + + /* replace event with a new one without snaping to seek on all streams */ + gst_event_unref (event); + if (rate >= 0 && start_type != GST_SEEK_TYPE_NONE) { + start = ts; + } else if (rate < 0 && stop_type != GST_SEEK_TYPE_NONE) { + stop = ts; + } + event = + gst_event_new_seek (rate, format, REMOVE_SNAP_FLAGS (flags), + start_type, start, stop_type, stop); + GST_DEBUG_OBJECT (demux, "Adapted snap seek to %" GST_PTR_FORMAT, + event); + } + GST_DEBUG_OBJECT (demux, "Calling subclass seek: %" GST_PTR_FORMAT, + event); ret = demux_class->seek (demux, event); if (!ret) { @@ -2686,7 +2739,8 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream) period_start = gst_adaptive_demux_get_period_start_time (demux); /* TODO check return */ - gst_adaptive_demux_stream_seek (demux, stream, ts); + gst_adaptive_demux_stream_seek (demux, stream, demux->segment.rate >= 0, + 0, ts, &ts); segment.position = ts - period_start + offset; } @@ -3050,12 +3104,13 @@ gst_adaptive_demux_is_live (GstAdaptiveDemux * demux) /* must be called with manifest_lock taken */ static GstFlowReturn gst_adaptive_demux_stream_seek (GstAdaptiveDemux * demux, - GstAdaptiveDemuxStream * stream, GstClockTime ts) + GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags, + GstClockTime ts, GstClockTime * final_ts) { GstAdaptiveDemuxClass *klass = GST_ADAPTIVE_DEMUX_GET_CLASS (demux); if (klass->stream_seek) - return klass->stream_seek (stream, ts); + return klass->stream_seek (stream, forward, flags, ts, final_ts); return GST_FLOW_ERROR; } diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h index e7ce22783..55f3992ad 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h @@ -310,7 +310,7 @@ struct _GstAdaptiveDemuxClass void (*advance_period) (GstAdaptiveDemux * demux); void (*stream_free) (GstAdaptiveDemuxStream * stream); - GstFlowReturn (*stream_seek) (GstAdaptiveDemuxStream * stream, GstClockTime ts); + GstFlowReturn (*stream_seek) (GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags, GstClockTime target_ts, GstClockTime * final_ts); gboolean (*stream_has_next_fragment) (GstAdaptiveDemuxStream * stream); GstFlowReturn (*stream_advance_fragment) (GstAdaptiveDemuxStream * stream); /** |