Chromium Code Reviews| 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> | 14 #include <stdlib.h> |
| 15 #include <algorithm> | |
| 15 | 16 |
| 16 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win dow.h" | 17 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_win dow.h" |
| 17 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_ filter.h" | 18 #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" | 19 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter .h" |
| 19 | 20 |
| 20 namespace webrtc { | 21 namespace webrtc { |
| 21 namespace testing { | 22 namespace testing { |
| 22 namespace bwe { | 23 namespace bwe { |
| 23 namespace { | 24 namespace { |
| 24 const int kFeedbackIntervalsMs = 3; | 25 const int kFeedbackIntervalsMs = 5; |
| 25 // BBR uses this value to double sending rate each round trip. Design document | 26 // BBR uses this value to double sending rate each round trip. Design document |
| 26 // suggests using this value. | 27 // suggests using this value. |
| 27 const float kHighGain = 2.885f; | 28 const float kHighGain = 2.885f; |
| 28 // 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 |
| 29 // time. | 30 // time. |
| 30 const float kDrainGain = 1 / kHighGain; | 31 const float kDrainGain = 1 / kHighGain; |
| 31 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from | 32 // kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from |
| 32 // experiments, according to the design document. | 33 // experiments, according to the design document. |
| 33 const float kStartupGrowthTarget = 1.25f; | 34 const float kStartupGrowthTarget = 1.25f; |
| 34 const int kMaxRoundsWithoutGrowth = 3; | 35 const int kMaxRoundsWithoutGrowth = 3; |
| 35 // Pacing gain values for Probe Bandwidth mode. | 36 // Pacing gain values for Probe Bandwidth mode. |
| 36 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; | 37 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 size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); |
| 38 // The least amount of rounds PROBE_RTT mode should last. | 39 // Least amount number of rounds PROBE_RTT should last. |
| 39 const int kProbeRttDurationRounds = 1; | 40 const int kProbeRttDurationRounds = 1; |
| 40 // The least amount of milliseconds PROBE_RTT mode should last. | 41 // The least amount of milliseconds PROBE_RTT mode should last. |
| 41 const int kProbeRttDurationMs = 200; | 42 const int kProbeRttDurationMs = 200; |
| 42 // 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. |
| 43 const float kTargetCongestionWindowGain = 1; | 44 const float kTargetCongestionWindowGain = 1; |
| 44 // 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 |
| 45 // 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 |
| 46 // 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 |
| 47 // utilization. Value chosen by observations on different tests. | 48 // utilization. Value chosen by observations on different tests. |
| 48 const float kCruisingCongestionWindowGain = 1.5f; | 49 const float kCruisingCongestionWindowGain = 1.5f; |
| 49 // Expiration time for min_rtt sample, which is set to 10 seconds according to | 50 // Pacing gain specific for Recovery mode. Chosen by experiments in simulation |
| 50 // BBR design doc. | 51 // tool. |
| 51 const int64_t kMinRttFilterSizeMs = 10000; | 52 const float kRecoveryPacingGain = 0.5f; |
| 53 // Congestion window gain specific for Recovery mode. Chosen by experiments in | |
| 54 // simulation tool. | |
| 55 const float kRecoveryCongestionWindowGain = 1.5f; | |
| 56 // Number of rounds over which average rtt is stored for Recovery mode. | |
| 57 const size_t kPastRttsFilterSize = 1; | |
| 58 // Threshold to assume average rtt has increased for a round. Chosen by | |
| 59 // experiments in simulation tool. | |
| 60 const float kRttIncreaseThreshold = 3; | |
| 61 // Threshold to assume average rtt has decreased for a round. Chosen by | |
| 62 // experiments in simulation tool. | |
| 63 const float kRttDecreaseThreshold = 1.5f; | |
| 52 } // namespace | 64 } // namespace |
| 53 | 65 |
| 54 BbrBweSender::BbrBweSender(Clock* clock) | 66 BbrBweSender::BbrBweSender(Clock* clock) |
| 55 : BweSender(0), | 67 : BweSender(0), |
| 56 clock_(clock), | 68 clock_(clock), |
| 57 mode_(STARTUP), | 69 mode_(STARTUP), |
| 58 max_bandwidth_filter_(new MaxBandwidthFilter()), | 70 max_bandwidth_filter_(new MaxBandwidthFilter()), |
| 59 min_rtt_filter_(new MinRttFilter()), | 71 min_rtt_filter_(new MinRttFilter()), |
| 60 congestion_window_(new CongestionWindow()), | 72 congestion_window_(new CongestionWindow()), |
| 61 rand_(new Random(time(NULL))), | 73 rand_(new Random(time(NULL))), |
| 62 round_count_(0), | 74 round_count_(0), |
| 63 last_packet_sent_(0), | |
| 64 round_trip_end_(0), | 75 round_trip_end_(0), |
| 65 full_bandwidth_reached_(false), | 76 full_bandwidth_reached_(false), |
| 66 cycle_start_time_ms_(0), | 77 cycle_start_time_ms_(0), |
| 67 cycle_index_(0), | 78 cycle_index_(0), |
| 79 bytes_acked_(0), | |
| 68 prior_in_flight_(0), | 80 prior_in_flight_(0), |
| 69 probe_rtt_start_time_ms_(0), | 81 probe_rtt_start_time_ms_(0), |
| 70 minimum_congestion_window_start_time_ms_(), | 82 minimum_congestion_window_start_time_ms_(0), |
| 71 minimum_congestion_window_start_round_(0) { | 83 minimum_congestion_window_start_round_(0), |
| 84 bytes_sent_(0), | |
| 85 last_packet_sent_sequence_number_(0), | |
| 86 last_packet_acked_sequence_number_(0), | |
| 87 last_packet_ack_time_(0), | |
| 88 last_packet_send_time_(0), | |
| 89 pacing_rate_bps_(0), | |
| 90 last_packet_send_time_during_high_gain_ms_(-1), | |
| 91 data_sent_before_high_gain_started_bytes_(-1), | |
| 92 data_sent_before_high_gain_ended_bytes_(-1), | |
| 93 first_packet_ack_time_during_high_gain_ms_(-1), | |
| 94 last_packet_ack_time_during_high_gain_ms_(-1), | |
| 95 data_acked_before_high_gain_started_bytes_(-1), | |
| 96 data_acked_before_high_gain_ended_bytes_(-1), | |
| 97 first_packet_seq_num_during_high_gain_(-1), | |
| 98 last_packet_seq_num_during_high_gain_(-1), | |
| 99 high_gain_over_(false), | |
| 100 packet_stats_(), | |
| 101 past_rtts_() { | |
| 72 // Initially enter Startup mode. | 102 // Initially enter Startup mode. |
| 73 EnterStartup(); | 103 EnterStartup(); |
| 74 } | 104 } |
| 75 | 105 |
| 76 BbrBweSender::~BbrBweSender() {} | 106 BbrBweSender::~BbrBweSender() {} |
| 77 | 107 |
| 78 int BbrBweSender::GetFeedbackIntervalMs() const { | 108 int BbrBweSender::GetFeedbackIntervalMs() const { |
| 79 return kFeedbackIntervalsMs; | 109 return kFeedbackIntervalsMs; |
| 80 } | 110 } |
| 81 | 111 |
| 112 void BbrBweSender::CalculatePacingRate() { | |
| 113 pacing_rate_bps_ = | |
| 114 max_bandwidth_filter_->max_bandwidth_estimate_bps() * pacing_gain_; | |
| 115 } | |
| 116 | |
| 117 void BbrBweSender::HandleLoss(uint64_t last_acked_packet, | |
| 118 uint64_t recently_acked_packet) { | |
| 119 // Logic specific to wrapping sequence numbers. | |
| 120 if (!last_acked_packet) | |
| 121 return; | |
| 122 for (uint16_t i = last_acked_packet + 1; | |
| 123 AheadOrAt<uint64_t>(recently_acked_packet - 1, i); i++) | |
| 124 congestion_window_->AckReceived(packet_stats_[i].payload_size_bytes); | |
| 125 } | |
| 126 | |
| 127 void BbrBweSender::AddToPastRtts(int64_t rtt_sample_ms) { | |
| 128 uint64_t last_round = 0; | |
| 129 if (!past_rtts_.empty()) | |
| 130 last_round = past_rtts_.back().round; | |
| 131 | |
| 132 // Try to add the sample to the last round. | |
| 133 if (last_round == round_count_ && !past_rtts_.empty()) { | |
| 134 past_rtts_.back().sum_of_rtts_ms += rtt_sample_ms; | |
| 135 past_rtts_.back().num_samples++; | |
| 136 } else { | |
| 137 // If the sample belongs to a new round, keep number of rounds in the window | |
| 138 // equal to |kPastRttsFilterSize|. | |
| 139 if (past_rtts_.size() == kPastRttsFilterSize) | |
| 140 past_rtts_.pop_front(); | |
| 141 past_rtts_.push_back( | |
| 142 BbrBweSender::AverageRtt(rtt_sample_ms, 1, round_count_)); | |
| 143 } | |
| 144 } | |
| 145 | |
| 82 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { | 146 void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { |
| 147 int64_t now_ms = clock_->TimeInMilliseconds(); | |
| 148 last_packet_ack_time_ = now_ms; | |
| 149 prior_in_flight_ = bytes_acked_; | |
| 83 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); | 150 const BbrBweFeedback& fb = static_cast<const BbrBweFeedback&>(feedback); |
| 84 // feedback_vector holds values of acknowledged packets' sequence numbers. | 151 // feedback_vector holds values of acknowledged packets' sequence numbers. |
| 85 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); | 152 const std::vector<uint64_t>& feedback_vector = fb.packet_feedback_vector(); |
| 86 // Check if new round started for the connection. Round is the period of time | 153 // Go through all the packets acked, update variables/containers accordingly. |
| 87 // from sending packet to its acknowledgement. | 154 for (uint64_t f : feedback_vector) { |
| 155 // Completing packet information with a recently received ack. | |
| 156 PacketStats* packet = &packet_stats_[f]; | |
| 157 bytes_acked_ += packet->payload_size_bytes; | |
| 158 packet->data_sent_bytes = bytes_sent_; | |
| 159 packet->last_sent_packet_send_time_ms = last_packet_send_time_; | |
| 160 packet->data_acked_bytes = bytes_acked_; | |
| 161 packet->ack_time_ms = now_ms; | |
| 162 // Logic specific to applying "bucket" to high gain, in order to have | |
| 163 // quicker ramp-up. We check if we started receiving acks for the packets | |
| 164 // sent during high gain phase. | |
| 165 if (packet->sequence_number == first_packet_seq_num_during_high_gain_) { | |
| 166 first_packet_ack_time_during_high_gain_ms_ = now_ms; | |
| 167 data_acked_before_high_gain_started_bytes_ = bytes_acked_; | |
| 168 } | |
| 169 // If the last packet of high gain phase has been acked, high gain phase is | |
| 170 // over. | |
| 171 if (packet->sequence_number == last_packet_seq_num_during_high_gain_) { | |
| 172 last_packet_ack_time_during_high_gain_ms_ = now_ms; | |
| 173 data_acked_before_high_gain_ended_bytes_ = bytes_acked_; | |
| 174 high_gain_over_ = true; | |
| 175 } | |
| 176 // Notify pacer that an ack was received, to adjust data inflight. | |
| 177 // TODO(gnish): Add implementation for BitrateObserver class, to notify | |
| 178 // pacer about incoming acks. | |
| 179 congestion_window_->AckReceived(packet->payload_size_bytes); | |
| 180 HandleLoss(last_packet_acked_sequence_number_, packet->sequence_number); | |
| 181 last_packet_acked_sequence_number_ = packet->sequence_number; | |
| 182 // Logic for wrapping sequence numbers. If round started with packet number | |
| 183 // x, it can never end on y, if x > y. That could happen when sequence | |
| 184 // numbers are wrapped after some point. | |
| 185 if (packet->sequence_number == 0) | |
| 186 round_trip_end_ = 0; | |
| 187 } | |
| 188 // Check if new round started for the connection. | |
| 88 bool new_round_started = false; | 189 bool new_round_started = false; |
| 89 if (!feedback_vector.empty()) { | 190 if (!feedback_vector.empty()) { |
| 90 uint64_t last_acked_packet = *feedback_vector.rbegin(); | 191 if (last_packet_acked_sequence_number_ > round_trip_end_) { |
| 91 if (last_acked_packet > round_trip_end_) { | |
| 92 new_round_started = true; | 192 new_round_started = true; |
| 93 round_count_++; | 193 round_count_++; |
| 94 round_trip_end_ = last_packet_sent_; | 194 round_trip_end_ = last_packet_sent_sequence_number_; |
| 95 } | 195 } |
| 96 } | 196 } |
| 197 bool min_rtt_expired = false; | |
| 198 min_rtt_expired = | |
| 199 UpdateBandwidthAndMinRtt(now_ms, feedback_vector, bytes_acked_); | |
| 97 if (new_round_started && !full_bandwidth_reached_) { | 200 if (new_round_started && !full_bandwidth_reached_) { |
| 98 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( | 201 full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( |
| 99 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); | 202 kStartupGrowthTarget, kMaxRoundsWithoutGrowth); |
| 100 } | 203 } |
| 101 int now_ms = clock_->TimeInMilliseconds(); | |
| 102 switch (mode_) { | 204 switch (mode_) { |
| 103 break; | 205 break; |
| 104 case STARTUP: | 206 case STARTUP: |
| 105 TryExitingStartup(); | 207 TryExitingStartup(); |
| 106 break; | 208 break; |
| 107 case DRAIN: | 209 case DRAIN: |
| 108 TryExitingDrain(now_ms); | 210 TryExitingDrain(now_ms); |
| 109 break; | 211 break; |
| 110 case PROBE_BW: | 212 case PROBE_BW: |
| 111 TryUpdatingCyclePhase(now_ms); | 213 TryUpdatingCyclePhase(now_ms); |
| 112 break; | 214 break; |
| 113 case PROBE_RTT: | 215 case PROBE_RTT: |
| 114 TryExitingProbeRtt(now_ms, 0); | 216 TryExitingProbeRtt(now_ms, round_count_); |
| 217 break; | |
| 218 case RECOVERY: | |
| 219 TryExitingRecovery(new_round_started); | |
| 115 break; | 220 break; |
| 116 } | 221 } |
| 117 TryEnteringProbeRtt(now_ms); | 222 TryEnteringProbeRtt(now_ms); |
| 118 // TODO(gnish): implement functions updating congestion window and pacing rate | 223 TryEnteringRecovery(new_round_started); // Comment this line to disable |
| 119 // controllers. | 224 // entering Recovery mode. |
| 225 for (uint64_t f : feedback_vector) | |
| 226 AddToPastRtts(packet_stats_[f].ack_time_ms - packet_stats_[f].send_time_ms); | |
| 227 CalculatePacingRate(); | |
| 228 // Make sure we don't get stuck when pacing_rate is 0, because of simulation | |
| 229 // tool specifics. | |
| 230 if (!pacing_rate_bps_) | |
| 231 pacing_rate_bps_ = 100; | |
| 232 BWE_TEST_LOGGING_PLOT(1, "SendRate", now_ms, pacing_rate_bps_ / 1000); | |
| 233 // TODO(gnish): Add implementation for BitrateObserver class to update pacing | |
| 234 // rate for the pacer and the encoder. | |
| 120 } | 235 } |
| 121 | 236 |
| 122 size_t BbrBweSender::TargetCongestionWindow(float gain) { | 237 size_t BbrBweSender::TargetCongestionWindow(float gain) { |
| 123 size_t target_congestion_window = | 238 size_t target_congestion_window = |
| 124 congestion_window_->GetTargetCongestionWindow( | 239 congestion_window_->GetTargetCongestionWindow( |
| 125 max_bandwidth_filter_->max_bandwidth_estimate_bps(), | 240 max_bandwidth_filter_->max_bandwidth_estimate_bps(), |
| 126 min_rtt_filter_->min_rtt_ms(), gain); | 241 min_rtt_filter_->min_rtt_ms(), gain); |
| 127 return target_congestion_window; | 242 return target_congestion_window; |
| 128 } | 243 } |
| 129 | 244 |
| 130 bool BbrBweSender::UpdateBandwidthAndMinRtt() { | 245 rtc::Optional<int64_t> BbrBweSender::CalculateBandwidthSample( |
| 131 return false; | 246 size_t data_sent_bytes, |
| 247 int64_t send_time_delta_ms, | |
| 248 size_t data_acked_bytes, | |
| 249 int64_t ack_time_delta_ms) { | |
| 250 rtc::Optional<int64_t> bandwidth_sample; | |
| 251 if (send_time_delta_ms > 0) | |
| 252 *bandwidth_sample = data_sent_bytes * 8000 / send_time_delta_ms; | |
| 253 rtc::Optional<int64_t> ack_rate; | |
| 254 if (ack_time_delta_ms > 0) | |
| 255 *ack_rate = data_acked_bytes * 8000 / ack_time_delta_ms; | |
| 256 // If send rate couldn't be calculated automaticaly set |bandwidth_sample| to | |
| 257 // ack_rate. | |
| 258 if (!bandwidth_sample) | |
| 259 bandwidth_sample = ack_rate; | |
| 260 if (bandwidth_sample && ack_rate) | |
| 261 *bandwidth_sample = std::min(*bandwidth_sample, *ack_rate); | |
| 262 return bandwidth_sample; | |
| 263 } | |
| 264 | |
| 265 void BbrBweSender::AddSampleForHighGain() { | |
| 266 if (!high_gain_over_) | |
| 267 return; | |
| 268 high_gain_over_ = false; | |
| 269 // Calculate data sent/acked and time elapsed only for packets sent during | |
| 270 // high gain phase. | |
| 271 size_t data_sent_bytes = data_sent_before_high_gain_ended_bytes_ - | |
| 272 data_sent_before_high_gain_started_bytes_; | |
| 273 int64_t send_time_delta_ms = last_packet_send_time_during_high_gain_ms_ - | |
| 274 *first_packet_send_time_during_high_gain_ms_; | |
| 275 size_t data_acked_bytes = data_acked_before_high_gain_ended_bytes_ - | |
| 276 data_acked_before_high_gain_started_bytes_; | |
| 277 int64_t ack_time_delta_ms = last_packet_ack_time_during_high_gain_ms_ - | |
| 278 first_packet_ack_time_during_high_gain_ms_; | |
| 279 rtc::Optional<int64_t> bandwidth_sample = CalculateBandwidthSample( | |
| 280 data_sent_bytes, send_time_delta_ms, data_acked_bytes, ack_time_delta_ms); | |
| 281 if (bandwidth_sample) | |
| 282 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, round_count_); | |
| 283 first_packet_send_time_during_high_gain_ms_.reset(); | |
| 284 } | |
| 285 | |
| 286 bool BbrBweSender::UpdateBandwidthAndMinRtt( | |
| 287 int64_t now_ms, | |
| 288 const std::vector<uint64_t>& feedback_vector, | |
| 289 int64_t bytes_acked) { | |
| 290 rtc::Optional<int64_t> min_rtt_sample_ms; | |
| 291 for (uint64_t f : feedback_vector) { | |
| 292 PacketStats packet = packet_stats_[f]; | |
| 293 size_t data_sent_bytes = | |
| 294 packet.data_sent_bytes - packet.data_sent_before_last_sent_packet_bytes; | |
| 295 int64_t send_time_delta_ms = | |
| 296 packet.last_sent_packet_send_time_ms - packet.send_time_ms; | |
| 297 size_t data_acked_bytes = packet.data_acked_bytes - | |
| 298 packet.data_acked_before_last_acked_packet_bytes; | |
| 299 int64_t ack_time_delta_ms = | |
| 300 packet.ack_time_ms - packet.last_acked_packet_ack_time_ms; | |
| 301 rtc::Optional<int64_t> bandwidth_sample = | |
| 302 CalculateBandwidthSample(data_sent_bytes, send_time_delta_ms, | |
| 303 data_acked_bytes, ack_time_delta_ms); | |
| 304 if (bandwidth_sample) | |
| 305 max_bandwidth_filter_->AddBandwidthSample(*bandwidth_sample, | |
| 306 round_count_); | |
| 307 AddSampleForHighGain(); // Comment to disable bucket for high gain. | |
| 308 if (!min_rtt_sample_ms) | |
| 309 *min_rtt_sample_ms = packet.ack_time_ms - packet.send_time_ms; | |
| 310 else | |
| 311 *min_rtt_sample_ms = std::min(*min_rtt_sample_ms, | |
| 312 packet.ack_time_ms - packet.send_time_ms); | |
| 313 BWE_TEST_LOGGING_PLOT(1, "MinRtt", now_ms, | |
| 314 packet.ack_time_ms - packet.send_time_ms); | |
| 315 } | |
| 316 if (!min_rtt_sample_ms) | |
| 317 return false; | |
| 318 bool min_rtt_expired = min_rtt_filter_->MinRttExpired(now_ms); | |
| 319 min_rtt_filter_->AddRttSample(*min_rtt_sample_ms, now_ms); | |
|
philipel
2017/08/08 11:54:54
Don't you want to reverse line 318 and 319?
gnish1
2017/08/08 13:19:56
Done.
| |
| 320 return min_rtt_expired; | |
| 132 } | 321 } |
| 133 | 322 |
| 134 void BbrBweSender::EnterStartup() { | 323 void BbrBweSender::EnterStartup() { |
| 135 mode_ = STARTUP; | 324 mode_ = STARTUP; |
| 136 pacing_gain_ = kHighGain; | 325 pacing_gain_ = kHighGain; |
| 137 congestion_window_gain_ = kHighGain; | 326 congestion_window_gain_ = kHighGain; |
| 138 } | 327 } |
| 139 | 328 |
| 140 void BbrBweSender::TryExitingStartup() { | 329 void BbrBweSender::TryExitingStartup() { |
| 141 if (full_bandwidth_reached_) { | 330 if (full_bandwidth_reached_) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 advance_cycle_phase = true; | 372 advance_cycle_phase = true; |
| 184 if (advance_cycle_phase) { | 373 if (advance_cycle_phase) { |
| 185 cycle_index_++; | 374 cycle_index_++; |
| 186 cycle_index_ %= kGainCycleLength; | 375 cycle_index_ %= kGainCycleLength; |
| 187 pacing_gain_ = kPacingGain[cycle_index_]; | 376 pacing_gain_ = kPacingGain[cycle_index_]; |
| 188 cycle_start_time_ms_ = now_ms; | 377 cycle_start_time_ms_ = now_ms; |
| 189 } | 378 } |
| 190 } | 379 } |
| 191 | 380 |
| 192 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { | 381 void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { |
| 193 if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && | 382 if (min_rtt_filter_->MinRttExpired(now_ms) && mode_ != PROBE_RTT) { |
| 194 mode_ != PROBE_RTT) { | |
| 195 mode_ = PROBE_RTT; | 383 mode_ = PROBE_RTT; |
| 196 pacing_gain_ = 1; | 384 pacing_gain_ = 1; |
| 197 probe_rtt_start_time_ms_ = now_ms; | 385 probe_rtt_start_time_ms_ = now_ms; |
| 198 minimum_congestion_window_start_time_ms_.reset(); | 386 minimum_congestion_window_start_time_ms_.reset(); |
| 199 } | 387 } |
| 200 } | 388 } |
| 201 | 389 |
| 202 // minimum_congestion_window_start_time_'s value is set to the first moment when | 390 // |minimum_congestion_window_start_time_|'s value is set to the first moment |
| 203 // data inflight was less then kMinimumCongestionWindowBytes, we should make | 391 // when data inflight was less then |
| 204 // sure that BBR has been in PROBE_RTT mode for at least one round or 200ms. | 392 // |CongestionWindow::kMinimumCongestionWindowBytes|, we should make sure that |
| 393 // BBR has been in PROBE_RTT mode for at least one round or 200ms. | |
| 205 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { | 394 void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { |
| 206 if (!minimum_congestion_window_start_time_ms_) { | 395 if (!minimum_congestion_window_start_time_ms_) { |
| 207 if (congestion_window_->data_inflight() <= | 396 if (congestion_window_->data_inflight() <= |
| 208 CongestionWindow::kMinimumCongestionWindowBytes) { | 397 CongestionWindow::kMinimumCongestionWindowBytes) { |
| 209 *minimum_congestion_window_start_time_ms_ = now_ms; | 398 *minimum_congestion_window_start_time_ms_ = now_ms; |
| 210 minimum_congestion_window_start_round_ = round; | 399 minimum_congestion_window_start_round_ = round; |
| 211 } | 400 } |
| 212 } else { | 401 } else { |
| 213 if (now_ms - *minimum_congestion_window_start_time_ms_ >= | 402 if (now_ms - *minimum_congestion_window_start_time_ms_ >= |
| 214 kProbeRttDurationMs && | 403 kProbeRttDurationMs && |
| 215 round - minimum_congestion_window_start_round_ >= | 404 round - minimum_congestion_window_start_round_ >= |
| 216 kProbeRttDurationRounds) | 405 kProbeRttDurationRounds) |
| 217 EnterProbeBw(now_ms); | 406 EnterProbeBw(now_ms); |
| 218 } | 407 } |
| 219 } | 408 } |
| 220 | 409 |
| 410 void BbrBweSender::TryEnteringRecovery(bool new_round_started) { | |
| 411 // If we are already in Recovery don't try to enter. | |
| 412 if (mode_ == RECOVERY || !new_round_started || !full_bandwidth_reached_) | |
| 413 return; | |
| 414 uint64_t increased_rtt_round_counter = 0; | |
| 415 // If average rtt for past |kPastRttsFilterSize| rounds has been more than | |
| 416 // some multiplier of min_rtt_ms enter Recovery. | |
| 417 for (BbrBweSender::AverageRtt i : past_rtts_) { | |
| 418 if (i.sum_of_rtts_ms / (int64_t)i.num_samples >= | |
| 419 *min_rtt_filter_->min_rtt_ms() * kRttIncreaseThreshold) | |
| 420 increased_rtt_round_counter++; | |
| 421 } | |
| 422 if (increased_rtt_round_counter < kPastRttsFilterSize) | |
| 423 return; | |
| 424 mode_ = RECOVERY; | |
| 425 pacing_gain_ = kRecoveryPacingGain; | |
| 426 congestion_window_gain_ = kRecoveryCongestionWindowGain; | |
| 427 } | |
| 428 | |
| 429 void BbrBweSender::TryExitingRecovery(bool new_round_started) { | |
| 430 if (mode_ != RECOVERY || !new_round_started || !full_bandwidth_reached_) | |
| 431 return; | |
| 432 // If average rtt for the past round has decreased sufficiently exit Recovery. | |
| 433 if (!past_rtts_.empty()) { | |
| 434 BbrBweSender::AverageRtt last_round_sample = past_rtts_.back(); | |
| 435 if (last_round_sample.sum_of_rtts_ms / last_round_sample.num_samples <= | |
| 436 *min_rtt_filter_->min_rtt_ms() * kRttDecreaseThreshold) { | |
| 437 EnterProbeBw(clock_->TimeInMilliseconds()); | |
| 438 } | |
| 439 } | |
| 440 } | |
| 441 | |
| 221 int64_t BbrBweSender::TimeUntilNextProcess() { | 442 int64_t BbrBweSender::TimeUntilNextProcess() { |
| 222 return 100; | 443 return 50; |
| 223 } | 444 } |
| 224 | 445 |
| 225 void BbrBweSender::OnPacketsSent(const Packets& packets) { | 446 void BbrBweSender::OnPacketsSent(const Packets& packets) { |
| 226 last_packet_sent_ = | 447 for (Packet* packet : packets) { |
| 227 static_cast<const MediaPacket*>(packets.back())->sequence_number(); | 448 if (packet->GetPacketType() == Packet::kMedia) { |
| 449 MediaPacket* media_packet = static_cast<MediaPacket*>(packet); | |
| 450 bytes_sent_ += media_packet->payload_size(); | |
| 451 PacketStats packet_stats = PacketStats( | |
| 452 media_packet->sequence_number(), 0, | |
| 453 media_packet->sender_timestamp_ms(), 0, last_packet_ack_time_, | |
| 454 media_packet->payload_size(), 0, bytes_sent_, 0, bytes_acked_); | |
| 455 packet_stats_[media_packet->sequence_number()] = packet_stats; | |
| 456 last_packet_send_time_ = media_packet->sender_timestamp_ms(); | |
| 457 last_packet_sent_sequence_number_ = media_packet->sequence_number(); | |
| 458 // If this is the first packet sent for high gain phase, save data for it. | |
| 459 if (!first_packet_send_time_during_high_gain_ms_ && pacing_gain_ > 1) { | |
| 460 *first_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; | |
| 461 data_sent_before_high_gain_started_bytes_ = bytes_sent_; | |
| 462 first_packet_seq_num_during_high_gain_ = | |
| 463 media_packet->sequence_number(); | |
| 464 } | |
| 465 // This condition ensures that |last_packet_seq_num_during_high_gain_| | |
| 466 // will contain a sequence number of the last packet sent during high gain | |
| 467 // phase. | |
| 468 if (pacing_gain_ > 1) { | |
| 469 last_packet_send_time_during_high_gain_ms_ = last_packet_send_time_; | |
| 470 data_sent_before_high_gain_ended_bytes_ = bytes_sent_; | |
| 471 last_packet_seq_num_during_high_gain_ = media_packet->sequence_number(); | |
| 472 } | |
| 473 congestion_window_->PacketSent(media_packet->payload_size()); | |
| 474 } | |
| 475 } | |
| 228 } | 476 } |
| 229 | 477 |
| 230 void BbrBweSender::Process() {} | 478 void BbrBweSender::Process() {} |
| 231 | 479 |
| 232 BbrBweReceiver::BbrBweReceiver(int flow_id) | 480 BbrBweReceiver::BbrBweReceiver(int flow_id) |
| 233 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} | 481 : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} |
| 234 | 482 |
| 235 BbrBweReceiver::~BbrBweReceiver() {} | 483 BbrBweReceiver::~BbrBweReceiver() {} |
| 236 | 484 |
| 237 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, | 485 void BbrBweReceiver::ReceivePacket(int64_t arrival_time_ms, |
| 238 const MediaPacket& media_packet) {} | 486 const MediaPacket& media_packet) {} |
| 239 | 487 |
| 240 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { | 488 FeedbackPacket* BbrBweReceiver::GetFeedback(int64_t now_ms) { |
| 241 return nullptr; | 489 return nullptr; |
| 242 } | 490 } |
| 243 } // namespace bwe | 491 } // namespace bwe |
| 244 } // namespace testing | 492 } // namespace testing |
| 245 } // namespace webrtc | 493 } // namespace webrtc |
| OLD | NEW |