mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-02 21:48:55 +00:00
dashdemux: handle top-level index urls
Parse and provide access to top-level index segments if available. dashdemux should push those whenever a header is pushed. Fixes #700489
This commit is contained in:
parent
54d87f071c
commit
d68fffc217
3 changed files with 100 additions and 27 deletions
|
@ -1686,35 +1686,63 @@ gst_dash_demux_select_representations (GstDashDemux * demux)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFragment *
|
static GstBuffer *
|
||||||
|
gst_dash_demux_download_header_fragment (GstDashDemux * demux, guint stream_idx,
|
||||||
|
gchar * path, gint64 range_start, gint64 range_end)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
gchar *next_header_uri;
|
||||||
|
GstFragment *fragment;
|
||||||
|
|
||||||
|
if (strncmp (path, "http://", 7) != 0) {
|
||||||
|
next_header_uri =
|
||||||
|
g_strconcat (gst_mpdparser_get_baseURL (demux->client, stream_idx),
|
||||||
|
path, NULL);
|
||||||
|
g_free (path);
|
||||||
|
} else {
|
||||||
|
next_header_uri = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
|
gst_dash_demux_get_next_header (GstDashDemux * demux, guint stream_idx)
|
||||||
{
|
{
|
||||||
gchar *initializationURL;
|
gchar *initializationURL;
|
||||||
gchar *next_header_uri;
|
GstBuffer *header_buffer, *index_buffer = NULL;
|
||||||
GstFragment *fragment;
|
|
||||||
gint64 range_start, range_end;
|
gint64 range_start, range_end;
|
||||||
|
|
||||||
if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
|
if (!gst_mpd_client_get_next_header (demux->client, &initializationURL,
|
||||||
stream_idx, &range_start, &range_end))
|
stream_idx, &range_start, &range_end))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strncmp (initializationURL, "http://", 7) != 0) {
|
GST_INFO_OBJECT (demux, "Fetching header %s %" G_GINT64_FORMAT "-%"
|
||||||
next_header_uri =
|
G_GINT64_FORMAT, initializationURL, range_start, range_end);
|
||||||
g_strconcat (gst_mpdparser_get_baseURL (demux->client, stream_idx),
|
header_buffer = gst_dash_demux_download_header_fragment (demux, stream_idx,
|
||||||
initializationURL, NULL);
|
initializationURL, range_start, range_end);
|
||||||
g_free (initializationURL);
|
|
||||||
} else {
|
/* check if we have an index */
|
||||||
next_header_uri = initializationURL;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_INFO_OBJECT (demux, "Fetching header %s %" G_GINT64_FORMAT "-%"
|
if (index_buffer && header_buffer) {
|
||||||
G_GINT64_FORMAT, next_header_uri, range_start, range_end);
|
header_buffer = gst_buffer_append (header_buffer, index_buffer);
|
||||||
|
} else if (index_buffer) {
|
||||||
|
gst_buffer_unref (index_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
fragment = gst_uri_downloader_fetch_uri_with_range (demux->downloader,
|
return header_buffer;
|
||||||
next_header_uri, range_start, range_end);
|
|
||||||
g_free (next_header_uri);
|
|
||||||
|
|
||||||
return fragment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -1824,7 +1852,8 @@ static gboolean
|
||||||
gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
{
|
{
|
||||||
GstActiveStream *active_stream;
|
GstActiveStream *active_stream;
|
||||||
GstFragment *download, *header;
|
GstFragment *download;
|
||||||
|
GstBuffer *header_buffer;
|
||||||
gchar *next_fragment_uri;
|
gchar *next_fragment_uri;
|
||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
|
@ -1923,16 +1952,11 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
|
|
||||||
if (selected_stream->need_header) {
|
if (selected_stream->need_header) {
|
||||||
/* We need to fetch a new header */
|
/* We need to fetch a new header */
|
||||||
if ((header =
|
if ((header_buffer =
|
||||||
gst_dash_demux_get_next_header (demux, stream_idx)) == NULL) {
|
gst_dash_demux_get_next_header (demux, stream_idx)) == NULL) {
|
||||||
GST_WARNING_OBJECT (demux, "Unable to fetch header");
|
GST_WARNING_OBJECT (demux, "Unable to fetch header");
|
||||||
} else {
|
} 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);
|
buffer = gst_buffer_append (header_buffer, buffer);
|
||||||
g_object_unref (header);
|
|
||||||
}
|
}
|
||||||
selected_stream->need_header = FALSE;
|
selected_stream->need_header = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer,
|
||||||
gst_mpdparser_get_xml_prop_unsigned_integer (a_node,
|
gst_mpdparser_get_xml_prop_unsigned_integer (a_node,
|
||||||
"presentationTimeOffset", 0);
|
"presentationTimeOffset", 0);
|
||||||
seg_base_type->indexRange =
|
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 =
|
seg_base_type->indexRangeExact =
|
||||||
gst_mpdparser_get_xml_prop_boolean (a_node, "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) {
|
||||||
if (seg_base_type->indexRange)
|
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->Initialization);
|
||||||
gst_mpdparser_free_url_type_node (seg_base_type->RepresentationIndex);
|
gst_mpdparser_free_url_type_node (seg_base_type->RepresentationIndex);
|
||||||
g_slice_free (GstSegmentBaseType, seg_base_type);
|
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;
|
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
|
GstClockTime
|
||||||
gst_mpd_client_get_current_position (GstMpdClient * client)
|
gst_mpd_client_get_current_position (GstMpdClient * client)
|
||||||
{
|
{
|
||||||
|
|
|
@ -142,7 +142,7 @@ struct _GstSegmentBaseType
|
||||||
{
|
{
|
||||||
guint timescale;
|
guint timescale;
|
||||||
guint presentationTimeOffset;
|
guint presentationTimeOffset;
|
||||||
gchar *indexRange;
|
GstRange *indexRange;
|
||||||
gboolean indexRangeExact;
|
gboolean indexRangeExact;
|
||||||
/* Initialization node */
|
/* Initialization node */
|
||||||
GstURLType *Initialization;
|
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_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_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 (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_is_live (GstMpdClient * client);
|
||||||
gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts);
|
gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue