blob: 2aeed51a013ea40926dbcac5bc2e11b74d4409e5 [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"
Oleh Prypina40f8242017-12-21 13:32:23 +010025#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/ptr_util.h"
27#include "rtc_base/rate_limiter.h"
28#include "rtc_base/socket.h"
29#include "rtc_base/timeutils.h"
30#include "system_wrappers/include/field_trial.h"
nisse559af382017-03-21 06:41:12 -070031
32namespace webrtc {
33namespace {
34
stefan9e117c5e12017-08-16 08:16:25 -070035const char kCwndExperiment[] = "WebRTC-CwndExperiment";
philipela4205512017-09-26 05:36:58 -070036const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment";
stefan74418272017-08-17 02:13:54 -070037const int64_t kDefaultAcceptedQueueMs = 250;
stefan9e117c5e12017-08-16 08:16:25 -070038
39bool CwndExperimentEnabled() {
40 std::string experiment_string =
41 webrtc::field_trial::FindFullName(kCwndExperiment);
42 // The experiment is enabled iff the field trial string begins with "Enabled".
43 return experiment_string.find("Enabled") == 0;
44}
45
stefan74418272017-08-17 02:13:54 -070046bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) {
47 RTC_DCHECK(accepted_queue_ms);
48 std::string experiment_string =
49 webrtc::field_trial::FindFullName(kCwndExperiment);
50 int parsed_values =
51 sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms);
52 if (parsed_values == 1) {
53 RTC_CHECK_GE(*accepted_queue_ms, 0)
54 << "Accepted must be greater than or equal to 0.";
55 return true;
56 }
57 return false;
58}
59
nisse559af382017-03-21 06:41:12 -070060static const int64_t kRetransmitWindowSizeMs = 500;
61
62// Makes sure that the bitrate and the min, max values are in valid range.
63static void ClampBitrates(int* bitrate_bps,
64 int* min_bitrate_bps,
65 int* max_bitrate_bps) {
66 // TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
67 // and that we don't try to set the min bitrate to 0 from any applications.
68 // The congestion controller should allow a min bitrate of 0.
69 if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps())
70 *min_bitrate_bps = congestion_controller::GetMinBitrateBps();
71 if (*max_bitrate_bps > 0)
72 *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps);
73 if (*bitrate_bps > 0)
74 *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps);
75}
76
tschumim3fae6282017-06-11 23:57:17 -070077std::vector<webrtc::PacketFeedback> ReceivedPacketFeedbackVector(
78 const std::vector<webrtc::PacketFeedback>& input) {
79 std::vector<PacketFeedback> received_packet_feedback_vector;
80 auto is_received = [](const webrtc::PacketFeedback& packet_feedback) {
81 return packet_feedback.arrival_time_ms !=
82 webrtc::PacketFeedback::kNotReceived;
83 };
84 std::copy_if(input.begin(), input.end(),
85 std::back_inserter(received_packet_feedback_vector),
86 is_received);
87 return received_packet_feedback_vector;
88}
89
90void SortPacketFeedbackVector(
91 std::vector<webrtc::PacketFeedback>* const input) {
92 RTC_DCHECK(input);
93 std::sort(input->begin(), input->end(), PacketFeedbackComparator());
94}
95
nisse559af382017-03-21 06:41:12 -070096} // namespace
97
98SendSideCongestionController::SendSideCongestionController(
99 const Clock* clock,
100 Observer* observer,
101 RtcEventLog* event_log,
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200102 PacedSender* pacer)
nisse559af382017-03-21 06:41:12 -0700103 : clock_(clock),
104 observer_(observer),
105 event_log_(event_log),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200106 pacer_(pacer),
nisse559af382017-03-21 06:41:12 -0700107 bitrate_controller_(
108 BitrateController::CreateBitrateController(clock_, event_log)),
tschumim3fae6282017-06-11 23:57:17 -0700109 acknowledged_bitrate_estimator_(
tereliuse75d96b2017-06-30 08:11:44 -0700110 rtc::MakeUnique<AcknowledgedBitrateEstimator>()),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200111 probe_controller_(new ProbeController(pacer_, clock_)),
nisse559af382017-03-21 06:41:12 -0700112 retransmission_rate_limiter_(
113 new RateLimiter(clock, kRetransmitWindowSizeMs)),
114 transport_feedback_adapter_(clock_),
115 last_reported_bitrate_bps_(0),
116 last_reported_fraction_loss_(0),
117 last_reported_rtt_(0),
118 network_state_(kNetworkUp),
stefan9e117c5e12017-08-16 08:16:25 -0700119 pause_pacer_(false),
120 pacer_paused_(false),
nisse559af382017-03-21 06:41:12 -0700121 min_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
tschumim9d117642017-07-17 01:41:41 -0700122 delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)),
stefan9e117c5e12017-08-16 08:16:25 -0700123 in_cwnd_experiment_(CwndExperimentEnabled()),
stefan74418272017-08-17 02:13:54 -0700124 accepted_queue_ms_(kDefaultAcceptedQueueMs),
philipela4205512017-09-26 05:36:58 -0700125 was_in_alr_(false),
126 pacer_pushback_experiment_(
Lu Liuc1094eb2018-01-17 19:45:43 +0000127 webrtc::field_trial::IsEnabled(kPacerPushbackExperiment)) {
nisse559af382017-03-21 06:41:12 -0700128 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
stefan74418272017-08-17 02:13:54 -0700129 if (in_cwnd_experiment_ &&
130 !ReadCwndExperimentParameter(&accepted_queue_ms_)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100131 RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
132 "from field trial string. Experiment disabled.";
stefan74418272017-08-17 02:13:54 -0700133 in_cwnd_experiment_ = false;
134 }
nisse559af382017-03-21 06:41:12 -0700135}
136
137SendSideCongestionController::~SendSideCongestionController() {}
138
elad.alond12a8e12017-03-23 11:04:48 -0700139void SendSideCongestionController::RegisterPacketFeedbackObserver(
140 PacketFeedbackObserver* observer) {
141 transport_feedback_adapter_.RegisterPacketFeedbackObserver(observer);
142}
143
144void SendSideCongestionController::DeRegisterPacketFeedbackObserver(
145 PacketFeedbackObserver* observer) {
146 transport_feedback_adapter_.DeRegisterPacketFeedbackObserver(observer);
147}
148
nisse23425f92017-04-03 04:54:25 -0700149void SendSideCongestionController::RegisterNetworkObserver(Observer* observer) {
150 rtc::CritScope cs(&observer_lock_);
151 RTC_DCHECK(observer_ == nullptr);
152 observer_ = observer;
153}
154
155void SendSideCongestionController::DeRegisterNetworkObserver(
156 Observer* observer) {
157 rtc::CritScope cs(&observer_lock_);
158 RTC_DCHECK_EQ(observer_, observer);
159 observer_ = nullptr;
160}
161
nisse559af382017-03-21 06:41:12 -0700162void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps,
163 int start_bitrate_bps,
164 int max_bitrate_bps) {
165 ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
166 bitrate_controller_->SetBitrates(start_bitrate_bps, min_bitrate_bps,
167 max_bitrate_bps);
168
169 probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
170 max_bitrate_bps);
171
172 {
173 rtc::CritScope cs(&bwe_lock_);
174 if (start_bitrate_bps > 0)
175 delay_based_bwe_->SetStartBitrate(start_bitrate_bps);
176 min_bitrate_bps_ = min_bitrate_bps;
177 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
178 }
179 MaybeTriggerOnNetworkChanged();
180}
181
182// TODO(holmer): Split this up and use SetBweBitrates in combination with
183// OnNetworkRouteChanged.
184void SendSideCongestionController::OnNetworkRouteChanged(
185 const rtc::NetworkRoute& network_route,
186 int bitrate_bps,
187 int min_bitrate_bps,
188 int max_bitrate_bps) {
189 ClampBitrates(&bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
190 // TODO(honghaiz): Recreate this object once the bitrate controller is
191 // no longer exposed outside SendSideCongestionController.
192 bitrate_controller_->ResetBitrates(bitrate_bps, min_bitrate_bps,
193 max_bitrate_bps);
194
195 transport_feedback_adapter_.SetNetworkIds(network_route.local_network_id,
196 network_route.remote_network_id);
197 {
198 rtc::CritScope cs(&bwe_lock_);
199 min_bitrate_bps_ = min_bitrate_bps;
200 delay_based_bwe_.reset(new DelayBasedBwe(event_log_, clock_));
tschumim3fae6282017-06-11 23:57:17 -0700201 acknowledged_bitrate_estimator_.reset(new AcknowledgedBitrateEstimator());
nisse559af382017-03-21 06:41:12 -0700202 delay_based_bwe_->SetStartBitrate(bitrate_bps);
203 delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
204 }
205
206 probe_controller_->Reset();
207 probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps, max_bitrate_bps);
208
209 MaybeTriggerOnNetworkChanged();
210}
211
212BitrateController* SendSideCongestionController::GetBitrateController() const {
213 return bitrate_controller_.get();
214}
215
srtea6092a92017-11-22 19:37:43 +0100216bool SendSideCongestionController::AvailableBandwidth(
217 uint32_t* bandwidth) const {
218 return bitrate_controller_->AvailableBandwidth(bandwidth);
219}
220
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100221RtcpBandwidthObserver* SendSideCongestionController::GetBandwidthObserver()
222 const {
223 return bitrate_controller_.get();
224}
225
nisse559af382017-03-21 06:41:12 -0700226RateLimiter* SendSideCongestionController::GetRetransmissionRateLimiter() {
227 return retransmission_rate_limiter_.get();
228}
229
230void SendSideCongestionController::EnablePeriodicAlrProbing(bool enable) {
231 probe_controller_->EnablePeriodicAlrProbing(enable);
232}
233
nisse559af382017-03-21 06:41:12 -0700234int64_t SendSideCongestionController::GetPacerQueuingDelayMs() const {
235 return IsNetworkDown() ? 0 : pacer_->QueueInMs();
236}
237
asaperssonfc5e81c2017-04-19 23:28:53 -0700238int64_t SendSideCongestionController::GetFirstPacketTimeMs() const {
239 return pacer_->FirstSentPacketTimeMs();
240}
241
nisse76e62b02017-05-31 02:24:52 -0700242TransportFeedbackObserver*
243SendSideCongestionController::GetTransportFeedbackObserver() {
244 return this;
245}
246
nisse559af382017-03-21 06:41:12 -0700247void SendSideCongestionController::SignalNetworkState(NetworkState state) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100248 RTC_LOG(LS_INFO) << "SignalNetworkState "
249 << (state == kNetworkUp ? "Up" : "Down");
nisse559af382017-03-21 06:41:12 -0700250 {
251 rtc::CritScope cs(&network_state_lock_);
stefan9e117c5e12017-08-16 08:16:25 -0700252 pause_pacer_ = state == kNetworkDown;
nisse559af382017-03-21 06:41:12 -0700253 network_state_ = state;
254 }
255 probe_controller_->OnNetworkStateChanged(state);
256 MaybeTriggerOnNetworkChanged();
257}
258
259void SendSideCongestionController::SetTransportOverhead(
260 size_t transport_overhead_bytes_per_packet) {
261 transport_feedback_adapter_.SetTransportOverhead(
Oleh Prypina40f8242017-12-21 13:32:23 +0100262 rtc::dchecked_cast<int>(transport_overhead_bytes_per_packet));
nisse559af382017-03-21 06:41:12 -0700263}
264
265void SendSideCongestionController::OnSentPacket(
266 const rtc::SentPacket& sent_packet) {
267 // We're not interested in packets without an id, which may be stun packets,
268 // etc, sent on the same transport.
269 if (sent_packet.packet_id == -1)
270 return;
271 transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id,
272 sent_packet.send_time_ms);
stefana86f57e2017-08-26 06:33:43 -0700273 if (in_cwnd_experiment_)
274 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
nisse559af382017-03-21 06:41:12 -0700275}
276
277void SendSideCongestionController::OnRttUpdate(int64_t avg_rtt_ms,
278 int64_t max_rtt_ms) {
279 rtc::CritScope cs(&bwe_lock_);
280 delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
281}
282
283int64_t SendSideCongestionController::TimeUntilNextProcess() {
284 return bitrate_controller_->TimeUntilNextProcess();
285}
286
287void SendSideCongestionController::Process() {
stefan9e117c5e12017-08-16 08:16:25 -0700288 bool pause_pacer;
289 // TODO(holmer): Once this class is running on a task queue we should
290 // replace this with a task instead.
291 {
292 rtc::CritScope lock(&network_state_lock_);
293 pause_pacer = pause_pacer_;
294 }
295 if (pause_pacer && !pacer_paused_) {
296 pacer_->Pause();
297 pacer_paused_ = true;
298 } else if (!pause_pacer && pacer_paused_) {
299 pacer_->Resume();
300 pacer_paused_ = false;
301 }
nisse559af382017-03-21 06:41:12 -0700302 bitrate_controller_->Process();
303 probe_controller_->Process();
304 MaybeTriggerOnNetworkChanged();
305}
306
307void SendSideCongestionController::AddPacket(
elad.alond12a8e12017-03-23 11:04:48 -0700308 uint32_t ssrc,
nisse559af382017-03-21 06:41:12 -0700309 uint16_t sequence_number,
310 size_t length,
311 const PacedPacketInfo& pacing_info) {
elad.alond12a8e12017-03-23 11:04:48 -0700312 transport_feedback_adapter_.AddPacket(ssrc, sequence_number, length,
313 pacing_info);
nisse559af382017-03-21 06:41:12 -0700314}
315
316void SendSideCongestionController::OnTransportFeedback(
317 const rtcp::TransportFeedback& feedback) {
erikvargabf5a2fc2017-06-16 05:02:05 -0700318 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700319 transport_feedback_adapter_.OnTransportFeedback(feedback);
Björn Terelius87f3a142017-12-01 19:03:43 +0000320 std::vector<PacketFeedback> feedback_vector = ReceivedPacketFeedbackVector(
321 transport_feedback_adapter_.GetTransportFeedbackVector());
tschumim3fae6282017-06-11 23:57:17 -0700322 SortPacketFeedbackVector(&feedback_vector);
tschumim9d117642017-07-17 01:41:41 -0700323
324 bool currently_in_alr =
325 pacer_->GetApplicationLimitedRegionStartTime().has_value();
terelius3376c842017-07-31 04:23:25 -0700326 if (was_in_alr_ && !currently_in_alr) {
327 int64_t now_ms = rtc::TimeMillis();
328 acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms);
329 probe_controller_->SetAlrEndedTimeMs(now_ms);
tschumim9d117642017-07-17 01:41:41 -0700330 }
331 was_in_alr_ = currently_in_alr;
332
tschumim3fae6282017-06-11 23:57:17 -0700333 acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(
tereliuse75d96b2017-06-30 08:11:44 -0700334 feedback_vector);
nisse559af382017-03-21 06:41:12 -0700335 DelayBasedBwe::Result result;
336 {
337 rtc::CritScope cs(&bwe_lock_);
tschumim3fae6282017-06-11 23:57:17 -0700338 result = delay_based_bwe_->IncomingPacketFeedbackVector(
339 feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps());
nisse559af382017-03-21 06:41:12 -0700340 }
terelius3376c842017-07-31 04:23:25 -0700341 if (result.updated) {
nisse559af382017-03-21 06:41:12 -0700342 bitrate_controller_->OnDelayBasedBweResult(result);
terelius3376c842017-07-31 04:23:25 -0700343 // Update the estimate in the ProbeController, in case we want to probe.
344 MaybeTriggerOnNetworkChanged();
345 }
346 if (result.recovered_from_overuse)
347 probe_controller_->RequestProbe();
stefana86f57e2017-08-26 06:33:43 -0700348 if (in_cwnd_experiment_)
349 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
stefan9e117c5e12017-08-16 08:16:25 -0700350}
351
352void SendSideCongestionController::LimitOutstandingBytes(
353 size_t num_outstanding_bytes) {
stefana86f57e2017-08-26 06:33:43 -0700354 RTC_DCHECK(in_cwnd_experiment_);
355 rtc::CritScope lock(&network_state_lock_);
Björn Terelius87f3a142017-12-01 19:03:43 +0000356 rtc::Optional<int64_t> min_rtt_ms =
357 transport_feedback_adapter_.GetMinFeedbackLoopRtt();
stefana86f57e2017-08-26 06:33:43 -0700358 // No valid RTT. Could be because send-side BWE isn't used, in which case
359 // we don't try to limit the outstanding packets.
Björn Terelius87f3a142017-12-01 19:03:43 +0000360 if (!min_rtt_ms)
stefan9e117c5e12017-08-16 08:16:25 -0700361 return;
stefana86f57e2017-08-26 06:33:43 -0700362 const size_t kMinCwndBytes = 2 * 1500;
363 size_t max_outstanding_bytes =
Björn Terelius87f3a142017-12-01 19:03:43 +0000364 std::max<size_t>((*min_rtt_ms + accepted_queue_ms_) *
stefana86f57e2017-08-26 06:33:43 -0700365 last_reported_bitrate_bps_ / 1000 / 8,
366 kMinCwndBytes);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100367 RTC_LOG(LS_INFO) << clock_->TimeInMilliseconds()
368 << " Outstanding bytes: " << num_outstanding_bytes
369 << " pacer queue: " << pacer_->QueueInMs()
370 << " max outstanding: " << max_outstanding_bytes;
Björn Terelius87f3a142017-12-01 19:03:43 +0000371 RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_rtt_ms
Mirko Bonadei675513b2017-11-09 11:09:25 +0100372 << " Bitrate: " << last_reported_bitrate_bps_;
stefana86f57e2017-08-26 06:33:43 -0700373 pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes;
nisse559af382017-03-21 06:41:12 -0700374}
375
376std::vector<PacketFeedback>
377SendSideCongestionController::GetTransportFeedbackVector() const {
erikvargabf5a2fc2017-06-16 05:02:05 -0700378 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700379 return transport_feedback_adapter_.GetTransportFeedbackVector();
380}
381
382void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {
nisse559af382017-03-21 06:41:12 -0700383 uint32_t bitrate_bps;
384 uint8_t fraction_loss;
385 int64_t rtt;
386 bool estimate_changed = bitrate_controller_->GetNetworkParameters(
387 &bitrate_bps, &fraction_loss, &rtt);
388 if (estimate_changed) {
389 pacer_->SetEstimatedBitrate(bitrate_bps);
390 probe_controller_->SetEstimatedBitrate(bitrate_bps);
391 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
392 }
393
philipela4205512017-09-26 05:36:58 -0700394 if (!pacer_pushback_experiment_) {
395 bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps;
396 } else {
397 if (IsNetworkDown()) {
398 bitrate_bps = 0;
399 } else {
400 int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs();
401
402 if (queue_length_ms == 0) {
403 encoding_rate_ = 1.0;
404 } else if (queue_length_ms > 50) {
405 float encoding_rate = 1.0 - queue_length_ms / 1000.0;
406 encoding_rate_ = std::min(encoding_rate_, encoding_rate);
407 encoding_rate_ = std::max(encoding_rate_, 0.0f);
408 }
409
410 bitrate_bps *= encoding_rate_;
411 bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps;
412 }
413 }
nisse559af382017-03-21 06:41:12 -0700414
415 if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {
416 int64_t probing_interval_ms;
417 {
418 rtc::CritScope cs(&bwe_lock_);
terelius67370452017-04-19 09:15:04 -0700419 probing_interval_ms = delay_based_bwe_->GetExpectedBwePeriodMs();
nisse559af382017-03-21 06:41:12 -0700420 }
nisse23425f92017-04-03 04:54:25 -0700421 {
422 rtc::CritScope cs(&observer_lock_);
423 if (observer_) {
424 observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt,
425 probing_interval_ms);
426 }
427 }
nisse559af382017-03-21 06:41:12 -0700428 }
429}
430
431bool SendSideCongestionController::HasNetworkParametersToReportChanged(
432 uint32_t bitrate_bps,
433 uint8_t fraction_loss,
434 int64_t rtt) {
435 rtc::CritScope cs(&network_state_lock_);
436 bool changed =
437 last_reported_bitrate_bps_ != bitrate_bps ||
438 (bitrate_bps > 0 && (last_reported_fraction_loss_ != fraction_loss ||
439 last_reported_rtt_ != rtt));
440 if (changed && (last_reported_bitrate_bps_ == 0 || bitrate_bps == 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100441 RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: " << bitrate_bps
442 << " bps.";
nisse559af382017-03-21 06:41:12 -0700443 }
444 last_reported_bitrate_bps_ = bitrate_bps;
445 last_reported_fraction_loss_ = fraction_loss;
446 last_reported_rtt_ = rtt;
447 return changed;
448}
449
450bool SendSideCongestionController::IsSendQueueFull() const {
451 return pacer_->ExpectedQueueTimeMs() > PacedSender::kMaxQueueLengthMs;
452}
453
454bool SendSideCongestionController::IsNetworkDown() const {
455 rtc::CritScope cs(&network_state_lock_);
456 return network_state_ == kNetworkDown;
457}
458
459} // namespace webrtc