blob: cb3e610e38feac70fdaaf0ad8fddc8594c788078 [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"
Ilya Nikolaevskiy2ffe3e82018-01-17 19:57:24 +000031#include "system_wrappers/include/runtime_enabled_features.h"
nisse559af382017-03-21 06:41:12 -070032
33namespace webrtc {
34namespace {
35
stefan9e117c5e12017-08-16 08:16:25 -070036const char kCwndExperiment[] = "WebRTC-CwndExperiment";
philipela4205512017-09-26 05:36:58 -070037const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment";
stefan74418272017-08-17 02:13:54 -070038const int64_t kDefaultAcceptedQueueMs = 250;
stefan9e117c5e12017-08-16 08:16:25 -070039
40bool CwndExperimentEnabled() {
41 std::string experiment_string =
42 webrtc::field_trial::FindFullName(kCwndExperiment);
43 // The experiment is enabled iff the field trial string begins with "Enabled".
44 return experiment_string.find("Enabled") == 0;
45}
46
stefan74418272017-08-17 02:13:54 -070047bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) {
48 RTC_DCHECK(accepted_queue_ms);
49 std::string experiment_string =
50 webrtc::field_trial::FindFullName(kCwndExperiment);
51 int parsed_values =
52 sscanf(experiment_string.c_str(), "Enabled-%" PRId64, accepted_queue_ms);
53 if (parsed_values == 1) {
54 RTC_CHECK_GE(*accepted_queue_ms, 0)
55 << "Accepted must be greater than or equal to 0.";
56 return true;
57 }
58 return false;
59}
60
nisse559af382017-03-21 06:41:12 -070061static const int64_t kRetransmitWindowSizeMs = 500;
62
63// Makes sure that the bitrate and the min, max values are in valid range.
64static void ClampBitrates(int* bitrate_bps,
65 int* min_bitrate_bps,
66 int* max_bitrate_bps) {
67 // TODO(holmer): We should make sure the default bitrates are set to 10 kbps,
68 // and that we don't try to set the min bitrate to 0 from any applications.
69 // The congestion controller should allow a min bitrate of 0.
70 if (*min_bitrate_bps < congestion_controller::GetMinBitrateBps())
71 *min_bitrate_bps = congestion_controller::GetMinBitrateBps();
72 if (*max_bitrate_bps > 0)
73 *max_bitrate_bps = std::max(*min_bitrate_bps, *max_bitrate_bps);
74 if (*bitrate_bps > 0)
75 *bitrate_bps = std::max(*min_bitrate_bps, *bitrate_bps);
76}
77
tschumim3fae6282017-06-11 23:57:17 -070078std::vector<webrtc::PacketFeedback> ReceivedPacketFeedbackVector(
79 const std::vector<webrtc::PacketFeedback>& input) {
80 std::vector<PacketFeedback> received_packet_feedback_vector;
81 auto is_received = [](const webrtc::PacketFeedback& packet_feedback) {
82 return packet_feedback.arrival_time_ms !=
83 webrtc::PacketFeedback::kNotReceived;
84 };
85 std::copy_if(input.begin(), input.end(),
86 std::back_inserter(received_packet_feedback_vector),
87 is_received);
88 return received_packet_feedback_vector;
89}
90
91void SortPacketFeedbackVector(
92 std::vector<webrtc::PacketFeedback>* const input) {
93 RTC_DCHECK(input);
94 std::sort(input->begin(), input->end(), PacketFeedbackComparator());
95}
96
Ilya Nikolaevskiy2ffe3e82018-01-17 19:57:24 +000097bool IsPacerPushbackExperimentEnabled() {
98 return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment) || (
99 !webrtc::field_trial::IsDisabled(kPacerPushbackExperiment) &&
100 webrtc::runtime_enabled_features::IsFeatureEnabled(
101 webrtc::runtime_enabled_features::kDualStreamModeFeatureName));
102}
103
nisse559af382017-03-21 06:41:12 -0700104} // namespace
105
106SendSideCongestionController::SendSideCongestionController(
107 const Clock* clock,
108 Observer* observer,
109 RtcEventLog* event_log,
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200110 PacedSender* pacer)
nisse559af382017-03-21 06:41:12 -0700111 : clock_(clock),
112 observer_(observer),
113 event_log_(event_log),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200114 pacer_(pacer),
nisse559af382017-03-21 06:41:12 -0700115 bitrate_controller_(
116 BitrateController::CreateBitrateController(clock_, event_log)),
tschumim3fae6282017-06-11 23:57:17 -0700117 acknowledged_bitrate_estimator_(
tereliuse75d96b2017-06-30 08:11:44 -0700118 rtc::MakeUnique<AcknowledgedBitrateEstimator>()),
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200119 probe_controller_(new ProbeController(pacer_, clock_)),
nisse559af382017-03-21 06:41:12 -0700120 retransmission_rate_limiter_(
121 new RateLimiter(clock, kRetransmitWindowSizeMs)),
122 transport_feedback_adapter_(clock_),
123 last_reported_bitrate_bps_(0),
124 last_reported_fraction_loss_(0),
125 last_reported_rtt_(0),
126 network_state_(kNetworkUp),
stefan9e117c5e12017-08-16 08:16:25 -0700127 pause_pacer_(false),
128 pacer_paused_(false),
nisse559af382017-03-21 06:41:12 -0700129 min_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
tschumim9d117642017-07-17 01:41:41 -0700130 delay_based_bwe_(new DelayBasedBwe(event_log_, clock_)),
stefan9e117c5e12017-08-16 08:16:25 -0700131 in_cwnd_experiment_(CwndExperimentEnabled()),
stefan74418272017-08-17 02:13:54 -0700132 accepted_queue_ms_(kDefaultAcceptedQueueMs),
philipela4205512017-09-26 05:36:58 -0700133 was_in_alr_(false),
134 pacer_pushback_experiment_(
Ilya Nikolaevskiy2ffe3e82018-01-17 19:57:24 +0000135 IsPacerPushbackExperimentEnabled()) {
nisse559af382017-03-21 06:41:12 -0700136 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
stefan74418272017-08-17 02:13:54 -0700137 if (in_cwnd_experiment_ &&
138 !ReadCwndExperimentParameter(&accepted_queue_ms_)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100139 RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
140 "from field trial string. Experiment disabled.";
stefan74418272017-08-17 02:13:54 -0700141 in_cwnd_experiment_ = false;
142 }
nisse559af382017-03-21 06:41:12 -0700143}
144
145SendSideCongestionController::~SendSideCongestionController() {}
146
elad.alond12a8e12017-03-23 11:04:48 -0700147void SendSideCongestionController::RegisterPacketFeedbackObserver(
148 PacketFeedbackObserver* observer) {
149 transport_feedback_adapter_.RegisterPacketFeedbackObserver(observer);
150}
151
152void SendSideCongestionController::DeRegisterPacketFeedbackObserver(
153 PacketFeedbackObserver* observer) {
154 transport_feedback_adapter_.DeRegisterPacketFeedbackObserver(observer);
155}
156
nisse23425f92017-04-03 04:54:25 -0700157void SendSideCongestionController::RegisterNetworkObserver(Observer* observer) {
158 rtc::CritScope cs(&observer_lock_);
159 RTC_DCHECK(observer_ == nullptr);
160 observer_ = observer;
161}
162
163void SendSideCongestionController::DeRegisterNetworkObserver(
164 Observer* observer) {
165 rtc::CritScope cs(&observer_lock_);
166 RTC_DCHECK_EQ(observer_, observer);
167 observer_ = nullptr;
168}
169
nisse559af382017-03-21 06:41:12 -0700170void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps,
171 int start_bitrate_bps,
172 int max_bitrate_bps) {
173 ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
174 bitrate_controller_->SetBitrates(start_bitrate_bps, min_bitrate_bps,
175 max_bitrate_bps);
176
177 probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
178 max_bitrate_bps);
179
180 {
181 rtc::CritScope cs(&bwe_lock_);
182 if (start_bitrate_bps > 0)
183 delay_based_bwe_->SetStartBitrate(start_bitrate_bps);
184 min_bitrate_bps_ = min_bitrate_bps;
185 delay_based_bwe_->SetMinBitrate(min_bitrate_bps_);
186 }
187 MaybeTriggerOnNetworkChanged();
188}
189
190// TODO(holmer): Split this up and use SetBweBitrates in combination with
191// OnNetworkRouteChanged.
192void SendSideCongestionController::OnNetworkRouteChanged(
193 const rtc::NetworkRoute& network_route,
194 int bitrate_bps,
195 int min_bitrate_bps,
196 int max_bitrate_bps) {
197 ClampBitrates(&bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
198 // TODO(honghaiz): Recreate this object once the bitrate controller is
199 // no longer exposed outside SendSideCongestionController.
200 bitrate_controller_->ResetBitrates(bitrate_bps, min_bitrate_bps,
201 max_bitrate_bps);
202
203 transport_feedback_adapter_.SetNetworkIds(network_route.local_network_id,
204 network_route.remote_network_id);
205 {
206 rtc::CritScope cs(&bwe_lock_);
207 min_bitrate_bps_ = min_bitrate_bps;
208 delay_based_bwe_.reset(new DelayBasedBwe(event_log_, clock_));
tschumim3fae6282017-06-11 23:57:17 -0700209 acknowledged_bitrate_estimator_.reset(new AcknowledgedBitrateEstimator());
nisse559af382017-03-21 06:41:12 -0700210 delay_based_bwe_->SetStartBitrate(bitrate_bps);
211 delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
212 }
213
214 probe_controller_->Reset();
215 probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps, max_bitrate_bps);
216
217 MaybeTriggerOnNetworkChanged();
218}
219
220BitrateController* SendSideCongestionController::GetBitrateController() const {
221 return bitrate_controller_.get();
222}
223
srtea6092a92017-11-22 19:37:43 +0100224bool SendSideCongestionController::AvailableBandwidth(
225 uint32_t* bandwidth) const {
226 return bitrate_controller_->AvailableBandwidth(bandwidth);
227}
228
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100229RtcpBandwidthObserver* SendSideCongestionController::GetBandwidthObserver()
230 const {
231 return bitrate_controller_.get();
232}
233
nisse559af382017-03-21 06:41:12 -0700234RateLimiter* SendSideCongestionController::GetRetransmissionRateLimiter() {
235 return retransmission_rate_limiter_.get();
236}
237
238void SendSideCongestionController::EnablePeriodicAlrProbing(bool enable) {
239 probe_controller_->EnablePeriodicAlrProbing(enable);
240}
241
nisse559af382017-03-21 06:41:12 -0700242int64_t SendSideCongestionController::GetPacerQueuingDelayMs() const {
243 return IsNetworkDown() ? 0 : pacer_->QueueInMs();
244}
245
asaperssonfc5e81c2017-04-19 23:28:53 -0700246int64_t SendSideCongestionController::GetFirstPacketTimeMs() const {
247 return pacer_->FirstSentPacketTimeMs();
248}
249
nisse76e62b02017-05-31 02:24:52 -0700250TransportFeedbackObserver*
251SendSideCongestionController::GetTransportFeedbackObserver() {
252 return this;
253}
254
nisse559af382017-03-21 06:41:12 -0700255void SendSideCongestionController::SignalNetworkState(NetworkState state) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100256 RTC_LOG(LS_INFO) << "SignalNetworkState "
257 << (state == kNetworkUp ? "Up" : "Down");
nisse559af382017-03-21 06:41:12 -0700258 {
259 rtc::CritScope cs(&network_state_lock_);
stefan9e117c5e12017-08-16 08:16:25 -0700260 pause_pacer_ = state == kNetworkDown;
nisse559af382017-03-21 06:41:12 -0700261 network_state_ = state;
262 }
263 probe_controller_->OnNetworkStateChanged(state);
264 MaybeTriggerOnNetworkChanged();
265}
266
267void SendSideCongestionController::SetTransportOverhead(
268 size_t transport_overhead_bytes_per_packet) {
269 transport_feedback_adapter_.SetTransportOverhead(
Oleh Prypina40f8242017-12-21 13:32:23 +0100270 rtc::dchecked_cast<int>(transport_overhead_bytes_per_packet));
nisse559af382017-03-21 06:41:12 -0700271}
272
273void SendSideCongestionController::OnSentPacket(
274 const rtc::SentPacket& sent_packet) {
275 // We're not interested in packets without an id, which may be stun packets,
276 // etc, sent on the same transport.
277 if (sent_packet.packet_id == -1)
278 return;
279 transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id,
280 sent_packet.send_time_ms);
stefana86f57e2017-08-26 06:33:43 -0700281 if (in_cwnd_experiment_)
282 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
nisse559af382017-03-21 06:41:12 -0700283}
284
285void SendSideCongestionController::OnRttUpdate(int64_t avg_rtt_ms,
286 int64_t max_rtt_ms) {
287 rtc::CritScope cs(&bwe_lock_);
288 delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
289}
290
291int64_t SendSideCongestionController::TimeUntilNextProcess() {
292 return bitrate_controller_->TimeUntilNextProcess();
293}
294
295void SendSideCongestionController::Process() {
stefan9e117c5e12017-08-16 08:16:25 -0700296 bool pause_pacer;
297 // TODO(holmer): Once this class is running on a task queue we should
298 // replace this with a task instead.
299 {
300 rtc::CritScope lock(&network_state_lock_);
301 pause_pacer = pause_pacer_;
302 }
303 if (pause_pacer && !pacer_paused_) {
304 pacer_->Pause();
305 pacer_paused_ = true;
306 } else if (!pause_pacer && pacer_paused_) {
307 pacer_->Resume();
308 pacer_paused_ = false;
309 }
nisse559af382017-03-21 06:41:12 -0700310 bitrate_controller_->Process();
311 probe_controller_->Process();
312 MaybeTriggerOnNetworkChanged();
313}
314
315void SendSideCongestionController::AddPacket(
elad.alond12a8e12017-03-23 11:04:48 -0700316 uint32_t ssrc,
nisse559af382017-03-21 06:41:12 -0700317 uint16_t sequence_number,
318 size_t length,
319 const PacedPacketInfo& pacing_info) {
elad.alond12a8e12017-03-23 11:04:48 -0700320 transport_feedback_adapter_.AddPacket(ssrc, sequence_number, length,
321 pacing_info);
nisse559af382017-03-21 06:41:12 -0700322}
323
324void SendSideCongestionController::OnTransportFeedback(
325 const rtcp::TransportFeedback& feedback) {
erikvargabf5a2fc2017-06-16 05:02:05 -0700326 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700327 transport_feedback_adapter_.OnTransportFeedback(feedback);
Björn Terelius87f3a142017-12-01 19:03:43 +0000328 std::vector<PacketFeedback> feedback_vector = ReceivedPacketFeedbackVector(
329 transport_feedback_adapter_.GetTransportFeedbackVector());
tschumim3fae6282017-06-11 23:57:17 -0700330 SortPacketFeedbackVector(&feedback_vector);
tschumim9d117642017-07-17 01:41:41 -0700331
332 bool currently_in_alr =
333 pacer_->GetApplicationLimitedRegionStartTime().has_value();
terelius3376c842017-07-31 04:23:25 -0700334 if (was_in_alr_ && !currently_in_alr) {
335 int64_t now_ms = rtc::TimeMillis();
336 acknowledged_bitrate_estimator_->SetAlrEndedTimeMs(now_ms);
337 probe_controller_->SetAlrEndedTimeMs(now_ms);
tschumim9d117642017-07-17 01:41:41 -0700338 }
339 was_in_alr_ = currently_in_alr;
340
tschumim3fae6282017-06-11 23:57:17 -0700341 acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(
tereliuse75d96b2017-06-30 08:11:44 -0700342 feedback_vector);
nisse559af382017-03-21 06:41:12 -0700343 DelayBasedBwe::Result result;
344 {
345 rtc::CritScope cs(&bwe_lock_);
tschumim3fae6282017-06-11 23:57:17 -0700346 result = delay_based_bwe_->IncomingPacketFeedbackVector(
347 feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps());
nisse559af382017-03-21 06:41:12 -0700348 }
terelius3376c842017-07-31 04:23:25 -0700349 if (result.updated) {
nisse559af382017-03-21 06:41:12 -0700350 bitrate_controller_->OnDelayBasedBweResult(result);
terelius3376c842017-07-31 04:23:25 -0700351 // Update the estimate in the ProbeController, in case we want to probe.
352 MaybeTriggerOnNetworkChanged();
353 }
354 if (result.recovered_from_overuse)
355 probe_controller_->RequestProbe();
stefana86f57e2017-08-26 06:33:43 -0700356 if (in_cwnd_experiment_)
357 LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
stefan9e117c5e12017-08-16 08:16:25 -0700358}
359
360void SendSideCongestionController::LimitOutstandingBytes(
361 size_t num_outstanding_bytes) {
stefana86f57e2017-08-26 06:33:43 -0700362 RTC_DCHECK(in_cwnd_experiment_);
363 rtc::CritScope lock(&network_state_lock_);
Björn Terelius87f3a142017-12-01 19:03:43 +0000364 rtc::Optional<int64_t> min_rtt_ms =
365 transport_feedback_adapter_.GetMinFeedbackLoopRtt();
stefana86f57e2017-08-26 06:33:43 -0700366 // No valid RTT. Could be because send-side BWE isn't used, in which case
367 // we don't try to limit the outstanding packets.
Björn Terelius87f3a142017-12-01 19:03:43 +0000368 if (!min_rtt_ms)
stefan9e117c5e12017-08-16 08:16:25 -0700369 return;
stefana86f57e2017-08-26 06:33:43 -0700370 const size_t kMinCwndBytes = 2 * 1500;
371 size_t max_outstanding_bytes =
Björn Terelius87f3a142017-12-01 19:03:43 +0000372 std::max<size_t>((*min_rtt_ms + accepted_queue_ms_) *
stefana86f57e2017-08-26 06:33:43 -0700373 last_reported_bitrate_bps_ / 1000 / 8,
374 kMinCwndBytes);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100375 RTC_LOG(LS_INFO) << clock_->TimeInMilliseconds()
376 << " Outstanding bytes: " << num_outstanding_bytes
377 << " pacer queue: " << pacer_->QueueInMs()
378 << " max outstanding: " << max_outstanding_bytes;
Björn Terelius87f3a142017-12-01 19:03:43 +0000379 RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_rtt_ms
Mirko Bonadei675513b2017-11-09 11:09:25 +0100380 << " Bitrate: " << last_reported_bitrate_bps_;
stefana86f57e2017-08-26 06:33:43 -0700381 pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes;
nisse559af382017-03-21 06:41:12 -0700382}
383
384std::vector<PacketFeedback>
385SendSideCongestionController::GetTransportFeedbackVector() const {
erikvargabf5a2fc2017-06-16 05:02:05 -0700386 RTC_DCHECK_RUNS_SERIALIZED(&worker_race_);
nisse559af382017-03-21 06:41:12 -0700387 return transport_feedback_adapter_.GetTransportFeedbackVector();
388}
389
390void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {
nisse559af382017-03-21 06:41:12 -0700391 uint32_t bitrate_bps;
392 uint8_t fraction_loss;
393 int64_t rtt;
394 bool estimate_changed = bitrate_controller_->GetNetworkParameters(
395 &bitrate_bps, &fraction_loss, &rtt);
396 if (estimate_changed) {
397 pacer_->SetEstimatedBitrate(bitrate_bps);
398 probe_controller_->SetEstimatedBitrate(bitrate_bps);
399 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
400 }
401
philipela4205512017-09-26 05:36:58 -0700402 if (!pacer_pushback_experiment_) {
403 bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps;
404 } else {
405 if (IsNetworkDown()) {
406 bitrate_bps = 0;
407 } else {
408 int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs();
409
410 if (queue_length_ms == 0) {
411 encoding_rate_ = 1.0;
412 } else if (queue_length_ms > 50) {
413 float encoding_rate = 1.0 - queue_length_ms / 1000.0;
414 encoding_rate_ = std::min(encoding_rate_, encoding_rate);
415 encoding_rate_ = std::max(encoding_rate_, 0.0f);
416 }
417
418 bitrate_bps *= encoding_rate_;
419 bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps;
420 }
421 }
nisse559af382017-03-21 06:41:12 -0700422
423 if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {
424 int64_t probing_interval_ms;
425 {
426 rtc::CritScope cs(&bwe_lock_);
terelius67370452017-04-19 09:15:04 -0700427 probing_interval_ms = delay_based_bwe_->GetExpectedBwePeriodMs();
nisse559af382017-03-21 06:41:12 -0700428 }
nisse23425f92017-04-03 04:54:25 -0700429 {
430 rtc::CritScope cs(&observer_lock_);
431 if (observer_) {
432 observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt,
433 probing_interval_ms);
434 }
435 }
nisse559af382017-03-21 06:41:12 -0700436 }
437}
438
439bool SendSideCongestionController::HasNetworkParametersToReportChanged(
440 uint32_t bitrate_bps,
441 uint8_t fraction_loss,
442 int64_t rtt) {
443 rtc::CritScope cs(&network_state_lock_);
444 bool changed =
445 last_reported_bitrate_bps_ != bitrate_bps ||
446 (bitrate_bps > 0 && (last_reported_fraction_loss_ != fraction_loss ||
447 last_reported_rtt_ != rtt));
448 if (changed && (last_reported_bitrate_bps_ == 0 || bitrate_bps == 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100449 RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: " << bitrate_bps
450 << " bps.";
nisse559af382017-03-21 06:41:12 -0700451 }
452 last_reported_bitrate_bps_ = bitrate_bps;
453 last_reported_fraction_loss_ = fraction_loss;
454 last_reported_rtt_ = rtt;
455 return changed;
456}
457
458bool SendSideCongestionController::IsSendQueueFull() const {
459 return pacer_->ExpectedQueueTimeMs() > PacedSender::kMaxQueueLengthMs;
460}
461
462bool SendSideCongestionController::IsNetworkDown() const {
463 rtc::CritScope cs(&network_state_lock_);
464 return network_state_ == kNetworkDown;
465}
466
467} // namespace webrtc