dashdemux: Implement lazy-loading of external periods

https://bugzilla.gnome.org/show_bug.cgi?id=752230
This commit is contained in:
Sebastian Dröge 2015-09-22 16:17:38 +02:00
parent b70dab8f27
commit 93d85bd361
4 changed files with 121 additions and 30 deletions

View file

@ -736,7 +736,8 @@ gst_dash_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) { if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
manifest = (gchar *) mapinfo.data; manifest = (gchar *) mapinfo.data;
if (gst_mpd_parse (dashdemux->client, manifest, mapinfo.size)) { if (gst_mpd_parse (dashdemux->client, manifest, mapinfo.size)) {
if (gst_mpd_client_setup_media_presentation (dashdemux->client)) { if (gst_mpd_client_setup_media_presentation (dashdemux->client, 0, 0,
NULL)) {
ret = TRUE; ret = TRUE;
} else { } else {
GST_ELEMENT_ERROR (demux, STREAM, DECODE, GST_ELEMENT_ERROR (demux, STREAM, DECODE,
@ -1208,6 +1209,10 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
target_pos = (GstClockTime) demux->segment.stop; target_pos = (GstClockTime) demux->segment.stop;
/* select the requested Period in the Media Presentation */ /* select the requested Period in the Media Presentation */
if (!gst_mpd_client_setup_media_presentation (dashdemux->client, target_pos,
-1, NULL))
return FALSE;
current_period = 0; current_period = 0;
for (list = g_list_first (dashdemux->client->periods); list; for (list = g_list_first (dashdemux->client->periods); list;
list = g_list_next (list)) { list = g_list_next (list)) {
@ -1295,7 +1300,8 @@ gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
period_idx = gst_mpd_client_get_period_index (dashdemux->client); period_idx = gst_mpd_client_get_period_index (dashdemux->client);
/* setup video, audio and subtitle streams, starting from current Period */ /* setup video, audio and subtitle streams, starting from current Period */
if (!gst_mpd_client_setup_media_presentation (new_client)) { if (!gst_mpd_client_setup_media_presentation (new_client, -1,
(period_id ? -1 : period_idx), period_id)) {
/* TODO */ /* TODO */
} }

View file

@ -2978,6 +2978,9 @@ gst_mpd_client_get_period_index_at_time (GstMpdClient * client,
if (time_offset < 0) if (time_offset < 0)
return 0; return 0;
if (!gst_mpd_client_setup_media_presentation (client, time_offset, -1, NULL))
return 0;
for (idx = 0, iter = client->periods; iter; idx++, iter = g_list_next (iter)) { for (idx = 0, iter = client->periods; iter; idx++, iter = g_list_next (iter)) {
stream_period = iter->data; stream_period = iter->data;
if (stream_period->start <= time_offset if (stream_period->start <= time_offset
@ -3893,12 +3896,9 @@ gst_mpd_client_fetch_external_period (GstMpdClient * client,
return new_periods; return new_periods;
} }
/* TODO: Implement xlink actuation onRequest properly. Currently we download
* each external MPD immediately when iterating over the periods. We should
* do this only when actually switching to this period.
*/
gboolean gboolean
gst_mpd_client_setup_media_presentation (GstMpdClient * client) gst_mpd_client_setup_media_presentation (GstMpdClient * client,
GstClockTime time, gint period_idx, const gchar * period_id)
{ {
GstStreamPeriod *stream_period; GstStreamPeriod *stream_period;
GstClockTime start, duration; GstClockTime start, duration;
@ -3909,8 +3909,30 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->mpd_node != NULL, FALSE); g_return_val_if_fail (client->mpd_node != NULL, FALSE);
/* Check if we set up the media presentation far enough already */
for (list = client->periods; list; list = list->next) {
GstStreamPeriod *stream_period = list->data;
if ((time != GST_CLOCK_TIME_NONE
&& stream_period->duration != GST_CLOCK_TIME_NONE
&& stream_period->start + stream_period->duration >= time)
|| (time != GST_CLOCK_TIME_NONE && stream_period->start >= time))
return TRUE;
if (period_idx != -1 && stream_period->number >= period_idx)
return TRUE;
if (period_id != NULL && stream_period->period->id != NULL
&& strcmp (stream_period->period->id, period_id) == 0)
return TRUE;
}
GST_DEBUG ("Building the list of Periods in the Media Presentation"); GST_DEBUG ("Building the list of Periods in the Media Presentation");
/* clean the old period list, if any */ /* clean the old period list, if any */
/* TODO: In theory we could reuse the ones we have so far but that
* seems more complicated than the overhead caused here
*/
if (client->periods) { if (client->periods) {
g_list_foreach (client->periods, g_list_foreach (client->periods,
(GFunc) gst_mpdparser_free_stream_period, NULL); (GFunc) gst_mpdparser_free_stream_period, NULL);
@ -4076,10 +4098,24 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
GST_LOG (" - added Period %d start=%" GST_TIME_FORMAT " duration=%" GST_LOG (" - added Period %d start=%" GST_TIME_FORMAT " duration=%"
GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration)); GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
if ((time != GST_CLOCK_TIME_NONE
&& stream_period->duration != GST_CLOCK_TIME_NONE
&& stream_period->start + stream_period->duration >= time)
|| (time != GST_CLOCK_TIME_NONE && stream_period->start >= time))
break;
if (period_idx != -1 && stream_period->number >= period_idx)
break;
if (period_id != NULL && stream_period->period->id != NULL
&& strcmp (stream_period->period->id, period_id) == 0)
break;
list = list->next; list = list->next;
} }
GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", GST_DEBUG
("Found a total of %d valid Periods in the Media Presentation up to this point",
idx); idx);
return ret; return ret;
@ -5052,6 +5088,10 @@ gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id)
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
g_return_val_if_fail (period_id != NULL, FALSE); g_return_val_if_fail (period_id != NULL, FALSE);
if (!gst_mpd_client_setup_media_presentation (client, GST_CLOCK_TIME_NONE, -1,
period_id))
return FALSE;
for (period_idx = 0, iter = client->periods; iter; for (period_idx = 0, iter = client->periods; iter;
period_idx++, iter = g_list_next (iter)) { period_idx++, iter = g_list_next (iter)) {
next_stream_period = iter->data; next_stream_period = iter->data;
@ -5076,6 +5116,9 @@ gst_mpd_client_set_period_index (GstMpdClient * client, guint period_idx)
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
if (!gst_mpd_client_setup_media_presentation (client, -1, period_idx, NULL))
return FALSE;
next_stream_period = g_list_nth_data (client->periods, period_idx); next_stream_period = g_list_nth_data (client->periods, period_idx);
if (next_stream_period != NULL) { if (next_stream_period != NULL) {
client->period_idx = period_idx; client->period_idx = period_idx;

View file

@ -531,7 +531,7 @@ void gst_mpd_client_set_uri_downloader (GstMpdClient * client, GstUriDownloader
gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size); gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
/* Streaming management */ /* Streaming management */
gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client); gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client, GstClockTime time, gint period_index, const gchar *period_id);
gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set); gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set);
gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation); gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream); GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);

View file

@ -2567,7 +2567,9 @@ GST_START_TEST (dash_mpdparser_various_duration_formats)
ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml)); ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
periodNode = periodNode =
@ -2643,7 +2645,9 @@ GST_START_TEST (dash_mpdparser_setup_media_presentation)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
gst_mpd_client_free (mpdclient); gst_mpd_client_free (mpdclient);
@ -2678,7 +2682,9 @@ GST_START_TEST (dash_mpdparser_setup_streaming)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the first adaptation set of the first period */ /* get the first adaptation set of the first period */
@ -2725,7 +2731,9 @@ GST_START_TEST (dash_mpdparser_period_selection)
fail_unless (mpdclient->periods == NULL); fail_unless (mpdclient->periods == NULL);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* check the periods */ /* check the periods */
@ -2791,7 +2799,9 @@ GST_START_TEST (dash_mpdparser_get_period_at_time)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* request period for a time before availabilityStartTime, expect period index 0 */ /* request period for a time before availabilityStartTime, expect period index 0 */
@ -2858,7 +2868,9 @@ GST_START_TEST (dash_mpdparser_adaptationSet_handling)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* period0 has 1 adaptation set */ /* period0 has 1 adaptation set */
@ -2920,7 +2932,9 @@ GST_START_TEST (dash_mpdparser_representation_selection)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient); adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient);
@ -2993,7 +3007,9 @@ GST_START_TEST (dash_mpdparser_activeStream_selection)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3093,7 +3109,9 @@ GST_START_TEST (dash_mpdparser_activeStream_parameters)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3177,7 +3195,9 @@ GST_START_TEST (dash_mpdparser_get_audio_languages)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3226,7 +3246,9 @@ setup_mpd_client (const gchar * xml)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3451,7 +3473,9 @@ GST_START_TEST (dash_mpdparser_get_streamPresentationOffset)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3523,7 +3547,9 @@ GST_START_TEST (dash_mpdparser_segments)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3664,7 +3690,9 @@ GST_START_TEST (dash_mpdparser_headers)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3738,7 +3766,9 @@ GST_START_TEST (dash_mpdparser_fragments)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3885,7 +3915,9 @@ GST_START_TEST (dash_mpdparser_inherited_segmentURL)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -3990,7 +4022,9 @@ GST_START_TEST (dash_mpdparser_segment_list)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -4066,7 +4100,9 @@ GST_START_TEST (dash_mpdparser_segment_template)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -4167,7 +4203,9 @@ GST_START_TEST (dash_mpdparser_segment_timeline)
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* get the list of adaptation sets of the first period */ /* get the list of adaptation sets of the first period */
@ -4343,7 +4381,9 @@ GST_START_TEST (dash_mpdparser_wrong_period_duration_inferred_from_next_period)
fail_unless (mpdclient->periods == NULL); fail_unless (mpdclient->periods == NULL);
/* process the xml data */ /* process the xml data */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, TRUE); assert_equals_int (ret, TRUE);
/* Period0 should be present */ /* Period0 should be present */
@ -4388,7 +4428,9 @@ GST_START_TEST
/* process the xml data /* process the xml data
* should fail due to wrong duration in Period0 (start > mediaPresentationDuration) * should fail due to wrong duration in Period0 (start > mediaPresentationDuration)
*/ */
ret = gst_mpd_client_setup_media_presentation (mpdclient); ret =
gst_mpd_client_setup_media_presentation (mpdclient, GST_CLOCK_TIME_NONE,
-1, NULL);
assert_equals_int (ret, FALSE); assert_equals_int (ret, FALSE);
gst_mpd_client_free (mpdclient); gst_mpd_client_free (mpdclient);