dashdemux: add support for range based segments
authorThiago Santos <thiago.sousa.santos@collabora.com>
Thu, 20 Jun 2013 06:52:31 +0000 (03:52 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Mon, 1 Jul 2013 17:22:01 +0000 (14:22 -0300)
Use the mediaRange information and pass it to the uridownloader
to correctly download only the segment ranges indicated in the
MPD

https://bugzilla.gnome.org/show_bug.cgi?id=702206

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

index 3928989..4530fd2 100644 (file)
@@ -1691,9 +1691,10 @@ gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
   gchar *initializationURL;
   gchar *next_header_uri;
   GstFragment *fragment;
+  gint64 range_start, range_end;
 
   if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
-          stream_idx))
+          stream_idx, &range_start, &range_end))
     return NULL;
 
   if (strncmp (initializationURL, "http://", 7) != 0) {
@@ -1705,9 +1706,11 @@ gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
     next_header_uri = initializationURL;
   }
 
-  GST_INFO_OBJECT (demux, "Fetching header %s", next_header_uri);
+  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 (demux->downloader, next_header_uri);
+  fragment = gst_uri_downloader_fetch_uri_with_range (demux->downloader,
+      next_header_uri, range_start, range_end);
   g_free (next_header_uri);
 
   return fragment;
@@ -1883,22 +1886,25 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
   if (selected_stream) {
     guint stream_idx = selected_stream->index;
     GstBuffer *buffer;
+    gint64 range_start, range_end;
 
     if (gst_mpd_client_get_next_fragment (demux->client,
-            stream_idx, &discont, &next_fragment_uri, &duration, &timestamp)) {
+            stream_idx, &discont, &next_fragment_uri, &range_start, &range_end,
+            &duration, &timestamp)) {
 
       g_get_current_time (&start);
       GST_INFO_OBJECT (demux, "Next fragment for stream #%i", stream_idx);
       GST_INFO_OBJECT (demux,
           "Fetching next fragment %s ts:%" GST_TIME_FORMAT " dur:%"
-          GST_TIME_FORMAT, next_fragment_uri, GST_TIME_ARGS (timestamp),
-          GST_TIME_ARGS (duration));
+          GST_TIME_FORMAT " Range:%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT,
+          next_fragment_uri, GST_TIME_ARGS (timestamp),
+          GST_TIME_ARGS (duration), range_start, range_end);
 
       /* got a fragment to fetch, no end of period */
       end_of_period = FALSE;
 
-      download = gst_uri_downloader_fetch_uri (demux->downloader,
-          next_fragment_uri);
+      download = gst_uri_downloader_fetch_uri_with_range (demux->downloader,
+          next_fragment_uri, range_start, range_end);
       g_free (next_fragment_uri);
 
       if (download == NULL)
index bbbcdf9..19eab29 100644 (file)
@@ -111,8 +111,6 @@ 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,
     GstActiveStream * stream, gchar ** query);
-static gchar *gst_mpdparser_get_segmentURL_for_range (gchar * url,
-    GstRange * range);
 static gchar *gst_mpdparser_get_mediaURL (GstActiveStream * stream,
     GstSegmentURLNode * segmentURL);
 static gchar *gst_mpdparser_get_initializationURL (GstURLType *
@@ -1878,14 +1876,14 @@ gst_mpdparser_get_segment_base (GstPeriodNode * Period,
     if (Representation && Representation->SegmentList
         && Representation->SegmentList->MultSegBaseType
         && Representation->SegmentList->MultSegBaseType->SegBaseType
-        && Representation->SegmentList->MultSegBaseType->
-        SegBaseType->Initialization) {
+        && Representation->SegmentList->MultSegBaseType->SegBaseType->
+        Initialization) {
       SegmentBase = Representation->SegmentList->MultSegBaseType->SegBaseType;
     } else if (AdaptationSet && AdaptationSet->SegmentList
         && AdaptationSet->SegmentList->MultSegBaseType
         && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType
-        && AdaptationSet->SegmentList->MultSegBaseType->
-        SegBaseType->Initialization) {
+        && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType->
+        Initialization) {
       SegmentBase = AdaptationSet->SegmentList->MultSegBaseType->SegBaseType;
     } else if (Period && Period->SegmentList
         && Period->SegmentList->MultSegBaseType
@@ -2353,25 +2351,6 @@ gst_mpdparser_free_active_stream (GstActiveStream * active_stream)
 }
 
 static gchar *
-gst_mpdparser_get_segmentURL_for_range (gchar * url, GstRange * range)
-{
-  gchar *segmentURL;
-
-  if (range) {
-    gchar *range_suffix;
-    range_suffix =
-        g_strdup_printf ("?range=%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
-        range->first_byte_pos, range->last_byte_pos);
-    segmentURL = g_strconcat (url, range_suffix, NULL);
-    g_free (range_suffix);
-  } else {
-    segmentURL = g_strdup (url);
-  }
-
-  return segmentURL;
-}
-
-static gchar *
 gst_mpdparser_get_mediaURL (GstActiveStream * stream,
     GstSegmentURLNode * segmentURL)
 {
@@ -2383,8 +2362,7 @@ gst_mpdparser_get_mediaURL (GstActiveStream * stream,
   url_prefix = segmentURL->media ? segmentURL->media : stream->baseURL;
   g_return_val_if_fail (url_prefix != NULL, NULL);
 
-  return gst_mpdparser_get_segmentURL_for_range (segmentURL->media,
-      segmentURL->mediaRange);
+  return segmentURL->media;
 }
 
 static gchar *
@@ -2393,8 +2371,7 @@ gst_mpdparser_get_initializationURL (GstURLType * InitializationURL)
   g_return_val_if_fail (InitializationURL != NULL, NULL);
   g_return_val_if_fail (InitializationURL->sourceURL != NULL, NULL);
 
-  return gst_mpdparser_get_segmentURL_for_range (InitializationURL->sourceURL,
-      InitializationURL->range);
+  return InitializationURL->sourceURL;
 }
 
 static gchar *
@@ -3296,6 +3273,7 @@ gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client,
 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)
 {
   GstActiveStream *stream = NULL;
@@ -3324,7 +3302,7 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
 
   GST_DEBUG ("currentChunk->SegmentURL = %p", currentChunk->SegmentURL);
   if (currentChunk->SegmentURL != NULL) {
-    mediaURL = gst_mpdparser_get_mediaURL (stream, currentChunk->SegmentURL);
+    mediaURL = g_strdup (gst_mpdparser_get_mediaURL (stream, currentChunk->SegmentURL));
   } else if (stream->cur_seg_template != NULL) {
     mediaURL =
         gst_mpdparser_build_URL_from_template (stream->cur_seg_template->media,
@@ -3336,6 +3314,13 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
   *timestamp = currentChunk->start_time;
   *duration = currentChunk->duration;
   *discontinuity = segment_idx != currentChunk->number;
+  *range_start = 0;
+  *range_end = -1;
+  if (currentChunk->SegmentURL->mediaRange) {
+    *range_start = currentChunk->SegmentURL->mediaRange->first_byte_pos;
+    *range_end = currentChunk->SegmentURL->mediaRange->last_byte_pos;
+  }
+
   if (mediaURL == NULL) {
     /* single segment with URL encoded in the baseURL syntax element */
     *uri = g_strdup (stream->baseURL);
@@ -3355,7 +3340,7 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
 
 gboolean
 gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
-    guint stream_idx)
+    guint stream_idx, gint64 * range_start, gint64 * range_end)
 {
   GstActiveStream *stream;
   GstStreamPeriod *stream_period;
@@ -3367,13 +3352,22 @@ gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
   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 header");
   GST_MPD_CLIENT_LOCK (client);
   *uri = NULL;
   if (stream->cur_segment_base && stream->cur_segment_base->Initialization) {
     *uri =
-        gst_mpdparser_get_initializationURL (stream->
-        cur_segment_base->Initialization);
+        g_strdup (gst_mpdparser_get_initializationURL (stream->cur_segment_base->
+        Initialization));
+    if (stream->cur_segment_base->Initialization->range) {
+      *range_start =
+          stream->cur_segment_base->Initialization->range->first_byte_pos;
+      *range_end =
+          stream->cur_segment_base->Initialization->range->last_byte_pos;
+    }
   } else if (stream->cur_seg_template) {
     const gchar *initialization = NULL;
     if (stream->cur_seg_template->initialization) {
index 1069c5e..9f005ba 100644 (file)
@@ -473,8 +473,8 @@ GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client);
 GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
 gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
 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, GstClockTime *duration, GstClockTime *timestamp);
-gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx);
+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_is_live (GstMpdClient * client);
 gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts);