diff --git a/rtc_base/experiments/BUILD.gn b/rtc_base/experiments/BUILD.gn index 927e8c7d16..830fd50a06 100644 --- a/rtc_base/experiments/BUILD.gn +++ b/rtc_base/experiments/BUILD.gn @@ -196,6 +196,20 @@ rtc_static_library("experimental_screenshare_settings") { ] } +rtc_static_library("stable_target_rate_experiment") { + sources = [ + "stable_target_rate_experiment.cc", + "stable_target_rate_experiment.h", + ] + deps = [ + ":field_trial_parser", + ":rate_control_settings", + "../../api/transport:field_trial_based_config", + "../../api/transport:webrtc_key_value_config", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + if (rtc_include_tests) { rtc_source_set("experiments_unittests") { testonly = true @@ -212,6 +226,7 @@ if (rtc_include_tests) { "quality_scaling_experiment_unittest.cc", "rate_control_settings_unittest.cc", "rtt_mult_experiment_unittest.cc", + "stable_target_rate_experiment_unittest.cc", "struct_parameters_parser_unittest.cc", ] deps = [ @@ -224,6 +239,7 @@ if (rtc_include_tests) { ":quality_scaling_experiment", ":rate_control_settings", ":rtt_mult_experiment", + ":stable_target_rate_experiment", "..:gunit_helpers", "../:rtc_base_tests_utils", "../../api/video_codecs:video_codecs_api", diff --git a/rtc_base/experiments/stable_target_rate_experiment.cc b/rtc_base/experiments/stable_target_rate_experiment.cc new file mode 100644 index 0000000000..28b541320b --- /dev/null +++ b/rtc_base/experiments/stable_target_rate_experiment.cc @@ -0,0 +1,72 @@ +/* + * Copyright 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/stable_target_rate_experiment.h" + +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/experiments/rate_control_settings.h" + +namespace webrtc { +namespace { +constexpr char kFieldTrialName[] = "WebRTC-StableTargetRate"; +} // namespace + +StableTargetRateExperiment::StableTargetRateExperiment( + const WebRtcKeyValueConfig* const key_value_config, + absl::optional default_video_hysteresis, + absl::optional default_screenshare_hysteresis) + : enabled_("enabled", false), + video_hysteresis_factor_("video_hysteresis_factor", + default_video_hysteresis), + screenshare_hysteresis_factor_("screenshare_hysteresis_factor", + default_screenshare_hysteresis) { + ParseFieldTrial( + {&enabled_, &video_hysteresis_factor_, &screenshare_hysteresis_factor_}, + key_value_config->Lookup(kFieldTrialName)); +} + +StableTargetRateExperiment::StableTargetRateExperiment( + StableTargetRateExperiment&&) = default; + +StableTargetRateExperiment StableTargetRateExperiment::ParseFromFieldTrials() { + FieldTrialBasedConfig config; + return ParseFromKeyValueConfig(&config); +} + +StableTargetRateExperiment StableTargetRateExperiment::ParseFromKeyValueConfig( + const WebRtcKeyValueConfig* const key_value_config) { + if (key_value_config->Lookup("WebRTC-VideoRateControl") != "") { + RateControlSettings rate_control = + RateControlSettings::ParseFromKeyValueConfig(key_value_config); + return StableTargetRateExperiment(key_value_config, + rate_control.GetSimulcastHysteresisFactor( + VideoCodecMode::kRealtimeVideo), + rate_control.GetSimulcastHysteresisFactor( + VideoCodecMode::kScreensharing)); + } + return StableTargetRateExperiment(key_value_config, absl::nullopt, + absl::nullopt); +} + +bool StableTargetRateExperiment::IsEnabled() const { + return enabled_.Get(); +} + +absl::optional StableTargetRateExperiment::GetVideoHysteresisFactor() + const { + return video_hysteresis_factor_.GetOptional(); +} + +absl::optional +StableTargetRateExperiment::GetScreenshareHysteresisFactor() const { + return screenshare_hysteresis_factor_.GetOptional(); +} + +} // namespace webrtc diff --git a/rtc_base/experiments/stable_target_rate_experiment.h b/rtc_base/experiments/stable_target_rate_experiment.h new file mode 100644 index 0000000000..b56108d797 --- /dev/null +++ b/rtc_base/experiments/stable_target_rate_experiment.h @@ -0,0 +1,43 @@ +/* + * Copyright 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. + */ + +#ifndef RTC_BASE_EXPERIMENTS_STABLE_TARGET_RATE_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_STABLE_TARGET_RATE_EXPERIMENT_H_ + +#include "api/transport/webrtc_key_value_config.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class StableTargetRateExperiment { + public: + StableTargetRateExperiment(StableTargetRateExperiment&&); + static StableTargetRateExperiment ParseFromFieldTrials(); + static StableTargetRateExperiment ParseFromKeyValueConfig( + const WebRtcKeyValueConfig* const key_value_config); + + bool IsEnabled() const; + absl::optional GetVideoHysteresisFactor() const; + absl::optional GetScreenshareHysteresisFactor() const; + + private: + explicit StableTargetRateExperiment( + const WebRtcKeyValueConfig* const key_value_config, + absl::optional default_video_hysteresis, + absl::optional default_screenshare_hysteresis); + + FieldTrialParameter enabled_; + FieldTrialOptional video_hysteresis_factor_; + FieldTrialOptional screenshare_hysteresis_factor_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_STABLE_TARGET_RATE_EXPERIMENT_H_ diff --git a/rtc_base/experiments/stable_target_rate_experiment_unittest.cc b/rtc_base/experiments/stable_target_rate_experiment_unittest.cc new file mode 100644 index 0000000000..86629f4e87 --- /dev/null +++ b/rtc_base/experiments/stable_target_rate_experiment_unittest.cc @@ -0,0 +1,80 @@ +/* + * Copyright 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/stable_target_rate_experiment.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(StableBweExperimentTest, Default) { + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_FALSE(config.IsEnabled()); + EXPECT_FALSE(config.GetVideoHysteresisFactor()); + EXPECT_FALSE(config.GetScreenshareHysteresisFactor()); +} + +TEST(StableBweExperimentTest, EnabledNoHysteresis) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-StableTargetRate/enabled:true/"); + + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_TRUE(config.IsEnabled()); + EXPECT_FALSE(config.GetVideoHysteresisFactor()); + EXPECT_FALSE(config.GetScreenshareHysteresisFactor()); +} + +TEST(StableBweExperimentTest, EnabledWithHysteresis) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-StableTargetRate/" + "enabled:true," + "video_hysteresis_factor:1.1," + "screenshare_hysteresis_factor:1.2/"); + + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_TRUE(config.IsEnabled()); + EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.1); + EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.2); +} + +TEST(StableBweExperimentTest, OnNoHysteresisPropagatesVideoRateHystersis) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-StableTargetRate/enabled:true/" + "WebRTC-VideoRateControl/video_hysteresis:1.3," + "screenshare_hysteresis:1.4/"); + + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_TRUE(config.IsEnabled()); + EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.3); + EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.4); +} + +TEST(StableBweExperimentTest, HysteresisOverrideVideoRateHystersis) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-StableTargetRate/" + "enabled:true," + "video_hysteresis_factor:1.1," + "screenshare_hysteresis_factor:1.2/" + "WebRTC-VideoRateControl/video_hysteresis:1.3," + "screenshare_hysteresis:1.4/"); + + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_TRUE(config.IsEnabled()); + EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.1); + EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.2); +} + +} // namespace webrtc