1 /*
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 "absl/strings/match.h"
19 #include "api/transport/field_trial_based_config.h"
20 #include "rtc_base/logging.h"
21 #include "rtc_base/numerics/safe_conversions.h"
22
23 namespace webrtc {
24
25 namespace {
26
27 const int kDefaultAcceptedQueueMs = 250;
28
29 const int kDefaultMinPushbackTargetBitrateBps = 30000;
30
31 const char kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName[] =
32 "WebRTC-UseBaseHeavyVP8TL3RateAllocation";
33
34 const char* kVideoHysteresisFieldTrialname =
35 "WebRTC-SimulcastUpswitchHysteresisPercent";
36 const char* kScreenshareHysteresisFieldTrialname =
37 "WebRTC-SimulcastScreenshareUpswitchHysteresisPercent";
38
IsEnabled(const WebRtcKeyValueConfig * const key_value_config,absl::string_view key)39 bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config,
40 absl::string_view key) {
41 return absl::StartsWith(key_value_config->Lookup(key), "Enabled");
42 }
43
ParseHysteresisFactor(const WebRtcKeyValueConfig * const key_value_config,absl::string_view key,double * output_value)44 void ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config,
45 absl::string_view key,
46 double* output_value) {
47 std::string group_name = key_value_config->Lookup(key);
48 int percent = 0;
49 if (!group_name.empty() && sscanf(group_name.c_str(), "%d", &percent) == 1 &&
50 percent >= 0) {
51 *output_value = 1.0 + (percent / 100.0);
52 }
53 }
54
55 } // namespace
56
57 constexpr char CongestionWindowConfig::kKey[];
58
Parser()59 std::unique_ptr<StructParametersParser> CongestionWindowConfig::Parser() {
60 return StructParametersParser::Create("QueueSize", &queue_size_ms, //
61 "MinBitrate", &min_bitrate_bps,
62 "InitWin", &initial_data_window,
63 "DropFrame", &drop_frame_only);
64 }
65
66 // static
Parse(absl::string_view config)67 CongestionWindowConfig CongestionWindowConfig::Parse(absl::string_view config) {
68 CongestionWindowConfig res;
69 res.Parser()->Parse(config);
70 return res;
71 }
72
73 constexpr char VideoRateControlConfig::kKey[];
74
Parser()75 std::unique_ptr<StructParametersParser> VideoRateControlConfig::Parser() {
76 // The empty comments ensures that each pair is on a separate line.
77 return StructParametersParser::Create(
78 "pacing_factor", &pacing_factor, //
79 "alr_probing", &alr_probing, //
80 "vp8_qp_max", &vp8_qp_max, //
81 "vp8_min_pixels", &vp8_min_pixels, //
82 "trust_vp8", &trust_vp8, //
83 "trust_vp9", &trust_vp9, //
84 "video_hysteresis", &video_hysteresis, //
85 "screenshare_hysteresis", &screenshare_hysteresis, //
86 "probe_max_allocation", &probe_max_allocation, //
87 "bitrate_adjuster", &bitrate_adjuster, //
88 "adjuster_use_headroom", &adjuster_use_headroom, //
89 "vp8_s0_boost", &vp8_s0_boost, //
90 "vp8_base_heavy_tl3_alloc", &vp8_base_heavy_tl3_alloc, //
91 "vp8_dynamic_rate", &vp8_dynamic_rate, //
92 "vp9_dynamic_rate", &vp9_dynamic_rate);
93 }
94
RateControlSettings(const WebRtcKeyValueConfig * const key_value_config)95 RateControlSettings::RateControlSettings(
96 const WebRtcKeyValueConfig* const key_value_config)
97 : congestion_window_config_(CongestionWindowConfig::Parse(
98 key_value_config->Lookup(CongestionWindowConfig::kKey))) {
99 video_config_.vp8_base_heavy_tl3_alloc = IsEnabled(
100 key_value_config, kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName);
101 ParseHysteresisFactor(key_value_config, kVideoHysteresisFieldTrialname,
102 &video_config_.video_hysteresis);
103 ParseHysteresisFactor(key_value_config, kScreenshareHysteresisFieldTrialname,
104 &video_config_.screenshare_hysteresis);
105 video_config_.Parser()->Parse(
106 key_value_config->Lookup(VideoRateControlConfig::kKey));
107 }
108
109 RateControlSettings::~RateControlSettings() = default;
110 RateControlSettings::RateControlSettings(RateControlSettings&&) = default;
111
ParseFromFieldTrials()112 RateControlSettings RateControlSettings::ParseFromFieldTrials() {
113 FieldTrialBasedConfig field_trial_config;
114 return RateControlSettings(&field_trial_config);
115 }
116
ParseFromKeyValueConfig(const WebRtcKeyValueConfig * const key_value_config)117 RateControlSettings RateControlSettings::ParseFromKeyValueConfig(
118 const WebRtcKeyValueConfig* const key_value_config) {
119 FieldTrialBasedConfig field_trial_config;
120 return RateControlSettings(key_value_config ? key_value_config
121 : &field_trial_config);
122 }
123
UseCongestionWindow() const124 bool RateControlSettings::UseCongestionWindow() const {
125 return static_cast<bool>(congestion_window_config_.queue_size_ms);
126 }
127
GetCongestionWindowAdditionalTimeMs() const128 int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
129 return congestion_window_config_.queue_size_ms.value_or(
130 kDefaultAcceptedQueueMs);
131 }
132
UseCongestionWindowPushback() const133 bool RateControlSettings::UseCongestionWindowPushback() const {
134 return congestion_window_config_.queue_size_ms &&
135 congestion_window_config_.min_bitrate_bps;
136 }
137
UseCongestionWindowDropFrameOnly() const138 bool RateControlSettings::UseCongestionWindowDropFrameOnly() const {
139 return congestion_window_config_.drop_frame_only;
140 }
141
CongestionWindowMinPushbackTargetBitrateBps() const142 uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
143 const {
144 return congestion_window_config_.min_bitrate_bps.value_or(
145 kDefaultMinPushbackTargetBitrateBps);
146 }
147
148 absl::optional<DataSize>
CongestionWindowInitialDataWindow() const149 RateControlSettings::CongestionWindowInitialDataWindow() const {
150 return congestion_window_config_.initial_data_window;
151 }
152
GetPacingFactor() const153 absl::optional<double> RateControlSettings::GetPacingFactor() const {
154 return video_config_.pacing_factor;
155 }
156
UseAlrProbing() const157 bool RateControlSettings::UseAlrProbing() const {
158 return video_config_.alr_probing;
159 }
160
LibvpxVp8QpMax() const161 absl::optional<int> RateControlSettings::LibvpxVp8QpMax() const {
162 if (video_config_.vp8_qp_max &&
163 (*video_config_.vp8_qp_max < 0 || *video_config_.vp8_qp_max > 63)) {
164 RTC_LOG(LS_WARNING) << "Unsupported vp8_qp_max_ value, ignored.";
165 return absl::nullopt;
166 }
167 return video_config_.vp8_qp_max;
168 }
169
LibvpxVp8MinPixels() const170 absl::optional<int> RateControlSettings::LibvpxVp8MinPixels() const {
171 if (video_config_.vp8_min_pixels && *video_config_.vp8_min_pixels < 1) {
172 return absl::nullopt;
173 }
174 return video_config_.vp8_min_pixels;
175 }
176
LibvpxVp8TrustedRateController() const177 bool RateControlSettings::LibvpxVp8TrustedRateController() const {
178 return video_config_.trust_vp8;
179 }
180
Vp8BoostBaseLayerQuality() const181 bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
182 return video_config_.vp8_s0_boost;
183 }
184
Vp8DynamicRateSettings() const185 bool RateControlSettings::Vp8DynamicRateSettings() const {
186 return video_config_.vp8_dynamic_rate;
187 }
188
LibvpxVp9TrustedRateController() const189 bool RateControlSettings::LibvpxVp9TrustedRateController() const {
190 return video_config_.trust_vp9;
191 }
192
Vp9DynamicRateSettings() const193 bool RateControlSettings::Vp9DynamicRateSettings() const {
194 return video_config_.vp9_dynamic_rate;
195 }
196
GetSimulcastHysteresisFactor(VideoCodecMode mode) const197 double RateControlSettings::GetSimulcastHysteresisFactor(
198 VideoCodecMode mode) const {
199 if (mode == VideoCodecMode::kScreensharing) {
200 return video_config_.screenshare_hysteresis;
201 }
202 return video_config_.video_hysteresis;
203 }
204
GetSimulcastHysteresisFactor(VideoEncoderConfig::ContentType content_type) const205 double RateControlSettings::GetSimulcastHysteresisFactor(
206 VideoEncoderConfig::ContentType content_type) const {
207 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
208 return video_config_.screenshare_hysteresis;
209 }
210 return video_config_.video_hysteresis;
211 }
212
Vp8BaseHeavyTl3RateAllocation() const213 bool RateControlSettings::Vp8BaseHeavyTl3RateAllocation() const {
214 return video_config_.vp8_base_heavy_tl3_alloc;
215 }
216
TriggerProbeOnMaxAllocatedBitrateChange() const217 bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const {
218 return video_config_.probe_max_allocation;
219 }
220
UseEncoderBitrateAdjuster() const221 bool RateControlSettings::UseEncoderBitrateAdjuster() const {
222 return video_config_.bitrate_adjuster;
223 }
224
BitrateAdjusterCanUseNetworkHeadroom() const225 bool RateControlSettings::BitrateAdjusterCanUseNetworkHeadroom() const {
226 return video_config_.adjuster_use_headroom;
227 }
228
229 } // namespace webrtc
230