dashdemux: fix seeking on multiple streams
authorThiago Santos <thiago.sousa.santos@collabora.com>
Mon, 28 Jan 2013 22:43:46 +0000 (19:43 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 21:14:34 +0000 (18:14 -0300)
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
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 4c62f4e3aff0eca4b1936f1014b3e0f9d701ceb4..3d5b1a0a270580c44dfcb8a928cc0ae99aedc432 100644 (file)
@@ -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);
+      /* Update the current sequence on all streams */
+      for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
+        GstDashDemuxStream *stream = iter->data;
 
-      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 ());
+        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);
       }
-
-      /* 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);
       /* Calculate offset in the next fragment */
       demux->position = gst_mpd_client_get_current_position (demux->client);
       demux->position_shift = start - demux->position;
index 3d464c5fc634586a92d681b7713e1cbda3584425..0339046781a374002a8c06891688e70a5c48c843 100644 (file)
@@ -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);
index 3fafe884a5ad36045520552e2ffd2971525d0b3c..632f455abdab671532324ded20dff922fde75e59 100644 (file)
@@ -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);