From 80c6973319b91c375b944cc92af1ac82f86bcc1e Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 28 Jan 2013 19:43:46 -0300 Subject: [PATCH] dashdemux: fix seeking on multiple streams Each stream has its own durations and timestamps, the fragment number is different for each stream when seeking, so the seek has to be done for all streams, rather than on a single stream and propagated to others --- ext/dash/gstdashdemux.c | 91 ++++++++++++++++++++--------------------- ext/dash/gstmpdparser.c | 4 +- ext/dash/gstmpdparser.h | 1 + 3 files changed, 46 insertions(+), 50 deletions(-) diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index 4c62f4e3af..3d5b1a0a27 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -531,10 +531,9 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event) GList *list; GstClockTime current_pos, target_pos; guint current_sequence, current_period; - GstActiveStream *stream; + GstActiveStream *active_stream; GstMediaSegment *chunk; GstStreamPeriod *period; - guint nb_active_stream; GSList *iter; GST_WARNING_OBJECT (demux, "Received seek event"); @@ -555,6 +554,26 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event) GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); + if (flags & GST_SEEK_FLAG_FLUSH) { + GST_DEBUG_OBJECT (demux, "sending flush start"); + for (iter = demux->streams; iter; iter = g_slist_next (iter)) { + GstDashDemuxStream *stream; + stream = iter->data; + gst_pad_push_event (stream->pad, gst_event_new_flush_start ()); + } + } + + /* Stop the demux */ + demux->cancelled = TRUE; + gst_dash_demux_stop (demux); + + /* Wait for streaming to finish */ + g_static_rec_mutex_lock (&demux->stream_lock); + + /* Clear the buffering queue */ + /* FIXME: allow seeking in the buffering queue */ + gst_dash_demux_clear_queues (demux); + //GST_MPD_CLIENT_LOCK (demux->client); /* select the requested Period in the Media Presentation */ @@ -582,57 +601,35 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event) return FALSE; } - stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0); - current_pos = 0; - current_sequence = 0; - for (list = g_list_first (stream->segments); list; - list = g_list_next (list)) { - chunk = list->data; - current_pos = chunk->start_time; - //current_sequence = chunk->number; - GST_WARNING_OBJECT (demux, "%llu <= %llu (%llu)", current_pos, - target_pos, chunk->duration); - if (current_pos <= target_pos - && target_pos < current_pos + chunk->duration) { - break; - } - current_sequence++; - } - //GST_MPD_CLIENT_UNLOCK (demux->client); - if (list == NULL) { GST_WARNING_OBJECT (demux, "Could not find seeked fragment"); return FALSE; } - /* We can actually perform the seek */ - nb_active_stream = gst_mpdparser_get_nb_active_stream (demux->client); - - if (flags & GST_SEEK_FLAG_FLUSH) { - GST_DEBUG_OBJECT (demux, "sending flush start"); - for (iter = demux->streams; iter; iter = g_slist_next (iter)) { - GstDashDemuxStream *stream; - stream = iter->data; - gst_pad_push_event (stream->pad, gst_event_new_flush_start ()); - } - } - - /* Stop the demux */ - demux->cancelled = TRUE; - gst_dash_demux_stop (demux); - - /* Wait for streaming to finish */ - g_static_rec_mutex_lock (&demux->stream_lock); - - /* Clear the buffering queue */ - /* FIXME: allow seeking in the buffering queue */ - gst_dash_demux_clear_queues (demux); - - //GST_MPD_CLIENT_LOCK (demux->client); - GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence); /* Update the current sequence on all streams */ - gst_mpd_client_set_segment_index_for_all_streams (demux->client, - current_sequence); + for (iter = demux->streams; iter; iter = g_slist_next (iter)) { + GstDashDemuxStream *stream = iter->data; + + active_stream = + gst_mpdparser_get_active_stream_by_index (demux->client, + stream->index); + current_pos = 0; + current_sequence = 0; + for (list = g_list_first (active_stream->segments); list; + list = g_list_next (list)) { + chunk = list->data; + current_pos = chunk->start_time; + //current_sequence = chunk->number; + GST_WARNING_OBJECT (demux, "%llu <= %llu (%llu)", current_pos, + target_pos, chunk->duration); + if (current_pos <= target_pos + && target_pos < current_pos + chunk->duration) { + break; + } + current_sequence++; + } + gst_mpd_client_set_segment_index (active_stream, current_sequence); + } /* Calculate offset in the next fragment */ demux->position = gst_mpd_client_get_current_position (demux->client); demux->position_shift = start - demux->position; diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c index 3d464c5fc6..0339046781 100644 --- a/ext/dash/gstmpdparser.c +++ b/ext/dash/gstmpdparser.c @@ -127,8 +127,6 @@ static gboolean gst_mpd_client_add_media_segment (GstActiveStream * stream, GstClockTime start_time, GstClockTime duration); static const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType); static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client); -static void gst_mpd_client_set_segment_index (GstActiveStream * stream, - guint segment_idx); /* Adaptation Set */ static GstAdaptationSetNode @@ -3338,7 +3336,7 @@ gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, } } -static void +void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx) { g_return_if_fail (stream != NULL); diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h index 3fafe884a5..632f455abd 100644 --- a/ext/dash/gstmpdparser.h +++ b/ext/dash/gstmpdparser.h @@ -496,6 +496,7 @@ guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client); /* Segment */ void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx); guint gst_mpd_client_get_segment_index (GstActiveStream * stream); +void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx); /* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */ const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream);