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 = 350;
28
29 const int kDefaultMinPushbackTargetBitrateBps = 30000;
30
31 const char kCongestionWindowDefaultFieldTrialString[] =
32 "QueueSize:350,MinBitrate:30000,DropFrame:true";
33
34 const char kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName[] =
35 "WebRTC-UseBaseHeavyVP8TL3RateAllocation";
36
37 const char* kVideoHysteresisFieldTrialname =
38 "WebRTC-SimulcastUpswitchHysteresisPercent";
39 const char* kScreenshareHysteresisFieldTrialname =
40 "WebRTC-SimulcastScreenshareUpswitchHysteresisPercent";
41
IsEnabled(const WebRtcKeyValueConfig * const key_value_config,absl::string_view key)42 bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config,
43 absl::string_view key) {
44 return absl::StartsWith(key_value_config->Lookup(key), "Enabled");
45 }
46
ParseHysteresisFactor(const WebRtcKeyValueConfig * const key_value_config,absl::string_view key,double * output_value)47 void ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config,
48 absl::string_view key,
49 double* output_value) {
50 std::string group_name = key_value_config->Lookup(key);
51 int percent = 0;
52 if (!group_name.empty() && sscanf(group_name.c_str(), "%d", &percent) == 1 &&
53 percent >= 0) {
54 *output_value = 1.0 + (percent / 100.0);
55 }
56 }
57
58 } // namespace
59
60 constexpr char CongestionWindowConfig::kKey[];
61
Parser()62 std::unique_ptr<StructParametersParser> CongestionWindowConfig::Parser() {
63 return StructParametersParser::Create("QueueSize", &queue_size_ms, //
64 "MinBitrate", &min_bitrate_bps,
65 "InitWin", &initial_data_window,
66 "DropFrame", &drop_frame_only);
67 }
68
69 // static
Parse(absl::string_view config)70 CongestionWindowConfig CongestionWindowConfig::Parse(absl::string_view config) {
71 CongestionWindowConfig res;
72 res.Parser()->Parse(config);
73 return res;
74 }
75
76 constexpr char VideoRateControlConfig::kKey[];
77
Parser()78 std::unique_ptr<StructParametersParser> VideoRateControlConfig::Parser() {
79 // The empty comments ensures that each pair is on a separate line.
80 return StructParametersParser::Create(
81 "pacing_factor", &pacing_factor, //
82 "alr_probing", &alr_probing, //
83 "vp8_qp_max", &vp8_qp_max, //
84 "vp8_min_pixels", &vp8_min_pixels, //
85 "trust_vp8", &trust_vp8, //
86 "trust_vp9", &trust_vp9, //
87 "video_hysteresis", &video_hysteresis, //
88 "screenshare_hysteresis", &screenshare_hysteresis, //
89 "probe_max_allocation", &probe_max_allocation, //
90 "bitrate_adjuster", &bitrate_adjuster, //
91 "adjuster_use_headroom", &adjuster_use_headroom, //
92 "vp8_s0_boost", &vp8_s0_boost, //
93 "vp8_base_heavy_tl3_alloc", &vp8_base_heavy_tl3_alloc);
94 }
95
RateControlSettings(const WebRtcKeyValueConfig * const key_value_config)96 RateControlSettings::RateControlSettings(
97 const WebRtcKeyValueConfig* const key_value_config) {
98 std::string congestion_window_config =
99 key_value_config->Lookup(CongestionWindowConfig::kKey).empty()
100 ? kCongestionWindowDefaultFieldTrialString
101 : key_value_config->Lookup(CongestionWindowConfig::kKey);
102 congestion_window_config_ =
103 CongestionWindowConfig::Parse(congestion_window_config);
104 video_config_.vp8_base_heavy_tl3_alloc = IsEnabled(
105 key_value_config, kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName);
106 ParseHysteresisFactor(key_value_config, kVideoHysteresisFieldTrialname,
107 &video_config_.video_hysteresis);
108 ParseHysteresisFactor(key_value_config, kScreenshareHysteresisFieldTrialname,
109 &video_config_.screenshare_hysteresis);
110 video_config_.Parser()->Parse(
111 key_value_config->Lookup(VideoRateControlConfig::kKey));
112 }
113
114 RateControlSettings::~RateControlSettings() = default;
115 RateControlSettings::RateControlSettings(RateControlSettings&&) = default;
116
ParseFromFieldTrials()117 RateControlSettings RateControlSettings::ParseFromFieldTrials() {
118 FieldTrialBasedConfig field_trial_config;
119 return RateControlSettings(&field_trial_config);
120 }
121
ParseFromKeyValueConfig(const WebRtcKeyValueConfig * const key_value_config)122 RateControlSettings RateControlSettings::ParseFromKeyValueConfig(
123 const WebRtcKeyValueConfig* const key_value_config) {
124 FieldTrialBasedConfig field_trial_config;
125 return RateControlSettings(key_value_config ? key_value_config
126 : &field_trial_config);
127 }
128
UseCongestionWindow() const129 bool RateControlSettings::UseCongestionWindow() const {
130 return static_cast<bool>(congestion_window_config_.queue_size_ms);
131 }
132
GetCongestionWindowAdditionalTimeMs() const133 int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
134 return congestion_window_config_.queue_size_ms.value_or(
135 kDefaultAcceptedQueueMs);
136 }
137
UseCongestionWindowPushback() const138 bool RateControlSettings::UseCongestionWindowPushback() const {
139 return congestion_window_config_.queue_size_ms &&
140 congestion_window_config_.min_bitrate_bps;
141 }
142
UseCongestionWindowDropFrameOnly() const143 bool RateControlSettings::UseCongestionWindowDropFrameOnly() const {
144 return congestion_window_config_.drop_frame_only;
145 }
146
CongestionWindowMinPushbackTargetBitrateBps() const147 uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
148 const {
149 return congestion_window_config_.min_bitrate_bps.value_or(
150 kDefaultMinPushbackTargetBitrateBps);
151 }
152
153 absl::optional<DataSize>
CongestionWindowInitialDataWindow() const154 RateControlSettings::CongestionWindowInitialDataWindow() const {
155 return congestion_window_config_.initial_data_window;
156 }
157
GetPacingFactor() const158 absl::optional<double> RateControlSettings::GetPacingFactor() const {
159 return video_config_.pacing_factor;
160 }
161
UseAlrProbing() const162 bool RateControlSettings::UseAlrProbing() const {
163 return video_config_.alr_probing;
164 }
165
LibvpxVp8QpMax() const166 absl::optional<int> RateControlSettings::LibvpxVp8QpMax() const {
167 if (video_config_.vp8_qp_max &&
168 (*video_config_.vp8_qp_max < 0 || *video_config_.vp8_qp_max > 63)) {
169 RTC_LOG(LS_WARNING) << "Unsupported vp8_qp_max_ value, ignored.";
170 return absl::nullopt;
171 }
172 return video_config_.vp8_qp_max;
173 }
174
LibvpxVp8MinPixels() const175 absl::optional<int> RateControlSettings::LibvpxVp8MinPixels() const {
176 if (video_config_.vp8_min_pixels && *video_config_.vp8_min_pixels < 1) {
177 return absl::nullopt;
178 }
179 return video_config_.vp8_min_pixels;
180 }
181
LibvpxVp8TrustedRateController() const182 bool RateControlSettings::LibvpxVp8TrustedRateController() const {
183 return video_config_.trust_vp8;
184 }
185
Vp8BoostBaseLayerQuality() const186 bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
187 return video_config_.vp8_s0_boost;
188 }
189
LibvpxVp9TrustedRateController() const190 bool RateControlSettings::LibvpxVp9TrustedRateController() const {
191 return video_config_.trust_vp9;
192 }
193
GetSimulcastHysteresisFactor(VideoCodecMode mode) const194 double RateControlSettings::GetSimulcastHysteresisFactor(
195 VideoCodecMode mode) const {
196 if (mode == VideoCodecMode::kScreensharing) {
197 return video_config_.screenshare_hysteresis;
198 }
199 return video_config_.video_hysteresis;
200 }
201
GetSimulcastHysteresisFactor(VideoEncoderConfig::ContentType content_type) const202 double RateControlSettings::GetSimulcastHysteresisFactor(
203 VideoEncoderConfig::ContentType content_type) const {
204 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
205 return video_config_.screenshare_hysteresis;
206 }
207 return video_config_.video_hysteresis;
208 }
209
Vp8BaseHeavyTl3RateAllocation() const210 bool RateControlSettings::Vp8BaseHeavyTl3RateAllocation() const {
211 return video_config_.vp8_base_heavy_tl3_alloc;
212 }
213
TriggerProbeOnMaxAllocatedBitrateChange() const214 bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const {
215 return video_config_.probe_max_allocation;
216 }
217
UseEncoderBitrateAdjuster() const218 bool RateControlSettings::UseEncoderBitrateAdjuster() const {
219 return video_config_.bitrate_adjuster;
220 }
221
BitrateAdjusterCanUseNetworkHeadroom() const222 bool RateControlSettings::BitrateAdjusterCanUseNetworkHeadroom() const {
223 return video_config_.adjuster_use_headroom;
224 }
225
226 } // namespace webrtc
227