OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 * | 9 * |
10 */ | 10 */ |
11 | 11 |
12 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" | 12 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" |
13 | 13 |
| 14 #include <stdlib.h> |
| 15 |
| 16 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win
dow.h" |
14 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_
filter.h" | 17 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_
filter.h" |
| 18 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter
.h" |
15 | 19 |
16 namespace webrtc { | 20 namespace webrtc { |
17 namespace testing { | 21 namespace testing { |
18 namespace bwe { | 22 namespace bwe { |
19 namespace { | 23 namespace { |
20 const int kFeedbackIntervalsMs = 100; | 24 const int kFeedbackIntervalsMs = 100; |
21 // BBR uses this value to double sending rate each round trip. Design document | 25 // BBR uses this value to double sending rate each round trip. Design document |
22 // suggests using this value. | 26 // suggests using this value. |
23 const float kHighGain = 2.885f; | 27 const float kHighGain = 2.885f; |
24 // BBR uses this value to drain queues created during STARTUP in one round trip | 28 // BBR uses this value to drain queues created during STARTUP in one round trip |
25 // time. | 29 // time. |
26 const float kDrainGain = 1 / kHighGain; | 30 const float kDrainGain = 1 / kHighGain; |
27 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from | 31 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from |
28 // experiments, according to the design document. | 32 // experiments, according to the design document. |
29 const float kStartupGrowthTarget = 1.25f; | 33 const float kStartupGrowthTarget = 1.25f; |
30 const int kMaxRoundsWithoutGrowth = 3; | 34 const int kMaxRoundsWithoutGrowth = 3; |
| 35 // Pacing gain values for Probe Bandwidth mode. |
| 36 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; |
| 37 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); |
| 38 const int kMinimumCongestionWindow = 4000; |
| 39 const int kProbeRttDurationRounds = 1; |
| 40 const int kProbeRttDurationMs = 200; |
31 } // namespace | 41 } // namespace |
32 | 42 |
33 BbrBweSender::BbrBweSender(Clock* clock) | 43 BbrBweSender::BbrBweSender(Clock* clock) |
34 : BweSender(0), | 44 : BweSender(0), |
35 clock_(clock), | 45 clock_(clock), |
36 mode_(STARTUP), | 46 mode_(STARTUP), |
37 max_bandwidth_filter_(new MaxBandwidthFilter()), | 47 max_bandwidth_filter_(new MaxBandwidthFilter()), |
| 48 min_rtt_filter_(new MinRttFilter()), |
| 49 congestion_window_(new CongestionWindow()), |
38 round_count_(0), | 50 round_count_(0), |
39 last_packet_sent_(0), | 51 last_packet_sent_(0), |
40 round_trip_end_(0), | 52 round_trip_end_(0), |
41 full_bandwidth_reached_(false) { | 53 full_bandwidth_reached_(false), |
| 54 cycle_start_time_ms_(0), |
| 55 cycle_index_(0), |
| 56 prior_in_flight_(0), |
| 57 probe_rtt_start_time_ms_(0), |
| 58 minimum_congestion_window_start_time_ms_(0), |
| 59 minimum_congestion_window_start_round_(0) { |
42 // Initially enter Startup mode. | 60 // Initially enter Startup mode. |
43 EnterStartup(); | 61 EnterStartup(); |
44 } | 62 } |
45 | 63 |
46 BbrBweSender::~BbrBweSender() {} | 64 BbrBweSender::~BbrBweSender() {} |
47 | 65 |
48 int BbrBweSender::GetFeedbackIntervalMs() const { | 66 int BbrBweSender::GetFeedbackIntervalMs() const { |
49 return kFeedbackIntervalsMs; | 67 return kFeedbackIntervalsMs; |
50 } | 68 } |
51 | 69 |
(...skipping 22 matching lines...) Expand all Loading... |
74 case STARTUP: | 92 case STARTUP: |
75 TryExitingStartup(); | 93 TryExitingStartup(); |
76 break; | 94 break; |
77 case DRAIN: | 95 case DRAIN: |
78 TryExitingDrain(now_ms); | 96 TryExitingDrain(now_ms); |
79 break; | 97 break; |
80 case PROBE_BW: | 98 case PROBE_BW: |
81 TryUpdatingCyclePhase(now_ms); | 99 TryUpdatingCyclePhase(now_ms); |
82 break; | 100 break; |
83 case PROBE_RTT: | 101 case PROBE_RTT: |
84 TryExitingProbeRtt(now_ms); | 102 TryExitingProbeRtt(now_ms, 0, false); |
85 break; | 103 break; |
86 } | 104 } |
87 TryEnteringProbeRtt(now_ms); | 105 TryEnteringProbeRtt(now_ms, false); |
88 // TODO(gnish): implement functions updating congestion window and pacing rate | 106 // TODO(gnish): implement functions updating congestion window and pacing rate |
89 // controllers. | 107 // controllers. |
90 } | 108 } |
91 | 109 |
| 110 size_t BbrBweSender::TargetCongestionWindow(float gain) { |
| 111 size_t target_congestion_window = |
| 112 congestion_window_->GetTargetCongestionWindow( |
| 113 max_bandwidth_filter_->max_bandwidth_estimate_bps(), |
| 114 min_rtt_filter_->min_rtt_ms(), gain); |
| 115 return target_congestion_window; |
| 116 } |
| 117 |
92 bool BbrBweSender::UpdateBandwidthAndMinRtt() { | 118 bool BbrBweSender::UpdateBandwidthAndMinRtt() { |
93 return false; | 119 return false; |
94 } | 120 } |
95 | 121 |
96 void BbrBweSender::EnterStartup() { | 122 void BbrBweSender::EnterStartup() { |
97 mode_ = STARTUP; | 123 mode_ = STARTUP; |
98 pacing_gain_ = kHighGain; | 124 pacing_gain_ = kHighGain; |
99 congestion_window_gain_ = kHighGain; | 125 congestion_window_gain_ = kHighGain; |
100 } | 126 } |
101 | 127 |
102 void BbrBweSender::TryExitingStartup() { | 128 void BbrBweSender::TryExitingStartup() { |
103 if (full_bandwidth_reached_) { | 129 if (full_bandwidth_reached_) { |
104 mode_ = DRAIN; | 130 mode_ = DRAIN; |
105 pacing_gain_ = kDrainGain; | 131 pacing_gain_ = kDrainGain; |
106 congestion_window_gain_ = kHighGain; | 132 congestion_window_gain_ = kHighGain; |
107 } | 133 } |
108 } | 134 } |
109 | 135 |
110 void BbrBweSender::TryExitingDrain(int64_t now_ms) {} | 136 void BbrBweSender::TryExitingDrain(int64_t now_ms) { |
| 137 if (congestion_window_->data_inflight() <= TargetCongestionWindow(1)) |
| 138 EnterProbeBw(now_ms); |
| 139 } |
111 | 140 |
112 void BbrBweSender::EnterProbeBw(int64_t now_ms) {} | 141 // Start probing with a random gain value, which is different form 0.75, |
| 142 // starting with 0.75 doesn't offer any benefits as there are no queues to be |
| 143 // drained. |
| 144 void BbrBweSender::EnterProbeBw(int64_t now_ms) { |
| 145 mode_ = PROBE_BW; |
| 146 congestion_window_gain_ = 1.5f; |
| 147 unsigned int seed = time(NULL); |
| 148 int index = rand_r(&seed) % (kGainCycleLength - 1); |
| 149 if (index == 1) |
| 150 index = kGainCycleLength - 1; |
| 151 pacing_gain_ = kPacingGain[index]; |
| 152 cycle_start_time_ms_ = now_ms; |
| 153 cycle_index_ = index; |
| 154 } |
113 | 155 |
114 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {} | 156 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { |
| 157 // Each phase should last rougly min_rtt ms time. |
| 158 bool advance_cycle_phase = |
| 159 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); |
| 160 // If BBR was probing and it couldn't increase data inflight sufficiently in |
| 161 // one min_rtt time, continue probing. |
| 162 if (pacing_gain_ > 1.0 && |
| 163 prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) |
| 164 advance_cycle_phase = false; |
| 165 // If BBR has already drained queues there is no point in continuing draining |
| 166 // phase. |
| 167 if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) |
| 168 advance_cycle_phase = true; |
| 169 if (advance_cycle_phase) { |
| 170 cycle_index_++; |
| 171 cycle_index_ %= kGainCycleLength; |
| 172 pacing_gain_ = kPacingGain[cycle_index_]; |
| 173 cycle_start_time_ms_ = now_ms; |
| 174 } |
| 175 } |
115 | 176 |
116 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {} | 177 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms, bool min_rtt_expired) { |
117 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms) {} | 178 if (min_rtt_expired && mode_ != PROBE_RTT) { |
| 179 mode_ = PROBE_RTT; |
| 180 pacing_gain_ = 1; |
| 181 probe_rtt_start_time_ms_ = now_ms; |
| 182 minimum_congestion_window_start_time_ms_ = -1; |
| 183 } |
| 184 } |
| 185 |
| 186 // minimum_congestion_window_start_time_'s value is set to the first moment when |
| 187 // data inflight was less then kMinimumCongestionWindow, we should make sure |
| 188 // that BBR has been in PROBE_RTT mode for at least one round or 200ms. |
| 189 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, |
| 190 int64_t round, |
| 191 bool min_rtt_expired) { |
| 192 if (minimum_congestion_window_start_time_ms_ == -1) { |
| 193 if (congestion_window_->data_inflight() <= kMinimumCongestionWindow) { |
| 194 minimum_congestion_window_start_time_ms_ = now_ms; |
| 195 minimum_congestion_window_start_round_ = round; |
| 196 } |
| 197 } else { |
| 198 if (now_ms - minimum_congestion_window_start_time_ms_ >= |
| 199 kProbeRttDurationMs && |
| 200 round - minimum_congestion_window_start_round_ >= |
| 201 kProbeRttDurationRounds) |
| 202 EnterProbeBw(now_ms); |
| 203 } |
| 204 } |
118 | 205 |
119 int64_t BbrBweSender::TimeUntilNextProcess() { | 206 int64_t BbrBweSender::TimeUntilNextProcess() { |
120 return 100; | 207 return 100; |
121 } | 208 } |
122 | 209 |
123 void BbrBweSender::OnPacketsSent(const Packets& packets) { | 210 void BbrBweSender::OnPacketsSent(const Packets& packets) { |
124 last_packet_sent_ = | 211 last_packet_sent_ = |
125 static_cast<const MediaPacket*>(packets.back())->sequence_number(); | 212 static_cast<const MediaPacket*>(packets.back())->sequence_number(); |
126 } | 213 } |
127 | 214 |
128 void BbrBweSender::Process() {} | 215 void BbrBweSender::Process() {} |
129 | 216 |
130 BbrBweReceiver::BbrBweReceiver(int flow_id) | 217 BbrBweReceiver::BbrBweReceiver(int flow_id) |
131 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} | 218 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} |
132 | 219 |
133 BbrBweReceiver::~BbrBweReceiver() {} | 220 BbrBweReceiver::~BbrBweReceiver() {} |
134 | 221 |
135 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, | 222 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, |
136 const MediaPacket& media_packet) {} | 223 const MediaPacket& media_packet) {} |
137 | 224 |
138 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { | 225 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { |
139 return nullptr; | 226 return nullptr; |
140 } | 227 } |
141 } // namespace bwe | 228 } // namespace bwe |
142 } // namespace testing | 229 } // namespace testing |
143 } // namespace webrtc | 230 } // namespace webrtc |
OLD | NEW |