blob: 8bd5714841b76d33bbbc5037bc8d5882bb4ee083 [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
Sebastian Jansson16180952018-12-12 16:49:10 +010037CongestionControlHandler::CongestionControlHandler()
38 : pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()),
Christoffer Rodbrob357e542018-11-23 11:19:32 +010039 disable_pacer_emergency_stop_(IsPacerEmergencyStopDisabled()) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +020040 sequenced_checker_.Detach();
41}
42
43CongestionControlHandler::~CongestionControlHandler() {}
44
Sebastian Jansson16180952018-12-12 16:49:10 +010045void CongestionControlHandler::SetTargetRate(
46 TargetTransferRate new_target_rate) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +020047 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Sebastian Jansson16180952018-12-12 16:49:10 +010048 last_incoming_ = new_target_rate;
Sebastian Jansson74c066c2018-10-15 14:31:24 +020049}
50
Sebastian Jansson16180952018-12-12 16:49:10 +010051void CongestionControlHandler::SetNetworkAvailability(bool network_available) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +020052 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
Sebastian Jansson16180952018-12-12 16:49:10 +010053 network_available_ = network_available;
Sebastian Jansson74c066c2018-10-15 14:31:24 +020054}
55
Sebastian Jansson16180952018-12-12 16:49:10 +010056void CongestionControlHandler::SetPacerQueue(TimeDelta expected_queue_time) {
Sebastian Jansson74c066c2018-10-15 14:31:24 +020057 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
58 pacer_expected_queue_ms_ = expected_queue_time.ms();
Sebastian Jansson74c066c2018-10-15 14:31:24 +020059}
60
Sebastian Jansson16180952018-12-12 16:49:10 +010061absl::optional<TargetTransferRate> CongestionControlHandler::GetUpdate() {
62 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
63 if (!last_incoming_.has_value())
64 return absl::nullopt;
65 TargetTransferRate new_outgoing = *last_incoming_;
66 DataRate log_target_rate = new_outgoing.target_rate;
67 bool pause_encoding = false;
Sebastian Jansson74c066c2018-10-15 14:31:24 +020068 if (!network_available_) {
Sebastian Jansson16180952018-12-12 16:49:10 +010069 pause_encoding = true;
Christoffer Rodbrob357e542018-11-23 11:19:32 +010070 } else if (pacer_pushback_experiment_) {
Sebastian Jansson16180952018-12-12 16:49:10 +010071 const int64_t queue_length_ms = pacer_expected_queue_ms_;
Sebastian Jansson74c066c2018-10-15 14:31:24 +020072 if (queue_length_ms == 0) {
73 encoding_rate_ratio_ = 1.0;
74 } else if (queue_length_ms > 50) {
75 double encoding_ratio = 1.0 - queue_length_ms / 1000.0;
76 encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio);
77 encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0);
78 }
Sebastian Jansson16180952018-12-12 16:49:10 +010079 new_outgoing.target_rate = new_outgoing.target_rate * encoding_rate_ratio_;
80 log_target_rate = new_outgoing.target_rate;
81 if (new_outgoing.target_rate < DataRate::kbps(50))
82 pause_encoding = true;
83 } else if (!disable_pacer_emergency_stop_ &&
84 pacer_expected_queue_ms_ > PacedSender::kMaxQueueLengthMs) {
85 pause_encoding = true;
Sebastian Jansson74c066c2018-10-15 14:31:24 +020086 }
Sebastian Jansson16180952018-12-12 16:49:10 +010087 if (pause_encoding)
88 new_outgoing.target_rate = DataRate::Zero();
89 if (!last_reported_ ||
90 last_reported_->target_rate != new_outgoing.target_rate ||
91 (!new_outgoing.target_rate.IsZero() &&
92 (last_reported_->network_estimate.loss_rate_ratio !=
93 new_outgoing.network_estimate.loss_rate_ratio ||
94 last_reported_->network_estimate.round_trip_time !=
95 new_outgoing.network_estimate.round_trip_time))) {
96 if (encoder_paused_in_last_report_ != pause_encoding)
97 RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: "
98 << ToString(log_target_rate) << ".";
99 encoder_paused_in_last_report_ = pause_encoding;
100 last_reported_ = new_outgoing;
101 return new_outgoing;
Sebastian Jansson74c066c2018-10-15 14:31:24 +0200102 }
Sebastian Jansson16180952018-12-12 16:49:10 +0100103 return absl::nullopt;
Sebastian Jansson74c066c2018-10-15 14:31:24 +0200104}
105
106} // namespace webrtc