rtpsession: don't use invalid times in RTCP timeouts

An invalid timeout can be calculated when we disabled RTCP by setting the
bandwidth to 0. Make sure all code can handle this case.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674626
This commit is contained in:
Wim Taymans 2013-07-23 17:40:02 +02:00
parent 25e0f0d6b6
commit dece8413ef

View file

@ -2067,7 +2067,8 @@ rtp_session_process_bye (RTPSession * sess, GstRTCPPacket * packet,
/* some members went away since the previous timeout estimate. /* some members went away since the previous timeout estimate.
* Perform reverse reconsideration but only when we are not scheduling a * Perform reverse reconsideration but only when we are not scheduling a
* BYE ourselves. */ * BYE ourselves. */
if (arrival->current_time < sess->next_rtcp_check_time) { if (sess->next_rtcp_check_time != GST_CLOCK_TIME_NONE &&
arrival->current_time < sess->next_rtcp_check_time) {
GstClockTime time_remaining; GstClockTime time_remaining;
time_remaining = sess->next_rtcp_check_time - arrival->current_time; time_remaining = sess->next_rtcp_check_time - arrival->current_time;
@ -2489,6 +2490,7 @@ add_bitrates (gpointer key, RTPSource * source, gdouble * bandwidth)
*bandwidth += source->bitrate; *bandwidth += source->bitrate;
} }
/* must be called with session lock */
static GstClockTime static GstClockTime
calculate_rtcp_interval (RTPSession * sess, gboolean deterministic, calculate_rtcp_interval (RTPSession * sess, gboolean deterministic,
gboolean first) gboolean first)
@ -2569,7 +2571,11 @@ rtp_session_schedule_bye_locked (RTPSession * sess, const gchar * reason,
/* reschedule transmission */ /* reschedule transmission */
sess->last_rtcp_send_time = current_time; sess->last_rtcp_send_time = current_time;
interval = calculate_rtcp_interval (sess, FALSE, TRUE); interval = calculate_rtcp_interval (sess, FALSE, TRUE);
sess->next_rtcp_check_time = current_time + interval;
if (interval != GST_CLOCK_TIME_NONE)
sess->next_rtcp_check_time = current_time + interval;
else
sess->next_rtcp_check_time = GST_CLOCK_TIME_NONE;
GST_DEBUG ("Schedule BYE for %" GST_TIME_FORMAT ", %" GST_TIME_FORMAT, GST_DEBUG ("Schedule BYE for %" GST_TIME_FORMAT ", %" GST_TIME_FORMAT,
GST_TIME_ARGS (interval), GST_TIME_ARGS (sess->next_rtcp_check_time)); GST_TIME_ARGS (interval), GST_TIME_ARGS (sess->next_rtcp_check_time));
@ -2639,7 +2645,7 @@ rtp_session_next_timeout (RTPSession * sess, GstClockTime current_time)
", next time: %" GST_TIME_FORMAT, ", next time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_time), GST_TIME_ARGS (result)); GST_TIME_ARGS (current_time), GST_TIME_ARGS (result));
if (result < current_time) { if (result == GST_CLOCK_TIME_NONE || result < current_time) {
GST_DEBUG ("take current time as base"); GST_DEBUG ("take current time as base");
/* our previous check time expired, start counting from the current time /* our previous check time expired, start counting from the current time
* again. */ * again. */
@ -2795,6 +2801,10 @@ session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
is_sender = RTP_SOURCE_IS_SENDER (source); is_sender = RTP_SOURCE_IS_SENDER (source);
is_active = RTP_SOURCE_IS_ACTIVE (source); is_active = RTP_SOURCE_IS_ACTIVE (source);
/* nothing to do when without RTCP */
if (data->interval == GST_CLOCK_TIME_NONE)
return;
/* our own rtcp interval may have been forced low by secondary configuration, /* our own rtcp interval may have been forced low by secondary configuration,
* while sender side may still operate with higher interval, * while sender side may still operate with higher interval,
* so do not just take our interval to decide on timing out sender, * so do not just take our interval to decide on timing out sender,
@ -2977,7 +2987,8 @@ is_rtcp_time (RTPSession * sess, GstClockTime current_time, ReportData * data)
goto early; goto early;
/* no need to check yet */ /* no need to check yet */
if (sess->next_rtcp_check_time > current_time) { if (sess->next_rtcp_check_time == GST_CLOCK_TIME_NONE ||
sess->next_rtcp_check_time > current_time) {
GST_DEBUG ("no check time yet, next %" GST_TIME_FORMAT " > now %" GST_DEBUG ("no check time yet, next %" GST_TIME_FORMAT " > now %"
GST_TIME_FORMAT, GST_TIME_ARGS (sess->next_rtcp_check_time), GST_TIME_FORMAT, GST_TIME_ARGS (sess->next_rtcp_check_time),
GST_TIME_ARGS (current_time)); GST_TIME_ARGS (current_time));
@ -2987,16 +2998,20 @@ is_rtcp_time (RTPSession * sess, GstClockTime current_time, ReportData * data)
/* get elapsed time since we last reported */ /* get elapsed time since we last reported */
elapsed = current_time - sess->last_rtcp_send_time; elapsed = current_time - sess->last_rtcp_send_time;
new_send_time = data->interval;
/* perform forward reconsideration */ /* perform forward reconsideration */
new_send_time = rtp_stats_add_rtcp_jitter (&sess->stats, data->interval); if (new_send_time != GST_CLOCK_TIME_NONE) {
new_send_time = rtp_stats_add_rtcp_jitter (&sess->stats, new_send_time);
GST_DEBUG ("forward reconsideration %" GST_TIME_FORMAT ", elapsed %" GST_DEBUG ("forward reconsideration %" GST_TIME_FORMAT ", elapsed %"
GST_TIME_FORMAT, GST_TIME_ARGS (new_send_time), GST_TIME_ARGS (elapsed)); GST_TIME_FORMAT, GST_TIME_ARGS (new_send_time),
GST_TIME_ARGS (elapsed));
new_send_time += sess->last_rtcp_send_time; new_send_time += sess->last_rtcp_send_time;
}
/* check if reconsideration */ /* check if reconsideration */
if (current_time < new_send_time) { if (new_send_time == GST_CLOCK_TIME_NONE || current_time < new_send_time) {
GST_DEBUG ("reconsider RTCP for %" GST_TIME_FORMAT, GST_DEBUG ("reconsider RTCP for %" GST_TIME_FORMAT,
GST_TIME_ARGS (new_send_time)); GST_TIME_ARGS (new_send_time));
/* store new check time */ /* store new check time */
@ -3010,25 +3025,29 @@ early:
GST_DEBUG ("can send RTCP now, next interval %" GST_TIME_FORMAT, GST_DEBUG ("can send RTCP now, next interval %" GST_TIME_FORMAT,
GST_TIME_ARGS (new_send_time)); GST_TIME_ARGS (new_send_time));
sess->next_rtcp_check_time = current_time + new_send_time;
/* Apply the rules from RFC 4585 section 3.5.3 */ sess->next_rtcp_check_time = new_send_time;
if (sess->stats.min_interval != 0 && !sess->first_rtcp) { if (new_send_time != GST_CLOCK_TIME_NONE) {
GstClockTimeDiff T_rr_current_interval = g_random_double_range (0.5, 1.5) * sess->next_rtcp_check_time += current_time;
sess->stats.min_interval;
/* This will caused the RTCP to be suppressed if no FB packets are added */ /* Apply the rules from RFC 4585 section 3.5.3 */
if (sess->last_rtcp_send_time + T_rr_current_interval > if (sess->stats.min_interval != 0 && !sess->first_rtcp) {
sess->next_rtcp_check_time) { GstClockTimeDiff T_rr_current_interval =
GST_DEBUG ("RTCP packet could be suppressed min: %" GST_TIME_FORMAT g_random_double_range (0.5, 1.5) * sess->stats.min_interval;
" last: %" GST_TIME_FORMAT
" + T_rr_current_interval: %" GST_TIME_FORMAT /* This will caused the RTCP to be suppressed if no FB packets are added */
" > sess->next_rtcp_check_time: %" GST_TIME_FORMAT, if (sess->last_rtcp_send_time + T_rr_current_interval >
GST_TIME_ARGS (sess->stats.min_interval), sess->next_rtcp_check_time) {
GST_TIME_ARGS (sess->last_rtcp_send_time), GST_DEBUG ("RTCP packet could be suppressed min: %" GST_TIME_FORMAT
GST_TIME_ARGS (T_rr_current_interval), " last: %" GST_TIME_FORMAT
GST_TIME_ARGS (sess->next_rtcp_check_time)); " + T_rr_current_interval: %" GST_TIME_FORMAT
data->may_suppress = TRUE; " > sess->next_rtcp_check_time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (sess->stats.min_interval),
GST_TIME_ARGS (sess->last_rtcp_send_time),
GST_TIME_ARGS (T_rr_current_interval),
GST_TIME_ARGS (sess->next_rtcp_check_time));
data->may_suppress = TRUE;
}
} }
} }
@ -3224,6 +3243,9 @@ rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
if (GST_CLOCK_TIME_IS_VALID (sess->next_early_rtcp_time)) if (GST_CLOCK_TIME_IS_VALID (sess->next_early_rtcp_time))
goto dont_send; goto dont_send;
if (!GST_CLOCK_TIME_IS_VALID (sess->next_rtcp_check_time))
goto dont_send;
/* Ignore the request a scheduled packet will be in time anyway */ /* Ignore the request a scheduled packet will be in time anyway */
if (current_time + max_delay > sess->next_rtcp_check_time) if (current_time + max_delay > sess->next_rtcp_check_time)
goto dont_send; goto dont_send;