summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorThiago Santos <thiagoss@osg.samsung.com>2016-01-27 13:31:10 -0300
committerThiago Santos <thiagoss@osg.samsung.com>2016-02-04 14:05:08 -0300
commit731ab94cc3ffc7dd906423a008ceca94962ab992 (patch)
treeb78eb5fbc0af4a07259cec8234add88555fe1089 /gst-libs
parentf16916f7e7e29c145c9fc99ca53b66f71acf5f1b (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.c71
-rw-r--r--gst-libs/gst/adaptivedemux/gstadaptivedemux.h2
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);
/**