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