delay_based_bwe.cc (12256B)
1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/congestion_controller/goog_cc/delay_based_bwe.h" 12 13 #include <algorithm> 14 #include <cstdint> 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 #include <vector> 19 20 #include "api/field_trials_view.h" 21 #include "api/network_state_predictor.h" 22 #include "api/rtc_event_log/rtc_event_log.h" 23 #include "api/transport/bandwidth_usage.h" 24 #include "api/transport/network_types.h" 25 #include "api/units/data_rate.h" 26 #include "api/units/data_size.h" 27 #include "api/units/time_delta.h" 28 #include "api/units/timestamp.h" 29 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h" 30 #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" 31 #include "modules/congestion_controller/goog_cc/inter_arrival_delta.h" 32 #include "modules/congestion_controller/goog_cc/trendline_estimator.h" 33 #include "modules/remote_bitrate_estimator/include/bwe_defines.h" 34 #include "rtc_base/checks.h" 35 #include "rtc_base/experiments/struct_parameters_parser.h" 36 #include "rtc_base/logging.h" 37 #include "rtc_base/race_checker.h" 38 #include "system_wrappers/include/metrics.h" 39 40 namespace webrtc { 41 namespace { 42 constexpr TimeDelta kStreamTimeOut = TimeDelta::Seconds(2); 43 constexpr TimeDelta kSendTimeGroupLength = TimeDelta::Millis(5); 44 45 // This ssrc is used to fulfill the current API but will be removed 46 // after the API has been changed. 47 constexpr uint32_t kFixedSsrc = 0; 48 } // namespace 49 50 BweSeparateAudioPacketsSettings::BweSeparateAudioPacketsSettings( 51 const FieldTrialsView* key_value_config) { 52 Parser()->Parse( 53 key_value_config->Lookup(BweSeparateAudioPacketsSettings::kKey)); 54 } 55 56 std::unique_ptr<StructParametersParser> 57 BweSeparateAudioPacketsSettings::Parser() { 58 return StructParametersParser::Create( // 59 "enabled", &enabled, // 60 "packet_threshold", &packet_threshold, // 61 "time_threshold", &time_threshold); 62 } 63 64 DelayBasedBwe::Result::Result() 65 : updated(false), 66 probe(false), 67 target_bitrate(DataRate::Zero()), 68 recovered_from_overuse(false), 69 delay_detector_state(BandwidthUsage::kBwNormal) {} 70 71 DelayBasedBwe::DelayBasedBwe(const FieldTrialsView* key_value_config, 72 RtcEventLog* event_log, 73 NetworkStatePredictor* network_state_predictor) 74 : event_log_(event_log), 75 key_value_config_(key_value_config), 76 separate_audio_(key_value_config), 77 audio_packets_since_last_video_(0), 78 last_video_packet_recv_time_(Timestamp::MinusInfinity()), 79 network_state_predictor_(network_state_predictor), 80 video_delay_detector_( 81 new TrendlineEstimator(*key_value_config_, network_state_predictor_)), 82 audio_delay_detector_( 83 new TrendlineEstimator(*key_value_config_, network_state_predictor_)), 84 active_delay_detector_(video_delay_detector_.get()), 85 last_seen_packet_(Timestamp::MinusInfinity()), 86 uma_recorded_(false), 87 rate_control_(*key_value_config, /*send_side=*/true), 88 prev_bitrate_(DataRate::Zero()), 89 prev_state_(BandwidthUsage::kBwNormal) { 90 RTC_LOG(LS_INFO) 91 << "Initialized DelayBasedBwe with separate audio overuse detection" 92 << separate_audio_.Parser()->Encode(); 93 } 94 95 DelayBasedBwe::~DelayBasedBwe() {} 96 97 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( 98 const TransportPacketsFeedback& msg, 99 std::optional<DataRate> acked_bitrate, 100 std::optional<DataRate> probe_bitrate, 101 std::optional<NetworkStateEstimate> network_estimate, 102 bool in_alr) { 103 RTC_DCHECK_RUNS_SERIALIZED(&network_race_); 104 105 auto packet_feedback_vector = msg.SortedByReceiveTime(); 106 // TODO(holmer): An empty feedback vector here likely means that 107 // all acks were too late and that the send time history had 108 // timed out. We should reduce the rate when this occurs. 109 if (packet_feedback_vector.empty()) { 110 RTC_LOG(LS_WARNING) << "Very late feedback received."; 111 return DelayBasedBwe::Result(); 112 } 113 114 if (!uma_recorded_) { 115 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, 116 BweNames::kSendSideTransportSeqNum, 117 BweNames::kBweNamesMax); 118 uma_recorded_ = true; 119 } 120 bool delayed_feedback = true; 121 bool recovered_from_overuse = false; 122 BandwidthUsage prev_detector_state = active_delay_detector_->State(); 123 for (const auto& packet_feedback : packet_feedback_vector) { 124 delayed_feedback = false; 125 IncomingPacketFeedback(packet_feedback, msg.feedback_time); 126 if (prev_detector_state == BandwidthUsage::kBwUnderusing && 127 active_delay_detector_->State() == BandwidthUsage::kBwNormal) { 128 recovered_from_overuse = true; 129 } 130 prev_detector_state = active_delay_detector_->State(); 131 } 132 133 if (delayed_feedback) { 134 // TODO(bugs.webrtc.org/10125): Design a better mechanism to safe-guard 135 // against building very large network queues. 136 return Result(); 137 } 138 rate_control_.SetInApplicationLimitedRegion(in_alr); 139 rate_control_.SetNetworkStateEstimate(network_estimate); 140 return MaybeUpdateEstimate(acked_bitrate, probe_bitrate, 141 std::move(network_estimate), 142 recovered_from_overuse, in_alr, msg.feedback_time); 143 } 144 145 void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, 146 Timestamp at_time) { 147 // Reset if the stream has timed out. 148 if (last_seen_packet_.IsInfinite() || 149 at_time - last_seen_packet_ > kStreamTimeOut) { 150 video_inter_arrival_delta_ = 151 std::make_unique<InterArrivalDelta>(kSendTimeGroupLength); 152 audio_inter_arrival_delta_ = 153 std::make_unique<InterArrivalDelta>(kSendTimeGroupLength); 154 155 video_delay_detector_.reset( 156 new TrendlineEstimator(*key_value_config_, network_state_predictor_)); 157 audio_delay_detector_.reset( 158 new TrendlineEstimator(*key_value_config_, network_state_predictor_)); 159 active_delay_detector_ = video_delay_detector_.get(); 160 } 161 last_seen_packet_ = at_time; 162 163 // As an alternative to ignoring small packets, we can separate audio and 164 // video packets for overuse detection. 165 DelayIncreaseDetectorInterface* delay_detector_for_packet = 166 video_delay_detector_.get(); 167 if (separate_audio_.enabled) { 168 if (packet_feedback.sent_packet.audio) { 169 delay_detector_for_packet = audio_delay_detector_.get(); 170 audio_packets_since_last_video_++; 171 if (audio_packets_since_last_video_ > separate_audio_.packet_threshold && 172 packet_feedback.receive_time - last_video_packet_recv_time_ > 173 separate_audio_.time_threshold) { 174 active_delay_detector_ = audio_delay_detector_.get(); 175 } 176 } else { 177 audio_packets_since_last_video_ = 0; 178 last_video_packet_recv_time_ = 179 std::max(last_video_packet_recv_time_, packet_feedback.receive_time); 180 active_delay_detector_ = video_delay_detector_.get(); 181 } 182 } 183 DataSize packet_size = packet_feedback.sent_packet.size; 184 185 TimeDelta send_delta = TimeDelta::Zero(); 186 TimeDelta recv_delta = TimeDelta::Zero(); 187 int size_delta = 0; 188 189 InterArrivalDelta* inter_arrival_for_packet = 190 (separate_audio_.enabled && packet_feedback.sent_packet.audio) 191 ? audio_inter_arrival_delta_.get() 192 : video_inter_arrival_delta_.get(); 193 bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas( 194 packet_feedback.sent_packet.send_time, packet_feedback.receive_time, 195 at_time, packet_size.bytes(), &send_delta, &recv_delta, &size_delta); 196 197 delay_detector_for_packet->Update(recv_delta.ms<double>(), 198 send_delta.ms<double>(), 199 packet_feedback.sent_packet.send_time.ms(), 200 packet_feedback.receive_time.ms(), 201 packet_size.bytes(), calculated_deltas); 202 } 203 204 DataRate DelayBasedBwe::TriggerOveruse(Timestamp at_time, 205 std::optional<DataRate> link_capacity) { 206 RateControlInput input(BandwidthUsage::kBwOverusing, link_capacity); 207 return rate_control_.Update(input, at_time); 208 } 209 210 DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( 211 std::optional<DataRate> acked_bitrate, 212 std::optional<DataRate> probe_bitrate, 213 std::optional<NetworkStateEstimate> /* state_estimate */, 214 bool recovered_from_overuse, 215 bool /* in_alr */, 216 Timestamp at_time) { 217 Result result; 218 219 // Currently overusing the bandwidth. 220 if (active_delay_detector_->State() == BandwidthUsage::kBwOverusing) { 221 if (acked_bitrate && 222 rate_control_.TimeToReduceFurther(at_time, *acked_bitrate)) { 223 result.updated = 224 UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); 225 } else if (!acked_bitrate && rate_control_.ValidEstimate() && 226 rate_control_.InitialTimeToReduceFurther(at_time)) { 227 // Overusing before we have a measured acknowledged bitrate. Reduce send 228 // rate by 50% every 200 ms. 229 // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator 230 // so that we (almost) always have a bitrate estimate. 231 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, at_time); 232 result.updated = true; 233 result.probe = false; 234 result.target_bitrate = rate_control_.LatestEstimate(); 235 } 236 } else { 237 if (probe_bitrate) { 238 result.probe = true; 239 result.updated = true; 240 rate_control_.SetEstimate(*probe_bitrate, at_time); 241 result.target_bitrate = rate_control_.LatestEstimate(); 242 } else { 243 result.updated = 244 UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); 245 result.recovered_from_overuse = recovered_from_overuse; 246 } 247 } 248 BandwidthUsage detector_state = active_delay_detector_->State(); 249 if ((result.updated && prev_bitrate_ != result.target_bitrate) || 250 detector_state != prev_state_) { 251 DataRate bitrate = result.updated ? result.target_bitrate : prev_bitrate_; 252 253 if (event_log_) { 254 event_log_->Log(std::make_unique<RtcEventBweUpdateDelayBased>( 255 bitrate.bps(), detector_state)); 256 } 257 258 prev_bitrate_ = bitrate; 259 prev_state_ = detector_state; 260 } 261 262 result.delay_detector_state = detector_state; 263 return result; 264 } 265 266 bool DelayBasedBwe::UpdateEstimate(Timestamp at_time, 267 std::optional<DataRate> acked_bitrate, 268 DataRate* target_rate) { 269 const RateControlInput input(active_delay_detector_->State(), acked_bitrate); 270 *target_rate = rate_control_.Update(input, at_time); 271 return rate_control_.ValidEstimate(); 272 } 273 274 void DelayBasedBwe::OnRttUpdate(TimeDelta avg_rtt) { 275 rate_control_.SetRtt(avg_rtt); 276 } 277 278 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, 279 DataRate* bitrate) const { 280 // Currently accessed from both the process thread (see 281 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see 282 // Call::GetStats()). Should in the future only be accessed from a single 283 // thread. 284 RTC_DCHECK(ssrcs); 285 RTC_DCHECK(bitrate); 286 if (!rate_control_.ValidEstimate()) 287 return false; 288 289 *ssrcs = {kFixedSsrc}; 290 *bitrate = rate_control_.LatestEstimate(); 291 return true; 292 } 293 294 void DelayBasedBwe::SetStartBitrate(DataRate start_bitrate) { 295 RTC_LOG(LS_INFO) << "BWE Setting start bitrate to: " 296 << ToString(start_bitrate); 297 rate_control_.SetStartBitrate(start_bitrate); 298 } 299 300 void DelayBasedBwe::SetMinBitrate(DataRate min_bitrate) { 301 // Called from both the configuration thread and the network thread. Shouldn't 302 // be called from the network thread in the future. 303 rate_control_.SetMinBitrate(min_bitrate); 304 } 305 306 TimeDelta DelayBasedBwe::GetExpectedBwePeriod() const { 307 return rate_control_.GetExpectedBandwidthPeriod(); 308 } 309 310 } // namespace webrtc