diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index 5445ad4a40..20d6764195 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -736,7 +736,8 @@ gst_dash_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf) if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) { manifest = (gchar *) mapinfo.data; 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; } else { GST_ELEMENT_ERROR (demux, STREAM, DECODE, @@ -1208,6 +1209,10 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek) target_pos = (GstClockTime) demux->segment.stop; /* 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; for (list = g_list_first (dashdemux->client->periods); 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); /* 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 */ } diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c index 3e6c0fef52..bb9d7b0576 100644 --- a/ext/dash/gstmpdparser.c +++ b/ext/dash/gstmpdparser.c @@ -2978,6 +2978,9 @@ gst_mpd_client_get_period_index_at_time (GstMpdClient * client, if (time_offset < 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)) { stream_period = iter->data; if (stream_period->start <= time_offset @@ -3893,12 +3896,9 @@ gst_mpd_client_fetch_external_period (GstMpdClient * client, 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 -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; 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->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"); /* 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) { g_list_foreach (client->periods, (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_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; } - 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); 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 (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; period_idx++, iter = g_list_next (iter)) { 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->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); if (next_stream_period != NULL) { client->period_idx = period_idx; diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h index 85ddc8476e..36569b5673 100644 --- a/ext/dash/gstmpdparser.h +++ b/ext/dash/gstmpdparser.h @@ -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); /* 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_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation); GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream); diff --git a/tests/check/elements/dash_mpd.c b/tests/check/elements/dash_mpd.c index 66b6bd7f27..05d971185b 100644 --- a/tests/check/elements/dash_mpd.c +++ b/tests/check/elements/dash_mpd.c @@ -2567,7 +2567,9 @@ GST_START_TEST (dash_mpdparser_various_duration_formats) ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml)); 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); periodNode = @@ -2643,7 +2645,9 @@ GST_START_TEST (dash_mpdparser_setup_media_presentation) assert_equals_int (ret, TRUE); /* 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); gst_mpd_client_free (mpdclient); @@ -2678,7 +2682,9 @@ GST_START_TEST (dash_mpdparser_setup_streaming) assert_equals_int (ret, TRUE); /* 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); /* 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); /* 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); /* check the periods */ @@ -2791,7 +2799,9 @@ GST_START_TEST (dash_mpdparser_get_period_at_time) assert_equals_int (ret, TRUE); /* 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); /* 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); /* 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); /* period0 has 1 adaptation set */ @@ -2920,7 +2932,9 @@ GST_START_TEST (dash_mpdparser_representation_selection) assert_equals_int (ret, TRUE); /* 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); adaptationSets = gst_mpd_client_get_adaptation_sets (mpdclient); @@ -2993,7 +3007,9 @@ GST_START_TEST (dash_mpdparser_activeStream_selection) assert_equals_int (ret, TRUE); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* 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); /* Period0 should be present */ @@ -4388,7 +4428,9 @@ GST_START_TEST /* process the xml data * 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); gst_mpd_client_free (mpdclient);