Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(885)

Side by Side Diff: webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc

Issue 2999073002: Tweaked version of BBR for WebRTC. (Closed)
Patch Set: Updated according to comments. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 */
(...skipping 16 matching lines...) Expand all
27 // suggests using this value. 27 // suggests using this value.
28 const float kHighGain = 2.885f; 28 const float kHighGain = 2.885f;
29 // BBR uses this value to drain queues created during STARTUP in one round trip 29 // BBR uses this value to drain queues created during STARTUP in one round trip
30 // time. 30 // time.
31 const float kDrainGain = 1 / kHighGain; 31 const float kDrainGain = 1 / kHighGain;
32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from 32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from
33 // experiments, according to the design document. 33 // experiments, according to the design document.
34 const float kStartupGrowthTarget = 1.25f; 34 const float kStartupGrowthTarget = 1.25f;
35 const int kMaxRoundsWithoutGrowth = 3; 35 const int kMaxRoundsWithoutGrowth = 3;
36 // Pacing gain values for Probe Bandwidth mode. 36 // Pacing gain values for Probe Bandwidth mode.
37 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; 37 const float kPacingGain[] = {1.1, 0.9, 1, 1, 1, 1, 1, 1};
38 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); 38 const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]);
39 // Least number of rounds PROBE_RTT should last. 39 // Least number of rounds PROBE_RTT should last.
40 const int kProbeRttDurationRounds = 1; 40 const int kProbeRttDurationRounds = 1;
41 // The least amount of milliseconds PROBE_RTT mode should last. 41 // The least amount of milliseconds PROBE_RTT mode should last.
42 const int kProbeRttDurationMs = 200; 42 const int kProbeRttDurationMs = 200;
43 // Gain value for congestion window for assuming that network has no queues. 43 // Gain value for congestion window for assuming that network has no queues.
44 const float kTargetCongestionWindowGain = 1; 44 const float kTargetCongestionWindowGain = 1;
45 // Gain value for congestion window in PROBE_BW mode. In theory it should be 45 // Gain value for congestion window in PROBE_BW mode. In theory it should be
46 // equal to 1, but in practice because of delayed acks and the way networks 46 // equal to 1, but in practice because of delayed acks and the way networks
47 // work, it is nice to have some extra room in congestion window for full link 47 // work, it is nice to have some extra room in congestion window for full link
48 // utilization. Value chosen by observations on different tests. 48 // utilization. Value chosen by observations on different tests.
49 const float kCruisingCongestionWindowGain = 1.5f; 49 const float kCruisingCongestionWindowGain = 2;
50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation 50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation
51 // tool. 51 // tool.
52 const float kRecoveryPacingGain = 0.5f; 52 const float kRecoveryPacingGain = 0.5f;
53 // Congestion window gain specific for Recovery mode. Chosen by experiments in 53 // Congestion window gain specific for Recovery mode. Chosen by experiments in
54 // simulation tool. 54 // simulation tool.
55 const float kRecoveryCongestionWindowGain = 1.5f; 55 const float kRecoveryCongestionWindowGain = 1.5f;
56 // Number of rounds over which average RTT is stored for Recovery mode. 56 // Number of rounds over which average RTT is stored for Recovery mode.
57 const size_t kPastRttsFilterSize = 1; 57 const size_t kPastRttsFilterSize = 1;
58 // Threshold to assume average RTT has increased for a round. Chosen by 58 // Threshold to assume average RTT has increased for a round. Chosen by
59 // experiments in simulation tool. 59 // experiments in simulation tool.
60 const float kRttIncreaseThreshold = 3; 60 const float kRttIncreaseThreshold = 3;
61 // Threshold to assume average RTT has decreased for a round. Chosen by 61 // Threshold to assume average RTT has decreased for a round. Chosen by
62 // experiments in simulation tool. 62 // experiments in simulation tool.
63 const float kRttDecreaseThreshold = 1.5f; 63 const float kRttDecreaseThreshold = 1.5f;
64 // If |kCongestionWindowThreshold| of the congestion window is filled up, tell
65 // encoder to stop, to avoid building sender side queues.
66 const float kCongestionWindowThreshold = 0.69f;
67 // Duration we send at |kDefaultRatebps| in order to ensure BBR has data to work
68 // with.
69 const int64_t kDefaultDurationMs = 200;
70 const int64_t kDefaultRatebps = 300000;
71 // Congestion window gain for PROBE_RTT mode.
72 const float kProbeRttCongestionWindowGain = 0.65f;
73 // We need to be sure that data inflight has increased by at least
74 // |kTargetCongestionWindowGainForHighGain| compared to the congestion window in
75 // PROBE_BW's high gain phase, to make ramp-up quicker. As high gain value has
76 // been decreased from 1.25 to 1.1 we need to make
77 // |kTargetCongestionWindowGainForHighGain| slightly higher than the actual high
78 // gain value.
79 const float kTargetCongestionWindowGainForHighGain = 1.15f;
80 // Encoder rate gain value for PROBE_RTT mode.
81 const float kEncoderRateGainForProbeRtt = 0.1f;
64 } // namespace 82 } // namespace
65 83
66 BbrBweSender::BbrBweSender(Clock* clock) 84 BbrBweSender::BbrBweSender(BitrateObserver* observer, Clock* clock)
67 : BweSender(0), 85 : BweSender(0),
86 observer_(observer),
68 clock_(clock), 87 clock_(clock),
69 mode_(STARTUP), 88 mode_(STARTUP),
70 max_bandwidth_filter_(new MaxBandwidthFilter()), 89 max_bandwidth_filter_(new MaxBandwidthFilter()),
71 min_rtt_filter_(new MinRttFilter()), 90 min_rtt_filter_(new MinRttFilter()),
72 congestion_window_(new CongestionWindow()), 91 congestion_window_(new CongestionWindow()),
73 rand_(new Random(time(NULL))), 92 rand_(new Random(time(NULL))),
74 round_count_(0), 93 round_count_(0),
75 round_trip_end_(0), 94 round_trip_end_(0),
76 full_bandwidth_reached_(false), 95 full_bandwidth_reached_(false),
77 cycle_start_time_ms_(0), 96 cycle_start_time_ms_(0),
(...skipping 28 matching lines...) Expand all
106 125
107 int BbrBweSender::GetFeedbackIntervalMs() const { 126 int BbrBweSender::GetFeedbackIntervalMs() const {
108 return kFeedbackIntervalsMs; 127 return kFeedbackIntervalsMs;
109 } 128 }
110 129
111 void BbrBweSender::CalculatePacingRate() { 130 void BbrBweSender::CalculatePacingRate() {
112 pacing_rate_bps_ = 131 pacing_rate_bps_ =
113 max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_; 132 max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_;
114 } 133 }
115 134
116 void BbrBweSender::HandleLoss(uint64_t last_acked_packet, 135 void BbrBweSender::HandleLoss(uint64_t last_acked_packet,
terelius 2017/08/18 14:34:04 Pls add comment about what this does.
gnish1 2017/08/18 14:53:50 Done.
117 uint64_t recently_acked_packet) { 136 uint64_t recently_acked_packet) {
118 // Logic specific to wrapping sequence numbers. 137 // Logic specific to wrapping sequence numbers.
119 if (!last_acked_packet) 138 if (!last_acked_packet)
terelius 2017/08/18 14:34:04 Needed?
gnish1 2017/08/18 14:53:50 Done.
120 return; 139 return;
121 for (uint16_t i = last_acked_packet + 1; 140 for (uint16_t i = last_acked_packet + 1;
122 AheadOrAt<uint16_t>(recently_acked_packet - 1, i); i++) { 141 AheadOrAt<uint16_t>(recently_acked_packet - 1, i); i++) {
123 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes); 142 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes);
143 observer_->OnBytesAcked(packet_stats_[i].payload_size_bytes);
124 } 144 }
125 } 145 }
126 146
127 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) { 147 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) {
128 uint64_t last_round = 0; 148 uint64_t last_round = 0;
129 if (!past_rtts_.empty()) 149 if (!past_rtts_.empty())
130 last_round = past_rtts_.back().round; 150 last_round = past_rtts_.back().round;
131 151
132 // Try to add the sample to the last round. 152 // Try to add the sample to the last round.
133 if (last_round == round_count_ && !past_rtts_.empty()) { 153 if (last_round == round_count_ && !past_rtts_.empty()) {
134 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms; 154 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms;
135 past_rtts_.back().num_samples++; 155 past_rtts_.back().num_samples++;
136 } else { 156 } else {
137 // If the sample belongs to a new round, keep number of rounds in the window 157 // If the sample belongs to a new round, keep number of rounds in the window
138 // equal to |kPastRttsFilterSize|. 158 // equal to |kPastRttsFilterSize|.
139 if (past_rtts_.size() == kPastRttsFilterSize) 159 if (past_rtts_.size() == kPastRttsFilterSize)
140 past_rtts_.pop_front(); 160 past_rtts_.pop_front();
141 past_rtts_.push_back( 161 past_rtts_.push_back(
142 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_)); 162 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_));
143 } 163 }
144 } 164 }
145 165
146 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { 166 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {
147 int64_t now_ms = clock_->TimeInMilliseconds(); 167 int64_t now_ms = clock_->TimeInMilliseconds();
148 last_packet_ack_time_ = now_ms; 168 last_packet_ack_time_ = now_ms;
149 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); 169 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback);
150 // feedback_vector holds values of acknowledged packets' sequence numbers. 170 // feedback_vector holds values of acknowledged packets' sequence numbers.
151 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); 171 const std::vector<uint16_t>& feedback_vector = fb.packet_feedback_vector();
152 // Go through all the packets acked, update variables/containers accordingly. 172 // Go through all the packets acked, update variables/containers accordingly.
153 for (uint16_t sequence_number : feedback_vector) { 173 for (uint16_t sequence_number : feedback_vector) {
154 // Completing packet information with a recently received ack. 174 // Completing packet information with a recently received ack.
155 PacketStats* packet = &packet_stats_[sequence_number]; 175 PacketStats* packet = &packet_stats_[sequence_number];
156 bytes_acked_ += packet->payload_size_bytes; 176 bytes_acked_ += packet->payload_size_bytes;
157 packet->data_sent_bytes = bytes_sent_; 177 packet->data_sent_bytes = bytes_sent_;
158 packet->last_sent_packet_send_time_ms = last_packet_send_time_; 178 packet->last_sent_packet_send_time_ms = last_packet_send_time_;
159 packet->data_acked_bytes = bytes_acked_; 179 packet->data_acked_bytes = bytes_acked_;
160 packet->ack_time_ms = now_ms; 180 packet->ack_time_ms = now_ms;
161 // Logic specific to applying "bucket" to high gain, in order to have 181 // Logic specific to applying "bucket" to high gain, in order to have
162 // quicker ramp-up. We check if we started receiving acks for the packets 182 // quicker ramp-up. We check if we started receiving acks for the packets
163 // sent during high gain phase. 183 // sent during high gain phase.
164 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) { 184 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) {
165 first_packet_ack_time_during_high_gain_ms_ = now_ms; 185 first_packet_ack_time_during_high_gain_ms_ = now_ms;
166 // Substracting half of the packet's size to avoid overestimation. 186 // Substracting half of the packet's size to avoid overestimation.
167 data_acked_before_high_gain_started_bytes_ = 187 data_acked_before_high_gain_started_bytes_ =
168 bytes_acked_ - packet->payload_size_bytes / 2; 188 bytes_acked_ - packet->payload_size_bytes / 2;
169 } 189 }
170 // If the last packet of high gain phase has been acked, high gain phase is 190 // If the last packet of high gain phase has been acked, high gain phase is
171 // over. 191 // over.
172 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) { 192 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) {
173 last_packet_ack_time_during_high_gain_ms_ = now_ms; 193 last_packet_ack_time_during_high_gain_ms_ = now_ms;
174 data_acked_before_high_gain_ended_bytes_ = 194 data_acked_before_high_gain_ended_bytes_ =
175 bytes_acked_ - packet->payload_size_bytes / 2; 195 bytes_acked_ - packet->payload_size_bytes / 2;
176 high_gain_over_ = true; 196 high_gain_over_ = true;
177 } 197 }
178 // Notify pacer that an ack was received, to adjust data inflight. 198 observer_->OnBytesAcked(packet->payload_size_bytes);
179 // TODO(gnish): Add implementation for BitrateObserver class, to notify
180 // pacer about incoming acks.
181 congestion_window_->AckReceived(packet->payload_size_bytes); 199 congestion_window_->AckReceived(packet->payload_size_bytes);
182 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number); 200 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number);
183 last_packet_acked_sequence_number_ = packet->sequence_number; 201 last_packet_acked_sequence_number_ = packet->sequence_number;
184 // Logic for wrapping sequence numbers. If round started with packet number 202 // Logic for wrapping sequence numbers. If round started with packet number
185 // x, it can never end on y, if x > y. That could happen when sequence 203 // x, it can never end on y, if x > y. That could happen when sequence
186 // numbers are wrapped after some point. 204 // numbers are wrapped after some point.
187 if (packet->sequence_number == 0) 205 if (packet->sequence_number == 0)
188 round_trip_end_ = 0; 206 round_trip_end_ = 0;
189 } 207 }
190 // Check if new round started for the connection. 208 // Check if new round started for the connection.
191 bool new_round_started = false; 209 bool new_round_started = false;
192 if (!feedback_vector.empty()) { 210 if (!feedback_vector.empty()) {
193 if (last_packet_acked_sequence_number_ > round_trip_end_) { 211 if (last_packet_acked_sequence_number_ > round_trip_end_) {
194 new_round_started = true; 212 new_round_started = true;
195 round_count_++; 213 round_count_++;
196 round_trip_end_ = last_packet_sent_sequence_number_; 214 round_trip_end_ = last_packet_sent_sequence_number_;
197 } 215 }
198 } 216 }
199 bool min_rtt_expired = false; 217 TryEnteringProbeRtt(now_ms);
200 min_rtt_expired = 218 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_);
201 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_);
202 if (new_round_started && !full_bandwidth_reached_) { 219 if (new_round_started && !full_bandwidth_reached_) {
203 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( 220 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached(
204 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); 221 kStartupGrowthTarget, kMaxRoundsWithoutGrowth);
205 } 222 }
206 switch (mode_) { 223 switch (mode_) {
207 break; 224 break;
208 case STARTUP: 225 case STARTUP:
209 TryExitingStartup(); 226 TryExitingStartup();
210 break; 227 break;
211 case DRAIN: 228 case DRAIN:
212 TryExitingDrain(now_ms); 229 TryExitingDrain(now_ms);
213 break; 230 break;
214 case PROBE_BW: 231 case PROBE_BW:
215 TryUpdatingCyclePhase(now_ms); 232 TryUpdatingCyclePhase(now_ms);
216 break; 233 break;
217 case PROBE_RTT: 234 case PROBE_RTT:
218 TryExitingProbeRtt(now_ms, round_count_); 235 TryExitingProbeRtt(now_ms, round_count_);
219 break; 236 break;
220 case RECOVERY: 237 case RECOVERY:
221 TryExitingRecovery(new_round_started); 238 TryExitingRecovery(new_round_started);
222 break; 239 break;
223 } 240 }
224 TryEnteringProbeRtt(now_ms);
225 TryEnteringRecovery(new_round_started); // Comment this line to disable 241 TryEnteringRecovery(new_round_started); // Comment this line to disable
226 // entering Recovery mode. 242 // entering Recovery mode.
227 for (uint64_t f : feedback_vector) 243 for (uint16_t f : feedback_vector)
228 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms); 244 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms);
229 CalculatePacingRate(); 245 CalculatePacingRate();
246 size_t cwnd = congestion_window_->GetCongestionWindow(
247 mode_, max_bandwidth_filter_->max_bandwidth_estimate_bps(),
248 min_rtt_filter_->min_rtt_ms(), congestion_window_gain_);
230 // Make sure we don't get stuck when pacing_rate is 0, because of simulation 249 // Make sure we don't get stuck when pacing_rate is 0, because of simulation
231 // tool specifics. 250 // tool specifics.
232 if (!pacing_rate_bps_) 251 if (!pacing_rate_bps_)
233 pacing_rate_bps_ = 100; 252 pacing_rate_bps_ = 100;
234 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000); 253 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000);
235 // TODO(gnish): Add implementation for BitrateObserver class to update pacing 254 int64_t rate_for_pacer_bps = pacing_rate_bps_;
236 // rate for the pacer and the encoder. 255 // Encoder producing slightly more due to rounding errors, so we ask for 2%
terelius 2017/08/18 14:34:03 No longer true?
gnish1 2017/08/18 14:53:50 Done.
256 // less.
257 int64_t rate_for_encoder_bps = pacing_rate_bps_;
258 if (congestion_window_->data_inflight() >= cwnd * kCongestionWindowThreshold)
259 rate_for_encoder_bps = 0;
260 // We dont completely stop sending during PROBE_RTT, so we need encoder to
261 // produce something, another way of doing this would be telling encoder to
262 // stop and send padding instead of actual data.
263 if (mode_ == PROBE_RTT)
264 rate_for_encoder_bps = rate_for_pacer_bps * kEncoderRateGainForProbeRtt;
265 // Send for 300 kbps for first 200 ms, so that BBR has data to work with.
266 if (now_ms <= kDefaultDurationMs)
267 observer_->OnNetworkChanged(
268 kDefaultRatebps, kDefaultRatebps, false,
269 clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd);
270 else
271 observer_->OnNetworkChanged(
272 rate_for_encoder_bps, rate_for_pacer_bps, mode_ == PROBE_RTT,
273 clock_->TimeInMicroseconds() + kFeedbackIntervalsMs * 1000, cwnd);
237 } 274 }
238 275
239 size_t BbrBweSender::TargetCongestionWindow(float gain) { 276 size_t BbrBweSender::TargetCongestionWindow(float gain) {
240 size_t target_congestion_window = 277 size_t target_congestion_window =
241 congestion_window_->GetTargetCongestionWindow( 278 congestion_window_->GetTargetCongestionWindow(
242 max_bandwidth_filter_->max_bandwidth_estimate_bps(), 279 max_bandwidth_filter_->max_bandwidth_estimate_bps(),
243 min_rtt_filter_->min_rtt_ms(), gain); 280 min_rtt_filter_->min_rtt_ms(), gain);
244 return target_congestion_window; 281 return target_congestion_window;
245 } 282 }
246 283
247 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample( 284 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample(
248 size_t data_sent_bytes, 285 size_t data_sent_bytes,
249 int64_t send_time_delta_ms, 286 int64_t send_time_delta_ms,
250 size_t data_acked_bytes, 287 size_t data_acked_bytes,
251 int64_t ack_time_delta_ms) { 288 int64_t ack_time_delta_ms) {
252 rtc::Optional<int64_t> bandwidth_sample; 289 rtc::Optional<int64_t> bandwidth_sample;
253 if (send_time_delta_ms > 0) 290 if (send_time_delta_ms > 0)
254 *bandwidth_sample = data_sent_bytes * 8000 / send_time_delta_ms; 291 bandwidth_sample.emplace(data_sent_bytes * 8000 / send_time_delta_ms);
255 rtc::Optional<int64_t> ack_rate; 292 rtc::Optional<int64_t> ack_rate;
256 if (ack_time_delta_ms > 0) 293 if (ack_time_delta_ms > 0)
257 *ack_rate = data_acked_bytes * 8000 / ack_time_delta_ms; 294 ack_rate.emplace(data_acked_bytes * 8000 / ack_time_delta_ms);
258 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to 295 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to
259 // ack_rate. 296 // ack_rate.
260 if (!bandwidth_sample) 297 if (!bandwidth_sample)
261 bandwidth_sample = ack_rate; 298 bandwidth_sample = ack_rate;
262 if (bandwidth_sample && ack_rate) 299 if (bandwidth_sample && ack_rate)
263 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate); 300 bandwidth_sample.emplace(std::min(*bandwidth_sample, *ack_rate));
264 return bandwidth_sample; 301 return bandwidth_sample;
265 } 302 }
266 303
267 void BbrBweSender::AddSampleForHighGain() { 304 void BbrBweSender::AddSampleForHighGain() {
268 if (!high_gain_over_) 305 if (!high_gain_over_)
269 return; 306 return;
270 high_gain_over_ = false; 307 high_gain_over_ = false;
271 // Calculate data sent/acked and time elapsed only for packets sent during 308 // Calculate data sent/acked and time elapsed only for packets sent during
272 // high gain phase. 309 // high gain phase.
273 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ - 310 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ -
274 data_sent_before_high_gain_started_bytes_; 311 data_sent_before_high_gain_started_bytes_;
275 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ - 312 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ -
276 *first_packet_send_time_during_high_gain_ms_; 313 *first_packet_send_time_during_high_gain_ms_;
277 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ - 314 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ -
278 data_acked_before_high_gain_started_bytes_; 315 data_acked_before_high_gain_started_bytes_;
279 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ - 316 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ -
280 first_packet_ack_time_during_high_gain_ms_; 317 first_packet_ack_time_during_high_gain_ms_;
281 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample( 318 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample(
282 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms); 319 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms);
283 if (bandwidth_sample) 320 if (bandwidth_sample)
284 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_); 321 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_);
285 first_packet_send_time_during_high_gain_ms_.reset(); 322 first_packet_send_time_during_high_gain_ms_.reset();
286 } 323 }
287 324
288 bool BbrBweSender::UpdateBandwidthAndMinRtt( 325 void BbrBweSender::UpdateBandwidthAndMinRtt(
289 int64_t now_ms, 326 int64_t now_ms,
290 const std::vector<uint64_t>& feedback_vector, 327 const std::vector<uint16_t>& feedback_vector,
291 int64_t bytes_acked) { 328 int64_t bytes_acked) {
292 rtc::Optional<int64_t> min_rtt_sample_ms; 329 rtc::Optional<int64_t> min_rtt_sample_ms;
293 for (uint64_t f : feedback_vector) { 330 for (uint16_t f : feedback_vector) {
294 PacketStats packet = packet_stats_[f]; 331 PacketStats packet = packet_stats_[f];
295 size_t data_sent_bytes = 332 size_t data_sent_bytes =
296 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes; 333 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes;
297 int64_t send_time_delta_ms = 334 int64_t send_time_delta_ms =
298 packet.last_sent_packet_send_time_ms - packet.send_time_ms; 335 packet.last_sent_packet_send_time_ms - packet.send_time_ms;
299 size_t data_acked_bytes = packet.data_acked_bytes - 336 size_t data_acked_bytes = packet.data_acked_bytes -
300 packet.data_acked_before_last_acked_packet_bytes; 337 packet.data_acked_before_last_acked_packet_bytes;
301 int64_t ack_time_delta_ms = 338 int64_t ack_time_delta_ms =
302 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms; 339 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms;
303 rtc::Optional<int64_t> bandwidth_sample = 340 rtc::Optional<int64_t> bandwidth_sample =
304 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms, 341 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms,
305 data_acked_bytes, ack_time_delta_ms); 342 data_acked_bytes, ack_time_delta_ms);
306 if (bandwidth_sample) 343 if (bandwidth_sample)
307 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, 344 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample,
308 round_count_); 345 round_count_);
309 AddSampleForHighGain(); // Comment to disable bucket for high gain. 346 // AddSampleForHighGain(); // Comment to disable bucket for high gain.
310 if (!min_rtt_sample_ms) 347 if (!min_rtt_sample_ms)
311 *min_rtt_sample_ms = packet.ack_time_ms - packet.send_time_ms; 348 min_rtt_sample_ms.emplace(packet.ack_time_ms - packet.send_time_ms);
312 else 349 else
313 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms, 350 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms,
314 packet.ack_time_ms - packet.send_time_ms); 351 packet.ack_time_ms - packet.send_time_ms);
315 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms, 352 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms,
316 packet.ack_time_ms - packet.send_time_ms); 353 packet.ack_time_ms - packet.send_time_ms);
317 } 354 }
318 if (!min_rtt_sample_ms) 355 // We only feed RTT samples into the min_rtt filter which were not produced
319 return false; 356 // during 1.1 gain phase, to ensure they contain no queueing delay. But if the
320 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms); 357 // rtt sample from 1.1 gain phase improves the current estimate then we should
321 bool min_rtt_expired = min_rtt_filter_->MinRttExpired(now_ms); 358 // make it as a new best estimate.
322 return min_rtt_expired; 359 if (pacing_gain_ <= 1.0f || !min_rtt_filter_->min_rtt_ms() ||
360 *min_rtt_filter_->min_rtt_ms() >= *min_rtt_sample_ms)
361 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms);
323 } 362 }
324 363
325 void BbrBweSender::EnterStartup() { 364 void BbrBweSender::EnterStartup() {
326 mode_ = STARTUP; 365 mode_ = STARTUP;
327 pacing_gain_ = kHighGain; 366 pacing_gain_ = kHighGain;
328 congestion_window_gain_ = kHighGain; 367 congestion_window_gain_ = kHighGain;
329 } 368 }
330 369
331 void BbrBweSender::TryExitingStartup() { 370 void BbrBweSender::TryExitingStartup() {
332 if (full_bandwidth_reached_) { 371 if (full_bandwidth_reached_) {
(...skipping 25 matching lines...) Expand all
358 397
359 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { 398 void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {
360 // Each phase should last rougly min_rtt ms time. 399 // Each phase should last rougly min_rtt ms time.
361 bool advance_cycle_phase = false; 400 bool advance_cycle_phase = false;
362 if (min_rtt_filter_->min_rtt_ms()) 401 if (min_rtt_filter_->min_rtt_ms())
363 advance_cycle_phase = 402 advance_cycle_phase =
364 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); 403 now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms();
365 // If BBR was probing and it couldn't increase data inflight sufficiently in 404 // If BBR was probing and it couldn't increase data inflight sufficiently in
366 // one min_rtt time, continue probing. BBR design doc isn't clear about this, 405 // one min_rtt time, continue probing. BBR design doc isn't clear about this,
367 // but condition helps in quicker ramp-up and performs better. 406 // but condition helps in quicker ramp-up and performs better.
368 if (pacing_gain_ > 1.0 && congestion_window_->data_inflight() < 407 if (pacing_gain_ > 1.0 &&
369 TargetCongestionWindow(pacing_gain_)) 408 congestion_window_->data_inflight() <
409 TargetCongestionWindow(kTargetCongestionWindowGainForHighGain))
370 advance_cycle_phase = false; 410 advance_cycle_phase = false;
371 // If BBR has already drained queues there is no point in continuing draining 411 // If BBR has already drained queues there is no point in continuing draining
372 // phase. 412 // phase.
373 if (pacing_gain_ < 1.0 && 413 if (pacing_gain_ < 1.0 &&
374 congestion_window_->data_inflight() <= TargetCongestionWindow(1)) 414 congestion_window_->data_inflight() <= TargetCongestionWindow(1))
375 advance_cycle_phase = true; 415 advance_cycle_phase = true;
376 if (advance_cycle_phase) { 416 if (advance_cycle_phase) {
377 cycle_index_++; 417 cycle_index_++;
378 cycle_index_ %= kGainCycleLength; 418 cycle_index_ %= kGainCycleLength;
379 pacing_gain_ = kPacingGain[cycle_index_]; 419 pacing_gain_ = kPacingGain[cycle_index_];
380 cycle_start_time_ms_ = now_ms; 420 cycle_start_time_ms_ = now_ms;
381 } 421 }
382 } 422 }
383 423
384 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { 424 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {
385 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) { 425 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) {
386 mode_ = PROBE_RTT; 426 mode_ = PROBE_RTT;
387 pacing_gain_ = 1; 427 pacing_gain_ = 1;
428 congestion_window_gain_ = kProbeRttCongestionWindowGain;
388 probe_rtt_start_time_ms_ = now_ms; 429 probe_rtt_start_time_ms_ = now_ms;
389 minimum_congestion_window_start_time_ms_.reset(); 430 minimum_congestion_window_start_time_ms_.reset();
390 } 431 }
391 } 432 }
392 433
393 // |minimum_congestion_window_start_time_|'s value is set to the first moment 434 // |minimum_congestion_window_start_time_|'s value is set to the first moment
394 // when data inflight was less then 435 // when data inflight was less then
395 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that 436 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that
396 // BBR has been in PROBE_RTT mode for at least one round or 200ms. 437 // BBR has been in PROBE_RTT mode for at least one round or 200ms.
397 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { 438 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) {
398 if (!minimum_congestion_window_start_time_ms_) { 439 if (!minimum_congestion_window_start_time_ms_) {
399 if (congestion_window_->data_inflight() <= 440 if (congestion_window_->data_inflight() <=
400 CongestionWindow::kMinimumCongestionWindowBytes) { 441 TargetCongestionWindow(kProbeRttCongestionWindowGain)) {
401 *minimum_congestion_window_start_time_ms_ = now_ms; 442 minimum_congestion_window_start_time_ms_.emplace(now_ms);
402 minimum_congestion_window_start_round_ = round; 443 minimum_congestion_window_start_round_ = round;
403 } 444 }
404 } else { 445 } else {
405 if (now_ms - *minimum_congestion_window_start_time_ms_ >= 446 if (now_ms - *minimum_congestion_window_start_time_ms_ >=
406 kProbeRttDurationMs && 447 kProbeRttDurationMs &&
407 round - minimum_congestion_window_start_round_ >= 448 round - minimum_congestion_window_start_round_ >=
408 kProbeRttDurationRounds) 449 kProbeRttDurationRounds) {
409 EnterProbeBw(now_ms); 450 EnterProbeBw(now_ms);
451 }
410 } 452 }
411 } 453 }
412 454
413 void BbrBweSender::TryEnteringRecovery(bool new_round_started) { 455 void BbrBweSender::TryEnteringRecovery(bool new_round_started) {
414 // If we are already in Recovery don't try to enter. 456 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_ ||
415 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_) 457 !min_rtt_filter_->min_rtt_ms())
416 return; 458 return;
417 uint64_t increased_rtt_round_counter = 0; 459 uint64_t increased_rtt_round_counter = 0;
418 // If average RTT for past |kPastRttsFilterSize| rounds has been more than 460 // If average RTT for past |kPastRttsFilterSize| rounds has been more than
419 // some multiplier of min_rtt_ms enter Recovery. 461 // some multiplier of min_rtt_ms enter Recovery.
420 for (BbrBweSender::AverageRtt i : past_rtts_) { 462 for (BbrBweSender::AverageRtt i : past_rtts_) {
421 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >= 463 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >=
422 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold) 464 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold)
423 increased_rtt_round_counter++; 465 increased_rtt_round_counter++;
424 } 466 }
425 if (increased_rtt_round_counter < kPastRttsFilterSize) 467 if (increased_rtt_round_counter < kPastRttsFilterSize)
(...skipping 27 matching lines...) Expand all
453 bytes_sent_ += media_packet->payload_size(); 495 bytes_sent_ += media_packet->payload_size();
454 PacketStats packet_stats = PacketStats( 496 PacketStats packet_stats = PacketStats(
455 media_packet->sequence_number(), 0, 497 media_packet->sequence_number(), 0,
456 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_, 498 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_,
457 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_); 499 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_);
458 packet_stats_[media_packet->sequence_number()] = packet_stats; 500 packet_stats_[media_packet->sequence_number()] = packet_stats;
459 last_packet_send_time_ = media_packet->sender_timestamp_ms(); 501 last_packet_send_time_ = media_packet->sender_timestamp_ms();
460 last_packet_sent_sequence_number_ = media_packet->sequence_number(); 502 last_packet_sent_sequence_number_ = media_packet->sequence_number();
461 // If this is the first packet sent for high gain phase, save data for it. 503 // If this is the first packet sent for high gain phase, save data for it.
462 if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) { 504 if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) {
463 *first_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; 505 first_packet_send_time_during_high_gain_ms_.emplace(
506 last_packet_send_time_);
464 data_sent_before_high_gain_started_bytes_ = 507 data_sent_before_high_gain_started_bytes_ =
465 bytes_sent_ - media_packet->payload_size() / 2; 508 bytes_sent_ - media_packet->payload_size() / 2;
466 first_packet_seq_num_during_high_gain_ = 509 first_packet_seq_num_during_high_gain_ =
467 media_packet->sequence_number(); 510 media_packet->sequence_number();
468 } 511 }
469 // This condition ensures that |last_packet_seq_num_during_high_gain_| 512 // This condition ensures that |last_packet_seq_num_during_high_gain_|
470 // will contain a sequence number of the last packet sent during high gain 513 // will contain a sequence number of the last packet sent during high gain
471 // phase. 514 // phase.
472 if (pacing_gain_ > 1) { 515 if (pacing_gain_ > 1) {
473 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; 516 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_;
474 data_sent_before_high_gain_ended_bytes_ = 517 data_sent_before_high_gain_ended_bytes_ =
475 bytes_sent_ - media_packet->payload_size() / 2; 518 bytes_sent_ - media_packet->payload_size() / 2;
476 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number(); 519 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number();
477 } 520 }
478 congestion_window_->PacketSent(media_packet->payload_size()); 521 congestion_window_->PacketSent(media_packet->payload_size());
479 } 522 }
480 } 523 }
481 } 524 }
482 525
483 void BbrBweSender::Process() {} 526 void BbrBweSender::Process() {}
484 527
485 BbrBweReceiver::BbrBweReceiver(int flow_id) 528 BbrBweReceiver::BbrBweReceiver(int flow_id)
486 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} 529 : BweReceiver(flow_id, kReceivingRateTimeWindowMs),
530 clock_(0),
531 packet_feedbacks_(),
532 last_feedback_ms_(0) {}
487 533
488 BbrBweReceiver::~BbrBweReceiver() {} 534 BbrBweReceiver::~BbrBweReceiver() {}
489 535
490 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, 536 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms,
491 const MediaPacket& media_packet) {} 537 const MediaPacket& media_packet) {
538 packet_feedbacks_.push_back(media_packet.sequence_number());
539 BweReceiver::ReceivePacket(arrival_time_ms, media_packet);
540 }
492 541
493 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { 542 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) {
494 return nullptr; 543 last_feedback_ms_ = now_ms;
544 int64_t corrected_send_time_ms = 0L;
545 if (!received_packets_.empty()) {
546 PacketIdentifierNode* latest = *(received_packets_.begin());
547 corrected_send_time_ms =
548 latest->send_time_ms + now_ms - latest->arrival_time_ms;
549 }
550 FeedbackPacket* fb = new BbrBweFeedback(
551 flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedbacks_);
552 packet_feedbacks_.clear();
553 return fb;
495 } 554 }
496 } // namespace bwe 555 } // namespace bwe
497 } // namespace testing 556 } // namespace testing
498 } // namespace webrtc 557 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698