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