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