From 4f17112392d392e0cb841ea63382cef29154f33a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 20 Jun 2013 03:52:31 -0300 Subject: [PATCH] dashdemux: add support for range based segments 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 | 22 +++++++++++------- ext/dash/gstmpdparser.c | 60 ++++++++++++++++++++++--------------------------- ext/dash/gstmpdparser.h | 4 ++-- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index 3928989..4530fd2 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -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, ×tamp)) { + stream_idx, &discont, &next_fragment_uri, &range_start, &range_end, + &duration, ×tamp)) { 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) diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c index bbbcdf9..19eab29 100644 --- a/ext/dash/gstmpdparser.c +++ b/ext/dash/gstmpdparser.c @@ -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) { diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h index 1069c5e..9f005ba 100644 --- a/ext/dash/gstmpdparser.h +++ b/ext/dash/gstmpdparser.h @@ -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); -- 2.7.4