blob: b5a920d15bebd9f894cfccedb1deac2a8d25f6be [file] [log] [blame]
Sebastian Jansson74c066c2018-10-15 14:31:24 +02001/*
2 * Copyright (c) 2018 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/rtp/control_handler.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <algorithm>
14#include <vector>
15
16#include "api/units/data_rate.h"
Sebastian Jansson74c066c2018-10-15 14:31:24 +020017#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "rtc_base/numerics/safe_conversions.h"
Sebastian Jansson74c066c2018-10-15 14:31:24 +020019#include "rtc_base/numerics/safe_minmax.h"
20#include "system_wrappers/include/field_trial.h"
21
22namespace webrtc {
23namespace {
24
25// When PacerPushbackExperiment is enabled, build-up in the pacer due to
26// the congestion window and/or data spikes reduces encoder allocations.
Sebastian Jansson74c066c2018-10-15 14:31:24 +020027bool IsPacerPushbackExperimentEnabled() {
Christoffer Rodbrob357e542018-11-23 11:19:32 +010028 return field_trial::IsEnabled("WebRTC-PacerPushbackExperiment");
Sebastian Jansson74c066c2018-10-15 14:31:24 +020029}
Christoffer Rodbrob357e542018-11-23 11:19:32 +010030
31// By default, pacer emergency stops encoder when buffer reaches a high level.
32bool IsPacerEmergencyStopDisabled() {
33 return field_trial::IsEnabled("WebRTC-DisablePacerEmergencyStop");
34}
35
Sebastian Jansson74c066c2018-10-15 14:31:24 +020036} // namespace
37CongestionControlHandler::CongestionControlHandler(
38 NetworkChangedObserver* observer,
39 PacedSender* pacer)
40 : observer_(observer),
41 pacer_(pacer),
Christoffer Rodbrob357e542018-11-23 11:19:32 +010042 pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()),
43 disable_pacer_emergency_stop_(IsPacerEmergencyStopDisabled()) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +020044 sequenced_checker_.Detach();
45}
46
47CongestionControlHandler::~CongestionControlHandler() {}
48
49void CongestionControlHandler::PostUpdates(NetworkControlUpdate update) {
50 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
51 if (update.congestion_window) {
52 if (update.congestion_window->IsFinite())
53 pacer_->SetCongestionWindow(update.congestion_window->bytes());
54 else
55 pacer_->SetCongestionWindow(PacedSender::kNoCongestionWindow);
56 }
57 if (update.pacer_config) {
58 pacer_->SetPacingRates(update.pacer_config->data_rate().bps(),
59 update.pacer_config->pad_rate().bps());
60 }
61 for (const auto& probe : update.probe_cluster_configs) {
62 int64_t bitrate_bps = probe.target_data_rate.bps();
63 pacer_->CreateProbeCluster(bitrate_bps);
64 }
65 if (update.target_rate) {
66 current_target_rate_msg_ = *update.target_rate;
67 OnNetworkInvalidation();
68 }
69}
70
71void CongestionControlHandler::OnNetworkAvailability(NetworkAvailability msg) {
72 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
73 if (network_available_ != msg.network_available) {
74 network_available_ = msg.network_available;
75 pacer_->UpdateOutstandingData(0);
76 SetPacerState(!msg.network_available);
77 OnNetworkInvalidation();
78 }
79}
80
81void CongestionControlHandler::OnOutstandingData(DataSize in_flight_data) {
82 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
83 pacer_->UpdateOutstandingData(in_flight_data.bytes());
84 OnNetworkInvalidation();
85}
86
87void CongestionControlHandler::OnPacerQueueUpdate(
88 TimeDelta expected_queue_time) {
89 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
90 pacer_expected_queue_ms_ = expected_queue_time.ms();
91 OnNetworkInvalidation();
92}
93
94void CongestionControlHandler::SetPacerState(bool paused) {
95 if (paused && !pacer_paused_)
96 pacer_->Pause();
97 else if (!paused && pacer_paused_)
98 pacer_->Resume();
99 pacer_paused_ = paused;
100}
101
102void CongestionControlHandler::OnNetworkInvalidation() {
103 if (!current_target_rate_msg_.has_value())
104 return;
105
106 uint32_t target_bitrate_bps = current_target_rate_msg_->target_rate.bps();
107 int64_t rtt_ms =
108 current_target_rate_msg_->network_estimate.round_trip_time.ms();
109 float loss_rate_ratio =
110 current_target_rate_msg_->network_estimate.loss_rate_ratio;
111
112 int loss_ratio_255 = loss_rate_ratio * 255;
113 uint8_t fraction_loss =
114 rtc::dchecked_cast<uint8_t>(rtc::SafeClamp(loss_ratio_255, 0, 255));
115
116 int64_t probing_interval_ms =
117 current_target_rate_msg_->network_estimate.bwe_period.ms();
118
119 if (!network_available_) {
120 target_bitrate_bps = 0;
Christoffer Rodbrob357e542018-11-23 11:19:32 +0100121 } else if (pacer_pushback_experiment_) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +0200122 int64_t queue_length_ms = pacer_expected_queue_ms_;
123
124 if (queue_length_ms == 0) {
125 encoding_rate_ratio_ = 1.0;
126 } else if (queue_length_ms > 50) {
127 double encoding_ratio = 1.0 - queue_length_ms / 1000.0;
128 encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio);
129 encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0);
130 }
131
132 target_bitrate_bps *= encoding_rate_ratio_;
133 target_bitrate_bps = target_bitrate_bps < 50000 ? 0 : target_bitrate_bps;
Christoffer Rodbrob357e542018-11-23 11:19:32 +0100134 } else if (!disable_pacer_emergency_stop_) {
135 target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps;
Sebastian Jansson74c066c2018-10-15 14:31:24 +0200136 }
Christoffer Rodbrob357e542018-11-23 11:19:32 +0100137
Sebastian Jansson74c066c2018-10-15 14:31:24 +0200138 if (HasNetworkParametersToReportChanged(target_bitrate_bps, fraction_loss,
139 rtt_ms)) {
140 observer_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt_ms,
141 probing_interval_ms);
142 }
143}
144bool CongestionControlHandler::HasNetworkParametersToReportChanged(
145 int64_t target_bitrate_bps,
146 uint8_t fraction_loss,
147 int64_t rtt_ms) {
148 bool changed = last_reported_target_bitrate_bps_ != target_bitrate_bps ||
149 (target_bitrate_bps > 0 &&
150 (last_reported_fraction_loss_ != fraction_loss ||
151 last_reported_rtt_ms_ != rtt_ms));
152 if (changed &&
153 (last_reported_target_bitrate_bps_ == 0 || target_bitrate_bps == 0)) {
154 RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: "
155 << target_bitrate_bps << " bps.";
156 }
157 last_reported_target_bitrate_bps_ = target_bitrate_bps;
158 last_reported_fraction_loss_ = fraction_loss;
159 last_reported_rtt_ms_ = rtt_ms;
160 return changed;
161}
162
163bool CongestionControlHandler::IsSendQueueFull() const {
164 return pacer_expected_queue_ms_ > PacedSender::kMaxQueueLengthMs;
165}
166
167absl::optional<TargetTransferRate>
168CongestionControlHandler::last_transfer_rate() {
169 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
170 return current_target_rate_msg_;
171}
172
173} // namespace webrtc