blob: 608996b8ac6d814b5ddc7494774dd5c009859cc8 [file] [log] [blame]
Erik Språng71215642019-01-21 16:30:55 +01001/*
2 * Copyright (c) 2019 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 "rtc_base/experiments/rate_control_settings.h"
12
13#include <inttypes.h>
14#include <stdio.h>
15
16#include <string>
17
18#include "api/transport/field_trial_based_config.h"
19#include "rtc_base/logging.h"
20#include "rtc_base/numerics/safe_conversions.h"
21
22namespace webrtc {
23
24namespace {
25
Evan Shrubsolebd167cf2019-04-10 12:09:56 +000026const char* kCongestionWindowFieldTrialName = "WebRTC-CwndExperiment";
Erik Språng71215642019-01-21 16:30:55 +010027const int kDefaultAcceptedQueueMs = 250;
28
Evan Shrubsolebd167cf2019-04-10 12:09:56 +000029const char* kCongestionWindowPushbackFieldTrialName =
30 "WebRTC-CongestionWindowPushback";
Erik Språng71215642019-01-21 16:30:55 +010031const int kDefaultMinPushbackTargetBitrateBps = 30000;
32
Erik Språng4b4266f2019-01-23 12:48:13 +010033const char kVp8TrustedRateControllerFieldTrialName[] =
34 "WebRTC-LibvpxVp8TrustedRateController";
35const char kVp9TrustedRateControllerFieldTrialName[] =
36 "WebRTC-LibvpxVp9TrustedRateController";
37
Erik Språng2c58ba12019-01-23 16:53:18 +010038const char* kVideoHysteresisFieldTrialname =
39 "WebRTC-SimulcastUpswitchHysteresisPercent";
40const double kDefaultVideoHysteresisFactor = 1.0;
41const char* kScreenshareHysteresisFieldTrialname =
42 "WebRTC-SimulcastScreenshareUpswitchHysteresisPercent";
43// Default to 35% hysteresis for simulcast screenshare.
44const double kDefaultScreenshareHysteresisFactor = 1.35;
45
Evan Shrubsolebd167cf2019-04-10 12:09:56 +000046absl::optional<int> MaybeReadCwndExperimentParameter(
47 const WebRtcKeyValueConfig* const key_value_config) {
48 int64_t accepted_queue_ms;
49 std::string experiment_string =
50 key_value_config->Lookup(kCongestionWindowFieldTrialName);
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 rtc::checked_cast<int>(accepted_queue_ms);
57 } else if (experiment_string.find("Enabled") == 0) {
58 return kDefaultAcceptedQueueMs;
59 }
60 return absl::nullopt;
61}
62
63absl::optional<int> MaybeReadCongestionWindowPushbackExperimentParameter(
64 const WebRtcKeyValueConfig* const key_value_config) {
65 uint32_t min_pushback_target_bitrate_bps;
66 std::string experiment_string =
67 key_value_config->Lookup(kCongestionWindowPushbackFieldTrialName);
68 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%" PRIu32,
69 &min_pushback_target_bitrate_bps);
70 if (parsed_values == 1) {
71 RTC_CHECK_GE(min_pushback_target_bitrate_bps, 0)
72 << "Min pushback target bitrate must be greater than or equal to 0.";
73 return rtc::checked_cast<int>(min_pushback_target_bitrate_bps);
74 } else if (experiment_string.find("Enabled") == 0) {
75 return kDefaultMinPushbackTargetBitrateBps;
76 }
77 return absl::nullopt;
78}
79
Erik Språng4b4266f2019-01-23 12:48:13 +010080bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config,
81 absl::string_view key) {
82 return key_value_config->Lookup(key).find("Enabled") == 0;
83}
84
Erik Språng2c58ba12019-01-23 16:53:18 +010085double ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config,
86 absl::string_view key,
87 double default_value) {
88 std::string group_name = key_value_config->Lookup(key);
89 int percent = 0;
90 if (!group_name.empty() && sscanf(group_name.c_str(), "%d", &percent) == 1 &&
91 percent >= 0) {
92 return 1.0 + (percent / 100.0);
93 }
94 return default_value;
95}
96
Erik Språng71215642019-01-21 16:30:55 +010097} // namespace
98
99RateControlSettings::RateControlSettings(
100 const WebRtcKeyValueConfig* const key_value_config)
Evan Shrubsolebd167cf2019-04-10 12:09:56 +0000101 : congestion_window_("cwnd",
102 MaybeReadCwndExperimentParameter(key_value_config)),
103 congestion_window_pushback_(
104 "cwnd_pushback",
105 MaybeReadCongestionWindowPushbackExperimentParameter(
106 key_value_config)),
Erik Språngcd76eab2019-01-21 18:06:46 +0100107 pacing_factor_("pacing_factor"),
Erik Språng4b4266f2019-01-23 12:48:13 +0100108 alr_probing_("alr_probing", false),
109 trust_vp8_(
110 "trust_vp8",
111 IsEnabled(key_value_config, kVp8TrustedRateControllerFieldTrialName)),
Erik Språng2c58ba12019-01-23 16:53:18 +0100112 trust_vp9_(
113 "trust_vp9",
114 IsEnabled(key_value_config, kVp9TrustedRateControllerFieldTrialName)),
115 video_hysteresis_("video_hysteresis",
116 ParseHysteresisFactor(key_value_config,
117 kVideoHysteresisFieldTrialname,
118 kDefaultVideoHysteresisFactor)),
119 screenshare_hysteresis_(
120 "screenshare_hysteresis",
121 ParseHysteresisFactor(key_value_config,
122 kScreenshareHysteresisFieldTrialname,
Erik Språng5118bbc2019-01-29 18:28:06 +0100123 kDefaultScreenshareHysteresisFactor)),
Erik Språng7ca375c2019-02-06 16:20:17 +0100124 probe_max_allocation_("probe_max_allocation", true),
Erik Språng7f24fb92019-02-13 10:49:37 +0100125 bitrate_adjuster_("bitrate_adjuster", false),
126 vp8_s0_boost_("vp8_s0_boost", true) {
Evan Shrubsolebd167cf2019-04-10 12:09:56 +0000127 ParseFieldTrial({&congestion_window_, &congestion_window_pushback_,
128 &pacing_factor_, &alr_probing_, &trust_vp8_, &trust_vp9_,
Erik Språng7f24fb92019-02-13 10:49:37 +0100129 &video_hysteresis_, &screenshare_hysteresis_,
130 &probe_max_allocation_, &bitrate_adjuster_, &vp8_s0_boost_},
131 key_value_config->Lookup("WebRTC-VideoRateControl"));
Erik Språng71215642019-01-21 16:30:55 +0100132}
133
134RateControlSettings::~RateControlSettings() = default;
135RateControlSettings::RateControlSettings(RateControlSettings&&) = default;
136
137RateControlSettings RateControlSettings::ParseFromFieldTrials() {
138 FieldTrialBasedConfig field_trial_config;
139 return RateControlSettings(&field_trial_config);
140}
141
142RateControlSettings RateControlSettings::ParseFromKeyValueConfig(
143 const WebRtcKeyValueConfig* const key_value_config) {
144 FieldTrialBasedConfig field_trial_config;
145 return RateControlSettings(key_value_config ? key_value_config
146 : &field_trial_config);
147}
148
149bool RateControlSettings::UseCongestionWindow() const {
Jonas Olssoncb968092019-03-12 13:57:15 +0100150 return static_cast<bool>(congestion_window_);
Erik Språng71215642019-01-21 16:30:55 +0100151}
152
153int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
154 return congestion_window_.GetOptional().value_or(kDefaultAcceptedQueueMs);
155}
156
157bool RateControlSettings::UseCongestionWindowPushback() const {
158 return congestion_window_ && congestion_window_pushback_;
159}
160
161uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
162 const {
163 return congestion_window_pushback_.GetOptional().value_or(
164 kDefaultMinPushbackTargetBitrateBps);
165}
166
Erik Språngcd76eab2019-01-21 18:06:46 +0100167absl::optional<double> RateControlSettings::GetPacingFactor() const {
168 return pacing_factor_.GetOptional();
169}
170
171bool RateControlSettings::UseAlrProbing() const {
172 return alr_probing_.Get();
173}
174
Erik Språng4b4266f2019-01-23 12:48:13 +0100175bool RateControlSettings::LibvpxVp8TrustedRateController() const {
176 return trust_vp8_.Get();
177}
178
Erik Språng7f24fb92019-02-13 10:49:37 +0100179bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
180 return vp8_s0_boost_.Get();
181}
182
Erik Språng4b4266f2019-01-23 12:48:13 +0100183bool RateControlSettings::LibvpxVp9TrustedRateController() const {
184 return trust_vp9_.Get();
185}
186
Rasmus Brandtc402dbe2019-02-04 11:09:46 +0100187double RateControlSettings::GetSimulcastHysteresisFactor(
188 VideoCodecMode mode) const {
189 if (mode == VideoCodecMode::kScreensharing) {
190 return GetSimulcastScreenshareHysteresisFactor();
191 }
192 return GetSimulcastVideoHysteresisFactor();
193}
194
195double RateControlSettings::GetSimulcastHysteresisFactor(
196 VideoEncoderConfig::ContentType content_type) const {
197 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
198 return GetSimulcastScreenshareHysteresisFactor();
199 }
200 return GetSimulcastVideoHysteresisFactor();
201}
202
Erik Språng2c58ba12019-01-23 16:53:18 +0100203double RateControlSettings::GetSimulcastVideoHysteresisFactor() const {
204 return video_hysteresis_.Get();
205}
206
207double RateControlSettings::GetSimulcastScreenshareHysteresisFactor() const {
208 return screenshare_hysteresis_.Get();
209}
210
Erik Språng5118bbc2019-01-29 18:28:06 +0100211bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const {
212 return probe_max_allocation_.Get();
213}
214
Erik Språng7ca375c2019-02-06 16:20:17 +0100215bool RateControlSettings::UseEncoderBitrateAdjuster() const {
216 return bitrate_adjuster_.Get();
217}
218
Erik Språng71215642019-01-21 16:30:55 +0100219} // namespace webrtc