/* * 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 #include #include #include "api/transport/field_trial_based_config.h" #include "rtc_base/experiments/field_trial_parser.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 kVp8TrustedRateControllerFieldTrialName[] = "WebRTC-LibvpxVp8TrustedRateController"; const char kVp9TrustedRateControllerFieldTrialName[] = "WebRTC-LibvpxVp9TrustedRateController"; const char* kVideoHysteresisFieldTrialname = "WebRTC-SimulcastUpswitchHysteresisPercent"; const double kDefaultVideoHysteresisFactor = 1.0; const char* kScreenshareHysteresisFieldTrialname = "WebRTC-SimulcastScreenshareUpswitchHysteresisPercent"; // Default to 35% hysteresis for simulcast screenshare. const double kDefaultScreenshareHysteresisFactor = 1.35; bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config, absl::string_view key) { return key_value_config->Lookup(key).find("Enabled") == 0; } double ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config, absl::string_view key, double default_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) { return 1.0 + (percent / 100.0); } return default_value; } } // namespace RateControlSettings::RateControlSettings( const WebRtcKeyValueConfig* const key_value_config) : congestion_window_("QueueSize"), congestion_window_pushback_("MinBitrate"), pacing_factor_("pacing_factor"), alr_probing_("alr_probing", false), trust_vp8_( "trust_vp8", IsEnabled(key_value_config, kVp8TrustedRateControllerFieldTrialName)), trust_vp9_( "trust_vp9", IsEnabled(key_value_config, kVp9TrustedRateControllerFieldTrialName)), video_hysteresis_("video_hysteresis", ParseHysteresisFactor(key_value_config, kVideoHysteresisFieldTrialname, kDefaultVideoHysteresisFactor)), screenshare_hysteresis_( "screenshare_hysteresis", ParseHysteresisFactor(key_value_config, kScreenshareHysteresisFieldTrialname, kDefaultScreenshareHysteresisFactor)), probe_max_allocation_("probe_max_allocation", true), bitrate_adjuster_("bitrate_adjuster", false), vp8_s0_boost_("vp8_s0_boost", true) { ParseFieldTrial({&congestion_window_, &congestion_window_pushback_}, key_value_config->Lookup("WebRTC-CongestionWindow")); ParseFieldTrial({&pacing_factor_, &alr_probing_, &trust_vp8_, &trust_vp9_, &video_hysteresis_, &screenshare_hysteresis_, &probe_max_allocation_, &bitrate_adjuster_, &vp8_s0_boost_}, key_value_config->Lookup("WebRTC-VideoRateControl")); } 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(congestion_window_); } int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const { return congestion_window_.GetOptional().value_or(kDefaultAcceptedQueueMs); } bool RateControlSettings::UseCongestionWindowPushback() const { return congestion_window_ && congestion_window_pushback_; } uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps() const { return congestion_window_pushback_.GetOptional().value_or( kDefaultMinPushbackTargetBitrateBps); } absl::optional RateControlSettings::GetPacingFactor() const { return pacing_factor_.GetOptional(); } bool RateControlSettings::UseAlrProbing() const { return alr_probing_.Get(); } bool RateControlSettings::LibvpxVp8TrustedRateController() const { return trust_vp8_.Get(); } bool RateControlSettings::Vp8BoostBaseLayerQuality() const { return vp8_s0_boost_.Get(); } bool RateControlSettings::LibvpxVp9TrustedRateController() const { return trust_vp9_.Get(); } double RateControlSettings::GetSimulcastHysteresisFactor( VideoCodecMode mode) const { if (mode == VideoCodecMode::kScreensharing) { return GetSimulcastScreenshareHysteresisFactor(); } return GetSimulcastVideoHysteresisFactor(); } double RateControlSettings::GetSimulcastHysteresisFactor( VideoEncoderConfig::ContentType content_type) const { if (content_type == VideoEncoderConfig::ContentType::kScreen) { return GetSimulcastScreenshareHysteresisFactor(); } return GetSimulcastVideoHysteresisFactor(); } double RateControlSettings::GetSimulcastVideoHysteresisFactor() const { return video_hysteresis_.Get(); } double RateControlSettings::GetSimulcastScreenshareHysteresisFactor() const { return screenshare_hysteresis_.Get(); } bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const { return probe_max_allocation_.Get(); } bool RateControlSettings::UseEncoderBitrateAdjuster() const { return bitrate_adjuster_.Get(); } } // namespace webrtc