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 f2338b9c00e21c47d002b7b4c0539f0f2ec73d1c..2b7a74e084c644001fdc36b1045a2d946ac4b7e0 100644 |
--- a/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
+++ b/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc |
@@ -12,6 +12,8 @@ |
#include <algorithm> |
#include <cmath> |
+#include <limits> |
+#include <string> |
#include "webrtc/base/checks.h" |
#include "webrtc/base/logging.h" |
@@ -35,6 +37,10 @@ const int64_t kFeedbackIntervalMs = 1500; |
const int64_t kFeedbackTimeoutIntervals = 3; |
const int64_t kTimeoutIntervalMs = 1000; |
+const float kDefaultLowLossThreshold = 0.02f; |
+const float kDefaultHighLossThreshold = 0.1f; |
+const int kDefaultBitrateThresholdKbps = 0; |
+ |
struct UmaRampUpMetric { |
const char* metric_name; |
int bitrate_kbps; |
@@ -47,6 +53,52 @@ const UmaRampUpMetric kUmaRampupMetrics[] = { |
const size_t kNumUmaRampupMetrics = |
sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]); |
+const char kBweLosExperiment[] = "WebRTC-BweLossExperiment"; |
+ |
+bool BweLossExperimentIsEnabled() { |
+ std::string experiment_string = |
+ webrtc::field_trial::FindFullName(kBweLosExperiment); |
+ // The experiment is enabled iff the field trial string begins with "Enabled". |
+ return experiment_string.find("Enabled") == 0; |
+} |
+ |
+bool ReadBweLossExperimentParameters(float* low_loss_threshold, |
+ float* high_loss_threshold, |
+ uint32_t* bitrate_threshold_kbps) { |
+ RTC_DCHECK(low_loss_threshold); |
+ RTC_DCHECK(high_loss_threshold); |
+ RTC_DCHECK(bitrate_threshold_kbps); |
+ std::string experiment_string = |
+ webrtc::field_trial::FindFullName(kBweLosExperiment); |
+ int parsed_values = |
+ sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold, |
+ high_loss_threshold, bitrate_threshold_kbps); |
+ if (parsed_values == 3) { |
+ RTC_CHECK_GT(*low_loss_threshold, 0.0f) |
+ << "Loss threshold must be greater than 0."; |
+ RTC_CHECK_LE(*low_loss_threshold, 1.0f) |
+ << "Loss threshold must be less than or equal to 1."; |
+ RTC_CHECK_GT(*high_loss_threshold, 0.0f) |
+ << "Loss threshold must be greater than 0."; |
+ RTC_CHECK_LE(*high_loss_threshold, 1.0f) |
+ << "Loss threshold must be less than or equal to 1."; |
+ RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold) |
+ << "The low loss threshold must be less than or equal to the high loss " |
+ "threshold."; |
+ RTC_CHECK_GE(*bitrate_threshold_kbps, 0) |
+ << "Bitrate threshold can't be negative."; |
+ RTC_CHECK_LT(*bitrate_threshold_kbps, |
+ std::numeric_limits<int>::max() / 1000) |
+ << "Bitrate must be smaller enough to avoid overflows."; |
+ return true; |
+ } |
+ LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment " |
+ "experiment from field trial string. Using default."; |
+ *low_loss_threshold = kDefaultLowLossThreshold; |
+ *high_loss_threshold = kDefaultHighLossThreshold; |
+ *bitrate_threshold_kbps = kDefaultBitrateThresholdKbps; |
+ return false; |
+} |
} // namespace |
SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) |
@@ -74,8 +126,22 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) |
event_log_(event_log), |
last_rtc_event_log_ms_(-1), |
in_timeout_experiment_( |
- webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")) { |
+ webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")), |
+ low_loss_threshold_(kDefaultLowLossThreshold), |
+ high_loss_threshold_(kDefaultHighLossThreshold), |
+ bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) { |
RTC_DCHECK(event_log); |
+ if (BweLossExperimentIsEnabled()) { |
+ uint32_t bitrate_threshold_kbps; |
+ if (ReadBweLossExperimentParameters(&low_loss_threshold_, |
+ &high_loss_threshold_, |
+ &bitrate_threshold_kbps)) { |
+ LOG(LS_INFO) << "Enabled BweLossExperiment with parameters " |
+ << low_loss_threshold_ << ", " << high_loss_threshold_ |
+ << ", " << bitrate_threshold_kbps; |
+ bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000; |
+ } |
+ } |
} |
SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} |
@@ -229,7 +295,12 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
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) { |
+ // We only care about loss above a given bitrate threshold. |
+ float loss = last_fraction_loss_ / 256.0f; |
+ // We only make decisions based on loss when the bitrate is above a |
+ // threshold. This is a crude way of handling loss which is uncorrelated |
+ // to congestion. |
+ if (bitrate_ < bitrate_threshold_bps_ || loss <= low_loss_threshold_) { |
// Loss < 2%: Increase rate by 8% of the min bitrate in the last |
// kBweIncreaseIntervalMs. |
// Note that by remembering the bitrate over the last second one can |
@@ -247,23 +318,25 @@ void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) { |
// (gives a little extra increase at low rates, negligible at higher |
// rates). |
bitrate_ += 1000; |
- } else if (last_fraction_loss_ <= 26) { |
- // Loss between 2% - 10%: Do nothing. |
- } else { |
- // 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_)) { |
- time_last_decrease_ms_ = now_ms; |
- |
- // Reduce rate: |
- // newRate = rate * (1 - 0.5*lossRate); |
- // where packetLoss = 256*lossRate; |
- bitrate_ = static_cast<uint32_t>( |
- (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / |
- 512.0); |
- has_decreased_since_last_fraction_loss_ = true; |
+ } else if (bitrate_ > bitrate_threshold_bps_) { |
+ if (loss <= high_loss_threshold_) { |
+ // Loss between 2% - 10%: Do nothing. |
+ } else { |
+ // 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_)) { |
+ time_last_decrease_ms_ = now_ms; |
+ |
+ // Reduce rate: |
+ // newRate = rate * (1 - 0.5*lossRate); |
+ // where packetLoss = 256*lossRate; |
+ bitrate_ = static_cast<uint32_t>( |
+ (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / |
+ 512.0); |
+ has_decreased_since_last_fraction_loss_ = true; |
+ } |
} |
} |
} else if (time_since_feedback_ms > |