dashdemux: Implement lazy-loading of external periods
authorSebastian Dröge <sebastian@centricular.com>
Tue, 22 Sep 2015 14:17:38 +0000 (16:17 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 2 Oct 2015 08:01:56 +0000 (11:01 +0300)
https://bugzilla.gnome.org/show_bug.cgi?id=752230

ext/dash/gstdashdemux.c
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h
tests/check/elements/dash_mpd.c

index 5445ad4a4078ef7ccaff2ade5036f910b7098fa3..20d67641950331b72cfb40f5120bf5d2c676f6fe 100644 (file)
@@ -736,7 +736,8 @@ gst_dash_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
   if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
     manifest = (gchar *) mapinfo.data;
     if (gst_mpd_parse (dashdemux->client, manifest, mapinfo.size)) {
-      if (gst_mpd_client_setup_media_presentation (dashdemux->client)) {
+      if (gst_mpd_client_setup_media_presentation (dashdemux->client, 0, 0,
+              NULL)) {
         ret = TRUE;
       } else {
         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
@@ -1208,6 +1209,10 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
     target_pos = (GstClockTime) demux->segment.stop;
 
   /* select the requested Period in the Media Presentation */
+  if (!gst_mpd_client_setup_media_presentation (dashdemux->client, target_pos,
+          -1, NULL))
+    return FALSE;
+
   current_period = 0;
   for (list = g_list_first (dashdemux->client->periods); list;
       list = g_list_next (list)) {
@@ -1295,7 +1300,8 @@ gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
     period_idx = gst_mpd_client_get_period_index (dashdemux->client);
 
     /* setup video, audio and subtitle streams, starting from current Period */
-    if (!gst_mpd_client_setup_media_presentation (new_client)) {
+    if (!gst_mpd_client_setup_media_presentation (new_client, -1,
+            (period_id ? -1 : period_idx), period_id)) {
       /* TODO */
     }
 
index 3e6c0fef52765d9d3f49c9a0d731743d7a45d805..bb9d7b0576332d3b542e3a6736af5c6ba88e8925 100644 (file)
@@ -2978,6 +2978,9 @@ gst_mpd_client_get_period_index_at_time (GstMpdClient * client,
   if (time_offset < 0)
     return 0;
 
+  if (!gst_mpd_client_setup_media_presentation (client, time_offset, -1, NULL))
+    return 0;
+
   for (idx = 0, iter = client->periods; iter; idx++, iter = g_list_next (iter)) {
     stream_period = iter->data;
     if (stream_period->start <= time_offset
@@ -3893,12 +3896,9 @@ gst_mpd_client_fetch_external_period (GstMpdClient * client,
   return new_periods;
 }
 
-/* TODO: Implement xlink actuation onRequest properly. Currently we download
- * each external MPD immediately when iterating over the periods. We should
- * do this only when actually switching to this period.
- */
 gboolean
-gst_mpd_client_setup_media_presentation (GstMpdClient * client)
+gst_mpd_client_setup_media_presentation (GstMpdClient * client,
+    GstClockTime time, gint period_idx, const gchar * period_id)
 {
   GstStreamPeriod *stream_period;
   GstClockTime start, duration;
@@ -3909,8 +3909,30 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
   g_return_val_if_fail (client != NULL, FALSE);
   g_return_val_if_fail (client->mpd_node != NULL, FALSE);
 
+  /* Check if we set up the media presentation far enough already */
+  for (list = client->periods; list; list = list->next) {
+    GstStreamPeriod *stream_period = list->data;
+
+    if ((time != GST_CLOCK_TIME_NONE
+            && stream_period->duration != GST_CLOCK_TIME_NONE
+            && stream_period->start + stream_period->duration >= time)
+        || (time != GST_CLOCK_TIME_NONE && stream_period->start >= time))
+      return TRUE;
+
+    if (period_idx != -1 && stream_period->number >= period_idx)
+      return TRUE;
+
+    if (period_id != NULL && stream_period->period->id != NULL
+        && strcmp (stream_period->period->id, period_id) == 0)
+      return TRUE;
+
+  }
+
   GST_DEBUG ("Building the list of Periods in the Media Presentation");
   /* clean the old period list, if any */
+  /* TODO: In theory we could reuse the ones we have so far but that
+   * seems more complicated than the overhead caused here
+   */
   if (client->periods) {
     g_list_foreach (client->periods,
         (GFunc) gst_mpdparser_free_stream_period, NULL);
@@ -4076,10 +4098,24 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
     GST_LOG (" - added Period %d start=%" GST_TIME_FORMAT " duration=%"
         GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
 
+    if ((time != GST_CLOCK_TIME_NONE
+            && stream_period->duration != GST_CLOCK_TIME_NONE
+            && stream_period->start + stream_period->duration >= time)
+        || (time != GST_CLOCK_TIME_NONE && stream_period->start >= time))
+      break;
+
+    if (period_idx != -1 && stream_period->number >= period_idx)
+      break;
+
+    if (period_id != NULL && stream_period->period->id != NULL
+        && strcmp (stream_period->period->id, period_id) == 0)
+      break;
+
     list = list->next;
   }
 
-  GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation",
+  GST_DEBUG
+      ("Found a total of %d valid Periods in the Media Presentation up to this point",
       idx);
   return ret;
 
@@ -5052,6 +5088,10 @@ gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id)
   g_return_val_if_fail (client->periods != NULL, FALSE);
   g_return_val_if_fail (period_id != NULL, FALSE);
 
+  if (!gst_mpd_client_setup_media_presentation (client, GST_CLOCK_TIME_NONE, -1,
+          period_id))
+    return FALSE;
+
   for (period_idx = 0, iter = client->periods; iter;
       period_idx++, iter = g_list_next (iter)) {
     next_stream_period = iter->data;
@@ -5076,6 +5116,9 @@ gst_mpd_client_set_period_index (GstMpdClient * client, guint period_idx)
   g_return_val_if_fail (client != NULL, FALSE);
   g_return_val_if_fail (client->periods != NULL, FALSE);
 
+  if (!gst_mpd_client_setup_media_presentation (client, -1, period_idx, NULL))
+    return FALSE;
+
   next_stream_period = g_list_nth_data (client->periods, period_idx);
   if (next_stream_period != NULL) {
     client->period_idx = period_idx;
index 85ddc8476e271a78a582c27d1d501466b3ca9ba3..36569b5673a3fba17aaf38a115f0325d1c35dd31 100644 (file)
@@ -531,7 +531,7 @@ void gst_mpd_client_set_uri_downloader (GstMpdClient * client, GstUriDownloader
 gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
 
 /* Streaming management */
-gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client);
+gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client, GstClockTime time, gint period_index, const gchar *period_id);
 gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set);
 gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
 GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
index 66b6bd7f2746f7cca1c7276b08d25f1a3558f9b5..05d971185bfcff5ed0581d7081569810f60791de 100644 (file)
@@ -2567,7 +2567,9 @@ GST_START_TEST (dash_mpdparser_various_duration_formats)
   ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
   assert_equals_int (ret, TRUE);
 
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   periodNode =
@@ -2643,7 +2645,9 @@ GST_START_TEST (dash_mpdparser_setup_media_presentation)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   gst_mpd_client_free (mpdclient);
@@ -2678,7 +2682,9 @@ GST_START_TEST (dash_mpdparser_setup_streaming)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the first adaptation set of the first period */
@@ -2725,7 +2731,9 @@ GST_START_TEST (dash_mpdparser_period_selection)
   fail_unless (mpdclient->periods == NULL);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* check the periods */
@@ -2791,7 +2799,9 @@ GST_START_TEST (dash_mpdparser_get_period_at_time)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* request period for a time before availabilityStartTime, expect period index 0 */
@@ -2858,7 +2868,9 @@ GST_START_TEST (dash_mpdparser_adaptationSet_handling)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* period0 has 1 adaptation set */
@@ -2920,7 +2932,9 @@ GST_START_TEST (dash_mpdparser_representation_selection)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
@@ -2993,7 +3007,9 @@ GST_START_TEST (dash_mpdparser_activeStream_selection)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3093,7 +3109,9 @@ GST_START_TEST (dash_mpdparser_activeStream_parameters)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3177,7 +3195,9 @@ GST_START_TEST (dash_mpdparser_get_audio_languages)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3226,7 +3246,9 @@ setup_mpd_client (const gchar * xml)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3451,7 +3473,9 @@ GST_START_TEST (dash_mpdparser_get_streamPresentationOffset)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3523,7 +3547,9 @@ GST_START_TEST (dash_mpdparser_segments)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3664,7 +3690,9 @@ GST_START_TEST (dash_mpdparser_headers)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3738,7 +3766,9 @@ GST_START_TEST (dash_mpdparser_fragments)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3885,7 +3915,9 @@ GST_START_TEST (dash_mpdparser_inherited_segmentURL)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -3990,7 +4022,9 @@ GST_START_TEST (dash_mpdparser_segment_list)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -4066,7 +4100,9 @@ GST_START_TEST (dash_mpdparser_segment_template)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -4167,7 +4203,9 @@ GST_START_TEST (dash_mpdparser_segment_timeline)
   assert_equals_int (ret, TRUE);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* get the list of adaptation sets of the first period */
@@ -4343,7 +4381,9 @@ GST_START_TEST (dash_mpdparser_wrong_period_duration_inferred_from_next_period)
   fail_unless (mpdclient->periods == NULL);
 
   /* process the xml data */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, TRUE);
 
   /* Period0 should be present */
@@ -4388,7 +4428,9 @@ GST_START_TEST
   /* process the xml data
    * should fail due to wrong duration in Period0 (start > mediaPresentationDuration)
    */
-  ret = gst_mpd_client_setup_media_presentation (mpdclient);
+  ret =
+      gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
+      -1, NULL);
   assert_equals_int (ret, FALSE);
 
   gst_mpd_client_free (mpdclient);