diff --git a/ext/dash/gstdashdemux.c b/ext/dash/gstdashdemux.c index 25ee3307e1..a78c0e579a 100644 --- a/ext/dash/gstdashdemux.c +++ b/ext/dash/gstdashdemux.c @@ -2113,6 +2113,36 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux, gst_mpdparser_get_active_stream_by_index (demux->client, selected_stream->index); + /* If this is a live stream, check the segment end time to make sure + * it is available to download + */ + if (selected_stream && gst_mpd_client_is_live (demux->client) && + demux->client->mpd_node->minimumUpdatePeriod != -1) { + GstDateTime *seg_end_time; + GstDateTime *cur_time = gst_date_time_new_now_utc (); + + seg_end_time = + gst_mpd_client_get_next_segment_availability_end_time (demux->client, + *stream); + + if (seg_end_time) { + gint64 diff; + + cur_time = gst_date_time_new_now_utc (); + diff = gst_mpd_client_calculate_time_difference (cur_time, seg_end_time) + / GST_MSECOND; + gst_date_time_unref (seg_end_time); + gst_date_time_unref (cur_time); + if (diff > 0) { + GST_DEBUG_OBJECT (demux, + "Selected fragment has end timestamp > now (%" PRIi64 + "), delaying download", diff); + end_of_period = FALSE; + gst_dash_demux_download_wait (demux, diff); + } + } + } + /* Get the fragment corresponding to each stream index */ if (selected_stream) { guint stream_idx = selected_stream->index; diff --git a/ext/dash/gstmpdparser.c b/ext/dash/gstmpdparser.c index 955f046f0b..9fac7d8bb0 100644 --- a/ext/dash/gstmpdparser.c +++ b/ext/dash/gstmpdparser.c @@ -138,8 +138,6 @@ static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client, GstActiveStream * stream); static GstDateTime *gst_mpd_client_get_availability_start_time (GstMpdClient * client); -static gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1, - const GstDateTime * t2); /* Adaptation Set */ static GstAdaptationSetNode @@ -2863,7 +2861,7 @@ gst_mpd_client_get_segment_duration (GstMpdClient * client, { GstStreamPeriod *stream_period; GstMultSegmentBaseType *base = NULL; - GstClockTime duration; + GstClockTime duration = 0; guint timescale; g_return_val_if_fail (stream != NULL, GST_CLOCK_TIME_NONE); @@ -3564,7 +3562,7 @@ gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, return TRUE; } -static gint64 +gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1, const GstDateTime * t2) { @@ -3633,17 +3631,19 @@ gst_mpd_client_get_segment_index_at_time (GstMpdClient * client, return diff / seg_duration; } -GstDateTime * +static GstDateTime * gst_mpd_client_get_availability_start_time (GstMpdClient * client) { - GstDateTime *t; + GstDateTime *start_time; - g_return_val_if_fail (client != NULL, NULL); + if (client == NULL) + return (GstDateTime *) NULL; GST_MPD_CLIENT_LOCK (client); - t = client->mpd_node->availabilityStartTime; + start_time = client->mpd_node->availabilityStartTime; + gst_date_time_ref (start_time); GST_MPD_CLIENT_UNLOCK (client); - return t; + return start_time; } gboolean @@ -4283,6 +4283,45 @@ gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient * client, return nb_adapatation_set; } + +GstDateTime * +gst_mpd_client_get_next_segment_availability_end_time (GstMpdClient * client, + GstActiveStream * stream) +{ + GstDateTime *availability_start_time, *rv; + guint seg_idx; + GstClockTime seg_duration; + gint64 offset; + GstStreamPeriod *stream_period; + + g_return_val_if_fail (client != NULL, NULL); + g_return_val_if_fail (stream != NULL, NULL); + + stream_period = gst_mpdparser_get_stream_period (client); + + seg_idx = gst_mpd_client_get_segment_index (stream); + seg_duration = gst_mpd_client_get_segment_duration (client, stream); + if (seg_duration == 0) + return NULL; + availability_start_time = gst_mpd_client_get_availability_start_time (client); + if (availability_start_time == NULL) + return (GstDateTime *) NULL; + + if (stream_period && stream_period->period) { + GstDateTime *t = + gst_mpd_client_add_time_difference (availability_start_time, + stream_period->period->start * 1000); + gst_date_time_unref (availability_start_time); + availability_start_time = t; + } + + offset = (1 + seg_idx) * seg_duration; + rv = gst_mpd_client_add_time_difference (availability_start_time, + offset / GST_USECOND); + gst_date_time_unref (availability_start_time); + return rv; +} + gint gst_mpd_client_check_time_position (GstMpdClient * client, GstActiveStream * stream, GstClockTime ts, gint64 * diff) diff --git a/ext/dash/gstmpdparser.h b/ext/dash/gstmpdparser.h index 57c1d31321..ea2c953a37 100644 --- a/ext/dash/gstmpdparser.h +++ b/ext/dash/gstmpdparser.h @@ -504,6 +504,7 @@ gboolean gst_mpd_client_set_period_id (GstMpdClient *client, const gchar * perio guint gst_mpd_client_get_period_index (GstMpdClient *client); const gchar *gst_mpd_client_get_period_id (GstMpdClient *client); gboolean gst_mpd_client_has_next_period (GstMpdClient *client); +GstDateTime *gst_mpd_client_get_next_segment_availability_end_time (GstMpdClient * client, GstActiveStream * stream); /* Representation selection */ gint gst_mpdparser_get_rep_idx_with_max_bandwidth (GList *Representations, gint max_bandwidth); @@ -535,6 +536,9 @@ guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream); /* Support multi language */ guint gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient *client, GList **lang); + +gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1, const GstDateTime * t2); + G_END_DECLS #endif /* __GST_MPDPARSER_H__ */