Index: webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
diff --git a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
index 523036daf1aa8a3927368ebf068b447833812b15..f306fb255dc060c386569e343b19199eada30ab8 100644 |
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
@@ -30,6 +30,10 @@ const int kDefaultMinBitrateBps = 10000; |
const int kDefaultMaxBitrateBps = 1000000000; |
const int64_t kLowBitrateLogPeriodMs = 10000; |
const int64_t kRtcEventLogPeriodMs = 5000; |
+// Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals. |
+const int64_t kFeedbackIntervalMs = 1500; |
+const int64_t kFeedbackTimeoutIntervals = 3; |
+const int64_t kTimeoutIntervalMs = 1000; |
struct UmaRampUpMetric { |
const char* metric_name; |
@@ -53,7 +57,9 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) |
max_bitrate_configured_(kDefaultMaxBitrateBps), |
last_low_bitrate_log_ms_(-1), |
has_decreased_since_last_fraction_loss_(false), |
- time_last_receiver_block_ms_(-1), |
+ last_feedback_ms_(-1), |
+ last_packet_report_ms_(-1), |
+ last_timeout_ms_(-1), |
last_fraction_loss_(0), |
last_logged_fraction_loss_(0), |
last_round_trip_time_ms_(0), |
@@ -66,7 +72,9 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) |
uma_update_state_(kNoUpdate), |
rampup_uma_stats_updated_(kNumUmaRampupMetrics, false), |
event_log_(event_log), |
- last_rtc_event_log_ms_(-1) { |
+ last_rtc_event_log_ms_(-1), |
+ in_timeout_experiment_(webrtc::field_trial::FindFullName( |
+ "WebRTC-SendSideBwe") == "Enabled") { |
RTC_DCHECK(event_log); |
} |
@@ -130,6 +138,7 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, |
int64_t rtt, |
int number_of_packets, |
int64_t now_ms) { |
+ last_feedback_ms_ = now_ms; |
if (first_report_time_ms_ == -1) |
first_report_time_ms_ = now_ms; |
@@ -155,9 +164,9 @@ void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, |
// Reset accumulators. |
lost_packets_since_last_loss_update_Q8_ = 0; |
expected_packets_since_last_loss_update_ = 0; |
+ last_packet_report_ms_ = now_ms; |
+ UpdateEstimate(now_ms); |
} |
- time_last_receiver_block_ms_ = now_ms; |
- UpdateEstimate(now_ms); |
UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8); |
} |
@@ -201,8 +210,9 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
uint32_t prev_bitrate = bitrate_; |
if (bwe_incoming_ > bitrate_) |
bitrate_ = CapBitrateToThresholds(now_ms, bwe_incoming_); |
- if (delay_based_bitrate_bps_ > bitrate_) |
+ if (delay_based_bitrate_bps_ > bitrate_) { |
bitrate_ = CapBitrateToThresholds(now_ms, delay_based_bitrate_bps_); |
+ } |
if (bitrate_ != prev_bitrate) { |
min_bitrate_history_.clear(); |
min_bitrate_history_.push_back(std::make_pair(now_ms, bitrate_)); |
@@ -210,10 +220,14 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
} |
} |
UpdateMinHistory(now_ms); |
- // Only start updating bitrate when receiving receiver blocks. |
- // TODO(pbos): Handle the case when no receiver report is received for a very |
- // long time. |
- if (time_last_receiver_block_ms_ != -1) { |
+ if (last_packet_report_ms_ == -1) { |
+ // No feedback received. |
+ bitrate_ = CapBitrateToThresholds(now_ms, bitrate_); |
+ return; |
+ } |
+ int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_; |
+ int64_t time_since_feedback_ms = now_ms - last_feedback_ms_; |
+ if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) { |
if (last_fraction_loss_ <= 5) { |
// Loss < 2%: Increase rate by 8% of the min bitrate in the last |
// kBweIncreaseIntervalMs. |
@@ -223,7 +237,8 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
// If sending a constant 100kbps it can rampup immediatly to 108kbps |
// whenever a receiver report is received with lower packet loss. |
// If instead one would do: bitrate_ *= 1.08^(delta time), it would |
- // take over one second since the lower packet loss to achieve 108kbps. |
+ // take over one second since the lower packet loss to achieve |
+ // 108kbps. |
bitrate_ = static_cast<uint32_t>( |
min_bitrate_history_.front().second * 1.08 + 0.5); |
@@ -234,8 +249,8 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
} else if (last_fraction_loss_ <= 26) { |
// Loss between 2% - 10%: Do nothing. |
} else { |
- // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs + |
- // rtt. |
+ // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs |
+ // + rtt. |
if (!has_decreased_since_last_fraction_loss_ && |
(now_ms - time_last_decrease_ms_) >= |
(kBweDecreaseIntervalMs + last_round_trip_time_ms_)) { |
@@ -250,6 +265,20 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
has_decreased_since_last_fraction_loss_ = true; |
} |
} |
+ } else if (time_since_feedback_ms > |
+ kFeedbackTimeoutIntervals * kFeedbackIntervalMs && |
+ (last_timeout_ms_ == -1 || |
+ now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) { |
+ if (in_timeout_experiment_) { |
+ LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms |
+ << " ms), reducing bitrate."; |
+ bitrate_ *= 0.8; |
+ // Reset accumulators since we've already acted on missing feedback and |
+ // shouldn't to act again on these old lost packets. |
+ lost_packets_since_last_loss_update_Q8_ = 0; |
+ expected_packets_since_last_loss_update_ = 0; |
+ last_timeout_ms_ = now_ms; |
+ } |
} |
uint32_t capped_bitrate = CapBitrateToThresholds(now_ms, bitrate_); |
if (capped_bitrate != bitrate_ || |