mpdparser: initial support for Media Presentations made of several Periods
authorGianluca Gennari <gennarone@gmail.com>
Mon, 22 Oct 2012 16:12:30 +0000 (18:12 +0200)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 21:14:10 +0000 (18:14 -0300)
- build a list of the available Periods with their start and duration time
- add the list of GstStreamPeriod in the GstMpdClient data struct
- remove cur_period from GstMpdClient and introduce an API to get the current GstStreamPeriod
- several API clean-ups

ext/dash/gstdashdemux.c
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 72378b9..a3051e5 100644 (file)
@@ -641,6 +641,12 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
       gst_buffer_unref (demux->manifest);
       demux->manifest = NULL;
 
+      if (!gst_mpd_client_setup_media_presentation (demux->client)) {
+        GST_ELEMENT_ERROR (demux, STREAM, DECODE,
+            ("Incompatible manifest file."), (NULL));
+        return FALSE;
+      }
+
       if (!gst_mpd_client_setup_streaming (demux->client, GST_STREAM_VIDEO, "")) {
         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
             ("Incompatible manifest file."), (NULL));
@@ -649,8 +655,8 @@ gst_dash_demux_sink_event (GstPad * pad, GstEvent * event)
 
       GList *listLang = NULL;
       guint nb_audio =
-          gst_mpdparser_get_list_and_nb_of_audio_language (&listLang,
-          demux->client->cur_period->AdaptationSets);
+          gst_mpdparser_get_list_and_nb_of_audio_language (demux->client,
+          &listLang);
       if (nb_audio == 0)
         nb_audio = 1;
       GST_INFO_OBJECT (demux, "Number of language is=%d", nb_audio);
@@ -1470,7 +1476,7 @@ gst_dash_demux_get_next_fragment_set (GstDashDemux * demux)
    * header to initialize the new decoding chain
    * FIXME: redundant with needs_pad_switch */
   gboolean need_header = need_add_header (demux);
-  int stream_idx = 0;
+  guint stream_idx = 0;
   fragment_set = NULL;
   /* Get the fragment corresponding to each stream index */
   while (stream_idx < gst_mpdparser_get_nb_active_stream (demux->client)) {
index 6bc7f57..439199e 100644 (file)
@@ -75,6 +75,7 @@ static void gst_mpdparser_parse_root_node (GstMpdClient * client, xmlNode *a_nod
 /* Helper functions */
 static gint convert_to_millisecs (gint decimals, gint pos);
 static int strncmp_ext (const char *s1, const char *s2);
+static GstStreamPeriod *gst_mpdparser_get_stream_period (GstMpdClient * client);
 static gchar *gst_mpdparser_parse_baseURL (GstMpdClient * client);
 static gchar *gst_mpdparser_get_segmentURL_for_range (gchar *url, GstRange *range);
 static gchar *gst_mpdparser_get_mediaURL (GstMpdClient * client, GstSegmentURLNode *segmentURL);
@@ -83,9 +84,6 @@ 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);
 
-/* Period */
-static GstPeriodNode *gst_mpdparser_get_next_period (GList *Periods, GstPeriodNode *prev_period);
-
 /* Adaptation Set */
 static GstAdaptationSetNode *gst_mpdparser_get_first_adapt_set (GList *AdaptationSets);
 static GstAdaptationSetNode *gst_mpdparser_get_first_adapt_set_with_mimeType (GList *AdaptationSets, const gchar *mimeType);
@@ -123,6 +121,7 @@ static void gst_mpdparser_free_segment_url_node (GstSegmentURLNode * segment_url
 static void gst_mpdparser_free_base_url_node (GstBaseURL * base_url_node);
 static void gst_mpdparser_free_descriptor_type_node (GstDescriptorType * descriptor_type);
 static void gst_mpdparser_free_content_component_node (GstContentComponentNode * content_component_node);
+static void gst_mpdparser_free_stream_period (GstStreamPeriod * stream_period);
 static void gst_mpdparser_free_media_segment (GstMediaSegment * media_segment);
 static void gst_mpdparser_free_active_stream (GstActiveStream * active_stream);
 
@@ -1573,27 +1572,6 @@ strncmp_ext (const char *s1, const char *s2)
 }
 
 /* navigation functions */
-static GstPeriodNode *
-gst_mpdparser_get_next_period (GList * Periods, GstPeriodNode * prev_period)
-{
-  GList *list = NULL;
-
-  if (Periods == NULL)
-    return NULL;
-
-  if (prev_period == NULL) {
-    /* return the first period in the list */
-    list = g_list_first (Periods);
-  } else {
-    /* found prev_period in the list */
-    list = g_list_find (Periods, prev_period);
-    /* next period */
-    list = g_list_next (list);
-  }
-
-  return list ? (GstPeriodNode *) list->data : NULL;
-}
-
 static GstAdaptationSetNode *
 gst_mpdparser_get_first_adapt_set (GList * AdaptationSets)
 {
@@ -2166,6 +2144,14 @@ gst_mpdparser_free_content_component_node (GstContentComponentNode * content_com
 }
 
 static void
+gst_mpdparser_free_stream_period (GstStreamPeriod * stream_period)
+{
+  if (stream_period) {
+    g_slice_free (GstStreamPeriod, stream_period);
+  }
+}
+
+static void
 gst_mpdparser_free_media_segment (GstMediaSegment * media_segment)
 {
   if (media_segment) {
@@ -2279,22 +2265,32 @@ gst_mpdparser_build_URL_from_template (const gchar *url_template,
   return ret;
 }
 
+static GstStreamPeriod *
+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, client->period_idx);
+}
+
 /* select a stream and extract the baseURL (if present) */
 static gchar *
 gst_mpdparser_parse_baseURL (GstMpdClient * client)
 {
   GstActiveStream *stream;
+  GstStreamPeriod* stream_period;
   GstBaseURL *baseURL;
   GList *list;
   static gchar *baseURL_array[5];
   static gchar empty[] = "";
   gchar *ret = NULL;
 
-  /* select stream TODO: support multiple streams */
-  g_return_val_if_fail (client != NULL, empty);
-  g_return_val_if_fail (client->active_streams != NULL, empty);
-  stream = g_list_nth_data (client->active_streams, client->stream_idx);
+  stream = gst_mpdparser_get_active_stream_by_index (client, client->stream_idx);
   g_return_val_if_fail (stream != NULL, empty);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, empty);
+  g_return_val_if_fail (stream_period->period != NULL, empty);
 
   baseURL_array[0] = baseURL_array[1] = baseURL_array[2] = baseURL_array[3] = empty;
   baseURL_array[4] = NULL;
@@ -2307,7 +2303,7 @@ gst_mpdparser_parse_baseURL (GstMpdClient * client)
     }
     baseURL_array[0] = baseURL->baseURL;
   }
-  if ((list = client->cur_period->BaseURLs) != NULL) {
+  if ((list = stream_period->period->BaseURLs) != NULL) {
     baseURL = g_list_nth_data (list, stream->baseURL_idx);
     if (!baseURL) {
       baseURL = list->data;
@@ -2370,6 +2366,12 @@ void gst_mpd_client_free (GstMpdClient * client)
   if (client->mpd_node)
     gst_mpdparser_free_mpd_node (client->mpd_node);
 
+  if (client->periods) {
+    g_list_foreach (client->periods,
+        (GFunc) gst_mpdparser_free_stream_period, NULL);
+    g_list_free (client->periods);
+  }
+
   if (client->active_streams) {
     g_list_foreach (client->active_streams,
         (GFunc) gst_mpdparser_free_active_stream, NULL);
@@ -2482,6 +2484,7 @@ gst_mpd_client_add_media_segment (GstActiveStream *stream, GstSegmentURLNode *ur
 gboolean
 gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *stream, GstRepresentationNode *representation)
 {
+  GstStreamPeriod *stream_period;
   GList *rep_list;
   GstClockTime PeriodStart = 0, PeriodEnd, start_time, duration;
   GstMediaSegment *last_media_segment;
@@ -2504,23 +2507,12 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
     stream->segments = NULL;
   }
 
-  if (client->cur_period->start != -1) {
-    PeriodStart = client->cur_period->start * GST_MSECOND;
-  }
-  if (client->cur_period->duration != -1) {
-    PeriodEnd = client->cur_period->duration * GST_MSECOND;
-  } else {
-    GstPeriodNode *next_period_node = gst_mpdparser_get_next_period (client->mpd_node->Periods, client->cur_period);
-    if (next_period_node) {
-      PeriodEnd = next_period_node->start * GST_MSECOND;
-    } else {
-      if (client->mpd_node->mediaPresentationDuration != -1) {
-        PeriodEnd = client->mpd_node->mediaPresentationDuration * GST_MSECOND;
-      } else {
-        PeriodEnd = client->mpd_node->minimumUpdatePeriod * GST_MSECOND;
-      }
-    }
-  }
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, FALSE);
+  g_return_val_if_fail (stream_period->period != NULL, FALSE);
+
+  PeriodStart = stream_period->start;
+  PeriodEnd = stream_period->start + stream_period->duration;
 
   GST_LOG ("Building segment list for Period from %" GST_TIME_FORMAT " to %"
       GST_TIME_FORMAT, GST_TIME_ARGS (PeriodStart), GST_TIME_ARGS (PeriodEnd));
@@ -2530,13 +2522,13 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
 
     /* get the first segment_base of the selected representation */
     if ((stream->cur_segment_base =
-            gst_mpdparser_get_segment_base (client->cur_period, stream->cur_adapt_set, representation)) == NULL) {
+            gst_mpdparser_get_segment_base (stream_period->period, stream->cur_adapt_set, representation)) == NULL) {
       GST_DEBUG ("No useful SegmentBase node for the current Representation");
     }
 
     /* get the first segment_list of the selected representation */
     if ((stream->cur_segment_list =
-            gst_mpdparser_get_segment_list (client->cur_period, stream->cur_adapt_set, representation)) == NULL) {
+            gst_mpdparser_get_segment_list (stream_period->period, stream->cur_adapt_set, representation)) == NULL) {
       GST_DEBUG ("No useful SegmentList node for the current Representation");
       /* here we should have a single segment for each representation, whose URL is encoded in the baseURL element */
       if (!gst_mpd_client_add_media_segment (stream, NULL, 1, 0, 0, PeriodEnd)) {
@@ -2606,8 +2598,8 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
       stream->cur_seg_template = representation->SegmentTemplate;
     } else if (stream->cur_adapt_set->SegmentTemplate != NULL) {
       stream->cur_seg_template = stream->cur_adapt_set->SegmentTemplate;
-    } else if (client->cur_period->SegmentTemplate != NULL) {
-      stream->cur_seg_template = client->cur_period->SegmentTemplate;
+    } else if (stream_period->period->SegmentTemplate != NULL) {
+      stream->cur_seg_template = stream_period->period->SegmentTemplate;
     }
 
     if (stream->cur_seg_template == NULL || stream->cur_seg_template->MultSegBaseType == NULL) {
@@ -2684,19 +2676,108 @@ gst_mpd_client_setup_representation (GstMpdClient * client, GstActiveStream *str
 }
 
 gboolean
+gst_mpd_client_setup_media_presentation (GstMpdClient *client)
+{
+  GstStreamPeriod *stream_period;
+  GstPeriodNode *period_node;
+  GstClockTime start, duration;
+  GList *list, *next;
+  guint idx;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->mpd_node != NULL, FALSE);
+
+  GST_DEBUG ("Building the list of Periods in the Media Presentation");
+  /* clean the old period list, if any */
+  if (client->periods) {
+    g_list_foreach (client->periods,
+        (GFunc) gst_mpdparser_free_stream_period, NULL);
+    g_list_free (client->periods);
+    client->periods = NULL;
+  }
+
+  idx = 0;
+  start = 0;
+  duration = GST_CLOCK_TIME_NONE;
+  for (list = g_list_first (client->mpd_node->Periods); list; list = g_list_next (list)) {
+    period_node = (GstPeriodNode *) list->data;
+    if (period_node->start != -1) {
+      /* we have a regular period */
+      start = period_node->start * GST_MSECOND;
+    } else if (duration != GST_CLOCK_TIME_NONE) {
+      /* start time inferred from previous period, this is still a regular period */
+      start += duration;
+    } else if (idx == 0 && client->mpd_node->type == GST_MPD_FILE_TYPE_STATIC) {
+      /* first period of a static MPD file, start time is 0 */
+      start = 0;
+    } else {
+      /* this is an 'Early Available Period' */
+      goto early;
+    }
+
+    if (period_node->duration != -1) {
+      duration = period_node->duration * GST_MSECOND;
+    } else if ((next = g_list_next (list)) != NULL) {
+      /* try to infer this period duration from the start time of the next period */
+      GstPeriodNode *next_period_node = next->data;
+      if (next_period_node->start != -1) {
+        duration = next_period_node->start * GST_MSECOND - start;
+      } else {
+        /* Invalid MPD file! */
+        goto syntax_error;
+      }
+    } else if (client->mpd_node->mediaPresentationDuration != -1) {
+      /* last Period of the Media Presentation */
+      duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND - start;
+    } else {
+      /* Invalid MPD file! */
+      goto syntax_error;
+    }
+
+    stream_period = g_slice_new0 (GstStreamPeriod);
+    if (stream_period == NULL) {
+      goto no_mem;
+    }
+    client->periods = g_list_append (client->periods, stream_period);
+    stream_period->period = period_node;
+    stream_period->number = idx++;
+    stream_period->start = start;
+    stream_period->duration = duration;
+    ret = TRUE;
+    GST_LOG (" - added Period %d start=%" GST_TIME_FORMAT " duration=%"
+        GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
+  }
+
+  GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", idx);
+  return ret;
+
+early:
+  GST_WARNING ("Found an Early Available Period, skipping the rest of the Media Presentation");
+  return ret;
+
+syntax_error:
+  GST_WARNING ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation", idx);
+  return ret;
+
+no_mem:
+  GST_WARNING ("Allocation of GstStreamPeriod struct failed!");
+  return FALSE;
+}
+
+gboolean
 gst_mpd_client_setup_streaming (GstMpdClient * client,
     GstStreamMimeType mimeType, gchar* lang)
 {
   GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
   GstAdaptationSetNode *adapt_set;
   GstRepresentationNode *representation;
   GList *rep_list = NULL;
 
-  /* select a new period */
-  if (!client->cur_period)
-  if ((client->cur_period =
-          gst_mpdparser_get_next_period (client->mpd_node->Periods, client->cur_period)) == NULL) {
-    GST_WARNING ("No valid Period node in the MPD file, aborting...");
+  stream_period = gst_mpdparser_get_stream_period (client);
+  if (stream_period == NULL || stream_period->period == NULL) {
+    GST_DEBUG ("No more Period nodes in the MPD file, terminating...");
     return FALSE;
   }
 
@@ -2704,13 +2785,11 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
     case GST_STREAM_VIDEO:
       /* select the adaptation set for the video pipeline */
       adapt_set =
-          gst_mpdparser_get_adapt_set_with_mimeType_and_idx (client->
-          cur_period->AdaptationSets, "video", 0);
+          gst_mpdparser_get_adapt_set_with_mimeType_and_idx (stream_period->period->AdaptationSets, "video", 0);
       /* if we found no 'video' adaptation set, just get the first one */
       if (!adapt_set)
         adapt_set =
-            gst_mpdparser_get_first_adapt_set (client->cur_period->
-            AdaptationSets);
+            gst_mpdparser_get_first_adapt_set (stream_period->period->AdaptationSets);
       if (!adapt_set) {
         GST_INFO ("No adaptation set found, aborting...");
         return FALSE;
@@ -2730,13 +2809,11 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
       }
 #endif
       adapt_set =
-          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (client->
-          cur_period->AdaptationSets, "audio", lang);
+          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (stream_period->period->AdaptationSets, "audio", lang);
       /* if we did not found the requested audio language, get the first one */
       if (!adapt_set)
         adapt_set =
-            gst_mpdparser_get_first_adapt_set_with_mimeType (client->
-            cur_period->AdaptationSets, "audio");
+            gst_mpdparser_get_first_adapt_set_with_mimeType (stream_period->period->AdaptationSets, "audio");
       if (!adapt_set) {
         GST_INFO ("No audio adaptation set found");
         return FALSE;
@@ -2755,13 +2832,11 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
       }
 #endif
       adapt_set =
-          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (client->
-          cur_period->AdaptationSets, "application", lang);
+          gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (stream_period->period->AdaptationSets, "application", lang);
       /* if we did not found the requested subtitles language, get the first one */
       if (!adapt_set)
         adapt_set =
-            gst_mpdparser_get_first_adapt_set_with_mimeType (client->
-            cur_period->AdaptationSets, "application");
+            gst_mpdparser_get_first_adapt_set_with_mimeType (stream_period->period->AdaptationSets, "application");
       if (!adapt_set) {
         GST_INFO ("No application adaptation set found");
         return FALSE;
@@ -2880,17 +2955,17 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
 gboolean
 gst_mpd_client_get_next_header (GstMpdClient * client, const gchar **uri, guint stream_idx)
 {
-  GstActiveStream *stream = NULL;
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
 
-  /* select stream */
-  g_return_val_if_fail (client != NULL, FALSE);
-  g_return_val_if_fail (client->active_streams != NULL, FALSE);
-  stream = g_list_nth_data (client->active_streams, stream_idx);
+  stream = gst_mpdparser_get_active_stream_by_index (client, stream_idx);
   g_return_val_if_fail (stream != NULL, FALSE);
   g_return_val_if_fail (stream->cur_representation != NULL, FALSE);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, FALSE);
+  g_return_val_if_fail (stream_period->period != NULL, FALSE);
 
   GST_DEBUG ("Looking for current representation header");
-
   GST_MPD_CLIENT_LOCK (client);
   *uri = NULL;
   if (stream->cur_segment_base && stream->cur_segment_base->Initialization) {
@@ -2901,8 +2976,8 @@ gst_mpd_client_get_next_header (GstMpdClient * client, const gchar **uri, guint
       initialization = stream->cur_seg_template->initialization;
     } else if (stream->cur_adapt_set->SegmentTemplate && stream->cur_adapt_set->SegmentTemplate->initialization) {
       initialization = stream->cur_adapt_set->SegmentTemplate->initialization;
-    } else if (client->cur_period->SegmentTemplate && client->cur_period->SegmentTemplate->initialization) {
-      initialization = client->cur_period->SegmentTemplate->initialization;
+    } else if (stream_period->period->SegmentTemplate && stream_period->period->SegmentTemplate->initialization) {
+      initialization = stream_period->period->SegmentTemplate->initialization;
     }
     *uri = gst_mpdparser_build_URL_from_template (initialization,
         stream->cur_representation->id, 0, stream->cur_representation->bandwidth, 0);
@@ -2951,14 +3026,15 @@ GstClockTime
 gst_mpd_client_get_target_duration (GstMpdClient * client)
 {
   GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
   GstMultSegmentBaseType *base = NULL;
   GstClockTime duration;
   guint timescale;
 
-  g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
-  /* select stream TODO: support multiple streams */
-  stream = g_list_nth_data (client->active_streams, client->stream_idx);
+  stream = gst_mpdparser_get_active_stream_by_index (client, client->stream_idx);
   g_return_val_if_fail (stream != NULL, GST_CLOCK_TIME_NONE);
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, GST_CLOCK_TIME_NONE);
 
   if (stream->cur_segment_list) {
     base = stream->cur_segment_list->MultSegBaseType;
@@ -2969,11 +3045,7 @@ gst_mpd_client_get_target_duration (GstMpdClient * client)
   if (base == NULL || base->SegBaseType == NULL) {
     /* this may happen when we have a single segment */
     /* TODO: support SegmentTimeline */
-    if (client->cur_period->duration) {
-      duration = client->cur_period->duration * GST_MSECOND;
-    } else {
-      duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND;
-    }
+    duration = stream_period->duration;
   } else {
     duration = base->duration * GST_SECOND;
     timescale = base->SegBaseType->timescale;
@@ -2988,29 +3060,39 @@ gst_mpd_client_get_target_duration (GstMpdClient * client)
 gboolean
 gst_mpd_client_is_live (GstMpdClient * client)
 {
- return client->mpd_node->type == GST_MPD_FILE_TYPE_DYNAMIC;
+  g_return_val_if_fail (client != NULL, FALSE);
+  g_return_val_if_fail (client->mpd_node != NULL, FALSE);
+
+  return client->mpd_node->type == GST_MPD_FILE_TYPE_DYNAMIC;
 }
 
-guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client){
+guint
+gst_mpdparser_get_nb_active_stream (GstMpdClient *client){
+
+  g_return_val_if_fail (client != NULL, 0);
 
- g_return_val_if_fail (client != NULL, FALSE);
- return g_list_length (client->active_streams);
+  return g_list_length (client->active_streams);
 }
 
-guint gst_mpdparser_get_nb_adaptationSet(GstMpdClient *client)
+guint
+gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client)
 {
- g_return_val_if_fail (client != NULL, FALSE);
- g_return_val_if_fail (client->cur_period != NULL, FALSE);
- g_return_val_if_fail (client->cur_period->AdaptationSets != NULL, FALSE);
- return g_list_length (client->cur_period->AdaptationSets);
+  GstStreamPeriod *stream_period;
+
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, 0);
+  g_return_val_if_fail (stream_period->period != NULL, 0);
+
+  return g_list_length (stream_period->period->AdaptationSets);
 }
 
-GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, gint stream_idx)
+GstActiveStream *
+gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx)
 {
g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->active_streams != NULL, FALSE);
- return g_list_nth_data (client->active_streams,
-            stream_idx);
 g_return_val_if_fail (client != NULL, NULL);
 g_return_val_if_fail (client->active_streams != NULL, NULL);
+
+  return g_list_nth_data (client->active_streams, stream_idx);
 }
 
 static const gchar *
@@ -3097,19 +3179,21 @@ guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream)
 }
 
 guint
-gst_mpdparser_get_list_and_nb_of_audio_language (GList **lang,
-    GList *AdaptationSets)
+gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient *client,
+    GList **lang)
 {
-  GList *list;
+  GstStreamPeriod *stream_period;
   GstAdaptationSetNode *adapt_set;
+  GList *list;
   gchar *this_mimeType = "audio";
   gchar *mimeType = NULL;
   guint nb_adapatation_set = 0;
 
-  if (AdaptationSets == NULL)
-    return 0;
+  stream_period = gst_mpdparser_get_stream_period (client);
+  g_return_val_if_fail (stream_period != NULL, 0);
+  g_return_val_if_fail (stream_period->period != NULL, 0);
 
-  for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
+  for (list = g_list_first (stream_period->period->AdaptationSets); list; list = g_list_next (list)) {
     adapt_set = (GstAdaptationSetNode *) list->data;
     if (adapt_set) {
       gchar *this_lang = adapt_set->lang;
@@ -3130,6 +3214,7 @@ gst_mpdparser_get_list_and_nb_of_audio_language (GList **lang,
       }
     }
   }
+
   return nb_adapatation_set;
 }
 
index 601016b..0a8f3fe 100644 (file)
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
 
 typedef struct _GstMpdClient              GstMpdClient;
 typedef struct _GstActiveStream           GstActiveStream;
+typedef struct _GstStreamPeriod           GstStreamPeriod;
 typedef struct _GstMediaSegment           GstMediaSegment;
 typedef struct _GstMPDNode                GstMPDNode;
 typedef struct _GstPeriodNode             GstPeriodNode;
@@ -390,6 +391,19 @@ struct _GstMPDNode
 };
 
 /**
+ * GstStreamPeriod:
+ *
+ * Stream period data structure
+ */
+struct _GstStreamPeriod
+{
+  GstPeriodNode *period;                      /* Stream period */
+  guint number;                               /* Period number */
+  GstClockTime start;                         /* Period start time */
+  GstClockTime duration;                      /* Period duration */
+};
+
+/**
  * GstMediaSegment:
  *
  * Media segment data structure
@@ -422,29 +436,34 @@ struct _GstActiveStream
   GstSegmentBaseType *cur_segment_base;       /* active segment base */
   GstSegmentListNode *cur_segment_list;       /* active segment list */
   GstSegmentTemplateNode *cur_seg_template;   /* active segment template */
-  gint segment_idx;                           /* index of next sequence chunk */
-  GList *segments;                            /* list of GstMediaSegment nodes */
+  guint segment_idx;                          /* index of next sequence chunk */
+  GList *segments;                            /* list of GstMediaSegment */
 };
 
 struct _GstMpdClient
 {
-  GstMPDNode   *mpd_node;                     /* active MPD manifest file */
-  GstPeriodNode *cur_period;                  /* active period */
+  GstMPDNode *mpd_node;                       /* active MPD manifest file */
 
-  GList        *active_streams;               /* list of GstActiveStream (only one supported on the first implementation) */
-  guint        stream_idx;                    /* currently active stream */
+  GList *periods;                             /* list of GstStreamPeriod */
+  guint period_idx;                           /* index of current Period */
 
-  guint         update_failed_count;
-  gchar        *mpd_uri;                      /* manifest file URI */
-  GMutex       *lock;
+  GList *active_streams;                      /* list of GstActiveStream */
+  guint stream_idx;                           /* currently active stream */
+
+  guint update_failed_count;
+  gchar *mpd_uri;                             /* manifest file URI */
+  GMutex *lock;
 };
 
 /* Basic initialization/deinitialization functions */
 GstMpdClient *gst_mpd_client_new ();
 void gst_mpd_client_free (GstMpdClient * client);
 
-/* Basic parsing */
+/* MPD file parsing */
 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_streaming (GstMpdClient *client, GstStreamMimeType mimeType, gchar* lang);
 gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
 void gst_mpd_client_get_current_position (GstMpdClient *client, GstClockTime * timestamp);
@@ -463,20 +482,20 @@ GstMediaSegment *gst_mpdparser_get_chunk_by_index (GstMpdClient *client, guint i
 
 /* Active stream */
 guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client);
-GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, gint stream_idx);
+GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx);
 
 /* AdaptationSet */
-guint gst_mpdparser_get_nb_adaptationSet(GstMpdClient *client);
+guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
 
 /* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */
 const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream);
-guint  gst_mpd_client_get_video_stream_width (GstActiveStream * stream);
-guint  gst_mpd_client_get_video_stream_height (GstActiveStream * stream);
-guint  gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream);
-guint  gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream);
+guint gst_mpd_client_get_video_stream_width (GstActiveStream * stream);
+guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream);
+guint gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream);
+guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream);
 
 /* Support multi language */
-guint gst_mpdparser_get_list_and_nb_of_audio_language(GList **lang, GList *AdaptationSets);
+guint gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient *client, GList **lang);
 G_END_DECLS
 
 #endif /* __GST_MPDPARSER_H__ */