| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 #include "webrtc/modules/congestion_controller/delay_based_bwe.h" | 11 #include "webrtc/modules/congestion_controller/delay_based_bwe.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <cmath> | 14 #include <cmath> |
| 15 #include <string> |
| 15 | 16 |
| 16 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 17 #include "webrtc/base/constructormagic.h" | 18 #include "webrtc/base/constructormagic.h" |
| 18 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
| 19 #include "webrtc/base/thread_annotations.h" | 20 #include "webrtc/base/thread_annotations.h" |
| 20 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" | 21 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" |
| 21 #include "webrtc/modules/pacing/paced_sender.h" | 22 #include "webrtc/modules/pacing/paced_sender.h" |
| 22 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat
or.h" | 23 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat
or.h" |
| 23 #include "webrtc/system_wrappers/include/field_trial.h" | 24 #include "webrtc/system_wrappers/include/field_trial.h" |
| 24 #include "webrtc/system_wrappers/include/metrics.h" | 25 #include "webrtc/system_wrappers/include/metrics.h" |
| 25 #include "webrtc/typedefs.h" | 26 #include "webrtc/typedefs.h" |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 constexpr int kTimestampGroupLengthMs = 5; | 29 constexpr int kTimestampGroupLengthMs = 5; |
| 29 constexpr int kAbsSendTimeFraction = 18; | 30 constexpr int kAbsSendTimeFraction = 18; |
| 30 constexpr int kAbsSendTimeInterArrivalUpshift = 8; | 31 constexpr int kAbsSendTimeInterArrivalUpshift = 8; |
| 31 constexpr int kInterArrivalShift = | 32 constexpr int kInterArrivalShift = |
| 32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; | 33 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; |
| 33 constexpr double kTimestampToMs = | 34 constexpr double kTimestampToMs = |
| 34 1000.0 / static_cast<double>(1 << kInterArrivalShift); | 35 1000.0 / static_cast<double>(1 << kInterArrivalShift); |
| 35 // This ssrc is used to fulfill the current API but will be removed | 36 // This ssrc is used to fulfill the current API but will be removed |
| 36 // after the API has been changed. | 37 // after the API has been changed. |
| 37 constexpr uint32_t kFixedSsrc = 0; | 38 constexpr uint32_t kFixedSsrc = 0; |
| 38 constexpr int kInitialRateWindowMs = 500; | 39 constexpr int kInitialRateWindowMs = 500; |
| 39 constexpr int kRateWindowMs = 150; | 40 constexpr int kRateWindowMs = 150; |
| 40 | 41 |
| 42 constexpr size_t kDefaultTrendlineWindowSize = 15; |
| 43 constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; |
| 44 constexpr double kDefaultTrendlineThresholdGain = 4.0; |
| 45 |
| 41 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate"; | 46 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate"; |
| 47 const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter"; |
| 42 | 48 |
| 43 bool BitrateEstimateExperimentIsEnabled() { | 49 bool BitrateEstimateExperimentIsEnabled() { |
| 44 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) == | 50 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) == |
| 45 "Enabled"; | 51 "Enabled"; |
| 46 } | 52 } |
| 53 |
| 54 bool TrendlineFilterExperimentIsEnabled() { |
| 55 std::string experiment_string = |
| 56 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment); |
| 57 // The experiment is enabled iff the field trial string begins with "Enabled". |
| 58 return experiment_string.find("Enabled") == 0; |
| 59 } |
| 60 |
| 61 bool ReadTrendlineFilterExperimentParameters(size_t* window_points, |
| 62 double* smoothing_coef, |
| 63 double* threshold_gain) { |
| 64 RTC_DCHECK(TrendlineFilterExperimentIsEnabled()); |
| 65 std::string experiment_string = |
| 66 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment); |
| 67 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf,%lf", |
| 68 window_points, smoothing_coef, threshold_gain); |
| 69 if (parsed_values == 3) { |
| 70 RTC_CHECK_GT(*window_points, 1) << "Need at least 2 points to fit a line."; |
| 71 RTC_CHECK(0 <= *smoothing_coef && *smoothing_coef <= 1) |
| 72 << "Coefficient needs to be between 0 and 1 for weighted average."; |
| 73 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive."; |
| 74 return true; |
| 75 } |
| 76 LOG(LS_WARNING) << "Failed to parse parameters for BweTrendlineFilter " |
| 77 "experiment from field trial string. Using default."; |
| 78 *window_points = kDefaultTrendlineWindowSize; |
| 79 *smoothing_coef = kDefaultTrendlineSmoothingCoeff; |
| 80 *threshold_gain = kDefaultTrendlineThresholdGain; |
| 81 return false; |
| 82 } |
| 83 |
| 47 } // namespace | 84 } // namespace |
| 48 | 85 |
| 49 namespace webrtc { | 86 namespace webrtc { |
| 87 |
| 50 DelayBasedBwe::BitrateEstimator::BitrateEstimator() | 88 DelayBasedBwe::BitrateEstimator::BitrateEstimator() |
| 51 : sum_(0), | 89 : sum_(0), |
| 52 current_win_ms_(0), | 90 current_win_ms_(0), |
| 53 prev_time_ms_(-1), | 91 prev_time_ms_(-1), |
| 54 bitrate_estimate_(-1.0f), | 92 bitrate_estimate_(-1.0f), |
| 55 bitrate_estimate_var_(50.0f), | 93 bitrate_estimate_var_(50.0f), |
| 56 old_estimator_(kBitrateWindowMs, 8000), | 94 old_estimator_(kBitrateWindowMs, 8000), |
| 57 in_experiment_(BitrateEstimateExperimentIsEnabled()) {} | 95 in_experiment_(BitrateEstimateExperimentIsEnabled()) {} |
| 58 | 96 |
| 59 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) { | 97 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 163 |
| 126 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const { | 164 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const { |
| 127 if (bitrate_estimate_ < 0.f) | 165 if (bitrate_estimate_ < 0.f) |
| 128 return rtc::Optional<uint32_t>(); | 166 return rtc::Optional<uint32_t>(); |
| 129 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); | 167 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); |
| 130 } | 168 } |
| 131 | 169 |
| 132 DelayBasedBwe::DelayBasedBwe(Clock* clock) | 170 DelayBasedBwe::DelayBasedBwe(Clock* clock) |
| 133 : clock_(clock), | 171 : clock_(clock), |
| 134 inter_arrival_(), | 172 inter_arrival_(), |
| 135 estimator_(), | 173 kalman_estimator_(), |
| 174 trendline_estimator_(), |
| 136 detector_(OverUseDetectorOptions()), | 175 detector_(OverUseDetectorOptions()), |
| 137 receiver_incoming_bitrate_(), | 176 receiver_incoming_bitrate_(), |
| 138 last_update_ms_(-1), | 177 last_update_ms_(-1), |
| 139 last_seen_packet_ms_(-1), | 178 last_seen_packet_ms_(-1), |
| 140 uma_recorded_(false) { | 179 uma_recorded_(false), |
| 180 trendline_window_size_(kDefaultTrendlineWindowSize), |
| 181 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff), |
| 182 trendline_threshold_gain_(kDefaultTrendlineThresholdGain), |
| 183 in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()) { |
| 184 if (in_trendline_experiment_) { |
| 185 ReadTrendlineFilterExperimentParameters(&trendline_window_size_, |
| 186 &trendline_smoothing_coeff_, |
| 187 &trendline_threshold_gain_); |
| 188 } |
| 141 network_thread_.DetachFromThread(); | 189 network_thread_.DetachFromThread(); |
| 142 } | 190 } |
| 143 | 191 |
| 144 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( | 192 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( |
| 145 const std::vector<PacketInfo>& packet_feedback_vector) { | 193 const std::vector<PacketInfo>& packet_feedback_vector) { |
| 146 RTC_DCHECK(network_thread_.CalledOnValidThread()); | 194 RTC_DCHECK(network_thread_.CalledOnValidThread()); |
| 147 if (!uma_recorded_) { | 195 if (!uma_recorded_) { |
| 148 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, | 196 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, |
| 149 BweNames::kSendSideTransportSeqNum, | 197 BweNames::kSendSideTransportSeqNum, |
| 150 BweNames::kBweNamesMax); | 198 BweNames::kBweNamesMax); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 164 int64_t now_ms = clock_->TimeInMilliseconds(); | 212 int64_t now_ms = clock_->TimeInMilliseconds(); |
| 165 | 213 |
| 166 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size); | 214 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size); |
| 167 Result result; | 215 Result result; |
| 168 // Reset if the stream has timed out. | 216 // Reset if the stream has timed out. |
| 169 if (last_seen_packet_ms_ == -1 || | 217 if (last_seen_packet_ms_ == -1 || |
| 170 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { | 218 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { |
| 171 inter_arrival_.reset( | 219 inter_arrival_.reset( |
| 172 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, | 220 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, |
| 173 kTimestampToMs, true)); | 221 kTimestampToMs, true)); |
| 174 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); | 222 kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); |
| 223 trendline_estimator_.reset(new TrendlineEstimator( |
| 224 trendline_window_size_, trendline_smoothing_coeff_, |
| 225 trendline_threshold_gain_)); |
| 175 } | 226 } |
| 176 last_seen_packet_ms_ = now_ms; | 227 last_seen_packet_ms_ = now_ms; |
| 177 | 228 |
| 178 uint32_t send_time_24bits = | 229 uint32_t send_time_24bits = |
| 179 static_cast<uint32_t>( | 230 static_cast<uint32_t>( |
| 180 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) + | 231 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) + |
| 181 500) / | 232 500) / |
| 182 1000) & | 233 1000) & |
| 183 0x00FFFFFF; | 234 0x00FFFFFF; |
| 184 // Shift up send time to use the full 32 bits that inter_arrival works with, | 235 // Shift up send time to use the full 32 bits that inter_arrival works with, |
| 185 // so wrapping works properly. | 236 // so wrapping works properly. |
| 186 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; | 237 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; |
| 187 | 238 |
| 188 uint32_t ts_delta = 0; | 239 uint32_t ts_delta = 0; |
| 189 int64_t t_delta = 0; | 240 int64_t t_delta = 0; |
| 190 int size_delta = 0; | 241 int size_delta = 0; |
| 191 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms, | 242 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms, |
| 192 info.payload_size, &ts_delta, &t_delta, | 243 info.payload_size, &ts_delta, &t_delta, |
| 193 &size_delta)) { | 244 &size_delta)) { |
| 194 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); | 245 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); |
| 195 estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State(), | 246 if (in_trendline_experiment_) { |
| 247 trendline_estimator_->Update(t_delta, ts_delta_ms, info.arrival_time_ms); |
| 248 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms, |
| 249 trendline_estimator_->num_of_deltas(), |
| 196 info.arrival_time_ms); | 250 info.arrival_time_ms); |
| 197 detector_.Detect(estimator_->offset(), ts_delta_ms, | 251 |
| 198 estimator_->num_of_deltas(), info.arrival_time_ms); | 252 } else { |
| 253 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta, |
| 254 detector_.State(), info.arrival_time_ms); |
| 255 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms, |
| 256 kalman_estimator_->num_of_deltas(), |
| 257 info.arrival_time_ms); |
| 258 } |
| 199 } | 259 } |
| 200 | 260 |
| 201 int probing_bps = 0; | 261 int probing_bps = 0; |
| 202 if (info.probe_cluster_id != PacketInfo::kNotAProbe) { | 262 if (info.probe_cluster_id != PacketInfo::kNotAProbe) { |
| 203 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); | 263 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); |
| 204 } | 264 } |
| 205 rtc::Optional<uint32_t> acked_bitrate_bps = | 265 rtc::Optional<uint32_t> acked_bitrate_bps = |
| 206 receiver_incoming_bitrate_.bitrate_bps(); | 266 receiver_incoming_bitrate_.bitrate_bps(); |
| 207 // Currently overusing the bandwidth. | 267 // Currently overusing the bandwidth. |
| 208 if (detector_.State() == kBwOverusing) { | 268 if (detector_.State() == kBwOverusing) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 230 if (result.updated) | 290 if (result.updated) |
| 231 last_update_ms_ = now_ms; | 291 last_update_ms_ = now_ms; |
| 232 | 292 |
| 233 return result; | 293 return result; |
| 234 } | 294 } |
| 235 | 295 |
| 236 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, | 296 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, |
| 237 int64_t now_ms, | 297 int64_t now_ms, |
| 238 rtc::Optional<uint32_t> acked_bitrate_bps, | 298 rtc::Optional<uint32_t> acked_bitrate_bps, |
| 239 uint32_t* target_bitrate_bps) { | 299 uint32_t* target_bitrate_bps) { |
| 240 const RateControlInput input(detector_.State(), acked_bitrate_bps, | 300 // TODO(terelius): RateControlInput::noise_var is deprecated and will be |
| 241 estimator_->var_noise()); | 301 // removed. In the meantime, we set it to zero. |
| 302 const RateControlInput input(detector_.State(), acked_bitrate_bps, 0); |
| 242 rate_control_.Update(&input, now_ms); | 303 rate_control_.Update(&input, now_ms); |
| 243 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); | 304 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); |
| 244 return rate_control_.ValidEstimate(); | 305 return rate_control_.ValidEstimate(); |
| 245 } | 306 } |
| 246 | 307 |
| 247 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { | 308 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { |
| 248 rate_control_.SetRtt(avg_rtt_ms); | 309 rate_control_.SetRtt(avg_rtt_ms); |
| 249 } | 310 } |
| 250 | 311 |
| 251 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, | 312 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 263 *bitrate_bps = rate_control_.LatestEstimate(); | 324 *bitrate_bps = rate_control_.LatestEstimate(); |
| 264 return true; | 325 return true; |
| 265 } | 326 } |
| 266 | 327 |
| 267 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { | 328 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { |
| 268 // Called from both the configuration thread and the network thread. Shouldn't | 329 // Called from both the configuration thread and the network thread. Shouldn't |
| 269 // be called from the network thread in the future. | 330 // be called from the network thread in the future. |
| 270 rate_control_.SetMinBitrate(min_bitrate_bps); | 331 rate_control_.SetMinBitrate(min_bitrate_bps); |
| 271 } | 332 } |
| 272 } // namespace webrtc | 333 } // namespace webrtc |
| OLD | NEW |