230 lines
7.9 KiB
C++
230 lines
7.9 KiB
C++
/*
|
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "rtc_base/experiments/rate_control_settings.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
|
|
#include <string>
|
|
|
|
#include "absl/strings/match.h"
|
|
#include "api/transport/field_trial_based_config.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "rtc_base/numerics/safe_conversions.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
const int kDefaultAcceptedQueueMs = 250;
|
|
|
|
const int kDefaultMinPushbackTargetBitrateBps = 30000;
|
|
|
|
const char kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName[] =
|
|
"WebRTC-UseBaseHeavyVP8TL3RateAllocation";
|
|
|
|
const char* kVideoHysteresisFieldTrialname =
|
|
"WebRTC-SimulcastUpswitchHysteresisPercent";
|
|
const char* kScreenshareHysteresisFieldTrialname =
|
|
"WebRTC-SimulcastScreenshareUpswitchHysteresisPercent";
|
|
|
|
bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config,
|
|
absl::string_view key) {
|
|
return absl::StartsWith(key_value_config->Lookup(key), "Enabled");
|
|
}
|
|
|
|
void ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config,
|
|
absl::string_view key,
|
|
double* output_value) {
|
|
std::string group_name = key_value_config->Lookup(key);
|
|
int percent = 0;
|
|
if (!group_name.empty() && sscanf(group_name.c_str(), "%d", &percent) == 1 &&
|
|
percent >= 0) {
|
|
*output_value = 1.0 + (percent / 100.0);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
constexpr char CongestionWindowConfig::kKey[];
|
|
|
|
std::unique_ptr<StructParametersParser> CongestionWindowConfig::Parser() {
|
|
return StructParametersParser::Create("QueueSize", &queue_size_ms, //
|
|
"MinBitrate", &min_bitrate_bps,
|
|
"InitWin", &initial_data_window,
|
|
"DropFrame", &drop_frame_only);
|
|
}
|
|
|
|
// static
|
|
CongestionWindowConfig CongestionWindowConfig::Parse(absl::string_view config) {
|
|
CongestionWindowConfig res;
|
|
res.Parser()->Parse(config);
|
|
return res;
|
|
}
|
|
|
|
constexpr char VideoRateControlConfig::kKey[];
|
|
|
|
std::unique_ptr<StructParametersParser> VideoRateControlConfig::Parser() {
|
|
// The empty comments ensures that each pair is on a separate line.
|
|
return StructParametersParser::Create(
|
|
"pacing_factor", &pacing_factor, //
|
|
"alr_probing", &alr_probing, //
|
|
"vp8_qp_max", &vp8_qp_max, //
|
|
"vp8_min_pixels", &vp8_min_pixels, //
|
|
"trust_vp8", &trust_vp8, //
|
|
"trust_vp9", &trust_vp9, //
|
|
"video_hysteresis", &video_hysteresis, //
|
|
"screenshare_hysteresis", &screenshare_hysteresis, //
|
|
"probe_max_allocation", &probe_max_allocation, //
|
|
"bitrate_adjuster", &bitrate_adjuster, //
|
|
"adjuster_use_headroom", &adjuster_use_headroom, //
|
|
"vp8_s0_boost", &vp8_s0_boost, //
|
|
"vp8_base_heavy_tl3_alloc", &vp8_base_heavy_tl3_alloc, //
|
|
"vp8_dynamic_rate", &vp8_dynamic_rate, //
|
|
"vp9_dynamic_rate", &vp9_dynamic_rate);
|
|
}
|
|
|
|
RateControlSettings::RateControlSettings(
|
|
const WebRtcKeyValueConfig* const key_value_config)
|
|
: congestion_window_config_(CongestionWindowConfig::Parse(
|
|
key_value_config->Lookup(CongestionWindowConfig::kKey))) {
|
|
video_config_.vp8_base_heavy_tl3_alloc = IsEnabled(
|
|
key_value_config, kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName);
|
|
ParseHysteresisFactor(key_value_config, kVideoHysteresisFieldTrialname,
|
|
&video_config_.video_hysteresis);
|
|
ParseHysteresisFactor(key_value_config, kScreenshareHysteresisFieldTrialname,
|
|
&video_config_.screenshare_hysteresis);
|
|
video_config_.Parser()->Parse(
|
|
key_value_config->Lookup(VideoRateControlConfig::kKey));
|
|
}
|
|
|
|
RateControlSettings::~RateControlSettings() = default;
|
|
RateControlSettings::RateControlSettings(RateControlSettings&&) = default;
|
|
|
|
RateControlSettings RateControlSettings::ParseFromFieldTrials() {
|
|
FieldTrialBasedConfig field_trial_config;
|
|
return RateControlSettings(&field_trial_config);
|
|
}
|
|
|
|
RateControlSettings RateControlSettings::ParseFromKeyValueConfig(
|
|
const WebRtcKeyValueConfig* const key_value_config) {
|
|
FieldTrialBasedConfig field_trial_config;
|
|
return RateControlSettings(key_value_config ? key_value_config
|
|
: &field_trial_config);
|
|
}
|
|
|
|
bool RateControlSettings::UseCongestionWindow() const {
|
|
return static_cast<bool>(congestion_window_config_.queue_size_ms);
|
|
}
|
|
|
|
int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
|
|
return congestion_window_config_.queue_size_ms.value_or(
|
|
kDefaultAcceptedQueueMs);
|
|
}
|
|
|
|
bool RateControlSettings::UseCongestionWindowPushback() const {
|
|
return congestion_window_config_.queue_size_ms &&
|
|
congestion_window_config_.min_bitrate_bps;
|
|
}
|
|
|
|
bool RateControlSettings::UseCongestionWindowDropFrameOnly() const {
|
|
return congestion_window_config_.drop_frame_only;
|
|
}
|
|
|
|
uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
|
|
const {
|
|
return congestion_window_config_.min_bitrate_bps.value_or(
|
|
kDefaultMinPushbackTargetBitrateBps);
|
|
}
|
|
|
|
absl::optional<DataSize>
|
|
RateControlSettings::CongestionWindowInitialDataWindow() const {
|
|
return congestion_window_config_.initial_data_window;
|
|
}
|
|
|
|
absl::optional<double> RateControlSettings::GetPacingFactor() const {
|
|
return video_config_.pacing_factor;
|
|
}
|
|
|
|
bool RateControlSettings::UseAlrProbing() const {
|
|
return video_config_.alr_probing;
|
|
}
|
|
|
|
absl::optional<int> RateControlSettings::LibvpxVp8QpMax() const {
|
|
if (video_config_.vp8_qp_max &&
|
|
(*video_config_.vp8_qp_max < 0 || *video_config_.vp8_qp_max > 63)) {
|
|
RTC_LOG(LS_WARNING) << "Unsupported vp8_qp_max_ value, ignored.";
|
|
return absl::nullopt;
|
|
}
|
|
return video_config_.vp8_qp_max;
|
|
}
|
|
|
|
absl::optional<int> RateControlSettings::LibvpxVp8MinPixels() const {
|
|
if (video_config_.vp8_min_pixels && *video_config_.vp8_min_pixels < 1) {
|
|
return absl::nullopt;
|
|
}
|
|
return video_config_.vp8_min_pixels;
|
|
}
|
|
|
|
bool RateControlSettings::LibvpxVp8TrustedRateController() const {
|
|
return video_config_.trust_vp8;
|
|
}
|
|
|
|
bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
|
|
return video_config_.vp8_s0_boost;
|
|
}
|
|
|
|
bool RateControlSettings::Vp8DynamicRateSettings() const {
|
|
return video_config_.vp8_dynamic_rate;
|
|
}
|
|
|
|
bool RateControlSettings::LibvpxVp9TrustedRateController() const {
|
|
return video_config_.trust_vp9;
|
|
}
|
|
|
|
bool RateControlSettings::Vp9DynamicRateSettings() const {
|
|
return video_config_.vp9_dynamic_rate;
|
|
}
|
|
|
|
double RateControlSettings::GetSimulcastHysteresisFactor(
|
|
VideoCodecMode mode) const {
|
|
if (mode == VideoCodecMode::kScreensharing) {
|
|
return video_config_.screenshare_hysteresis;
|
|
}
|
|
return video_config_.video_hysteresis;
|
|
}
|
|
|
|
double RateControlSettings::GetSimulcastHysteresisFactor(
|
|
VideoEncoderConfig::ContentType content_type) const {
|
|
if (content_type == VideoEncoderConfig::ContentType::kScreen) {
|
|
return video_config_.screenshare_hysteresis;
|
|
}
|
|
return video_config_.video_hysteresis;
|
|
}
|
|
|
|
bool RateControlSettings::Vp8BaseHeavyTl3RateAllocation() const {
|
|
return video_config_.vp8_base_heavy_tl3_alloc;
|
|
}
|
|
|
|
bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const {
|
|
return video_config_.probe_max_allocation;
|
|
}
|
|
|
|
bool RateControlSettings::UseEncoderBitrateAdjuster() const {
|
|
return video_config_.bitrate_adjuster;
|
|
}
|
|
|
|
bool RateControlSettings::BitrateAdjusterCanUseNetworkHeadroom() const {
|
|
return video_config_.adjuster_use_headroom;
|
|
}
|
|
|
|
} // namespace webrtc
|