dashdemux: handle top-level index urls
authorThiago Santos <thiago.sousa.santos@collabora.com>
Mon, 1 Jul 2013 16:19:15 +0000 (13:19 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Mon, 1 Jul 2013 21:52:08 +0000 (18:52 -0300)
Parse and provide access to top-level index segments if available.
dashdemux should push those whenever a header is pushed.

Fixes #700489

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

index 70f7aad..a56896e 100644 (file)
@@ -1686,35 +1686,63 @@ gst_dash_demux_select_representations (GstDashDemux * demux)
   return ret;
 }
 
-static GstFragment *
-gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
+static GstBuffer *
+gst_dash_demux_download_header_fragment (GstDashDemux * demux, guint stream_idx,
+    gchar * path, gint64 range_start, gint64 range_end)
 {
-  gchar *initializationURL;
+  GstBuffer *buffer;
   gchar *next_header_uri;
   GstFragment *fragment;
-  gint64 range_start, range_end;
-
-  if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
-          stream_idx, &range_start, &range_end))
-    return NULL;
 
-  if (strncmp (initializationURL, "http://", 7) != 0) {
+  if (strncmp (path, "http://", 7) != 0) {
     next_header_uri =
         g_strconcat (gst_mpdparser_get_baseURL (demux->client, stream_idx),
-        initializationURL, NULL);
-    g_free (initializationURL);
+        path, NULL);
+    g_free (path);
   } else {
-    next_header_uri = initializationURL;
+    next_header_uri = path;
   }
 
-  GST_INFO_OBJECT (demux, "Fetching header %s %" G_GINT64_FORMAT "-%"
-      G_GINT64_FORMAT, next_header_uri, range_start, range_end);
-
   fragment = gst_uri_downloader_fetch_uri_with_range (demux->downloader,
       next_header_uri, range_start, range_end);
   g_free (next_header_uri);
+  buffer = gst_fragment_get_buffer (fragment);
+  g_object_unref (fragment);
+  return buffer;
+}
 
-  return fragment;
+static GstBuffer *
+gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
+{
+  gchar *initializationURL;
+  GstBuffer *header_buffer, *index_buffer = NULL;
+  gint64 range_start, range_end;
+
+  if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
+          stream_idx, &range_start, &range_end))
+    return NULL;
+
+  GST_INFO_OBJECT (demux, "Fetching header %s %" G_GINT64_FORMAT "-%"
+      G_GINT64_FORMAT, initializationURL, range_start, range_end);
+  header_buffer = gst_dash_demux_download_header_fragment (demux, stream_idx,
+      initializationURL, range_start, range_end);
+
+  /* check if we have an index */
+  if (gst_mpd_client_get_next_header_index (demux->client, &initializationURL,
+          stream_idx, &range_start, &range_end)) {
+    GST_INFO_OBJECT (demux, "Fetching index %s %" G_GINT64_FORMAT "-%"
+        G_GINT64_FORMAT, initializationURL, range_start, range_end);
+    index_buffer = gst_dash_demux_download_header_fragment (demux, stream_idx,
+        initializationURL, range_start, range_end);
+  }
+
+  if (index_buffer && header_buffer) {
+    header_buffer = gst_buffer_append (header_buffer, index_buffer);
+  } else if (index_buffer) {
+    gst_buffer_unref (index_buffer);
+  }
+
+  return header_buffer;
 }
 
 static GstCaps *
@@ -1824,7 +1852,8 @@ static gboolean
 gst_dash_demux_get_next_fragment (GstDashDemux * demux)
 {
   GstActiveStream *active_stream;
-  GstFragment *download, *header;
+  GstFragment *download;
+  GstBuffer *header_buffer;
   gchar *next_fragment_uri;
   GstClockTime duration;
   GstClockTime timestamp;
@@ -1923,16 +1952,11 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
 
       if (selected_stream->need_header) {
         /* We need to fetch a new header */
-        if ((header =
+        if ((header_buffer =
                 gst_dash_demux_get_next_header (demux, stream_idx)) == NULL) {
           GST_WARNING_OBJECT (demux, "Unable to fetch header");
         } else {
-          GstBuffer *header_buffer;
-          /* Replace fragment with a new one including the header */
-
-          header_buffer = gst_fragment_get_buffer (header);
           buffer = gst_buffer_append (header_buffer, buffer);
-          g_object_unref (header);
         }
         selected_stream->need_header = FALSE;
       }
index c1a03b9..92eaa11 100644 (file)
@@ -1098,7 +1098,7 @@ gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer,
       gst_mpdparser_get_xml_prop_unsigned_integer (a_node,
       "presentationTimeOffset", 0);
   seg_base_type->indexRange =
-      gst_mpdparser_get_xml_prop_string (a_node, "indexRange");
+      gst_mpdparser_get_xml_prop_range (a_node, "indexRange");
   seg_base_type->indexRangeExact =
       gst_mpdparser_get_xml_prop_boolean (a_node, "indexRangeExact");
 
@@ -2227,7 +2227,7 @@ gst_mpdparser_free_seg_base_type_ext (GstSegmentBaseType * seg_base_type)
 {
   if (seg_base_type) {
     if (seg_base_type->indexRange)
-      xmlFree (seg_base_type->indexRange);
+      g_slice_free (GstRange, seg_base_type->indexRange);
     gst_mpdparser_free_url_type_node (seg_base_type->Initialization);
     gst_mpdparser_free_url_type_node (seg_base_type->RepresentationIndex);
     g_slice_free (GstSegmentBaseType, seg_base_type);
@@ -3397,6 +3397,54 @@ gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
   return *uri == NULL ? FALSE : TRUE;
 }
 
+gboolean
+gst_mpd_client_get_next_header_index (GstMpdClient * client, gchar ** uri,
+    guint stream_idx, gint64 * range_start, gint64 * range_end)
+{
+  GstActiveStream *stream;
+  GstStreamPeriod *stream_period;
+
+  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);
+
+  *range_start = 0;
+  *range_end = -1;
+
+  GST_DEBUG ("Looking for current representation index");
+  GST_MPD_CLIENT_LOCK (client);
+  *uri = NULL;
+  if (stream->cur_segment_base && stream->cur_segment_base->indexRange) {
+    *uri =
+        g_strdup (gst_mpdparser_get_initializationURL (stream, stream->cur_segment_base->
+        Initialization));
+    *range_start =
+        stream->cur_segment_base->indexRange->first_byte_pos;
+    *range_end =
+        stream->cur_segment_base->indexRange->last_byte_pos;
+  } else if (stream->cur_seg_template) {
+    const gchar *initialization = NULL;
+    if (stream->cur_seg_template->index) {
+      initialization = stream->cur_seg_template->index;
+    } else if (stream->cur_adapt_set->SegmentTemplate
+        && stream->cur_adapt_set->SegmentTemplate->index) {
+      initialization = stream->cur_adapt_set->SegmentTemplate->index;
+    } else if (stream_period->period->SegmentTemplate
+        && stream_period->period->SegmentTemplate->index) {
+      initialization = stream_period->period->SegmentTemplate->index;
+    }
+    *uri = gst_mpdparser_build_URL_from_template (initialization,
+        stream->cur_representation->id, 0,
+        stream->cur_representation->bandwidth, 0);
+  }
+  GST_MPD_CLIENT_UNLOCK (client);
+
+  return *uri == NULL ? FALSE : TRUE;
+}
+
 GstClockTime
 gst_mpd_client_get_current_position (GstMpdClient * client)
 {
index 9f005ba..f7582f9 100644 (file)
@@ -142,7 +142,7 @@ struct _GstSegmentBaseType
 {
   guint timescale;
   guint presentationTimeOffset;
-  gchar *indexRange;
+  GstRange *indexRange;
   gboolean indexRangeExact;
   /* Initialization node */
   GstURLType *Initialization;
@@ -475,6 +475,7 @@ gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guin
 gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
 gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, gboolean *discontinuity, gchar **uri, gint64 * range_start, gint64 * range_end, GstClockTime *duration, GstClockTime *timestamp);
 gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);
+gboolean gst_mpd_client_get_next_header_index (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);
 gboolean gst_mpd_client_is_live (GstMpdClient * client);
 gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts);