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
This commit is contained in:
Thiago Santos 2013-06-20 03:52:31 -03:00
parent e76f3e95fd
commit 4f17112392
3 changed files with 43 additions and 43 deletions

View 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)

View 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
@ -2352,25 +2350,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) {

View 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);