blob: ccca69271247b8ba824b175bde14d0585375339a [file] [log] [blame]
nisse559af382017-03-21 06:41:12 -07001/*
2 * Copyright (c) 2012 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/congestion_controller/include/send_side_congestion_controller.h"
nisse559af382017-03-21 06:41:12 -070012
13#include <algorithm>
14#include <memory>
15#include <vector>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/bitrate_controller/include/bitrate_controller.h"
18#include "modules/congestion_controller/acknowledged_bitrate_estimator.h"
19#include "modules/congestion_controller/probe_controller.h"
20#include "modules/pacing/alr_detector.h"
21#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/format_macros.h"
24#include "rtc_base/logging.h"
25#include "rtc_base/ptr_util.h"
26#include "rtc_base/rate_limiter.h"
27#include "rtc_base/socket.h"
28#include "rtc_base/timeutils.h"
29#include "system_wrappers/include/field_trial.h"
nisse559af382017-03-21 06:41:12 -070030
31namespace webrtc {
32namespace {
33
stefan9e117c5e12017-08-16 08:16:25 -070034const char kCwndExperiment[] = "WebRTC-CwndExperiment";
philipela4205512017-09-26 05:36:58 -070035const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment";
stefan74418272017-08-17 02:13:54 -070036const int64_t kDefaultAcceptedQueueMs = 250;
stefan9e117c5e12017-08-16 08:16:25 -070037
38bool CwndExperimentEnabled() {
39 std::string experiment_string =
40 webrtc::field_trial::FindFullName(kCwndExperiment);
41 // The experiment is enabled iff the field trial string begins with "Enabled".
42 return experiment_string.find("Enabled") == 0;
43}
44
stefan74418272017-08-17 02:13:54 -070045bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) {
46 RTC_DCHECK(accepted_queue_ms);
47 std::string experiment_string =
48 webrtc::field_trial::FindFullName(kCwndExperiment);
49 int parsed_values =
50 sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms);
51 if (parsed_values == 1) {
52 RTC_CHECK_GE(*accepted_queue_ms, 0)
53 << "Accepted must be greater than or equal to 0.";
54 return true;
55 }
56 return false;
57}
58
nisse559af382017-03-21 06:41:12 -070059static const int64_t kRetransmitWindowSizeMs = 500;
60
61// Makes sure that the bitrate and the min, max values are in valid range.
62static void ClampBitrates(int* bitrate_bps,
63 int* min_bitrate_bps,
64 int* max_bitrate_bps) {
65 // TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
66 // and that we don't try to set the min bitrate to 0 from any applications.
67 // The congestion controller should allow a min bitrate of 0.
68 if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps())
69 *min_bitrate_bps = congestion_controller::GetMinBitrateBps();
70 if (*max_bitrate_bps > 0)
71 *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps);
72 if (*bitrate_bps > 0)
73 *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps);
74}
75
tschumim3fae6282017-06-11 23:57:17 -070076std::vector<webrtc::PacketFeedback> ReceivedPacketFeedbackVector(
77 const std::vector<webrtc::PacketFeedback>& input) {
78 std::vector<PacketFeedback> received_packet_feedback_vector;
79 auto is_received = [](const webrtc::PacketFeedback& packet_feedback) {
80 return packet_feedback.arrival_time_ms !=
81 webrtc::PacketFeedback::kNotReceived;
82 };
83 std::copy_if(input.begin(), input.end(),
84 std::back_inserter(received_packet_feedback_vector),
85 is_received);
86 return received_packet_feedback_vector;
87}
88
89void SortPacketFeedbackVector(
90 std::vector<webrtc::PacketFeedback>* const input) {
91 RTC_DCHECK(input);
92 std::sort(input->begin(), input->end(), PacketFeedbackComparator());
93}
94
nisse559af382017-03-21 06:41:12 -070095} // namespace
96
97SendSideCongestionController::SendSideCongestionController(
98 const Clock* clock,
99 Observer* observer,
100 RtcEventLog* event_log,
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200101 PacedSender* pacer)
nisse559af382017-03-21 06:41:12 -0700102 : clock_(clock),
103 observer_(observer),
104 event_log_(event_log),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200105 pacer_(pacer),
nisse559af382017-03-21 06:41:12 -0700106 bitrate_controller_(
107 BitrateController::CreateBitrateController(clock_, event_log)),
tschumim3fae6282017-06-11 23:57:17 -0700108 acknowledged_bitrate_estimator_(
tereliuse75d96b2017-06-30 08:11:44 -0700109 rtc::MakeUnique<AcknowledgedBitrateEstimator>()),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200110 probe_controller_(new ProbeController(pacer_, clock_)),
nisse559af382017-03-21 06:41:12 -0700111 retransmission_rate_limiter_(
112 new RateLimiter(clock, kRetransmitWindowSizeMs)),
113 transport_feedback_adapter_(clock_),
114 last_reported_bitrate_bps_(0),
115 last_reported_fraction_loss_(0),
116 last_reported_rtt_(0),
117 network_state_(kNetworkUp),
stefan9e117c5e12017-08-16 08:16:25 -0700118 pause_pacer_(false),
119 pacer_paused_(false),
nisse559af382017-03-21 06:41:12 -0700120 min_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
tschumim9d117642017-07-17 01:41:41 -0700121 delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)),
stefan9e117c5e12017-08-16 08:16:25 -0700122 in_cwnd_experiment_(CwndExperimentEnabled()),
stefan74418272017-08-17 02:13:54 -0700123 accepted_queue_ms_(kDefaultAcceptedQueueMs),
philipela4205512017-09-26 05:36:58 -0700124 was_in_alr_(false),
125 pacer_pushback_experiment_(
126 webrtc::field_trial::IsEnabled(kPacerPushbackExperiment)) {
nisse559af382017-03-21 06:41:12 -0700127 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
stefan74418272017-08-17 02:13:54 -0700128 if (in_cwnd_experiment_ &&
129 !ReadCwndExperimentParameter(&accepted_queue_ms_)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100130 RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
131 "from field trial string. Experiment disabled.";
stefan74418272017-08-17 02:13:54 -0700132 in_cwnd_experiment_ = false;
133 }
nisse559af382017-03-21 06:41:12 -0700134}
135
136SendSideCongestionController::~SendSideCongestionController() {}
137
elad.alond12a8e12017-03-23 11:04:48 -0700138void SendSideCongestionController::RegisterPacketFeedbackObserver(
139 PacketFeedbackObserver* observer) {
140 transport_feedback_adapter_.RegisterPacketFeedbackObserver(observer);
141}
142
143void SendSideCongestionController::DeRegisterPacketFeedbackObserver(
144 PacketFeedbackObserver* observer) {
145 transport_feedback_adapter_.DeRegisterPacketFeedbackObserver(observer);
146}
147
nisse23425f92017-04-03 04:54:25 -0700148void SendSideCongestionController::RegisterNetworkObserver(Observer* observer) {
149 rtc::CritScope cs(&observer_lock_);
150 RTC_DCHECK(observer_ == nullptr);
151 observer_ = observer;
152}
153
154void SendSideCongestionController::DeRegisterNetworkObserver(
155 Observer* observer) {
156 rtc::CritScope cs(&observer_lock_);
157 RTC_DCHECK_EQ(observer_, observer);
158 observer_ = nullptr;
159}
160
nisse559af382017-03-21 06:41:12 -0700161void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps,
162 int start_bitrate_bps,
163 int max_bitrate_bps) {
164 ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
165 bitrate_controller_->SetBitrates(start_bitrate_bps, min_bitrate_bps,
166 max_bitrate_bps);
167
168 probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
169 max_bitrate_bps);
170
171 {
172 rtc::CritScope cs(&bwe_lock_);
173 if (start_bitrate_bps > 0)
174 delay_based_bwe_->SetStartBitrate(start_bitrate_bps);
175 min_bitrate_bps_ = min_bitrate_bps;
176 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
177 }
178 MaybeTriggerOnNetworkChanged();
179}
180
181// TODO(holmer): Split this up and use SetBweBitrates in combination with
182// OnNetworkRouteChanged.
183void SendSideCongestionController::OnNetworkRouteChanged(
184 const rtc::NetworkRoute& network_route,
185 int bitrate_bps,
186 int min_bitrate_bps,
187 int max_bitrate_bps) {
188 ClampBitrates(&bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
189 // TODO(honghaiz): Recreate this object once the bitrate controller is
190 // no longer exposed outside SendSideCongestionController.
191 bitrate_controller_->ResetBitrates(bitrate_bps, min_bitrate_bps,
192 max_bitrate_bps);
193
194 transport_feedback_adapter_.SetNetworkIds(network_route.local_network_id,
195 network_route.remote_network_id);
196 {
197 rtc::CritScope cs(&bwe_lock_);
198 min_bitrate_bps_ = min_bitrate_bps;
199 delay_based_bwe_.reset(new DelayBasedBwe(event_log_, clock_));
tschumim3fae6282017-06-11 23:57:17 -0700200 acknowledged_bitrate_estimator_.reset(new AcknowledgedBitrateEstimator());
nisse559af382017-03-21 06:41:12 -0700201 delay_based_bwe_->SetStartBitrate(bitrate_bps);
202 delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
203 }
204
205 probe_controller_->Reset();
206 probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps, max_bitrate_bps);
207
208 MaybeTriggerOnNetworkChanged();
209}
210
211BitrateController* SendSideCongestionController::GetBitrateController() const {
212 return bitrate_controller_.get();
213}
214
srtea6092a92017-11-22 19:37:43 +0100215bool SendSideCongestionController::AvailableBandwidth(
216 uint32_t* bandwidth) const {
217 return bitrate_controller_->AvailableBandwidth(bandwidth);
218}
219
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100220RtcpBandwidthObserver* SendSideCongestionController::GetBandwidthObserver()
221 const {
222 return bitrate_controller_.get();
223}
224
nisse559af382017-03-21 06:41:12 -0700225RateLimiter* SendSideCongestionController::GetRetransmissionRateLimiter() {
226 return retransmission_rate_limiter_.get();
227}
228
229void SendSideCongestionController::EnablePeriodicAlrProbing(bool enable) {
230 probe_controller_->EnablePeriodicAlrProbing(enable);
231}
232
nisse559af382017-03-21 06:41:12 -0700233int64_t SendSideCongestionController::GetPacerQueuingDelayMs() const {
234 return IsNetworkDown() ? 0 : pacer_->QueueInMs();
235}
236
asaperssonfc5e81c2017-04-19 23:28:53 -0700237int64_t SendSideCongestionController::GetFirstPacketTimeMs() const {
238 return pacer_->FirstSentPacketTimeMs();
239}
240
nisse76e62b02017-05-31 02:24:52 -0700241TransportFeedbackObserver*
242SendSideCongestionController::GetTransportFeedbackObserver() {
243 return this;
244}
245
nisse559af382017-03-21 06:41:12 -0700246void SendSideCongestionController::SignalNetworkState(NetworkState state) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100247 RTC_LOG(LS_INFO) << "SignalNetworkState "
248 << (state == kNetworkUp ? "Up" : "Down");
nisse559af382017-03-21 06:41:12 -0700249 {
250 rtc::CritScope cs(&network_state_lock_);
stefan9e117c5e12017-08-16 08:16:25 -0700251 pause_pacer_ = state == kNetworkDown;
nisse559af382017-03-21 06:41:12 -0700252 network_state_ = state;
253 }
254 probe_controller_->OnNetworkStateChanged(state);
255 MaybeTriggerOnNetworkChanged();
256}
257
258void SendSideCongestionController::SetTransportOverhead(
259 size_t transport_overhead_bytes_per_packet) {
260 transport_feedback_adapter_.SetTransportOverhead(
261 transport_overhead_bytes_per_packet);
262}
263
264void SendSideCongestionController::OnSentPacket(
265 const rtc::SentPacket& sent_packet) {
266 // We're not interested in packets without an id, which may be stun packets,
267 // etc, sent on the same transport.
268 if (sent_packet.packet_id == -1)
269 return;
270 transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id,
271 sent_packet.send_time_ms);
stefana86f57e2017-08-26 06:33:43 -0700272 if (in_cwnd_experiment_)
273 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
nisse559af382017-03-21 06:41:12 -0700274}
275
276void SendSideCongestionController::OnRttUpdate(int64_t avg_rtt_ms,
277 int64_t max_rtt_ms) {
278 rtc::CritScope cs(&bwe_lock_);
279 delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
280}
281
282int64_t SendSideCongestionController::TimeUntilNextProcess() {
283 return bitrate_controller_->TimeUntilNextProcess();
284}
285
286void SendSideCongestionController::Process() {
stefan9e117c5e12017-08-16 08:16:25 -0700287 bool pause_pacer;
288 // TODO(holmer): Once this class is running on a task queue we should
289 // replace this with a task instead.
290 {
291 rtc::CritScope lock(&network_state_lock_);
292 pause_pacer = pause_pacer_;
293 }
294 if (pause_pacer && !pacer_paused_) {
295 pacer_->Pause();
296 pacer_paused_ = true;
297 } else if (!pause_pacer && pacer_paused_) {
298 pacer_->Resume();
299 pacer_paused_ = false;
300 }
nisse559af382017-03-21 06:41:12 -0700301 bitrate_controller_->Process();
302 probe_controller_->Process();
303 MaybeTriggerOnNetworkChanged();
304}
305
306void SendSideCongestionController::AddPacket(
elad.alond12a8e12017-03-23 11:04:48 -0700307 uint32_t ssrc,
nisse559af382017-03-21 06:41:12 -0700308 uint16_t sequence_number,
309 size_t length,
310 const PacedPacketInfo& pacing_info) {
elad.alond12a8e12017-03-23 11:04:48 -0700311 transport_feedback_adapter_.AddPacket(ssrc, sequence_number, length,
312 pacing_info);
nisse559af382017-03-21 06:41:12 -0700313}
314
315void SendSideCongestionController::OnTransportFeedback(
316 const rtcp::TransportFeedback& feedback) {
erikvargabf5a2fc2017-06-16 05:02:05 -0700317 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700318 transport_feedback_adapter_.OnTransportFeedback(feedback);
tschumim3fae6282017-06-11 23:57:17 -0700319 std::vector<PacketFeedback> feedback_vector = ReceivedPacketFeedbackVector(
320 transport_feedback_adapter_.GetTransportFeedbackVector());
321 SortPacketFeedbackVector(&feedback_vector);
tschumim9d117642017-07-17 01:41:41 -0700322
323 bool currently_in_alr =
324 pacer_->GetApplicationLimitedRegionStartTime().has_value();
terelius3376c842017-07-31 04:23:25 -0700325 if (was_in_alr_ && !currently_in_alr) {
326 int64_t now_ms = rtc::TimeMillis();
327 acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms);
328 probe_controller_->SetAlrEndedTimeMs(now_ms);
tschumim9d117642017-07-17 01:41:41 -0700329 }
330 was_in_alr_ = currently_in_alr;
331
tschumim3fae6282017-06-11 23:57:17 -0700332 acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(
tereliuse75d96b2017-06-30 08:11:44 -0700333 feedback_vector);
nisse559af382017-03-21 06:41:12 -0700334 DelayBasedBwe::Result result;
335 {
336 rtc::CritScope cs(&bwe_lock_);
tschumim3fae6282017-06-11 23:57:17 -0700337 result = delay_based_bwe_->IncomingPacketFeedbackVector(
338 feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps());
nisse559af382017-03-21 06:41:12 -0700339 }
terelius3376c842017-07-31 04:23:25 -0700340 if (result.updated) {
nisse559af382017-03-21 06:41:12 -0700341 bitrate_controller_->OnDelayBasedBweResult(result);
terelius3376c842017-07-31 04:23:25 -0700342 // Update the estimate in the ProbeController, in case we want to probe.
343 MaybeTriggerOnNetworkChanged();
344 }
345 if (result.recovered_from_overuse)
346 probe_controller_->RequestProbe();
stefana86f57e2017-08-26 06:33:43 -0700347 if (in_cwnd_experiment_)
348 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
stefan9e117c5e12017-08-16 08:16:25 -0700349}
350
351void SendSideCongestionController::LimitOutstandingBytes(
352 size_t num_outstanding_bytes) {
stefana86f57e2017-08-26 06:33:43 -0700353 RTC_DCHECK(in_cwnd_experiment_);
354 rtc::CritScope lock(&network_state_lock_);
355 rtc::Optional<int64_t> min_rtt_ms =
356 transport_feedback_adapter_.GetMinFeedbackLoopRtt();
357 // No valid RTT. Could be because send-side BWE isn't used, in which case
358 // we don't try to limit the outstanding packets.
359 if (!min_rtt_ms)
stefan9e117c5e12017-08-16 08:16:25 -0700360 return;
stefana86f57e2017-08-26 06:33:43 -0700361 const size_t kMinCwndBytes = 2 * 1500;
362 size_t max_outstanding_bytes =
363 std::max<size_t>((*min_rtt_ms + accepted_queue_ms_) *
364 last_reported_bitrate_bps_ / 1000 / 8,
365 kMinCwndBytes);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100366 RTC_LOG(LS_INFO) << clock_->TimeInMilliseconds()
367 << " Outstanding bytes: " << num_outstanding_bytes
368 << " pacer queue: " << pacer_->QueueInMs()
369 << " max outstanding: " << max_outstanding_bytes;
370 RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_rtt_ms
371 << " Bitrate: " << last_reported_bitrate_bps_;
stefana86f57e2017-08-26 06:33:43 -0700372 pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes;
nisse559af382017-03-21 06:41:12 -0700373}
374
375std::vector<PacketFeedback>
376SendSideCongestionController::GetTransportFeedbackVector() const {
erikvargabf5a2fc2017-06-16 05:02:05 -0700377 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700378 return transport_feedback_adapter_.GetTransportFeedbackVector();
379}
380
381void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {
nisse559af382017-03-21 06:41:12 -0700382 uint32_t bitrate_bps;
383 uint8_t fraction_loss;
384 int64_t rtt;
385 bool estimate_changed = bitrate_controller_->GetNetworkParameters(
386 &bitrate_bps, &fraction_loss, &rtt);
387 if (estimate_changed) {
388 pacer_->SetEstimatedBitrate(bitrate_bps);
389 probe_controller_->SetEstimatedBitrate(bitrate_bps);
390 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
391 }
392
philipela4205512017-09-26 05:36:58 -0700393 if (!pacer_pushback_experiment_) {
394 bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps;
395 } else {
396 if (IsNetworkDown()) {
397 bitrate_bps = 0;
398 } else {
399 int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs();
400
401 if (queue_length_ms == 0) {
402 encoding_rate_ = 1.0;
403 } else if (queue_length_ms > 50) {
404 float encoding_rate = 1.0 - queue_length_ms / 1000.0;
405 encoding_rate_ = std::min(encoding_rate_, encoding_rate);
406 encoding_rate_ = std::max(encoding_rate_, 0.0f);
407 }
408
409 bitrate_bps *= encoding_rate_;
410 bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps;
411 }
412 }
nisse559af382017-03-21 06:41:12 -0700413
414 if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {
415 int64_t probing_interval_ms;
416 {
417 rtc::CritScope cs(&bwe_lock_);
terelius67370452017-04-19 09:15:04 -0700418 probing_interval_ms = delay_based_bwe_->GetExpectedBwePeriodMs();
nisse559af382017-03-21 06:41:12 -0700419 }
nisse23425f92017-04-03 04:54:25 -0700420 {
421 rtc::CritScope cs(&observer_lock_);
422 if (observer_) {
423 observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt,
424 probing_interval_ms);
425 }
426 }
nisse559af382017-03-21 06:41:12 -0700427 }
428}
429
430bool SendSideCongestionController::HasNetworkParametersToReportChanged(
431 uint32_t bitrate_bps,
432 uint8_t fraction_loss,
433 int64_t rtt) {
434 rtc::CritScope cs(&network_state_lock_);
435 bool changed =
436 last_reported_bitrate_bps_ != bitrate_bps ||
437 (bitrate_bps > 0 && (last_reported_fraction_loss_ != fraction_loss ||
438 last_reported_rtt_ != rtt));
439 if (changed && (last_reported_bitrate_bps_ == 0 || bitrate_bps == 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100440 RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: " << bitrate_bps
441 << " bps.";
nisse559af382017-03-21 06:41:12 -0700442 }
443 last_reported_bitrate_bps_ = bitrate_bps;
444 last_reported_fraction_loss_ = fraction_loss;
445 last_reported_rtt_ = rtt;
446 return changed;
447}
448
449bool SendSideCongestionController::IsSendQueueFull() const {
450 return pacer_->ExpectedQueueTimeMs() > PacedSender::kMaxQueueLengthMs;
451}
452
453bool SendSideCongestionController::IsNetworkDown() const {
454 rtc::CritScope cs(&network_state_lock_);
455 return network_state_ == kNetworkDown;
456}
457
458} // namespace webrtc