Index: webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc |
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc |
index a2463fc872e89df01e3260f738a39cf770eb3b23..dfc8bdd62b7ed42bed5a3100129b5c0c64e19d2a 100644 |
--- a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc |
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc |
@@ -11,7 +11,11 @@ |
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" |
+#include <stdlib.h> |
+ |
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h" |
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" |
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h" |
namespace webrtc { |
namespace testing { |
@@ -28,6 +32,12 @@ const float kDrainGain = 1 / kHighGain; |
// experiments, according to the design document. |
const float kStartupGrowthTarget = 1.25f; |
const int kMaxRoundsWithoutGrowth = 3; |
+// Pacing gain values for Probe Bandwidth mode. |
+const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; |
+const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); |
+const int kMinimumCongestionWindow = 4000; |
+const int kProbeRttDurationRounds = 1; |
+const int kProbeRttDurationMs = 200; |
} // namespace |
BbrBweSender::BbrBweSender(Clock* clock) |
@@ -35,10 +45,18 @@ BbrBweSender::BbrBweSender(Clock* clock) |
clock_(clock), |
mode_(STARTUP), |
max_bandwidth_filter_(new MaxBandwidthFilter()), |
+ min_rtt_filter_(new MinRttFilter()), |
+ congestion_window_(new CongestionWindow()), |
round_count_(0), |
last_packet_sent_(0), |
round_trip_end_(0), |
- full_bandwidth_reached_(false) { |
+ full_bandwidth_reached_(false), |
+ cycle_start_time_ms_(0), |
+ cycle_index_(0), |
+ prior_in_flight_(0), |
+ probe_rtt_start_time_ms_(0), |
+ minimum_congestion_window_start_time_ms_(0), |
+ minimum_congestion_window_start_round_(0) { |
// Initially enter Startup mode. |
EnterStartup(); |
} |
@@ -81,14 +99,22 @@ void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { |
TryUpdatingCyclePhase(now_ms); |
break; |
case PROBE_RTT: |
- TryExitingProbeRtt(now_ms); |
+ TryExitingProbeRtt(now_ms, 0, false); |
break; |
} |
- TryEnteringProbeRtt(now_ms); |
+ TryEnteringProbeRtt(now_ms, false); |
// TODO(gnish): implement functions updating congestion window and pacing rate |
// controllers. |
} |
+size_t BbrBweSender::TargetCongestionWindow(float gain) { |
+ size_t target_congestion_window = |
+ congestion_window_->GetTargetCongestionWindow( |
+ max_bandwidth_filter_->max_bandwidth_estimate_bps(), |
+ min_rtt_filter_->min_rtt_ms(), gain); |
+ return target_congestion_window; |
+} |
+ |
bool BbrBweSender::UpdateBandwidthAndMinRtt() { |
return false; |
} |
@@ -107,14 +133,75 @@ void BbrBweSender::TryExitingStartup() { |
} |
} |
-void BbrBweSender::TryExitingDrain(int64_t now_ms) {} |
+void BbrBweSender::TryExitingDrain(int64_t now_ms) { |
+ if (congestion_window_->data_inflight() <= TargetCongestionWindow(1)) |
+ EnterProbeBw(now_ms); |
+} |
-void BbrBweSender::EnterProbeBw(int64_t now_ms) {} |
+// Start probing with a random gain value, which is different form 0.75, |
+// starting with 0.75 doesn't offer any benefits as there are no queues to be |
+// drained. |
+void BbrBweSender::EnterProbeBw(int64_t now_ms) { |
+ mode_ = PROBE_BW; |
+ congestion_window_gain_ = 1.5f; |
+ unsigned int seed = time(NULL); |
+ int index = rand_r(&seed) % (kGainCycleLength - 1); |
+ if (index == 1) |
+ index = kGainCycleLength - 1; |
+ pacing_gain_ = kPacingGain[index]; |
+ cycle_start_time_ms_ = now_ms; |
+ cycle_index_ = index; |
+} |
-void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {} |
+void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { |
+ // Each phase should last rougly min_rtt ms time. |
+ bool advance_cycle_phase = |
+ now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); |
+ // If BBR was probing and it couldn't increase data inflight sufficiently in |
+ // one min_rtt time, continue probing. |
+ if (pacing_gain_ > 1.0 && |
+ prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) |
+ advance_cycle_phase = false; |
+ // If BBR has already drained queues there is no point in continuing draining |
+ // phase. |
+ if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) |
+ advance_cycle_phase = true; |
+ if (advance_cycle_phase) { |
+ cycle_index_++; |
+ cycle_index_ %= kGainCycleLength; |
+ pacing_gain_ = kPacingGain[cycle_index_]; |
+ cycle_start_time_ms_ = now_ms; |
+ } |
+} |
-void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {} |
-void BbrBweSender::TryExitingProbeRtt(int64_t now_ms) {} |
+void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms, bool min_rtt_expired) { |
+ if (min_rtt_expired && mode_ != PROBE_RTT) { |
+ mode_ = PROBE_RTT; |
+ pacing_gain_ = 1; |
+ probe_rtt_start_time_ms_ = now_ms; |
+ minimum_congestion_window_start_time_ms_ = -1; |
+ } |
+} |
+ |
+// minimum_congestion_window_start_time_'s value is set to the first moment when |
+// data inflight was less then kMinimumCongestionWindow, we should make sure |
+// that BBR has been in PROBE_RTT mode for at least one round or 200ms. |
+void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, |
+ int64_t round, |
+ bool min_rtt_expired) { |
+ if (minimum_congestion_window_start_time_ms_ == -1) { |
+ if (congestion_window_->data_inflight() <= kMinimumCongestionWindow) { |
+ minimum_congestion_window_start_time_ms_ = now_ms; |
+ minimum_congestion_window_start_round_ = round; |
+ } |
+ } else { |
+ if (now_ms - minimum_congestion_window_start_time_ms_ >= |
+ kProbeRttDurationMs && |
+ round - minimum_congestion_window_start_round_ >= |
+ kProbeRttDurationRounds) |
+ EnterProbeBw(now_ms); |
+ } |
+} |
int64_t BbrBweSender::TimeUntilNextProcess() { |
return 100; |