dashdemux: stop fetching live fragments that don't yet exist

There is an issue for live streams where download_loop will keep
downloading segments until it gets a 404 error for a segment
that has not yet been published. This is a problem because this
request for a segment that doesn't exist will propagate all the
way back to the origin server(s). This means that dashdemux causes
extra load on the origin server(s) for segments that aren't yet
available.

This patch uses availabilityStartTime, period
and the host's idea of UTC to decide if a fragment is available to
be requested from an HTTP server and filter out requests for fragments
that are not yet available.

https://bugzilla.gnome.org/show_bug.cgi?id=701404
This commit is contained in:
Alex Ashley 2013-09-26 16:13:33 -03:00 committed by Thiago Santos
parent 4b5d560092
commit 42fd04ce48
3 changed files with 82 additions and 9 deletions

View file

@ -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;

View file

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

View file

@ -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__ */