dashdemux: complete support for manifest file updates
authorGianluca Gennari <gennarone@gmail.com>
Mon, 17 Dec 2012 14:19:33 +0000 (15:19 +0100)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 21:14:32 +0000 (18:14 -0300)
ext/dash/gstdashdemux.c
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 29a66eb..c98faf4 100644 (file)
@@ -508,7 +508,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
           GST_TIME_FORMAT, rate, start_type, GST_TIME_ARGS (start),
           GST_TIME_ARGS (stop));
 
-      GST_MPD_CLIENT_LOCK (demux->client);
+      //GST_MPD_CLIENT_LOCK (demux->client);
 
       /* select the requested Period in the Media Presentation */
       target_pos = (GstClockTime) start;
@@ -545,7 +545,7 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
           break;
         }
       }
-      GST_MPD_CLIENT_UNLOCK (demux->client);
+      //GST_MPD_CLIENT_UNLOCK (demux->client);
 
       if (list == NULL) {
         GST_WARNING_OBJECT (demux, "Could not find seeked fragment");
@@ -576,21 +576,15 @@ gst_dash_demux_src_event (GstPad * pad, GstEvent * event)
       /* FIXME: allow seeking in the buffering queue */
       gst_dash_demux_clear_queue (demux);
 
-      GST_MPD_CLIENT_LOCK (demux->client);
+      //GST_MPD_CLIENT_LOCK (demux->client);
       GST_DEBUG_OBJECT (demux, "Seeking to sequence %d", current_sequence);
       /* Update the current sequence on all streams */
-      for (stream_idx = 0; stream_idx < nb_active_stream; stream_idx++) {
-        stream =
-            gst_mpdparser_get_active_stream_by_index (demux->client,
-            stream_idx);
-        gst_mpd_client_set_segment_index (stream, current_sequence);
-      }
+      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;
       demux->need_segment = TRUE;
-      GST_MPD_CLIENT_UNLOCK (demux->client);
-
+      //GST_MPD_CLIENT_UNLOCK (demux->client);
 
       if (flags & GST_SEEK_FLAG_FLUSH) {
         GST_DEBUG_OBJECT (demux, "Sending flush stop on all pad");
@@ -624,6 +618,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
   guint i, nb_audio;
   gchar *lang;
 
+  GST_MPD_CLIENT_LOCK (demux->client);
   /* clean old active stream list, if any */
   gst_active_streams_free (demux->client);
 
@@ -649,6 +644,7 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
               GST_STREAM_APPLICATION, lang))
         GST_INFO_OBJECT (demux, "No application adaptation set found");
   }
+  GST_MPD_CLIENT_UNLOCK (demux->client);
 
   return TRUE;
 }
@@ -712,6 +708,9 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
           !gst_dash_demux_setup_all_streams (demux))
         return FALSE;
 
+      /* start playing from the first segment */
+      gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
+
       /* Send duration message */
       if (!gst_mpd_client_is_live (demux->client)) {
         GstClockTime duration =
@@ -1230,7 +1229,12 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
           GST_WARNING_OBJECT (demux, "Error parsing the manifest.");
           gst_buffer_unref (buffer);
         } else {
+          GstActiveStream *stream;
+          guint segment_index;
+
           gst_buffer_unref (buffer);
+          stream = gst_mpdparser_get_active_stream_by_index (demux->client, 0);
+          segment_index = gst_mpd_client_get_segment_index (stream);
           /* setup video, audio and subtitle streams, starting from first Period */
           if (!gst_mpd_client_setup_media_presentation (demux->client) ||
               !gst_mpd_client_set_period_index (demux->client, gst_mpd_client_get_period_index (demux->client)) ||
@@ -1238,6 +1242,10 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
             GST_DEBUG_OBJECT (demux, "Error setting up the updated manifest file");
             goto end_of_manifest;
           }
+          /* continue playing from the the next segment */
+          /* FIXME: support multiple streams with different segment duration */
+          gst_mpd_client_set_segment_index_for_all_streams (demux->client, segment_index);
+
           /* Send an updated duration message */
           duration = gst_mpd_client_get_media_presentation_duration (demux->client);
 
@@ -1298,6 +1306,8 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
           gst_task_start (demux->stream_task);
           goto end_of_manifest;
         }
+        /* start playing from the first segment of the new period */
+        gst_mpd_client_set_segment_index_for_all_streams (demux->client, 0);
         demux->end_of_period = FALSE;
       } else if (!demux->cancelled) {
         demux->client->update_failed_count++;
index 58c6ffe..5d0a844 100644 (file)
@@ -70,7 +70,7 @@ static void gst_mpdparser_parse_period_node (GList ** list, xmlNode * a_node);
 static void gst_mpdparser_parse_program_info_node (GList ** list, xmlNode * a_node);
 static void gst_mpdparser_parse_metrics_range_node (GList ** list, xmlNode * a_node);
 static void gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node);
-static void gst_mpdparser_parse_root_node (GstMpdClient * client, xmlNode *a_node);
+static void gst_mpdparser_parse_root_node (GstMPDNode ** pointer, xmlNode * a_node);
 
 /* Helper functions */
 static gint convert_to_millisecs (gint decimals, gint pos);
@@ -84,6 +84,7 @@ static gchar *gst_mpdparser_build_URL_from_template (const gchar *url_template,
 static gboolean gst_mpd_client_add_media_segment (GstActiveStream *stream, GstSegmentURLNode *url_node, guint number, guint start, 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 *gst_mpdparser_get_first_adapt_set_with_mimeType (GList *AdaptationSets, const gchar *mimeType);
@@ -1487,13 +1488,13 @@ gst_mpdparser_parse_metrics_node (GList ** list, xmlNode * a_node)
 }
 
 static void
-gst_mpdparser_parse_root_node (GstMpdClient * client, xmlNode *a_node)
+gst_mpdparser_parse_root_node (GstMPDNode ** pointer, xmlNode * a_node)
 {
   xmlNode *cur_node;
   GstMPDNode *new_mpd;
 
-  gst_mpdparser_free_mpd_node (client->mpd_node);
-  client->mpd_node = new_mpd = g_slice_new0 (GstMPDNode);
+  gst_mpdparser_free_mpd_node (*pointer);
+  *pointer = new_mpd = g_slice_new0 (GstMPDNode);
   if (new_mpd == NULL) {
     GST_WARNING ("Allocation of MPD node failed!");
     return;
@@ -2258,7 +2259,7 @@ gst_mpdparser_get_stream_period (GstMpdClient * client)
   g_return_val_if_fail (client != NULL, NULL);
   g_return_val_if_fail (client->periods != NULL, NULL);
 
-  return g_list_nth_data (client->periods, gst_mpd_client_get_period_index (client));
+  return g_list_nth_data (client->periods, client->period_idx);
 }
 
 /* select a stream and extract the baseURL (if present) */
@@ -2446,7 +2447,7 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
         GST_ERROR ("can not find the root element MPD, failed to parse the MPD file");
       } else {
         /* now we can parse the MPD root node and all children nodes, recursively */
-        gst_mpdparser_parse_root_node (client, root_element);
+        gst_mpdparser_parse_root_node (&client->mpd_node, root_element);
       }
       /* free the document */
       xmlFreeDoc (doc);
@@ -2726,6 +2727,7 @@ gst_mpd_client_setup_media_presentation (GstMpdClient *client)
   g_return_val_if_fail (client->mpd_node != NULL, FALSE);
 
   GST_DEBUG ("Building the list of Periods in the Media Presentation");
+  GST_MPD_CLIENT_LOCK (client);
   /* clean the old period list, if any */
   if (client->periods) {
     g_list_foreach (client->periods,
@@ -2786,18 +2788,22 @@ gst_mpd_client_setup_media_presentation (GstMpdClient *client)
         GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
   }
 
+  GST_MPD_CLIENT_UNLOCK (client);
   GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", idx);
   return ret;
 
 early:
+  GST_MPD_CLIENT_UNLOCK (client);
   GST_WARNING ("Found an Early Available Period, skipping the rest of the Media Presentation");
   return ret;
 
 syntax_error:
+  GST_MPD_CLIENT_UNLOCK (client);
   GST_WARNING ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation", idx);
   return ret;
 
 no_mem:
+  GST_MPD_CLIENT_UNLOCK (client);
   GST_WARNING ("Allocation of GstStreamPeriod struct failed!");
   return FALSE;
 }
@@ -2882,9 +2888,7 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
 
   stream->baseURL_idx = 0;
   stream->mimeType = mimeType;
-  stream->representation_idx = 0;
   stream->cur_adapt_set = adapt_set;
-  gst_mpd_client_set_segment_index (stream, 0);
 
   /* retrive representation list */
   if (stream->cur_adapt_set != NULL)
@@ -3062,34 +3066,65 @@ gboolean
 gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx)
 {
   GstStreamPeriod *next_stream_period;
+  gboolean ret = FALSE;
 
   g_return_val_if_fail (client != NULL, FALSE);
   g_return_val_if_fail (client->periods != NULL, FALSE);
 
+  GST_MPD_CLIENT_LOCK (client);
   next_stream_period = g_list_nth_data (client->periods, period_idx);
-  if (next_stream_period == NULL)
-    return FALSE;
-
-  client->period_idx = period_idx;
+  if (next_stream_period != NULL) {
+    client->period_idx = period_idx;
+    ret = TRUE;
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
 
-  return TRUE;
+  return ret;
 }
 
 guint
 gst_mpd_client_get_period_index (GstMpdClient *client)
 {
-  return client->period_idx;
+  guint period_idx;
+
+  g_return_val_if_fail (client != NULL, 0);
+  GST_MPD_CLIENT_LOCK (client);
+  period_idx = client->period_idx;
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return period_idx;
 }
 
 void
+gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient *client, guint segment_idx)
+{
+  GList *list;
+
+  g_return_if_fail (client != NULL);
+  g_return_if_fail (client->active_streams != NULL);
+
+  /* FIXME: support multiple streams with different segment duration */
+  for (list = g_list_first (client->active_streams); list; list = g_list_next (list)) {
+    GstActiveStream *stream = (GstActiveStream *) list->data;
+    if (stream) {
+      stream->segment_idx = segment_idx;
+    }
+  }
+}
+
+static void
 gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx)
 {
+  g_return_if_fail (stream != NULL);
+
   stream->segment_idx = segment_idx;
 }
 
 guint
 gst_mpd_client_get_segment_index (GstActiveStream * stream)
 {
+  g_return_val_if_fail (stream != NULL, 0);
+
   return stream->segment_idx;
 }
 
@@ -3103,8 +3138,8 @@ gst_mpd_client_is_live (GstMpdClient * client)
 }
 
 guint
-gst_mpdparser_get_nb_active_stream (GstMpdClient *client){
-
+gst_mpdparser_get_nb_active_stream (GstMpdClient *client)
+{
   g_return_val_if_fail (client != NULL, 0);
 
   return g_list_length (client->active_streams);
index 01c4598..d613298 100644 (file)
@@ -493,7 +493,7 @@ GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client,
 guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
 
 /* Segment */
-void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx);
+void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx);
 guint gst_mpd_client_get_segment_index (GstActiveStream * stream);
 
 /* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */