From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../libwebrtc/rtc_base/experiments/BUILD.gn | 300 ++++++++++ third_party/libwebrtc/rtc_base/experiments/DEPS | 8 + third_party/libwebrtc/rtc_base/experiments/OWNERS | 13 + .../rtc_base/experiments/alr_experiment.cc | 98 ++++ .../rtc_base/experiments/alr_experiment.h | 48 ++ .../experiments/alr_experiment_gn/moz.build | 225 ++++++++ .../experiments/balanced_degradation_settings.cc | 479 ++++++++++++++++ .../experiments/balanced_degradation_settings.h | 143 +++++ .../balanced_degradation_settings_gn/moz.build | 225 ++++++++ .../balanced_degradation_settings_unittest.cc | 620 +++++++++++++++++++++ .../bandwidth_quality_scaler_settings.cc | 43 ++ .../bandwidth_quality_scaler_settings.h | 35 ++ .../bandwidth_quality_scaler_settings_gn/moz.build | 225 ++++++++ .../bandwidth_quality_scaler_settings_unittest.cc | 49 ++ .../rtc_base/experiments/cpu_speed_experiment.cc | 89 +++ .../rtc_base/experiments/cpu_speed_experiment.h | 65 +++ .../experiments/cpu_speed_experiment_gn/moz.build | 225 ++++++++ .../experiments/cpu_speed_experiment_unittest.cc | 106 ++++ .../rtc_base/experiments/encoder_info_settings.cc | 214 +++++++ .../rtc_base/experiments/encoder_info_settings.h | 93 ++++ .../experiments/encoder_info_settings_gn/moz.build | 225 ++++++++ .../experiments/encoder_info_settings_unittest.cc | 102 ++++ .../rtc_base/experiments/field_trial_list.cc | 59 ++ .../rtc_base/experiments/field_trial_list.h | 226 ++++++++ .../experiments/field_trial_list_unittest.cc | 141 +++++ .../rtc_base/experiments/field_trial_parser.cc | 260 +++++++++ .../rtc_base/experiments/field_trial_parser.h | 291 ++++++++++ .../experiments/field_trial_parser_gn/moz.build | 228 ++++++++ .../experiments/field_trial_parser_unittest.cc | 185 ++++++ .../rtc_base/experiments/field_trial_units.cc | 116 ++++ .../rtc_base/experiments/field_trial_units.h | 41 ++ .../experiments/field_trial_units_unittest.cc | 87 +++ .../experiments/keyframe_interval_settings.cc | 39 ++ .../experiments/keyframe_interval_settings.h | 39 ++ .../moz.build | 225 ++++++++ .../keyframe_interval_settings_unittest.cc | 43 ++ .../experiments/min_video_bitrate_experiment.cc | 114 ++++ .../experiments/min_video_bitrate_experiment.h | 28 + .../min_video_bitrate_experiment_gn/moz.build | 225 ++++++++ .../min_video_bitrate_experiment_unittest.cc | 161 ++++++ .../normalize_simulcast_size_experiment.cc | 49 ++ .../normalize_simulcast_size_experiment.h | 25 + .../moz.build | 225 ++++++++ ...normalize_simulcast_size_experiment_unittest.cc | 59 ++ .../experiments/quality_rampup_experiment.cc | 82 +++ .../experiments/quality_rampup_experiment.h | 53 ++ .../quality_rampup_experiment_gn/moz.build | 225 ++++++++ .../quality_rampup_experiment_unittest.cc | 139 +++++ .../experiments/quality_scaler_settings.cc | 102 ++++ .../rtc_base/experiments/quality_scaler_settings.h | 46 ++ .../quality_scaler_settings_gn/moz.build | 225 ++++++++ .../quality_scaler_settings_unittest.cc | 103 ++++ .../experiments/quality_scaling_experiment.cc | 111 ++++ .../experiments/quality_scaling_experiment.h | 58 ++ .../quality_scaling_experiment_gn/moz.build | 225 ++++++++ .../quality_scaling_experiment_unittest.cc | 186 +++++++ .../rtc_base/experiments/rate_control_settings.cc | 183 ++++++ .../rtc_base/experiments/rate_control_settings.h | 93 ++++ .../experiments/rate_control_settings_gn/moz.build | 225 ++++++++ .../experiments/rate_control_settings_unittest.cc | 191 +++++++ .../rtc_base/experiments/rtt_mult_experiment.cc | 65 +++ .../rtc_base/experiments/rtt_mult_experiment.h | 35 ++ .../experiments/rtt_mult_experiment_gn/moz.build | 225 ++++++++ .../experiments/rtt_mult_experiment_unittest.cc | 62 +++ .../experiments/stable_target_rate_experiment.cc | 63 +++ .../experiments/stable_target_rate_experiment.h | 44 ++ .../stable_target_rate_experiment_gn/moz.build | 225 ++++++++ .../stable_target_rate_experiment_unittest.cc | 67 +++ .../experiments/struct_parameters_parser.cc | 135 +++++ .../experiments/struct_parameters_parser.h | 110 ++++ .../struct_parameters_parser_unittest.cc | 67 +++ 71 files changed, 9841 insertions(+) create mode 100644 third_party/libwebrtc/rtc_base/experiments/BUILD.gn create mode 100644 third_party/libwebrtc/rtc_base/experiments/DEPS create mode 100644 third_party/libwebrtc/rtc_base/experiments/OWNERS create mode 100644 third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/alr_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_list.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_list_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_parser.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_units.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/field_trial_units_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/rate_control_settings.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/rate_control_settings_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build create mode 100644 third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_unittest.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc create mode 100644 third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.h create mode 100644 third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc (limited to 'third_party/libwebrtc/rtc_base/experiments') diff --git a/third_party/libwebrtc/rtc_base/experiments/BUILD.gn b/third_party/libwebrtc/rtc_base/experiments/BUILD.gn new file mode 100644 index 0000000000..ac542cc301 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/BUILD.gn @@ -0,0 +1,300 @@ +# Copyright (c) 2018 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. + +import("../../webrtc.gni") + +rtc_library("alr_experiment") { + sources = [ + "alr_experiment.cc", + "alr_experiment.h", + ] + deps = [ + "..:logging", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings:strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("field_trial_parser") { + sources = [ + "field_trial_list.cc", + "field_trial_list.h", + "field_trial_parser.cc", + "field_trial_parser.h", + "field_trial_units.cc", + "field_trial_units.h", + "struct_parameters_parser.cc", + "struct_parameters_parser.h", + ] + deps = [ + "../../api/units:data_rate", + "../../api/units:data_size", + "../../api/units:time_delta", + "../../rtc_base:checks", + "../../rtc_base:logging", + "../../rtc_base:safe_conversions", + "../../rtc_base:stringutils", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings:strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("quality_rampup_experiment") { + sources = [ + "quality_rampup_experiment.cc", + "quality_rampup_experiment.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("quality_scaler_settings") { + sources = [ + "quality_scaler_settings.cc", + "quality_scaler_settings.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("bandwidth_quality_scaler_settings") { + sources = [ + "bandwidth_quality_scaler_settings.cc", + "bandwidth_quality_scaler_settings.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("quality_scaling_experiment") { + sources = [ + "quality_scaling_experiment.cc", + "quality_scaling_experiment.h", + ] + deps = [ + "..:logging", + "../../api/video_codecs:video_codecs_api", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("normalize_simulcast_size_experiment") { + sources = [ + "normalize_simulcast_size_experiment.cc", + "normalize_simulcast_size_experiment.h", + ] + deps = [ + "..:logging", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("balanced_degradation_settings") { + sources = [ + "balanced_degradation_settings.cc", + "balanced_degradation_settings.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../api:field_trials_view", + "../../api/video_codecs:video_codecs_api", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("cpu_speed_experiment") { + sources = [ + "cpu_speed_experiment.cc", + "cpu_speed_experiment.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("encoder_info_settings") { + sources = [ + "encoder_info_settings.cc", + "encoder_info_settings.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "../../api/video_codecs:video_codecs_api", + "../../system_wrappers:field_trial", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("rtt_mult_experiment") { + sources = [ + "rtt_mult_experiment.cc", + "rtt_mult_experiment.h", + ] + deps = [ + "..:logging", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("rate_control_settings") { + sources = [ + "rate_control_settings.cc", + "rate_control_settings.h", + ] + deps = [ + ":field_trial_parser", + "..:logging", + "..:safe_conversions", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + "../../api/units:data_size", + "../../api/video_codecs:video_codecs_api", + "../../system_wrappers:field_trial", + "../../video/config:encoder_config", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("keyframe_interval_settings_experiment") { + sources = [ + "keyframe_interval_settings.cc", + "keyframe_interval_settings.h", + ] + deps = [ + ":field_trial_parser", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("stable_target_rate_experiment") { + sources = [ + "stable_target_rate_experiment.cc", + "stable_target_rate_experiment.h", + ] + deps = [ + ":field_trial_parser", + "../../api:field_trials_view", + "../../api/transport:field_trial_based_config", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("min_video_bitrate_experiment") { + sources = [ + "min_video_bitrate_experiment.cc", + "min_video_bitrate_experiment.h", + ] + deps = [ + ":field_trial_parser", + "../../api/units:data_rate", + "../../api/video:video_frame", + "../../rtc_base:checks", + "../../rtc_base:logging", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +if (rtc_include_tests && !build_with_chromium) { + rtc_library("experiments_unittests") { + testonly = true + + sources = [ + "balanced_degradation_settings_unittest.cc", + "bandwidth_quality_scaler_settings_unittest.cc", + "cpu_speed_experiment_unittest.cc", + "encoder_info_settings_unittest.cc", + "field_trial_list_unittest.cc", + "field_trial_parser_unittest.cc", + "field_trial_units_unittest.cc", + "keyframe_interval_settings_unittest.cc", + "min_video_bitrate_experiment_unittest.cc", + "normalize_simulcast_size_experiment_unittest.cc", + "quality_rampup_experiment_unittest.cc", + "quality_scaler_settings_unittest.cc", + "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 = [ + ":balanced_degradation_settings", + ":bandwidth_quality_scaler_settings", + ":cpu_speed_experiment", + ":encoder_info_settings", + ":field_trial_parser", + ":keyframe_interval_settings_experiment", + ":min_video_bitrate_experiment", + ":normalize_simulcast_size_experiment", + ":quality_rampup_experiment", + ":quality_scaler_settings", + ":quality_scaling_experiment", + ":rate_control_settings", + ":rtt_mult_experiment", + ":stable_target_rate_experiment", + "..:gunit_helpers", + "../:rtc_base_tests_utils", + "../../api/units:data_rate", + "../../api/video:video_frame", + "../../api/video_codecs:video_codecs_api", + "../../system_wrappers:field_trial", + "../../test:field_trial", + "../../test:scoped_key_value_config", + "../../test:test_main", + "../../test:test_support", + "../../video/config:encoder_config", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] + } +} diff --git a/third_party/libwebrtc/rtc_base/experiments/DEPS b/third_party/libwebrtc/rtc_base/experiments/DEPS new file mode 100644 index 0000000000..7c8dddef06 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + "+system_wrappers", +] +specific_include_rules = { + ".*rate_control_settings.*": [ + "+video/config", + ], +} diff --git a/third_party/libwebrtc/rtc_base/experiments/OWNERS b/third_party/libwebrtc/rtc_base/experiments/OWNERS new file mode 100644 index 0000000000..0a3b89533d --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/OWNERS @@ -0,0 +1,13 @@ +asapersson@webrtc.org +sprang@webrtc.org +srte@webrtc.org + +per-file audio_allocation_settings*=srte@webrtc.org +per-file congestion_controller_experiment*=srte@webrtc.org +per-file cpu_speed_experiment*=asapersson@webrtc.org +per-file field_trial*=srte@webrtc.org +per-file keyframe_interval_settings*=brandtr@webrtc.org +per-file normalize_simulcast_size_experiment*=asapersson@webrtc.org +per-file quality_scaling_experiment*=asapersson@webrtc.org +per-file rtt_mult_experiment*=mhoro@webrtc.org +per-file rate_control_settings*=srte@webrtc.org diff --git a/third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc new file mode 100644 index 0000000000..f5d36f6867 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018 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/alr_experiment.h" + +#include +#include + +#include + +#include "absl/strings/string_view.h" +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +const char AlrExperimentSettings::kScreenshareProbingBweExperimentName[] = + "WebRTC-ProbingScreenshareBwe"; +const char AlrExperimentSettings::kStrictPacingAndProbingExperimentName[] = + "WebRTC-StrictPacingAndProbing"; +const char kDefaultProbingScreenshareBweSettings[] = "1.0,2875,80,40,-60,3"; + +bool AlrExperimentSettings::MaxOneFieldTrialEnabled() { + return AlrExperimentSettings::MaxOneFieldTrialEnabled( + FieldTrialBasedConfig()); +} + +bool AlrExperimentSettings::MaxOneFieldTrialEnabled( + const FieldTrialsView& key_value_config) { + return key_value_config.Lookup(kStrictPacingAndProbingExperimentName) + .empty() || + key_value_config.Lookup(kScreenshareProbingBweExperimentName).empty(); +} + +absl::optional +AlrExperimentSettings::CreateFromFieldTrial(absl::string_view experiment_name) { + return AlrExperimentSettings::CreateFromFieldTrial(FieldTrialBasedConfig(), + experiment_name); +} + +absl::optional +AlrExperimentSettings::CreateFromFieldTrial( + const FieldTrialsView& key_value_config, + absl::string_view experiment_name) { + absl::optional ret; + std::string group_name = key_value_config.Lookup(experiment_name); + + const std::string kIgnoredSuffix = "_Dogfood"; + std::string::size_type suffix_pos = group_name.rfind(kIgnoredSuffix); + if (suffix_pos != std::string::npos && + suffix_pos == group_name.length() - kIgnoredSuffix.length()) { + group_name.resize(group_name.length() - kIgnoredSuffix.length()); + } + + if (group_name.empty()) { + if (experiment_name == kScreenshareProbingBweExperimentName) { + // This experiment is now default-on with fixed settings. + // TODO(sprang): Remove this kill-switch and clean up experiment code. + group_name = kDefaultProbingScreenshareBweSettings; + } else { + return ret; + } + } + + AlrExperimentSettings settings; + if (sscanf(group_name.c_str(), "%f,%" PRId64 ",%d,%d,%d,%d", + &settings.pacing_factor, &settings.max_paced_queue_time, + &settings.alr_bandwidth_usage_percent, + &settings.alr_start_budget_level_percent, + &settings.alr_stop_budget_level_percent, + &settings.group_id) == 6) { + ret.emplace(settings); + RTC_LOG(LS_INFO) << "Using ALR experiment settings: " + "pacing factor: " + << settings.pacing_factor << ", max pacer queue length: " + << settings.max_paced_queue_time + << ", ALR bandwidth usage percent: " + << settings.alr_bandwidth_usage_percent + << ", ALR start budget level percent: " + << settings.alr_start_budget_level_percent + << ", ALR end budget level percent: " + << settings.alr_stop_budget_level_percent + << ", ALR experiment group ID: " << settings.group_id; + } else { + RTC_LOG(LS_INFO) << "Failed to parse ALR experiment: " << experiment_name; + } + + return ret; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/alr_experiment.h b/third_party/libwebrtc/rtc_base/experiments/alr_experiment.h new file mode 100644 index 0000000000..048fd90cab --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/alr_experiment.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 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_ALR_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_ALR_EXPERIMENT_H_ + +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/field_trials_view.h" + +namespace webrtc { +struct AlrExperimentSettings { + public: + float pacing_factor; + int64_t max_paced_queue_time; + int alr_bandwidth_usage_percent; + int alr_start_budget_level_percent; + int alr_stop_budget_level_percent; + // Will be sent to the receive side for stats slicing. + // Can be 0..6, because it's sent as a 3 bits value and there's also + // reserved value to indicate absence of experiment. + int group_id; + + static const char kScreenshareProbingBweExperimentName[]; + static const char kStrictPacingAndProbingExperimentName[]; + static absl::optional CreateFromFieldTrial( + absl::string_view experiment_name); + static absl::optional CreateFromFieldTrial( + const FieldTrialsView& key_value_config, + absl::string_view experiment_name); + static bool MaxOneFieldTrialEnabled(); + static bool MaxOneFieldTrialEnabled(const FieldTrialsView& key_value_config); + + private: + AlrExperimentSettings() = default; +}; +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_ALR_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build new file mode 100644 index 0000000000..574d7d6302 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("alr_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc new file mode 100644 index 0000000000..1652e31704 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc @@ -0,0 +1,479 @@ +/* + * 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/balanced_degradation_settings.h" + +#include + +#include "rtc_base/experiments/field_trial_list.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/logging.h" + +namespace webrtc { +namespace { +constexpr char kFieldTrial[] = "WebRTC-Video-BalancedDegradationSettings"; +constexpr int kMinFps = 1; +constexpr int kMaxFps = 100; // 100 means unlimited fps. + +std::vector DefaultConfigs() { + return {{320 * 240, + 7, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + {480 * 360, + 10, + 0, + 0, + 1, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + {640 * 480, + 15, + 0, + 0, + 1, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}}; +} + +bool IsValidConfig( + const BalancedDegradationSettings::CodecTypeSpecific& config) { + if (config.GetQpLow().has_value() != config.GetQpHigh().has_value()) { + RTC_LOG(LS_WARNING) << "Neither or both thresholds should be set."; + return false; + } + if (config.GetQpLow().has_value() && config.GetQpHigh().has_value() && + config.GetQpLow().value() >= config.GetQpHigh().value()) { + RTC_LOG(LS_WARNING) << "Invalid threshold value, low >= high threshold."; + return false; + } + if (config.GetFps().has_value() && (config.GetFps().value() < kMinFps || + config.GetFps().value() > kMaxFps)) { + RTC_LOG(LS_WARNING) << "Unsupported fps setting, value ignored."; + return false; + } + return true; +} + +bool IsValid(const BalancedDegradationSettings::CodecTypeSpecific& config1, + const BalancedDegradationSettings::CodecTypeSpecific& config2) { + bool both_or_none_set = ((config1.qp_low > 0) == (config2.qp_low > 0) && + (config1.qp_high > 0) == (config2.qp_high > 0) && + (config1.fps > 0) == (config2.fps > 0)); + if (!both_or_none_set) { + RTC_LOG(LS_WARNING) << "Invalid value, all/none should be set."; + return false; + } + if (config1.fps > 0 && config1.fps < config2.fps) { + RTC_LOG(LS_WARNING) << "Invalid fps/pixel value provided."; + return false; + } + return true; +} + +bool IsValid(const std::vector& configs) { + if (configs.size() <= 1) { + if (configs.size() == 1) + RTC_LOG(LS_WARNING) << "Unsupported size, value ignored."; + return false; + } + for (const auto& config : configs) { + if (config.fps < kMinFps || config.fps > kMaxFps) { + RTC_LOG(LS_WARNING) << "Unsupported fps setting, value ignored."; + return false; + } + } + int last_kbps = configs[0].kbps; + for (size_t i = 1; i < configs.size(); ++i) { + if (configs[i].kbps > 0) { + if (configs[i].kbps < last_kbps) { + RTC_LOG(LS_WARNING) << "Invalid bitrate value provided."; + return false; + } + last_kbps = configs[i].kbps; + } + } + for (size_t i = 1; i < configs.size(); ++i) { + if (configs[i].pixels < configs[i - 1].pixels || + configs[i].fps < configs[i - 1].fps) { + RTC_LOG(LS_WARNING) << "Invalid fps/pixel value provided."; + return false; + } + if (!IsValid(configs[i].vp8, configs[i - 1].vp8) || + !IsValid(configs[i].vp9, configs[i - 1].vp9) || + !IsValid(configs[i].h264, configs[i - 1].h264) || + !IsValid(configs[i].av1, configs[i - 1].av1) || + !IsValid(configs[i].generic, configs[i - 1].generic)) { + return false; + } + } + for (const auto& config : configs) { + if (!IsValidConfig(config.vp8) || !IsValidConfig(config.vp9) || + !IsValidConfig(config.h264) || !IsValidConfig(config.av1) || + !IsValidConfig(config.generic)) { + return false; + } + } + return true; +} + +std::vector GetValidOrDefault( + const std::vector& configs) { + if (IsValid(configs)) { + return configs; + } + return DefaultConfigs(); +} + +absl::optional GetThresholds( + VideoCodecType type, + const BalancedDegradationSettings::Config& config) { + absl::optional low; + absl::optional high; + + switch (type) { + case kVideoCodecVP8: + low = config.vp8.GetQpLow(); + high = config.vp8.GetQpHigh(); + break; + case kVideoCodecVP9: + low = config.vp9.GetQpLow(); + high = config.vp9.GetQpHigh(); + break; + case kVideoCodecH264: + low = config.h264.GetQpLow(); + high = config.h264.GetQpHigh(); + break; + case kVideoCodecAV1: + low = config.av1.GetQpLow(); + high = config.av1.GetQpHigh(); + break; + case kVideoCodecGeneric: + low = config.generic.GetQpLow(); + high = config.generic.GetQpHigh(); + break; + default: + break; + } + + if (low && high) { + RTC_LOG(LS_INFO) << "QP thresholds: low: " << *low << ", high: " << *high; + return absl::optional( + VideoEncoder::QpThresholds(*low, *high)); + } + return absl::nullopt; +} + +int GetFps(VideoCodecType type, + const absl::optional& config) { + if (!config.has_value()) { + return std::numeric_limits::max(); + } + + absl::optional fps; + switch (type) { + case kVideoCodecVP8: + fps = config->vp8.GetFps(); + break; + case kVideoCodecVP9: + fps = config->vp9.GetFps(); + break; + case kVideoCodecH264: + fps = config->h264.GetFps(); + break; + case kVideoCodecAV1: + fps = config->av1.GetFps(); + break; + case kVideoCodecGeneric: + fps = config->generic.GetFps(); + break; + default: + break; + } + + const int framerate = fps.value_or(config->fps); + + return (framerate == kMaxFps) ? std::numeric_limits::max() : framerate; +} + +absl::optional GetKbps( + VideoCodecType type, + const absl::optional& config) { + if (!config.has_value()) + return absl::nullopt; + + absl::optional kbps; + switch (type) { + case kVideoCodecVP8: + kbps = config->vp8.GetKbps(); + break; + case kVideoCodecVP9: + kbps = config->vp9.GetKbps(); + break; + case kVideoCodecH264: + kbps = config->h264.GetKbps(); + break; + case kVideoCodecAV1: + kbps = config->av1.GetKbps(); + break; + case kVideoCodecGeneric: + kbps = config->generic.GetKbps(); + break; + default: + break; + } + + if (kbps.has_value()) + return kbps; + + return config->kbps > 0 ? absl::optional(config->kbps) : absl::nullopt; +} + +absl::optional GetKbpsRes( + VideoCodecType type, + const absl::optional& config) { + if (!config.has_value()) + return absl::nullopt; + + absl::optional kbps_res; + switch (type) { + case kVideoCodecVP8: + kbps_res = config->vp8.GetKbpsRes(); + break; + case kVideoCodecVP9: + kbps_res = config->vp9.GetKbpsRes(); + break; + case kVideoCodecH264: + kbps_res = config->h264.GetKbpsRes(); + break; + case kVideoCodecAV1: + kbps_res = config->av1.GetKbpsRes(); + break; + case kVideoCodecGeneric: + kbps_res = config->generic.GetKbpsRes(); + break; + default: + break; + } + + if (kbps_res.has_value()) + return kbps_res; + + return config->kbps_res > 0 ? absl::optional(config->kbps_res) + : absl::nullopt; +} +} // namespace + +absl::optional BalancedDegradationSettings::CodecTypeSpecific::GetQpLow() + const { + return (qp_low > 0) ? absl::optional(qp_low) : absl::nullopt; +} + +absl::optional BalancedDegradationSettings::CodecTypeSpecific::GetQpHigh() + const { + return (qp_high > 0) ? absl::optional(qp_high) : absl::nullopt; +} + +absl::optional BalancedDegradationSettings::CodecTypeSpecific::GetFps() + const { + return (fps > 0) ? absl::optional(fps) : absl::nullopt; +} + +absl::optional BalancedDegradationSettings::CodecTypeSpecific::GetKbps() + const { + return (kbps > 0) ? absl::optional(kbps) : absl::nullopt; +} + +absl::optional BalancedDegradationSettings::CodecTypeSpecific::GetKbpsRes() + const { + return (kbps_res > 0) ? absl::optional(kbps_res) : absl::nullopt; +} + +BalancedDegradationSettings::Config::Config() = default; + +BalancedDegradationSettings::Config::Config(int pixels, + int fps, + int kbps, + int kbps_res, + int fps_diff, + CodecTypeSpecific vp8, + CodecTypeSpecific vp9, + CodecTypeSpecific h264, + CodecTypeSpecific av1, + CodecTypeSpecific generic) + : pixels(pixels), + fps(fps), + kbps(kbps), + kbps_res(kbps_res), + fps_diff(fps_diff), + vp8(vp8), + vp9(vp9), + h264(h264), + av1(av1), + generic(generic) {} + +BalancedDegradationSettings::BalancedDegradationSettings( + const FieldTrialsView& field_trials) { + FieldTrialStructList configs( + {FieldTrialStructMember("pixels", [](Config* c) { return &c->pixels; }), + FieldTrialStructMember("fps", [](Config* c) { return &c->fps; }), + FieldTrialStructMember("kbps", [](Config* c) { return &c->kbps; }), + FieldTrialStructMember("kbps_res", + [](Config* c) { return &c->kbps_res; }), + FieldTrialStructMember("fps_diff", + [](Config* c) { return &c->fps_diff; }), + FieldTrialStructMember("vp8_qp_low", + [](Config* c) { return &c->vp8.qp_low; }), + FieldTrialStructMember("vp8_qp_high", + [](Config* c) { return &c->vp8.qp_high; }), + FieldTrialStructMember("vp8_fps", [](Config* c) { return &c->vp8.fps; }), + FieldTrialStructMember("vp8_kbps", + [](Config* c) { return &c->vp8.kbps; }), + FieldTrialStructMember("vp8_kbps_res", + [](Config* c) { return &c->vp8.kbps_res; }), + FieldTrialStructMember("vp9_qp_low", + [](Config* c) { return &c->vp9.qp_low; }), + FieldTrialStructMember("vp9_qp_high", + [](Config* c) { return &c->vp9.qp_high; }), + FieldTrialStructMember("vp9_fps", [](Config* c) { return &c->vp9.fps; }), + FieldTrialStructMember("vp9_kbps", + [](Config* c) { return &c->vp9.kbps; }), + FieldTrialStructMember("vp9_kbps_res", + [](Config* c) { return &c->vp9.kbps_res; }), + FieldTrialStructMember("h264_qp_low", + [](Config* c) { return &c->h264.qp_low; }), + FieldTrialStructMember("h264_qp_high", + [](Config* c) { return &c->h264.qp_high; }), + FieldTrialStructMember("h264_fps", + [](Config* c) { return &c->h264.fps; }), + FieldTrialStructMember("h264_kbps", + [](Config* c) { return &c->h264.kbps; }), + FieldTrialStructMember("h264_kbps_res", + [](Config* c) { return &c->h264.kbps_res; }), + FieldTrialStructMember("av1_qp_low", + [](Config* c) { return &c->av1.qp_low; }), + FieldTrialStructMember("av1_qp_high", + [](Config* c) { return &c->av1.qp_high; }), + FieldTrialStructMember("av1_fps", [](Config* c) { return &c->av1.fps; }), + FieldTrialStructMember("av1_kbps", + [](Config* c) { return &c->av1.kbps; }), + FieldTrialStructMember("av1_kbps_res", + [](Config* c) { return &c->av1.kbps_res; }), + FieldTrialStructMember("generic_qp_low", + [](Config* c) { return &c->generic.qp_low; }), + FieldTrialStructMember("generic_qp_high", + [](Config* c) { return &c->generic.qp_high; }), + FieldTrialStructMember("generic_fps", + [](Config* c) { return &c->generic.fps; }), + FieldTrialStructMember("generic_kbps", + [](Config* c) { return &c->generic.kbps; }), + FieldTrialStructMember("generic_kbps_res", + [](Config* c) { return &c->generic.kbps_res; })}, + {}); + + ParseFieldTrial({&configs}, field_trials.Lookup(kFieldTrial)); + + configs_ = GetValidOrDefault(configs.Get()); + RTC_DCHECK_GT(configs_.size(), 1); +} + +BalancedDegradationSettings::~BalancedDegradationSettings() {} + +std::vector +BalancedDegradationSettings::GetConfigs() const { + return configs_; +} + +int BalancedDegradationSettings::MinFps(VideoCodecType type, int pixels) const { + return GetFps(type, GetMinFpsConfig(pixels)); +} + +absl::optional +BalancedDegradationSettings::GetMinFpsConfig(int pixels) const { + for (const auto& config : configs_) { + if (pixels <= config.pixels) + return config; + } + return absl::nullopt; +} + +int BalancedDegradationSettings::MaxFps(VideoCodecType type, int pixels) const { + return GetFps(type, GetMaxFpsConfig(pixels)); +} + +absl::optional +BalancedDegradationSettings::GetMaxFpsConfig(int pixels) const { + for (size_t i = 0; i < configs_.size() - 1; ++i) { + if (pixels <= configs_[i].pixels) + return configs_[i + 1]; + } + return absl::nullopt; +} + +bool BalancedDegradationSettings::CanAdaptUp(VideoCodecType type, + int pixels, + uint32_t bitrate_bps) const { + absl::optional min_kbps = GetKbps(type, GetMaxFpsConfig(pixels)); + if (!min_kbps.has_value() || bitrate_bps == 0) { + return true; // No limit configured or bitrate provided. + } + return bitrate_bps >= static_cast(min_kbps.value() * 1000); +} + +bool BalancedDegradationSettings::CanAdaptUpResolution( + VideoCodecType type, + int pixels, + uint32_t bitrate_bps) const { + absl::optional min_kbps = GetKbpsRes(type, GetMaxFpsConfig(pixels)); + if (!min_kbps.has_value() || bitrate_bps == 0) { + return true; // No limit configured or bitrate provided. + } + return bitrate_bps >= static_cast(min_kbps.value() * 1000); +} + +absl::optional BalancedDegradationSettings::MinFpsDiff(int pixels) const { + for (const auto& config : configs_) { + if (pixels <= config.pixels) { + return (config.fps_diff > kNoFpsDiff) + ? absl::optional(config.fps_diff) + : absl::nullopt; + } + } + return absl::nullopt; +} + +absl::optional +BalancedDegradationSettings::GetQpThresholds(VideoCodecType type, + int pixels) const { + return GetThresholds(type, GetConfig(pixels)); +} + +BalancedDegradationSettings::Config BalancedDegradationSettings::GetConfig( + int pixels) const { + for (const auto& config : configs_) { + if (pixels <= config.pixels) + return config; + } + return configs_.back(); // Use last above highest pixels. +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.h b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.h new file mode 100644 index 0000000000..0b5e03df3b --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.h @@ -0,0 +1,143 @@ +/* + * 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_BALANCED_DEGRADATION_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_BALANCED_DEGRADATION_SETTINGS_H_ + +#include + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "api/video_codecs/video_encoder.h" + +namespace webrtc { + +class BalancedDegradationSettings { + public: + static constexpr int kNoFpsDiff = -100; + + BalancedDegradationSettings(const FieldTrialsView& field_trials); + ~BalancedDegradationSettings(); + + struct CodecTypeSpecific { + CodecTypeSpecific() {} + CodecTypeSpecific(int qp_low, int qp_high, int fps, int kbps, int kbps_res) + : qp_low(qp_low), + qp_high(qp_high), + fps(fps), + kbps(kbps), + kbps_res(kbps_res) {} + + bool operator==(const CodecTypeSpecific& o) const { + return qp_low == o.qp_low && qp_high == o.qp_high && fps == o.fps && + kbps == o.kbps && kbps_res == o.kbps_res; + } + + absl::optional GetQpLow() const; + absl::optional GetQpHigh() const; + absl::optional GetFps() const; + absl::optional GetKbps() const; + absl::optional GetKbpsRes() const; + + // Optional settings. + int qp_low = 0; + int qp_high = 0; + int fps = 0; // If unset, defaults to `fps` in Config. + int kbps = 0; // If unset, defaults to `kbps` in Config. + int kbps_res = 0; // If unset, defaults to `kbps_res` in Config. + }; + + struct Config { + Config(); + Config(int pixels, + int fps, + int kbps, + int kbps_res, + int fps_diff, + CodecTypeSpecific vp8, + CodecTypeSpecific vp9, + CodecTypeSpecific h264, + CodecTypeSpecific av1, + CodecTypeSpecific generic); + + bool operator==(const Config& o) const { + return pixels == o.pixels && fps == o.fps && kbps == o.kbps && + kbps_res == o.kbps_res && fps_diff == o.fps_diff && vp8 == o.vp8 && + vp9 == o.vp9 && h264 == o.h264 && av1 == o.av1 && + generic == o.generic; + } + + // Example: + // WebRTC-Video-BalancedDegradationSettings/pixels:100|200|300,fps:5|15|25/ + // pixels <= 100 -> min framerate: 5 fps + // pixels <= 200 -> min framerate: 15 fps + // pixels <= 300 -> min framerate: 25 fps + // + // WebRTC-Video-BalancedDegradationSettings/pixels:100|200|300, + // fps:5|15|25, // Min framerate. + // kbps:0|60|70, // Min bitrate needed to adapt up. + // kbps_res:0|65|75/ // Min bitrate needed to adapt up in resolution. + // + // pixels: fps: kbps: kbps_res: + // 300 30 - - + // 300 25 70 kbps 75 kbps + // 200 25 70 kbps - + // 200 15 60 kbps 65 kbps + // 100 15 60 kbps - + // 100 5 + // optional optional + + int pixels = 0; // Video frame size. + // If the frame size is less than or equal to `pixels`: + int fps = 0; // Min framerate to be used. + int kbps = 0; // Min bitrate needed to adapt up (resolution/fps). + int kbps_res = 0; // Min bitrate needed to adapt up in resolution. + int fps_diff = kNoFpsDiff; // Min fps reduction needed (input fps - `fps`) + // w/o triggering a new subsequent downgrade + // check. + CodecTypeSpecific vp8; + CodecTypeSpecific vp9; + CodecTypeSpecific h264; + CodecTypeSpecific av1; + CodecTypeSpecific generic; + }; + + // Returns configurations from field trial on success (default on failure). + std::vector GetConfigs() const; + + // Gets the min/max framerate from `configs_` based on `pixels`. + int MinFps(VideoCodecType type, int pixels) const; + int MaxFps(VideoCodecType type, int pixels) const; + + // Checks if quality can be increased based on `pixels` and `bitrate_bps`. + bool CanAdaptUp(VideoCodecType type, int pixels, uint32_t bitrate_bps) const; + bool CanAdaptUpResolution(VideoCodecType type, + int pixels, + uint32_t bitrate_bps) const; + + // Gets the min framerate diff from `configs_` based on `pixels`. + absl::optional MinFpsDiff(int pixels) const; + + // Gets QpThresholds for the codec `type` based on `pixels`. + absl::optional GetQpThresholds( + VideoCodecType type, + int pixels) const; + + private: + absl::optional GetMinFpsConfig(int pixels) const; + absl::optional GetMaxFpsConfig(int pixels) const; + Config GetConfig(int pixels) const; + + std::vector configs_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_BALANCED_DEGRADATION_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build new file mode 100644 index 0000000000..34b388da69 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("balanced_degradation_settings_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc new file mode 100644 index 0000000000..a32dbb4aaa --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc @@ -0,0 +1,620 @@ +/* + * 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/balanced_degradation_settings.h" + +#include + +#include "rtc_base/gunit.h" +#include "test/gmock.h" +#include "test/scoped_key_value_config.h" + +namespace webrtc { +namespace { + +void VerifyIsDefault( + const std::vector& config) { + EXPECT_THAT(config, ::testing::ElementsAre( + BalancedDegradationSettings::Config{ + 320 * 240, + 7, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 480 * 360, + 10, + 0, + 0, + 1, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 640 * 480, + 15, + 0, + 0, + 1, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}})); +} +} // namespace + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfNoList) { + webrtc::test::ScopedKeyValueConfig field_trials(""); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); + EXPECT_TRUE(settings.CanAdaptUp(kVideoCodecVP8, 1, /*bitrate_bps*/ 1)); + EXPECT_TRUE( + settings.CanAdaptUpResolution(kVideoCodecVP8, 1, /*bitrate_bps*/ 1)); + EXPECT_FALSE(settings.MinFpsDiff(1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecVP8, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecVP9, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecH264, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecAV1, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecGeneric, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecMultiplex, 1)); +} + +TEST(BalancedDegradationSettings, GetsConfig) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:11|22|33,fps:5|15|25,other:4|5|6/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_THAT(settings.GetConfigs(), + ::testing::ElementsAre( + BalancedDegradationSettings::Config{ + 11, + 5, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 22, + 15, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 33, + 25, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}})); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigForZeroFpsValue) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:0|15|25/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfPixelsDecreases) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|999|3000,fps:5|15|25/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfFramerateDecreases) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|4|25/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsConfigWithSpecificFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_fps:7|8|9,vp9_fps:9|10|11," + "h264_fps:11|12|13,av1_fps:1|2|3,generic_fps:13|14|15/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_THAT(settings.GetConfigs(), + ::testing::ElementsAre( + BalancedDegradationSettings::Config{ + 1000, + 5, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 7, 0, 0}, + {0, 0, 9, 0, 0}, + {0, 0, 11, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 13, 0, 0}}, + BalancedDegradationSettings::Config{ + 2000, + 15, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 8, 0, 0}, + {0, 0, 10, 0, 0}, + {0, 0, 12, 0, 0}, + {0, 0, 2, 0, 0}, + {0, 0, 14, 0, 0}}, + BalancedDegradationSettings::Config{ + 3000, + 25, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 9, 0, 0}, + {0, 0, 11, 0, 0}, + {0, 0, 13, 0, 0}, + {0, 0, 3, 0, 0}, + {0, 0, 15, 0, 0}})); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigForZeroVp8FpsValue) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:7|15|25,vp8_fps:0|15|25/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigForInvalidFpsValue) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:7|15|25,vp8_fps:10|15|2000/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfVp8FramerateDecreases) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:4|5|25,vp8_fps:5|4|25/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsMinFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(5, settings.MinFps(kVideoCodecVP8, 1)); + EXPECT_EQ(5, settings.MinFps(kVideoCodecVP8, 1000)); + EXPECT_EQ(15, settings.MinFps(kVideoCodecVP8, 1001)); + EXPECT_EQ(15, settings.MinFps(kVideoCodecVP8, 2000)); + EXPECT_EQ(25, settings.MinFps(kVideoCodecVP8, 2001)); + EXPECT_EQ(25, settings.MinFps(kVideoCodecVP8, 3000)); + EXPECT_EQ(std::numeric_limits::max(), + settings.MinFps(kVideoCodecVP8, 3001)); +} + +TEST(BalancedDegradationSettings, GetsVp8MinFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_fps:7|10|12/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(7, settings.MinFps(kVideoCodecVP8, 1)); + EXPECT_EQ(7, settings.MinFps(kVideoCodecVP8, 1000)); + EXPECT_EQ(10, settings.MinFps(kVideoCodecVP8, 1001)); + EXPECT_EQ(10, settings.MinFps(kVideoCodecVP8, 2000)); + EXPECT_EQ(12, settings.MinFps(kVideoCodecVP8, 2001)); + EXPECT_EQ(12, settings.MinFps(kVideoCodecVP8, 3000)); + EXPECT_EQ(std::numeric_limits::max(), + settings.MinFps(kVideoCodecVP8, 3001)); +} + +TEST(BalancedDegradationSettings, GetsMaxFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(15, settings.MaxFps(kVideoCodecVP8, 1)); + EXPECT_EQ(15, settings.MaxFps(kVideoCodecVP8, 1000)); + EXPECT_EQ(25, settings.MaxFps(kVideoCodecVP8, 1001)); + EXPECT_EQ(25, settings.MaxFps(kVideoCodecVP8, 2000)); + EXPECT_EQ(std::numeric_limits::max(), + settings.MaxFps(kVideoCodecVP8, 2001)); +} + +TEST(BalancedDegradationSettings, GetsVp8MaxFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_fps:7|10|12/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(10, settings.MaxFps(kVideoCodecVP8, 1)); + EXPECT_EQ(10, settings.MaxFps(kVideoCodecVP8, 1000)); + EXPECT_EQ(12, settings.MaxFps(kVideoCodecVP8, 1001)); + EXPECT_EQ(12, settings.MaxFps(kVideoCodecVP8, 2000)); + EXPECT_EQ(std::numeric_limits::max(), + settings.MaxFps(kVideoCodecVP8, 2001)); +} + +TEST(BalancedDegradationSettings, GetsVp9Fps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp9_fps:7|10|12/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(7, settings.MinFps(kVideoCodecVP9, 1000)); + EXPECT_EQ(10, settings.MaxFps(kVideoCodecVP9, 1000)); +} + +TEST(BalancedDegradationSettings, GetsH264Fps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,h264_fps:8|11|13/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(11, settings.MinFps(kVideoCodecH264, 2000)); + EXPECT_EQ(13, settings.MaxFps(kVideoCodecH264, 2000)); +} + +TEST(BalancedDegradationSettings, GetsGenericFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,generic_fps:9|12|14/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(14, settings.MinFps(kVideoCodecGeneric, 3000)); + EXPECT_EQ(std::numeric_limits::max(), + settings.MaxFps(kVideoCodecGeneric, 3000)); +} + +TEST(BalancedDegradationSettings, GetsUnlimitedForMaxValidFps) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|100,vp8_fps:30|100|100/"); + const int kUnlimitedFps = std::numeric_limits::max(); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(15, settings.MinFps(kVideoCodecH264, 2000)); + EXPECT_EQ(kUnlimitedFps, settings.MinFps(kVideoCodecH264, 2001)); + EXPECT_EQ(30, settings.MinFps(kVideoCodecVP8, 1000)); + EXPECT_EQ(kUnlimitedFps, settings.MinFps(kVideoCodecVP8, 1001)); +} + +TEST(BalancedDegradationSettings, GetsConfigWithBitrate) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:11|22|33,fps:5|15|25,kbps:44|88|99,kbps_res:55|111|222," + "vp8_kbps:11|12|13,vp8_kbps_res:14|15|16," + "vp9_kbps:21|22|23,vp9_kbps_res:24|25|26," + "h264_kbps:31|32|33,h264_kbps_res:34|35|36," + "av1_kbps:41|42|43,av1_kbps_res:44|45|46," + "generic_kbps:51|52|53,generic_kbps_res:54|55|56/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_THAT(settings.GetConfigs(), + ::testing::ElementsAre( + BalancedDegradationSettings::Config{ + 11, + 5, + 44, + 55, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 11, 14}, + {0, 0, 0, 21, 24}, + {0, 0, 0, 31, 34}, + {0, 0, 0, 41, 44}, + {0, 0, 0, 51, 54}}, + BalancedDegradationSettings::Config{ + 22, + 15, + 88, + 111, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 12, 15}, + {0, 0, 0, 22, 25}, + {0, 0, 0, 32, 35}, + {0, 0, 0, 42, 45}, + {0, 0, 0, 52, 55}}, + BalancedDegradationSettings::Config{ + 33, + 25, + 99, + 222, + BalancedDegradationSettings::kNoFpsDiff, + {0, 0, 0, 13, 16}, + {0, 0, 0, 23, 26}, + {0, 0, 0, 33, 36}, + {0, 0, 0, 43, 46}, + {0, 0, 0, 53, 56}})); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfBitrateDecreases) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:11|22|33,fps:5|15|25,kbps:44|43|99/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, + GetsDefaultConfigIfBitrateDecreasesWithUnsetValue) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:11|22|33,fps:5|15|25,kbps:44|0|43/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, CanAdaptUp) { + VideoCodecType vp8 = kVideoCodecVP8; + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000|4000,fps:5|15|25|30,kbps:0|80|0|90," + "vp9_kbps:40|50|60|70/"); + BalancedDegradationSettings s(field_trials); + EXPECT_TRUE(s.CanAdaptUp(vp8, 1000, 0)); // No bitrate provided. + EXPECT_FALSE(s.CanAdaptUp(vp8, 1000, 79000)); + EXPECT_TRUE(s.CanAdaptUp(vp8, 1000, 80000)); + EXPECT_TRUE(s.CanAdaptUp(vp8, 1001, 1)); // No limit configured. + EXPECT_FALSE(s.CanAdaptUp(vp8, 3000, 89000)); + EXPECT_TRUE(s.CanAdaptUp(vp8, 3000, 90000)); + EXPECT_TRUE(s.CanAdaptUp(vp8, 3001, 1)); // No limit. +} + +TEST(BalancedDegradationSettings, CanAdaptUpWithCodecType) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000|4000,fps:5|15|25|30,vp8_kbps:0|30|40|50," + "vp9_kbps:0|60|70|80,h264_kbps:0|55|65|75,av1_kbps:0|77|88|99," + "generic_kbps:0|25|35|45/"); + BalancedDegradationSettings s(field_trials); + EXPECT_FALSE(s.CanAdaptUp(kVideoCodecVP8, 1000, 29000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecVP8, 1000, 30000)); + EXPECT_FALSE(s.CanAdaptUp(kVideoCodecVP9, 1000, 59000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecVP9, 1000, 60000)); + EXPECT_FALSE(s.CanAdaptUp(kVideoCodecH264, 1000, 54000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecH264, 1000, 55000)); + EXPECT_FALSE(s.CanAdaptUp(kVideoCodecAV1, 1000, 76000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecAV1, 1000, 77000)); + EXPECT_FALSE(s.CanAdaptUp(kVideoCodecGeneric, 1000, 24000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecGeneric, 1000, 25000)); + EXPECT_TRUE(s.CanAdaptUp(kVideoCodecMultiplex, 1000, 1)); // Not configured. +} + +TEST(BalancedDegradationSettings, CanAdaptUpResolution) { + VideoCodecType vp8 = kVideoCodecVP8; + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000|4000,fps:5|15|25|30,kbps_res:0|80|0|90," + "vp9_kbps_res:40|50|60|70/"); + BalancedDegradationSettings s(field_trials); + EXPECT_TRUE(s.CanAdaptUpResolution(vp8, 1000, 0)); // No bitrate provided. + EXPECT_FALSE(s.CanAdaptUpResolution(vp8, 1000, 79000)); + EXPECT_TRUE(s.CanAdaptUpResolution(vp8, 1000, 80000)); + EXPECT_TRUE(s.CanAdaptUpResolution(vp8, 1001, 1)); // No limit configured. + EXPECT_FALSE(s.CanAdaptUpResolution(vp8, 3000, 89000)); + EXPECT_TRUE(s.CanAdaptUpResolution(vp8, 3000, 90000)); + EXPECT_TRUE(s.CanAdaptUpResolution(vp8, 3001, 1)); // No limit. +} + +TEST(BalancedDegradationSettings, CanAdaptUpResolutionWithCodecType) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000|4000,fps:5|15|25|30,vp8_kbps_res:0|30|40|50," + "vp9_kbps_res:0|60|70|80,h264_kbps_res:0|55|65|75," + "av1_kbps_res:0|77|88|99,generic_kbps_res:0|25|35|45/"); + BalancedDegradationSettings s(field_trials); + EXPECT_FALSE(s.CanAdaptUpResolution(kVideoCodecVP8, 1000, 29000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecVP8, 1000, 30000)); + EXPECT_FALSE(s.CanAdaptUpResolution(kVideoCodecVP9, 1000, 59000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecVP9, 1000, 60000)); + EXPECT_FALSE(s.CanAdaptUpResolution(kVideoCodecH264, 1000, 54000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecH264, 1000, 55000)); + EXPECT_FALSE(s.CanAdaptUpResolution(kVideoCodecAV1, 1000, 76000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecAV1, 1000, 77000)); + EXPECT_FALSE(s.CanAdaptUpResolution(kVideoCodecGeneric, 1000, 24000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecGeneric, 1000, 25000)); + EXPECT_TRUE(s.CanAdaptUpResolution(kVideoCodecMultiplex, 1000, + 1)); // Not configured. +} + +TEST(BalancedDegradationSettings, GetsFpsDiff) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,fps_diff:0|-2|3/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(0, settings.MinFpsDiff(1)); + EXPECT_EQ(0, settings.MinFpsDiff(1000)); + EXPECT_EQ(-2, settings.MinFpsDiff(1001)); + EXPECT_EQ(-2, settings.MinFpsDiff(2000)); + EXPECT_EQ(3, settings.MinFpsDiff(2001)); + EXPECT_EQ(3, settings.MinFpsDiff(3000)); + EXPECT_FALSE(settings.MinFpsDiff(3001)); +} + +TEST(BalancedDegradationSettings, GetsNoFpsDiffIfValueBelowMinSetting) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,fps_diff:-100|-99|-101/"); + // Min valid fps_diff setting: -99. + BalancedDegradationSettings settings(field_trials); + EXPECT_FALSE(settings.MinFpsDiff(1000)); + EXPECT_EQ(-99, settings.MinFpsDiff(2000)); + EXPECT_FALSE(settings.MinFpsDiff(3000)); +} + +TEST(BalancedDegradationSettings, QpThresholdsNotSetByDefault) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecVP8, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecVP9, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecH264, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecAV1, 1)); + EXPECT_FALSE(settings.GetQpThresholds(kVideoCodecGeneric, 1)); +} + +TEST(BalancedDegradationSettings, GetsConfigWithQpThresholds) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_qp_low:89|90|88," + "vp8_qp_high:90|91|92,vp9_qp_low:27|28|29,vp9_qp_high:120|130|140," + "h264_qp_low:12|13|14,h264_qp_high:20|30|40,av1_qp_low:2|3|4," + "av1_qp_high:11|33|44,generic_qp_low:7|6|5,generic_qp_high:22|23|24/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_THAT(settings.GetConfigs(), + ::testing::ElementsAre( + BalancedDegradationSettings::Config{ + 1000, + 5, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {89, 90, 0, 0, 0}, + {27, 120, 0, 0, 0}, + {12, 20, 0, 0, 0}, + {2, 11, 0, 0, 0}, + {7, 22, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 2000, + 15, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {90, 91, 0, 0, 0}, + {28, 130, 0, 0, 0}, + {13, 30, 0, 0, 0}, + {3, 33, 0, 0, 0}, + {6, 23, 0, 0, 0}}, + BalancedDegradationSettings::Config{ + 3000, + 25, + 0, + 0, + BalancedDegradationSettings::kNoFpsDiff, + {88, 92, 0, 0, 0}, + {29, 140, 0, 0, 0}, + {14, 40, 0, 0, 0}, + {4, 44, 0, 0, 0}, + {5, 24, 0, 0, 0}})); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfOnlyHasLowThreshold) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_qp_low:89|90|88/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfOnlyHasHighThreshold) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25,vp8_qp_high:90|91|92/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfLowEqualsHigh) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "vp8_qp_low:89|90|88,vp8_qp_high:90|91|88/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigIfLowGreaterThanHigh) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "vp8_qp_low:89|90|88,vp8_qp_high:90|91|87/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsDefaultConfigForZeroQpValue) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "vp8_qp_low:89|0|88,vp8_qp_high:90|91|92/"); + BalancedDegradationSettings settings(field_trials); + VerifyIsDefault(settings.GetConfigs()); +} + +TEST(BalancedDegradationSettings, GetsVp8QpThresholds) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "vp8_qp_low:89|90|88,vp8_qp_high:90|91|92/"); + BalancedDegradationSettings settings(field_trials); + EXPECT_EQ(89, settings.GetQpThresholds(kVideoCodecVP8, 1)->low); + EXPECT_EQ(90, settings.GetQpThresholds(kVideoCodecVP8, 1)->high); + EXPECT_EQ(90, settings.GetQpThresholds(kVideoCodecVP8, 1000)->high); + EXPECT_EQ(91, settings.GetQpThresholds(kVideoCodecVP8, 1001)->high); + EXPECT_EQ(91, settings.GetQpThresholds(kVideoCodecVP8, 2000)->high); + EXPECT_EQ(92, settings.GetQpThresholds(kVideoCodecVP8, 2001)->high); + EXPECT_EQ(92, settings.GetQpThresholds(kVideoCodecVP8, 3000)->high); + EXPECT_EQ(92, settings.GetQpThresholds(kVideoCodecVP8, 3001)->high); +} + +TEST(BalancedDegradationSettings, GetsVp9QpThresholds) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "vp9_qp_low:55|56|57,vp9_qp_high:155|156|157/"); + BalancedDegradationSettings settings(field_trials); + const auto thresholds = settings.GetQpThresholds(kVideoCodecVP9, 1000); + EXPECT_TRUE(thresholds); + EXPECT_EQ(55, thresholds->low); + EXPECT_EQ(155, thresholds->high); +} + +TEST(BalancedDegradationSettings, GetsH264QpThresholds) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "h264_qp_low:21|22|23,h264_qp_high:41|43|42/"); + BalancedDegradationSettings settings(field_trials); + const auto thresholds = settings.GetQpThresholds(kVideoCodecH264, 2000); + EXPECT_TRUE(thresholds); + EXPECT_EQ(22, thresholds->low); + EXPECT_EQ(43, thresholds->high); +} + +TEST(BalancedDegradationSettings, GetsGenericQpThresholds) { + webrtc::test::ScopedKeyValueConfig field_trials( + "WebRTC-Video-BalancedDegradationSettings/" + "pixels:1000|2000|3000,fps:5|15|25," + "generic_qp_low:2|3|4,generic_qp_high:22|23|24/"); + BalancedDegradationSettings settings(field_trials); + const auto thresholds = settings.GetQpThresholds(kVideoCodecGeneric, 3000); + EXPECT_TRUE(thresholds); + EXPECT_EQ(4, thresholds->low); + EXPECT_EQ(24, thresholds->high); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc new file mode 100644 index 0000000000..0a9df493ed --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 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/bandwidth_quality_scaler_settings.h" + +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +BandwidthQualityScalerSettings::BandwidthQualityScalerSettings( + const FieldTrialsView* const key_value_config) + : bitrate_state_update_interval_s_("bitrate_state_update_interval_s_") { + ParseFieldTrial( + {&bitrate_state_update_interval_s_}, + key_value_config->Lookup("WebRTC-Video-BandwidthQualityScalerSettings")); +} + +BandwidthQualityScalerSettings +BandwidthQualityScalerSettings::ParseFromFieldTrials() { + FieldTrialBasedConfig field_trial_config; + return BandwidthQualityScalerSettings(&field_trial_config); +} + +absl::optional +BandwidthQualityScalerSettings::BitrateStateUpdateInterval() const { + if (bitrate_state_update_interval_s_ && + bitrate_state_update_interval_s_.Value() <= 0) { + RTC_LOG(LS_WARNING) + << "Unsupported bitrate_state_update_interval_s_ value, ignored."; + return absl::nullopt; + } + return bitrate_state_update_interval_s_.GetOptional(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.h b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.h new file mode 100644 index 0000000000..21e115df01 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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_BANDWIDTH_QUALITY_SCALER_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_BANDWIDTH_QUALITY_SCALER_SETTINGS_H_ + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class BandwidthQualityScalerSettings final { + public: + static BandwidthQualityScalerSettings ParseFromFieldTrials(); + + absl::optional BitrateStateUpdateInterval() const; + + private: + explicit BandwidthQualityScalerSettings( + const FieldTrialsView* const key_value_config); + + FieldTrialOptional bitrate_state_update_interval_s_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_BANDWIDTH_QUALITY_SCALER_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build new file mode 100644 index 0000000000..ccc00e5296 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("bandwidth_quality_scaler_settings_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_unittest.cc new file mode 100644 index 0000000000..fab22cede0 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_unittest.cc @@ -0,0 +1,49 @@ +/* + * Copyright 2021 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/bandwidth_quality_scaler_settings.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +TEST(BandwidthQualityScalerSettingsTest, ValuesNotSetByDefault) { + const auto settings = BandwidthQualityScalerSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings.BitrateStateUpdateInterval()); +} + +TEST(BandwidthQualityScalerSettingsTest, ParseBitrateStateUpdateInterval) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-BandwidthQualityScalerSettings/" + "bitrate_state_update_interval_s_:100/"); + EXPECT_EQ(100u, BandwidthQualityScalerSettings::ParseFromFieldTrials() + .BitrateStateUpdateInterval()); +} + +TEST(BandwidthQualityScalerSettingsTest, ParseAll) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-BandwidthQualityScalerSettings/" + "bitrate_state_update_interval_s_:100/"); + EXPECT_EQ(100u, BandwidthQualityScalerSettings::ParseFromFieldTrials() + .BitrateStateUpdateInterval()); +} + +TEST(BandwidthQualityScalerSettingsTest, DoesNotParseIncorrectValue) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-BandwidthQualityScalerSettings/" + "bitrate_state_update_interval_s_:??/"); + const auto settings = BandwidthQualityScalerSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings.BitrateStateUpdateInterval()); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc new file mode 100644 index 0000000000..7e61255260 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc @@ -0,0 +1,89 @@ +/* + * Copyright 2018 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/cpu_speed_experiment.h" + +#include + +#include "rtc_base/experiments/field_trial_list.h" +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { +namespace { +constexpr char kFieldTrial[] = "WebRTC-VP8-CpuSpeed-Arm"; +constexpr int kMinSetting = -16; +constexpr int kMaxSetting = -1; + +std::vector GetValidOrEmpty( + const std::vector& configs) { + if (configs.empty()) { + return {}; + } + + for (const auto& config : configs) { + if (config.cpu_speed < kMinSetting || config.cpu_speed > kMaxSetting) { + RTC_LOG(LS_WARNING) << "Unsupported cpu speed setting, value ignored."; + return {}; + } + } + + for (size_t i = 1; i < configs.size(); ++i) { + if (configs[i].pixels < configs[i - 1].pixels || + configs[i].cpu_speed > configs[i - 1].cpu_speed) { + RTC_LOG(LS_WARNING) << "Invalid parameter value provided."; + return {}; + } + } + + return configs; +} + +bool HasLeCores(const std::vector& configs) { + for (const auto& config : configs) { + if (config.cpu_speed_le_cores == 0) + return false; + } + return true; +} +} // namespace + +CpuSpeedExperiment::CpuSpeedExperiment() : cores_("cores") { + FieldTrialStructList configs( + {FieldTrialStructMember("pixels", [](Config* c) { return &c->pixels; }), + FieldTrialStructMember("cpu_speed", + [](Config* c) { return &c->cpu_speed; }), + FieldTrialStructMember( + "cpu_speed_le_cores", + [](Config* c) { return &c->cpu_speed_le_cores; })}, + {}); + ParseFieldTrial({&configs, &cores_}, field_trial::FindFullName(kFieldTrial)); + + configs_ = GetValidOrEmpty(configs.Get()); +} + +CpuSpeedExperiment::~CpuSpeedExperiment() {} + +absl::optional CpuSpeedExperiment::GetValue(int pixels, + int num_cores) const { + if (configs_.empty()) + return absl::nullopt; + + bool use_le = HasLeCores(configs_) && cores_ && num_cores <= cores_.Value(); + + for (const auto& config : configs_) { + if (pixels <= config.pixels) + return use_le ? absl::optional(config.cpu_speed_le_cores) + : absl::optional(config.cpu_speed); + } + return absl::optional(kMinSetting); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h new file mode 100644 index 0000000000..025c1ea8c9 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h @@ -0,0 +1,65 @@ +/* + * Copyright 2018 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_CPU_SPEED_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_CPU_SPEED_EXPERIMENT_H_ + +#include + +#include "absl/types/optional.h" + +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class CpuSpeedExperiment { + public: + CpuSpeedExperiment(); + ~CpuSpeedExperiment(); + + // Example: + // WebRTC-VP8-CpuSpeed-Arm/pixels:100|200|300,cpu_speed:-1|-2|-3/ + // pixels <= 100 -> cpu speed: -1 + // pixels <= 200 -> cpu speed: -2 + // pixels <= 300 -> cpu speed: -3 + + // WebRTC-VP8-CpuSpeed-Arm/pixels:100|200|300,cpu_speed:-1|-2|-3/, + // cpu_speed_le_cores:-4|-5|-6,cores:3/ + // If `num_cores` > 3 + // pixels <= 100 -> cpu speed: -1 + // pixels <= 200 -> cpu speed: -2 + // pixels <= 300 -> cpu speed: -3 + // else + // pixels <= 100 -> cpu speed: -4 + // pixels <= 200 -> cpu speed: -5 + // pixels <= 300 -> cpu speed: -6 + + struct Config { + int pixels = 0; // The video frame size. + int cpu_speed = 0; // The `cpu_speed` to be used if the frame size is less + // than or equal to `pixels`. + // Optional. + int cpu_speed_le_cores = 0; // Same as `cpu_speed` above but only used if + // `num_cores` <= `cores_`. + }; + + // Gets the cpu speed based on `pixels` and `num_cores`. + absl::optional GetValue(int pixels, int num_cores) const; + + private: + std::vector configs_; + + // Threshold for when to use `cpu_speed_le_cores`. + FieldTrialOptional cores_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_CPU_SPEED_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build new file mode 100644 index 0000000000..66d21c66a3 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("cpu_speed_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_unittest.cc new file mode 100644 index 0000000000..2105da3818 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_unittest.cc @@ -0,0 +1,106 @@ +/* + * Copyright 2018 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/cpu_speed_experiment.h" + +#include "rtc_base/gunit.h" +#include "test/field_trial.h" +#include "test/gmock.h" + +namespace webrtc { + +TEST(CpuSpeedExperimentTest, NoValueIfNotEnabled) { + CpuSpeedExperiment cpu_speed_config; + EXPECT_FALSE(cpu_speed_config.GetValue(1, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValue) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000,cpu_speed:-12,cores:4/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_EQ(-12, cpu_speed_config.GetValue(1, /*num_cores=*/1)); + EXPECT_EQ(-12, cpu_speed_config.GetValue(1000, /*num_cores=*/1)); + EXPECT_EQ(-16, cpu_speed_config.GetValue(1001, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValueWithList) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000|2000|3000,cpu_speed:-1|-10|-16/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_EQ(-1, cpu_speed_config.GetValue(1, /*num_cores=*/1)); + EXPECT_EQ(-1, cpu_speed_config.GetValue(1000, /*num_cores=*/1)); + EXPECT_EQ(-10, cpu_speed_config.GetValue(1001, /*num_cores=*/1)); + EXPECT_EQ(-10, cpu_speed_config.GetValue(2000, /*num_cores=*/1)); + EXPECT_EQ(-16, cpu_speed_config.GetValue(2001, /*num_cores=*/1)); + EXPECT_EQ(-16, cpu_speed_config.GetValue(3000, /*num_cores=*/1)); + EXPECT_EQ(-16, cpu_speed_config.GetValue(3001, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValueWithCores) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/" + "pixels:1000|2000|3000,cpu_speed:-1|-10|-16," + "cpu_speed_le_cores:-5|-11|-16,cores:2/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_EQ(-5, cpu_speed_config.GetValue(1000, /*num_cores=*/1)); + EXPECT_EQ(-11, cpu_speed_config.GetValue(2000, /*num_cores=*/2)); + EXPECT_EQ(-1, cpu_speed_config.GetValue(1000, /*num_cores=*/3)); + EXPECT_EQ(-10, cpu_speed_config.GetValue(2000, /*num_cores=*/4)); +} + +TEST(CpuSpeedExperimentTest, GetValueWithCoresUnconfigured) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/" + "pixels:1000|2000|3000,cpu_speed:-1|-10|-16," + "cpu_speed_le_cores:-5|-11|-16/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_EQ(-1, cpu_speed_config.GetValue(1000, /*num_cores=*/1)); + EXPECT_EQ(-10, cpu_speed_config.GetValue(2000, /*num_cores=*/2)); +} + +TEST(CpuSpeedExperimentTest, GetValueFailsForTooSmallValue) { + // Supported range: [-16, -1]. + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000|2000|3000,cpu_speed:-1|-10|-17/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_FALSE(cpu_speed_config.GetValue(1, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValueFailsForTooLargeValue) { + // Supported range: [-16, -1]. + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000|2000|3000,cpu_speed:0|-10|-16/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_FALSE(cpu_speed_config.GetValue(1, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValueFailsIfPixelsDecreases) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000|999|3000,cpu_speed:-5|-10|-16/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_FALSE(cpu_speed_config.GetValue(1, /*num_cores=*/1)); +} + +TEST(CpuSpeedExperimentTest, GetValueFailsIfCpuSpeedIncreases) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-CpuSpeed-Arm/pixels:1000|2000|3000,cpu_speed:-5|-4|-16/"); + + CpuSpeedExperiment cpu_speed_config; + EXPECT_FALSE(cpu_speed_config.GetValue(1, /*num_cores=*/1)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc new file mode 100644 index 0000000000..5f0bf2d7ac --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc @@ -0,0 +1,214 @@ +/* + * Copyright 2021 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/encoder_info_settings.h" + +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/experiments/field_trial_list.h" +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { +namespace { + +std::vector ToResolutionBitrateLimits( + const std::vector& limits) { + std::vector result; + for (const auto& limit : limits) { + result.push_back(VideoEncoder::ResolutionBitrateLimits( + limit.frame_size_pixels, limit.min_start_bitrate_bps, + limit.min_bitrate_bps, limit.max_bitrate_bps)); + } + return result; +} +constexpr float kDefaultMinBitratebps = 30000; +} // namespace + +// Default bitrate limits for simulcast with one active stream: +// {frame_size_pixels, min_start_bitrate_bps, min_bitrate_bps, max_bitrate_bps}. +std::vector +EncoderInfoSettings::GetDefaultSinglecastBitrateLimits( + VideoCodecType codec_type) { + // Specific limits for VP9. Other codecs use VP8 limits. + if (codec_type == kVideoCodecVP9) { + return {{320 * 180, 0, 30000, 150000}, + {480 * 270, 120000, 30000, 300000}, + {640 * 360, 190000, 30000, 420000}, + {960 * 540, 350000, 30000, 1000000}, + {1280 * 720, 480000, 30000, 1500000}}; + } + + return {{320 * 180, 0, 30000, 300000}, + {480 * 270, 200000, 30000, 500000}, + {640 * 360, 300000, 30000, 800000}, + {960 * 540, 500000, 30000, 1500000}, + {1280 * 720, 900000, 30000, 2500000}}; +} + +absl::optional +EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( + VideoCodecType codec_type, + int frame_size_pixels) { + VideoEncoder::EncoderInfo info; + info.resolution_bitrate_limits = + GetDefaultSinglecastBitrateLimits(codec_type); + return info.GetEncoderBitrateLimitsForResolution(frame_size_pixels); +} + +// Return the suitable bitrate limits for specified resolution when qp is +// untrusted, they are experimental values. +// TODO(bugs.webrtc.org/12942): Maybe we need to add other codecs(VP8/VP9) +// experimental values. +std::vector +EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted() { + // Specific limits for H264/AVC + return {{0 * 0, 0, 0, 0}, + {320 * 180, 0, 30000, 300000}, + {480 * 270, 300000, 30000, 500000}, + {640 * 360, 500000, 30000, 800000}, + {960 * 540, 800000, 30000, 1500000}, + {1280 * 720, 1500000, 30000, 2500000}, + {1920 * 1080, 2500000, 30000, 4000000}}; +} + +// Through linear interpolation, return the bitrate limit corresponding to the +// specified |frame_size_pixels|. +absl::optional +EncoderInfoSettings::GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted( + absl::optional frame_size_pixels, + const std::vector& + resolution_bitrate_limits) { + if (!frame_size_pixels.has_value() || frame_size_pixels.value() <= 0) { + return absl::nullopt; + } + + std::vector bitrate_limits = + resolution_bitrate_limits; + + // Sort the list of bitrate limits by resolution. + sort(bitrate_limits.begin(), bitrate_limits.end(), + [](const VideoEncoder::ResolutionBitrateLimits& lhs, + const VideoEncoder::ResolutionBitrateLimits& rhs) { + return lhs.frame_size_pixels < rhs.frame_size_pixels; + }); + + if (bitrate_limits.empty()) { + return absl::nullopt; + } + + int interpolation_index = -1; + for (size_t i = 0; i < bitrate_limits.size(); ++i) { + if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels.value()) { + interpolation_index = i; + break; + } + } + + // -1 means that the maximum resolution is exceeded, we will select the + // largest data as the return result. + if (interpolation_index == -1) { + return *bitrate_limits.rbegin(); + } + + // If we have a matching resolution, return directly without interpolation. + if (bitrate_limits[interpolation_index].frame_size_pixels == + frame_size_pixels.value()) { + return bitrate_limits[interpolation_index]; + } + + // No matching resolution, do a linear interpolate. + int lower_pixel_count = + bitrate_limits[interpolation_index - 1].frame_size_pixels; + int upper_pixel_count = bitrate_limits[interpolation_index].frame_size_pixels; + float alpha = (frame_size_pixels.value() - lower_pixel_count) * 1.0 / + (upper_pixel_count - lower_pixel_count); + int min_start_bitrate_bps = static_cast( + bitrate_limits[interpolation_index].min_start_bitrate_bps * alpha + + bitrate_limits[interpolation_index - 1].min_start_bitrate_bps * + (1.0 - alpha)); + int max_bitrate_bps = static_cast( + bitrate_limits[interpolation_index].max_bitrate_bps * alpha + + bitrate_limits[interpolation_index - 1].max_bitrate_bps * (1.0 - alpha)); + + if (max_bitrate_bps >= min_start_bitrate_bps) { + return VideoEncoder::ResolutionBitrateLimits( + frame_size_pixels.value(), min_start_bitrate_bps, kDefaultMinBitratebps, + max_bitrate_bps); + } else { + RTC_LOG(LS_WARNING) + << "BitRate interpolation calculating result is abnormal. " + << " lower_pixel_count = " << lower_pixel_count + << " upper_pixel_count = " << upper_pixel_count + << " frame_size_pixels = " << frame_size_pixels.value() + << " min_start_bitrate_bps = " << min_start_bitrate_bps + << " min_bitrate_bps = " << kDefaultMinBitratebps + << " max_bitrate_bps = " << max_bitrate_bps; + return absl::nullopt; + } +} + +EncoderInfoSettings::EncoderInfoSettings(absl::string_view name) + : requested_resolution_alignment_("requested_resolution_alignment"), + apply_alignment_to_all_simulcast_layers_( + "apply_alignment_to_all_simulcast_layers") { + FieldTrialStructList bitrate_limits( + {FieldTrialStructMember( + "frame_size_pixels", + [](BitrateLimit* b) { return &b->frame_size_pixels; }), + FieldTrialStructMember( + "min_start_bitrate_bps", + [](BitrateLimit* b) { return &b->min_start_bitrate_bps; }), + FieldTrialStructMember( + "min_bitrate_bps", + [](BitrateLimit* b) { return &b->min_bitrate_bps; }), + FieldTrialStructMember( + "max_bitrate_bps", + [](BitrateLimit* b) { return &b->max_bitrate_bps; })}, + {}); + + std::string name_str(name); + if (field_trial::FindFullName(name_str).empty()) { + // Encoder name not found, use common string applying to all encoders. + name_str = "WebRTC-GetEncoderInfoOverride"; + } + + ParseFieldTrial({&bitrate_limits, &requested_resolution_alignment_, + &apply_alignment_to_all_simulcast_layers_}, + field_trial::FindFullName(name_str)); + + resolution_bitrate_limits_ = ToResolutionBitrateLimits(bitrate_limits.Get()); +} + +absl::optional EncoderInfoSettings::requested_resolution_alignment() + const { + if (requested_resolution_alignment_ && + requested_resolution_alignment_.Value() < 1) { + RTC_LOG(LS_WARNING) << "Unsupported alignment value, ignored."; + return absl::nullopt; + } + return requested_resolution_alignment_.GetOptional(); +} + +EncoderInfoSettings::~EncoderInfoSettings() {} + +SimulcastEncoderAdapterEncoderInfoSettings:: + SimulcastEncoderAdapterEncoderInfoSettings() + : EncoderInfoSettings( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride") {} + +LibvpxVp8EncoderInfoSettings::LibvpxVp8EncoderInfoSettings() + : EncoderInfoSettings("WebRTC-VP8-GetEncoderInfoOverride") {} + +LibvpxVp9EncoderInfoSettings::LibvpxVp9EncoderInfoSettings() + : EncoderInfoSettings("WebRTC-VP9-GetEncoderInfoOverride") {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h new file mode 100644 index 0000000000..f4227ed631 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h @@ -0,0 +1,93 @@ +/* + * Copyright 2021 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_ENCODER_INFO_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_ENCODER_INFO_SETTINGS_H_ + +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/video_codecs/video_encoder.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class EncoderInfoSettings { + public: + virtual ~EncoderInfoSettings(); + + // Bitrate limits per resolution. + struct BitrateLimit { + int frame_size_pixels = 0; // The video frame size. + int min_start_bitrate_bps = 0; // The minimum bitrate to start encoding. + int min_bitrate_bps = 0; // The minimum bitrate. + int max_bitrate_bps = 0; // The maximum bitrate. + }; + + absl::optional requested_resolution_alignment() const; + bool apply_alignment_to_all_simulcast_layers() const { + return apply_alignment_to_all_simulcast_layers_.Get(); + } + std::vector resolution_bitrate_limits() + const { + return resolution_bitrate_limits_; + } + + static std::vector + GetDefaultSinglecastBitrateLimits(VideoCodecType codec_type); + + static absl::optional + GetDefaultSinglecastBitrateLimitsForResolution(VideoCodecType codec_type, + int frame_size_pixels); + + static std::vector + GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted(); + + static absl::optional + GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted( + absl::optional frame_size_pixels, + const std::vector& + resolution_bitrate_limits); + + protected: + explicit EncoderInfoSettings(absl::string_view name); + + private: + FieldTrialOptional requested_resolution_alignment_; + FieldTrialFlag apply_alignment_to_all_simulcast_layers_; + std::vector resolution_bitrate_limits_; +}; + +// EncoderInfo settings for SimulcastEncoderAdapter. +class SimulcastEncoderAdapterEncoderInfoSettings : public EncoderInfoSettings { + public: + SimulcastEncoderAdapterEncoderInfoSettings(); + ~SimulcastEncoderAdapterEncoderInfoSettings() override {} +}; + +// EncoderInfo settings for LibvpxVp8Encoder. +class LibvpxVp8EncoderInfoSettings : public EncoderInfoSettings { + public: + LibvpxVp8EncoderInfoSettings(); + ~LibvpxVp8EncoderInfoSettings() override {} +}; + +// EncoderInfo settings for LibvpxVp9Encoder. +class LibvpxVp9EncoderInfoSettings : public EncoderInfoSettings { + public: + LibvpxVp9EncoderInfoSettings(); + ~LibvpxVp9EncoderInfoSettings() override {} +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_ENCODER_INFO_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build new file mode 100644 index 0000000000..1cf3a5d0f4 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("encoder_info_settings_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_unittest.cc new file mode 100644 index 0000000000..929c777821 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_unittest.cc @@ -0,0 +1,102 @@ +/* + * Copyright 2021 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/encoder_info_settings.h" + +#include "rtc_base/gunit.h" +#include "test/field_trial.h" +#include "test/gmock.h" + +namespace webrtc { + +TEST(SimulcastEncoderAdapterSettingsTest, NoValuesWithoutFieldTrial) { + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_EQ(absl::nullopt, settings.requested_resolution_alignment()); + EXPECT_FALSE(settings.apply_alignment_to_all_simulcast_layers()); + EXPECT_TRUE(settings.resolution_bitrate_limits().empty()); +} + +TEST(SimulcastEncoderAdapterSettingsTest, NoValueForInvalidAlignment) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/" + "requested_resolution_alignment:0/"); + + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_EQ(absl::nullopt, settings.requested_resolution_alignment()); +} + +TEST(SimulcastEncoderAdapterSettingsTest, GetResolutionAlignment) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/" + "requested_resolution_alignment:2/"); + + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_EQ(2u, settings.requested_resolution_alignment()); + EXPECT_FALSE(settings.apply_alignment_to_all_simulcast_layers()); + EXPECT_TRUE(settings.resolution_bitrate_limits().empty()); +} + +TEST(SimulcastEncoderAdapterSettingsTest, GetApplyAlignment) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/" + "requested_resolution_alignment:3," + "apply_alignment_to_all_simulcast_layers/"); + + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_EQ(3u, settings.requested_resolution_alignment()); + EXPECT_TRUE(settings.apply_alignment_to_all_simulcast_layers()); + EXPECT_TRUE(settings.resolution_bitrate_limits().empty()); +} + +TEST(SimulcastEncoderAdapterSettingsTest, GetResolutionBitrateLimits) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/" + "frame_size_pixels:123," + "min_start_bitrate_bps:11000," + "min_bitrate_bps:44000," + "max_bitrate_bps:77000/"); + + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_EQ(absl::nullopt, settings.requested_resolution_alignment()); + EXPECT_FALSE(settings.apply_alignment_to_all_simulcast_layers()); + EXPECT_THAT(settings.resolution_bitrate_limits(), + ::testing::ElementsAre(VideoEncoder::ResolutionBitrateLimits{ + 123, 11000, 44000, 77000})); +} + +TEST(SimulcastEncoderAdapterSettingsTest, GetResolutionBitrateLimitsWithList) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/" + "frame_size_pixels:123|456|789," + "min_start_bitrate_bps:11000|22000|33000," + "min_bitrate_bps:44000|55000|66000," + "max_bitrate_bps:77000|88000|99000/"); + + SimulcastEncoderAdapterEncoderInfoSettings settings; + EXPECT_THAT( + settings.resolution_bitrate_limits(), + ::testing::ElementsAre( + VideoEncoder::ResolutionBitrateLimits{123, 11000, 44000, 77000}, + VideoEncoder::ResolutionBitrateLimits{456, 22000, 55000, 88000}, + VideoEncoder::ResolutionBitrateLimits{789, 33000, 66000, 99000})); +} + +TEST(EncoderSettingsTest, CommonSettingsUsedIfEncoderNameUnspecified) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-VP8-GetEncoderInfoOverride/requested_resolution_alignment:2/" + "WebRTC-GetEncoderInfoOverride/requested_resolution_alignment:3/"); + + LibvpxVp8EncoderInfoSettings vp8_settings; + EXPECT_EQ(2u, vp8_settings.requested_resolution_alignment()); + LibvpxVp9EncoderInfoSettings vp9_settings; + EXPECT_EQ(3u, vp9_settings.requested_resolution_alignment()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc new file mode 100644 index 0000000000..72cd79f2d2 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc @@ -0,0 +1,59 @@ +/* + * 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/field_trial_list.h" + +#include "absl/strings/string_view.h" + +namespace webrtc { + +FieldTrialListBase::FieldTrialListBase(absl::string_view key) + : FieldTrialParameterInterface(key), + failed_(false), + parse_got_called_(false) {} + +bool FieldTrialListBase::Failed() const { + return failed_; +} +bool FieldTrialListBase::Used() const { + return parse_got_called_; +} + +int FieldTrialListWrapper::Length() { + return GetList()->Size(); +} +bool FieldTrialListWrapper::Failed() { + return GetList()->Failed(); +} +bool FieldTrialListWrapper::Used() { + return GetList()->Used(); +} + +bool FieldTrialStructListBase::Parse(absl::optional str_value) { + RTC_DCHECK_NOTREACHED(); + return true; +} + +int FieldTrialStructListBase::ValidateAndGetLength() { + int length = -1; + for (std::unique_ptr& list : sub_lists_) { + if (list->Failed()) + return -1; + else if (!list->Used()) + continue; + else if (length == -1) + length = list->Length(); + else if (length != list->Length()) + return -1; + } + + return length; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_list.h b/third_party/libwebrtc/rtc_base/experiments/field_trial_list.h new file mode 100644 index 0000000000..261977243a --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_list.h @@ -0,0 +1,226 @@ +/* + * Copyright 2018 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_FIELD_TRIAL_LIST_H_ +#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_ + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/string_encode.h" + +// List support for field trial strings. FieldTrialList and FieldTrialStructList +// are used similarly to the other FieldTrialParameters, but take a variable +// number of parameters. A FieldTrialList parses a |-delimeted string into a +// list of T, using ParseTypedParameter to parse the individual tokens. +// Example string: "my_list:1|2|3,empty_list,other_list:aardvark". + +// A FieldTrialStructList combines multiple lists into a list-of-structs. It +// ensures that all its sublists parse correctly and have the same length, then +// uses user-supplied accessor functions to write those elements into structs of +// a user-supplied type. + +// See the unit test for usage and behavior. + +namespace webrtc { + +class FieldTrialListBase : public FieldTrialParameterInterface { + protected: + friend class FieldTrialListWrapper; + explicit FieldTrialListBase(absl::string_view key); + + bool Failed() const; + bool Used() const; + + virtual int Size() = 0; + + bool failed_; + bool parse_got_called_; +}; + +// This class represents a vector of type T. The elements are separated by a | +// and parsed using ParseTypedParameter. +template +class FieldTrialList : public FieldTrialListBase { + public: + explicit FieldTrialList(absl::string_view key) : FieldTrialList(key, {}) {} + FieldTrialList(absl::string_view key, std::initializer_list default_values) + : FieldTrialListBase(key), values_(default_values) {} + + std::vector Get() const { return values_; } + operator std::vector() const { return Get(); } + typename std::vector::const_reference operator[](size_t index) const { + return values_[index]; + } + const std::vector* operator->() const { return &values_; } + + protected: + bool Parse(absl::optional str_value) override { + parse_got_called_ = true; + + if (!str_value) { + values_.clear(); + return true; + } + + std::vector new_values_; + + for (const absl::string_view token : rtc::split(str_value.value(), '|')) { + absl::optional value = ParseTypedParameter(token); + if (value) { + new_values_.push_back(*value); + } else { + failed_ = true; + return false; + } + } + + values_.swap(new_values_); + return true; + } + + int Size() override { return values_.size(); } + + private: + std::vector values_; +}; + +class FieldTrialListWrapper { + public: + virtual ~FieldTrialListWrapper() = default; + + // Takes the element at the given index in the wrapped list and writes it to + // the given struct. + virtual void WriteElement(void* struct_to_write, int index) = 0; + + virtual FieldTrialListBase* GetList() = 0; + + int Length(); + + // Returns true iff the wrapped list has failed to parse at least one token. + bool Failed(); + + bool Used(); + + protected: + FieldTrialListWrapper() = default; +}; + +namespace field_trial_list_impl { +// The LambdaTypeTraits struct provides type information about lambdas in the +// template expressions below. +template +struct LambdaTypeTraits : public LambdaTypeTraits {}; + +template +struct LambdaTypeTraits { + using ret = RetType; + using src = SourceType; +}; + +template +struct TypedFieldTrialListWrapper : FieldTrialListWrapper { + public: + TypedFieldTrialListWrapper(absl::string_view key, + std::function sink) + : list_(key), sink_(sink) {} + + void WriteElement(void* struct_to_write, int index) override { + sink_(struct_to_write, list_[index]); + } + + FieldTrialListBase* GetList() override { return &list_; } + + private: + FieldTrialList list_; + std::function sink_; +}; + +} // namespace field_trial_list_impl + +template > +FieldTrialListWrapper* FieldTrialStructMember(absl::string_view key, + F accessor) { + return new field_trial_list_impl::TypedFieldTrialListWrapper< + typename Traits::ret>(key, [accessor](void* s, typename Traits::ret t) { + *accessor(static_cast(s)) = t; + }); +} + +// This base class is here to reduce the amount of code we have to generate for +// each type of FieldTrialStructList. +class FieldTrialStructListBase : public FieldTrialParameterInterface { + protected: + FieldTrialStructListBase( + std::initializer_list sub_lists) + : FieldTrialParameterInterface(""), sub_lists_() { + // Take ownership of the list wrappers generated by FieldTrialStructMember + // on the call site. + for (FieldTrialListWrapper* const* it = sub_lists.begin(); + it != sub_lists.end(); it++) { + sub_parameters_.push_back((*it)->GetList()); + sub_lists_.push_back(std::unique_ptr(*it)); + } + } + + // Check that all of our sublists that were in the field trial string had the + // same number of elements. If they do, we return that length. If they had + // different lengths, any sublist had parse failures or no sublists had + // user-supplied values, we return -1. + int ValidateAndGetLength(); + + bool Parse(absl::optional str_value) override; + + std::vector> sub_lists_; +}; + +template +class FieldTrialStructList : public FieldTrialStructListBase { + public: + FieldTrialStructList(std::initializer_list l, + std::initializer_list default_list) + : FieldTrialStructListBase(l), values_(default_list) {} + + std::vector Get() const { return values_; } + operator std::vector() const { return Get(); } + const S& operator[](size_t index) const { return values_[index]; } + const std::vector* operator->() const { return &values_; } + + protected: + void ParseDone() override { + int length = ValidateAndGetLength(); + + if (length == -1) + return; + + std::vector new_values(length, S()); + + for (std::unique_ptr& li : sub_lists_) { + if (li->Used()) { + for (int i = 0; i < length; i++) { + li->WriteElement(&new_values[i], i); + } + } + } + + values_.swap(new_values); + } + + private: + std::vector values_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_list_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_list_unittest.cc new file mode 100644 index 0000000000..221a3c6929 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_list_unittest.cc @@ -0,0 +1,141 @@ +/* + * 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/field_trial_list.h" + +#include "absl/strings/string_view.h" +#include "rtc_base/gunit.h" +#include "test/gmock.h" + +using testing::ElementsAre; +using testing::IsEmpty; + +namespace webrtc { + +struct Garment { + int price = 0; + std::string color = ""; + bool has_glitter = false; + + // Only needed for testing. + Garment() = default; + Garment(int p, absl::string_view c, bool g) + : price(p), color(c), has_glitter(g) {} + + bool operator==(const Garment& other) const { + return price == other.price && color == other.color && + has_glitter == other.has_glitter; + } +}; + +TEST(FieldTrialListTest, ParsesListParameter) { + FieldTrialList my_list("l", {5}); + EXPECT_THAT(my_list.Get(), ElementsAre(5)); + // If one element is invalid the list is unchanged. + ParseFieldTrial({&my_list}, "l:1|2|hat"); + EXPECT_THAT(my_list.Get(), ElementsAre(5)); + ParseFieldTrial({&my_list}, "l"); + EXPECT_THAT(my_list.Get(), IsEmpty()); + ParseFieldTrial({&my_list}, "l:1|2|3"); + EXPECT_THAT(my_list.Get(), ElementsAre(1, 2, 3)); + ParseFieldTrial({&my_list}, "l:-1"); + EXPECT_THAT(my_list.Get(), ElementsAre(-1)); + + FieldTrialList another_list("l", {"hat"}); + EXPECT_THAT(another_list.Get(), ElementsAre("hat")); + ParseFieldTrial({&another_list}, "l"); + EXPECT_THAT(another_list.Get(), IsEmpty()); + ParseFieldTrial({&another_list}, "l:"); + EXPECT_THAT(another_list.Get(), ElementsAre("")); + ParseFieldTrial({&another_list}, "l:scarf|hat|mittens"); + EXPECT_THAT(another_list.Get(), ElementsAre("scarf", "hat", "mittens")); + ParseFieldTrial({&another_list}, "l:scarf"); + EXPECT_THAT(another_list.Get(), ElementsAre("scarf")); +} + +// Normal usage. +TEST(FieldTrialListTest, ParsesStructList) { + FieldTrialStructList my_list( + {FieldTrialStructMember("color", [](Garment* g) { return &g->color; }), + FieldTrialStructMember("price", [](Garment* g) { return &g->price; }), + FieldTrialStructMember("has_glitter", + [](Garment* g) { return &g->has_glitter; })}, + {{1, "blue", false}, {2, "red", true}}); + + ParseFieldTrial({&my_list}, + "color:mauve|red|gold," + "price:10|20|30," + "has_glitter:1|0|1," + "other_param:asdf"); + + ASSERT_THAT(my_list.Get(), + ElementsAre(Garment{10, "mauve", true}, Garment{20, "red", false}, + Garment{30, "gold", true})); +} + +// One FieldTrialList has the wrong length, so we use the user-provided default +// list. +TEST(FieldTrialListTest, StructListKeepsDefaultWithMismatchingLength) { + FieldTrialStructList my_list( + {FieldTrialStructMember("wrong_length", + [](Garment* g) { return &g->color; }), + FieldTrialStructMember("price", [](Garment* g) { return &g->price; })}, + {{1, "blue", true}, {2, "red", false}}); + + ParseFieldTrial({&my_list}, + "wrong_length:mauve|magenta|chartreuse|indigo," + "garment:hat|hat|crown," + "price:10|20|30"); + + ASSERT_THAT(my_list.Get(), + ElementsAre(Garment{1, "blue", true}, Garment{2, "red", false})); +} + +// One list is missing. We set the values we're given, and the others remain +// as whatever the Garment default constructor set them to. +TEST(FieldTrialListTest, StructListUsesDefaultForMissingList) { + FieldTrialStructList my_list( + {FieldTrialStructMember("color", [](Garment* g) { return &g->color; }), + FieldTrialStructMember("price", [](Garment* g) { return &g->price; })}, + {{1, "blue", true}, {2, "red", false}}); + + ParseFieldTrial({&my_list}, "price:10|20|30"); + + ASSERT_THAT(my_list.Get(), + ElementsAre(Garment{10, "", false}, Garment{20, "", false}, + Garment{30, "", false})); +} + +// The user haven't provided values for any lists, so we use the default list. +TEST(FieldTrialListTest, StructListUsesDefaultListWithoutValues) { + FieldTrialStructList my_list( + {FieldTrialStructMember("color", [](Garment* g) { return &g->color; }), + FieldTrialStructMember("price", [](Garment* g) { return &g->price; })}, + {{1, "blue", true}, {2, "red", false}}); + + ParseFieldTrial({&my_list}, ""); + + ASSERT_THAT(my_list.Get(), + ElementsAre(Garment{1, "blue", true}, Garment{2, "red", false})); +} + +// Some lists are provided and all are empty, so we return a empty list. +TEST(FieldTrialListTest, StructListHandlesEmptyLists) { + FieldTrialStructList my_list( + {FieldTrialStructMember("color", [](Garment* g) { return &g->color; }), + FieldTrialStructMember("price", [](Garment* g) { return &g->price; })}, + {{1, "blue", true}, {2, "red", false}}); + + ParseFieldTrial({&my_list}, "color,price"); + + ASSERT_EQ(my_list.Get().size(), 0u); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc new file mode 100644 index 0000000000..78d5489f5e --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc @@ -0,0 +1,260 @@ +/* + * 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/field_trial_parser.h" + +#include + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/numerics/safe_conversions.h" + +namespace webrtc { + +FieldTrialParameterInterface::FieldTrialParameterInterface( + absl::string_view key) + : key_(key) {} +FieldTrialParameterInterface::~FieldTrialParameterInterface() { + RTC_DCHECK(used_) << "Field trial parameter with key: '" << key_ + << "' never used."; +} + +void ParseFieldTrial( + std::initializer_list fields, + absl::string_view trial_string) { + std::map field_map; + FieldTrialParameterInterface* keyless_field = nullptr; + for (FieldTrialParameterInterface* field : fields) { + field->MarkAsUsed(); + if (!field->sub_parameters_.empty()) { + for (FieldTrialParameterInterface* sub_field : field->sub_parameters_) { + RTC_DCHECK(!sub_field->key_.empty()); + sub_field->MarkAsUsed(); + field_map[sub_field->key_] = sub_field; + } + continue; + } + + if (field->key_.empty()) { + RTC_DCHECK(!keyless_field); + keyless_field = field; + } else { + field_map[field->key_] = field; + } + } + bool logged_unknown_key = false; + + absl::string_view tail = trial_string; + while (!tail.empty()) { + size_t key_end = tail.find_first_of(",:"); + absl::string_view key = tail.substr(0, key_end); + absl::optional opt_value; + if (key_end == absl::string_view::npos) { + tail = ""; + } else if (tail[key_end] == ':') { + tail = tail.substr(key_end + 1); + size_t value_end = tail.find(','); + opt_value.emplace(tail.substr(0, value_end)); + if (value_end == absl::string_view::npos) { + tail = ""; + } else { + tail = tail.substr(value_end + 1); + } + } else { + RTC_DCHECK_EQ(tail[key_end], ','); + tail = tail.substr(key_end + 1); + } + + auto field = field_map.find(key); + if (field != field_map.end()) { + if (!field->second->Parse(std::move(opt_value))) { + RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key + << "' in trial: \"" << trial_string << "\""; + } + } else if (!opt_value && keyless_field && !key.empty()) { + if (!keyless_field->Parse(std::string(key))) { + RTC_LOG(LS_WARNING) << "Failed to read empty key field with value '" + << key << "' in trial: \"" << trial_string << "\""; + } + } else if (key.empty() || key[0] != '_') { + // "_" is be used to prefix keys that are part of the string for + // debugging purposes but not neccessarily used. + // e.g. WebRTC-Experiment/param: value, _DebuggingString + if (!logged_unknown_key) { + RTC_LOG(LS_INFO) << "No field with key: '" << key + << "' (found in trial: \"" << trial_string << "\")"; + std::string valid_keys; + for (const auto& f : field_map) { + valid_keys.append(f.first.data(), f.first.size()); + valid_keys += ", "; + } + RTC_LOG(LS_INFO) << "Valid keys are: " << valid_keys; + logged_unknown_key = true; + } + } + } + + for (FieldTrialParameterInterface* field : fields) { + field->ParseDone(); + } +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + if (str == "true" || str == "1") { + return true; + } else if (str == "false" || str == "0") { + return false; + } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + double value; + char unit[2]{0, 0}; + if (sscanf(std::string(str).c_str(), "%lf%1s", &value, unit) >= 1) { + if (unit[0] == '%') + return value / 100; + return value; + } else { + return absl::nullopt; + } +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + int64_t value; + if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) { + if (rtc::IsValueInRangeForNumericType(value)) { + return static_cast(value); + } + } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + int64_t value; + if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) { + if (rtc::IsValueInRangeForNumericType(value)) { + return static_cast(value); + } + } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter( + absl::string_view str) { + return std::string(str); +} + +template <> +absl::optional> ParseTypedParameter>( + absl::string_view str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> ParseTypedParameter>( + absl::string_view str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str) { + return ParseOptionalParameter(str); +} + +FieldTrialFlag::FieldTrialFlag(absl::string_view key) + : FieldTrialFlag(key, false) {} + +FieldTrialFlag::FieldTrialFlag(absl::string_view key, bool default_value) + : FieldTrialParameterInterface(key), value_(default_value) {} + +bool FieldTrialFlag::Get() const { + return value_; +} + +webrtc::FieldTrialFlag::operator bool() const { + return value_; +} + +bool FieldTrialFlag::Parse(absl::optional str_value) { + // Only set the flag if there is no argument provided. + if (str_value) { + absl::optional opt_value = ParseTypedParameter(*str_value); + if (!opt_value) + return false; + value_ = *opt_value; + } else { + value_ = true; + } + return true; +} + +AbstractFieldTrialEnum::AbstractFieldTrialEnum( + absl::string_view key, + int default_value, + std::map mapping) + : FieldTrialParameterInterface(key), + value_(default_value), + enum_mapping_(mapping) { + for (auto& key_val : enum_mapping_) + valid_values_.insert(key_val.second); +} +AbstractFieldTrialEnum::AbstractFieldTrialEnum(const AbstractFieldTrialEnum&) = + default; +AbstractFieldTrialEnum::~AbstractFieldTrialEnum() = default; + +bool AbstractFieldTrialEnum::Parse(absl::optional str_value) { + if (str_value) { + auto it = enum_mapping_.find(*str_value); + if (it != enum_mapping_.end()) { + value_ = it->second; + return true; + } + absl::optional value = ParseTypedParameter(*str_value); + if (value.has_value() && + (valid_values_.find(*value) != valid_values_.end())) { + value_ = *value; + return true; + } + } + return false; +} + +template class FieldTrialParameter; +template class FieldTrialParameter; +template class FieldTrialParameter; +template class FieldTrialParameter; +template class FieldTrialParameter; + +template class FieldTrialConstrained; +template class FieldTrialConstrained; +template class FieldTrialConstrained; + +template class FieldTrialOptional; +template class FieldTrialOptional; +template class FieldTrialOptional; +template class FieldTrialOptional; +template class FieldTrialOptional; + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.h b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.h new file mode 100644 index 0000000000..822895e70b --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.h @@ -0,0 +1,291 @@ +/* + * Copyright 2018 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_FIELD_TRIAL_PARSER_H_ +#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_ + +#include + +#include +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +// Field trial parser functionality. Provides funcitonality to parse field trial +// argument strings in key:value format. Each parameter is described using +// key:value, parameters are separated with a ,. Values can't include the comma +// character, since there's no quote facility. For most types, white space is +// ignored. Parameters are declared with a given type for which an +// implementation of ParseTypedParameter should be provided. The +// ParseTypedParameter implementation is given whatever is between the : and the +// ,. If the key is provided without : a FieldTrialOptional will use nullopt. + +// Example string: "my_optional,my_int:3,my_string:hello" + +// For further description of usage and behavior, see the examples in the unit +// tests. + +namespace webrtc { +class FieldTrialParameterInterface { + public: + virtual ~FieldTrialParameterInterface(); + std::string key() const { return key_; } + + protected: + // Protected to allow implementations to provide assignment and copy. + FieldTrialParameterInterface(const FieldTrialParameterInterface&) = default; + FieldTrialParameterInterface& operator=(const FieldTrialParameterInterface&) = + default; + explicit FieldTrialParameterInterface(absl::string_view key); + friend void ParseFieldTrial( + std::initializer_list fields, + absl::string_view trial_string); + void MarkAsUsed() { used_ = true; } + virtual bool Parse(absl::optional str_value) = 0; + + virtual void ParseDone() {} + + std::vector sub_parameters_; + + private: + std::string key_; + bool used_ = false; +}; + +// ParseFieldTrial function parses the given string and fills the given fields +// with extracted values if available. +void ParseFieldTrial( + std::initializer_list fields, + absl::string_view trial_string); + +// Specialize this in code file for custom types. Should return absl::nullopt if +// the given string cannot be properly parsed. +template +absl::optional ParseTypedParameter(absl::string_view); + +// This class uses the ParseTypedParameter function to implement a parameter +// implementation with an enforced default value. +template +class FieldTrialParameter : public FieldTrialParameterInterface { + public: + FieldTrialParameter(absl::string_view key, T default_value) + : FieldTrialParameterInterface(key), value_(default_value) {} + T Get() const { return value_; } + operator T() const { return Get(); } + const T* operator->() const { return &value_; } + + void SetForTest(T value) { value_ = value; } + + protected: + bool Parse(absl::optional str_value) override { + if (str_value) { + absl::optional value = ParseTypedParameter(*str_value); + if (value.has_value()) { + value_ = value.value(); + return true; + } + } + return false; + } + + private: + T value_; +}; + +// This class uses the ParseTypedParameter function to implement a parameter +// implementation with an enforced default value and a range constraint. Values +// outside the configured range will be ignored. +template +class FieldTrialConstrained : public FieldTrialParameterInterface { + public: + FieldTrialConstrained(absl::string_view key, + T default_value, + absl::optional lower_limit, + absl::optional upper_limit) + : FieldTrialParameterInterface(key), + value_(default_value), + lower_limit_(lower_limit), + upper_limit_(upper_limit) {} + T Get() const { return value_; } + operator T() const { return Get(); } + const T* operator->() const { return &value_; } + + protected: + bool Parse(absl::optional str_value) override { + if (str_value) { + absl::optional value = ParseTypedParameter(*str_value); + if (value && (!lower_limit_ || *value >= *lower_limit_) && + (!upper_limit_ || *value <= *upper_limit_)) { + value_ = *value; + return true; + } + } + return false; + } + + private: + T value_; + absl::optional lower_limit_; + absl::optional upper_limit_; +}; + +class AbstractFieldTrialEnum : public FieldTrialParameterInterface { + public: + AbstractFieldTrialEnum(absl::string_view key, + int default_value, + std::map mapping); + ~AbstractFieldTrialEnum() override; + AbstractFieldTrialEnum(const AbstractFieldTrialEnum&); + + protected: + bool Parse(absl::optional str_value) override; + + protected: + int value_; + std::map enum_mapping_; + std::set valid_values_; +}; + +// The FieldTrialEnum class can be used to quickly define a parser for a +// specific enum. It handles values provided as integers and as strings if a +// mapping is provided. +template +class FieldTrialEnum : public AbstractFieldTrialEnum { + public: + FieldTrialEnum(absl::string_view key, + T default_value, + std::map mapping) + : AbstractFieldTrialEnum(key, + static_cast(default_value), + ToIntMap(mapping)) {} + T Get() const { return static_cast(value_); } + operator T() const { return Get(); } + + private: + static std::map ToIntMap(std::map mapping) { + std::map res; + for (const auto& it : mapping) + res[it.first] = static_cast(it.second); + return res; + } +}; + +// This class uses the ParseTypedParameter function to implement an optional +// parameter implementation that can default to absl::nullopt. +template +class FieldTrialOptional : public FieldTrialParameterInterface { + public: + explicit FieldTrialOptional(absl::string_view key) + : FieldTrialParameterInterface(key) {} + FieldTrialOptional(absl::string_view key, absl::optional default_value) + : FieldTrialParameterInterface(key), value_(default_value) {} + absl::optional GetOptional() const { return value_; } + const T& Value() const { return value_.value(); } + const T& operator*() const { return value_.value(); } + const T* operator->() const { return &value_.value(); } + explicit operator bool() const { return value_.has_value(); } + + protected: + bool Parse(absl::optional str_value) override { + if (str_value) { + absl::optional value = ParseTypedParameter(*str_value); + if (!value.has_value()) + return false; + value_ = value.value(); + } else { + value_ = absl::nullopt; + } + return true; + } + + private: + absl::optional value_; +}; + +// Equivalent to a FieldTrialParameter in the case that both key and value +// are present. If key is missing, evaluates to false. If key is present, but no +// explicit value is provided, the flag evaluates to true. +class FieldTrialFlag : public FieldTrialParameterInterface { + public: + explicit FieldTrialFlag(absl::string_view key); + FieldTrialFlag(absl::string_view key, bool default_value); + bool Get() const; + explicit operator bool() const; + + protected: + bool Parse(absl::optional str_value) override; + + private: + bool value_; +}; + +template +absl::optional> ParseOptionalParameter( + absl::string_view str) { + if (str.empty()) + return absl::optional(); + auto parsed = ParseTypedParameter(str); + if (parsed.has_value()) + return parsed; + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter( + absl::string_view str); + +template <> +absl::optional> ParseTypedParameter>( + absl::string_view str); +template <> +absl::optional> ParseTypedParameter>( + absl::string_view str); +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str); +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str); + +// Accepts true, false, else parsed with sscanf %i, true if != 0. +extern template class FieldTrialParameter; +// Interpreted using sscanf %lf. +extern template class FieldTrialParameter; +// Interpreted using sscanf %i. +extern template class FieldTrialParameter; +// Interpreted using sscanf %u. +extern template class FieldTrialParameter; +// Using the given value as is. +extern template class FieldTrialParameter; + +extern template class FieldTrialConstrained; +extern template class FieldTrialConstrained; +extern template class FieldTrialConstrained; + +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build new file mode 100644 index 0000000000..8147b9e99a --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build @@ -0,0 +1,228 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc", + "/third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc", + "/third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc", + "/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("field_trial_parser_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc new file mode 100644 index 0000000000..33d275a31c --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc @@ -0,0 +1,185 @@ +/* + * Copyright 2018 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/field_trial_parser.h" + +#include "absl/strings/string_view.h" +#include "rtc_base/experiments/field_trial_list.h" +#include "rtc_base/gunit.h" +#include "system_wrappers/include/field_trial.h" +#include "test/field_trial.h" +#include "test/gmock.h" + +namespace webrtc { +namespace { + +constexpr char kDummyExperiment[] = "WebRTC-DummyExperiment"; + +struct DummyExperiment { + FieldTrialFlag enabled = FieldTrialFlag("Enabled"); + FieldTrialParameter factor = FieldTrialParameter("f", 0.5); + FieldTrialParameter retries = FieldTrialParameter("r", 5); + FieldTrialParameter size = FieldTrialParameter("s", 3); + FieldTrialParameter ping = FieldTrialParameter("p", 0); + FieldTrialParameter hash = + FieldTrialParameter("h", "a80"); + + field_trial::FieldTrialsAllowedInScopeForTesting k{{kDummyExperiment}}; + + DummyExperiment() + : DummyExperiment(field_trial::FindFullName(kDummyExperiment)) {} + + explicit DummyExperiment(absl::string_view field_trial) { + ParseFieldTrial({&enabled, &factor, &retries, &size, &ping, &hash}, + field_trial); + } +}; + +enum class CustomEnum { + kDefault = 0, + kRed = 1, + kBlue = 2, +}; + +} // namespace + +TEST(FieldTrialParserTest, ParsesValidParameters) { + DummyExperiment exp("Enabled,f:-1.7,r:2,s:10,p:1,h:x7c"); + EXPECT_TRUE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), -1.7); + EXPECT_EQ(exp.retries.Get(), 2); + EXPECT_EQ(exp.size.Get(), 10u); + EXPECT_EQ(exp.ping.Get(), true); + EXPECT_EQ(exp.hash.Get(), "x7c"); +} +TEST(FieldTrialParserTest, InitializesFromFieldTrial) { + test::ScopedFieldTrials field_trials( + "WebRTC-OtherExperiment/Disabled/" + "WebRTC-DummyExperiment/Enabled,f:-1.7,r:2,s:10,p:1,h:x7c/" + "WebRTC-AnotherExperiment/Enabled,f:-3.1,otherstuff:beef/"); + DummyExperiment exp; + EXPECT_TRUE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), -1.7); + EXPECT_EQ(exp.retries.Get(), 2); + EXPECT_EQ(exp.size.Get(), 10u); + EXPECT_EQ(exp.ping.Get(), true); + EXPECT_EQ(exp.hash.Get(), "x7c"); +} +TEST(FieldTrialParserTest, UsesDefaults) { + DummyExperiment exp(""); + EXPECT_FALSE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), 0.5); + EXPECT_EQ(exp.retries.Get(), 5); + EXPECT_EQ(exp.size.Get(), 3u); + EXPECT_EQ(exp.ping.Get(), false); + EXPECT_EQ(exp.hash.Get(), "a80"); +} +TEST(FieldTrialParserTest, CanHandleMixedInput) { + DummyExperiment exp("p:true,h:,Enabled"); + EXPECT_TRUE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), 0.5); + EXPECT_EQ(exp.retries.Get(), 5); + EXPECT_EQ(exp.size.Get(), 3u); + EXPECT_EQ(exp.ping.Get(), true); + EXPECT_EQ(exp.hash.Get(), ""); +} +TEST(FieldTrialParserTest, ParsesDoubleParameter) { + FieldTrialParameter double_param("f", 0.0); + ParseFieldTrial({&double_param}, "f:45%"); + EXPECT_EQ(double_param.Get(), 0.45); + ParseFieldTrial({&double_param}, "f:34 %"); + EXPECT_EQ(double_param.Get(), 0.34); + ParseFieldTrial({&double_param}, "f:0.67"); + EXPECT_EQ(double_param.Get(), 0.67); +} +TEST(FieldTrialParserTest, IgnoresNewKey) { + DummyExperiment exp("Disabled,r:-11,foo"); + EXPECT_FALSE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), 0.5); + EXPECT_EQ(exp.retries.Get(), -11); +} +TEST(FieldTrialParserTest, IgnoresInvalid) { + DummyExperiment exp("Enabled,f,p:,r:%,,s:-1,:foo,h"); + EXPECT_TRUE(exp.enabled.Get()); + EXPECT_EQ(exp.factor.Get(), 0.5); + EXPECT_EQ(exp.retries.Get(), 5); + EXPECT_EQ(exp.size.Get(), 3u); + EXPECT_EQ(exp.ping.Get(), false); + EXPECT_EQ(exp.hash.Get(), "a80"); +} +TEST(FieldTrialParserTest, IgnoresOutOfRange) { + FieldTrialConstrained low("low", 10, absl::nullopt, 100); + FieldTrialConstrained high("high", 10, 5, absl::nullopt); + ParseFieldTrial({&low, &high}, "low:1000,high:0"); + EXPECT_EQ(low.Get(), 10); + EXPECT_EQ(high.Get(), 10); + ParseFieldTrial({&low, &high}, "low:inf,high:nan"); + EXPECT_EQ(low.Get(), 10); + EXPECT_EQ(high.Get(), 10); + ParseFieldTrial({&low, &high}, "low:20,high:20"); + EXPECT_EQ(low.Get(), 20); + EXPECT_EQ(high.Get(), 20); + + FieldTrialConstrained size("size", 5, 1, 10); + ParseFieldTrial({&size}, "size:0"); + EXPECT_EQ(size.Get(), 5u); +} +TEST(FieldTrialParserTest, ReadsValuesFromFieldWithoutKey) { + FieldTrialFlag enabled("Enabled"); + FieldTrialParameter req("", 10); + ParseFieldTrial({&enabled, &req}, "Enabled,20"); + EXPECT_EQ(req.Get(), 20); + ParseFieldTrial({&req}, "30"); + EXPECT_EQ(req.Get(), 30); +} +TEST(FieldTrialParserTest, ParsesOptionalParameters) { + FieldTrialOptional max_count("c", absl::nullopt); + ParseFieldTrial({&max_count}, ""); + EXPECT_FALSE(max_count.GetOptional().has_value()); + ParseFieldTrial({&max_count}, "c:10"); + EXPECT_EQ(max_count.GetOptional().value(), 10); + ParseFieldTrial({&max_count}, "c"); + EXPECT_FALSE(max_count.GetOptional().has_value()); + ParseFieldTrial({&max_count}, "c:20"); + EXPECT_EQ(max_count.GetOptional().value(), 20); + ParseFieldTrial({&max_count}, "c:"); + EXPECT_EQ(max_count.GetOptional().value(), 20); + + FieldTrialOptional max_size("c", absl::nullopt); + ParseFieldTrial({&max_size}, ""); + EXPECT_FALSE(max_size.GetOptional().has_value()); + ParseFieldTrial({&max_size}, "c:10"); + EXPECT_EQ(max_size.GetOptional().value(), 10u); + ParseFieldTrial({&max_size}, "c"); + EXPECT_FALSE(max_size.GetOptional().has_value()); + ParseFieldTrial({&max_size}, "c:20"); + EXPECT_EQ(max_size.GetOptional().value(), 20u); + + FieldTrialOptional optional_string("s", std::string("ab")); + ParseFieldTrial({&optional_string}, "s:"); + EXPECT_EQ(optional_string.GetOptional().value(), ""); + ParseFieldTrial({&optional_string}, "s"); + EXPECT_FALSE(optional_string.GetOptional().has_value()); +} +TEST(FieldTrialParserTest, ParsesCustomEnumParameter) { + FieldTrialEnum my_enum("e", CustomEnum::kDefault, + {{"default", CustomEnum::kDefault}, + {"red", CustomEnum::kRed}, + {"blue", CustomEnum::kBlue}}); + ParseFieldTrial({&my_enum}, ""); + EXPECT_EQ(my_enum.Get(), CustomEnum::kDefault); + ParseFieldTrial({&my_enum}, "e:red"); + EXPECT_EQ(my_enum.Get(), CustomEnum::kRed); + ParseFieldTrial({&my_enum}, "e:2"); + EXPECT_EQ(my_enum.Get(), CustomEnum::kBlue); + ParseFieldTrial({&my_enum}, "e:5"); + EXPECT_EQ(my_enum.Get(), CustomEnum::kBlue); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc new file mode 100644 index 0000000000..92af46a9e3 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc @@ -0,0 +1,116 @@ +/* + * Copyright 2018 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/field_trial_units.h" + +#include + +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +// Large enough to fit "seconds", the longest supported unit name. +#define RTC_TRIAL_UNIT_LENGTH_STR "7" +#define RTC_TRIAL_UNIT_SIZE 8 + +namespace webrtc { +namespace { + +struct ValueWithUnit { + double value; + std::string unit; +}; + +absl::optional ParseValueWithUnit(absl::string_view str) { + if (str == "inf") { + return ValueWithUnit{std::numeric_limits::infinity(), ""}; + } else if (str == "-inf") { + return ValueWithUnit{-std::numeric_limits::infinity(), ""}; + } else { + double double_val; + char unit_char[RTC_TRIAL_UNIT_SIZE]; + unit_char[0] = 0; + if (sscanf(std::string(str).c_str(), "%lf%" RTC_TRIAL_UNIT_LENGTH_STR "s", + &double_val, unit_char) >= 1) { + return ValueWithUnit{double_val, unit_char}; + } + } + return absl::nullopt; +} +} // namespace + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + absl::optional result = ParseValueWithUnit(str); + if (result) { + if (result->unit.empty() || result->unit == "kbps") { + return DataRate::KilobitsPerSec(result->value); + } else if (result->unit == "bps") { + return DataRate::BitsPerSec(result->value); + } + } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(absl::string_view str) { + absl::optional result = ParseValueWithUnit(str); + if (result) { + if (result->unit.empty() || result->unit == "bytes") + return DataSize::Bytes(result->value); + } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter( + absl::string_view str) { + absl::optional result = ParseValueWithUnit(str); + if (result) { + if (result->unit == "s" || result->unit == "seconds") { + return TimeDelta::Seconds(result->value); + } else if (result->unit == "us") { + return TimeDelta::Micros(result->value); + } else if (result->unit.empty() || result->unit == "ms") { + return TimeDelta::Millis(result->value); + } + } + return absl::nullopt; +} + +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(absl::string_view str) { + return ParseOptionalParameter(str); +} + +template class FieldTrialParameter; +template class FieldTrialParameter; +template class FieldTrialParameter; + +template class FieldTrialConstrained; +template class FieldTrialConstrained; +template class FieldTrialConstrained; + +template class FieldTrialOptional; +template class FieldTrialOptional; +template class FieldTrialOptional; +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_units.h b/third_party/libwebrtc/rtc_base/experiments/field_trial_units.h new file mode 100644 index 0000000000..408367c031 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_units.h @@ -0,0 +1,41 @@ +/* + * Copyright 2018 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_FIELD_TRIAL_UNITS_H_ +#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_UNITS_H_ + +#include "absl/strings/string_view.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter(absl::string_view str); +template <> +absl::optional ParseTypedParameter(absl::string_view str); + +extern template class FieldTrialParameter; +extern template class FieldTrialParameter; +extern template class FieldTrialParameter; + +extern template class FieldTrialConstrained; +extern template class FieldTrialConstrained; +extern template class FieldTrialConstrained; + +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; +extern template class FieldTrialOptional; +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_UNITS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/field_trial_units_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/field_trial_units_unittest.cc new file mode 100644 index 0000000000..8996663d8e --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_units_unittest.cc @@ -0,0 +1,87 @@ +/* + * Copyright 2018 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/field_trial_units.h" + +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { +struct DummyExperiment { + FieldTrialParameter target_rate = + FieldTrialParameter("t", DataRate::KilobitsPerSec(100)); + FieldTrialParameter period = + FieldTrialParameter("p", TimeDelta::Millis(100)); + FieldTrialOptional max_buffer = + FieldTrialOptional("b", absl::nullopt); + + explicit DummyExperiment(absl::string_view field_trial) { + ParseFieldTrial({&target_rate, &max_buffer, &period}, field_trial); + } +}; +} // namespace + +TEST(FieldTrialParserUnitsTest, FallsBackToDefaults) { + DummyExperiment exp(""); + EXPECT_EQ(exp.target_rate.Get(), DataRate::KilobitsPerSec(100)); + EXPECT_FALSE(exp.max_buffer.GetOptional().has_value()); + EXPECT_EQ(exp.period.Get(), TimeDelta::Millis(100)); +} +TEST(FieldTrialParserUnitsTest, ParsesUnitParameters) { + DummyExperiment exp("t:300kbps,b:5bytes,p:300ms"); + EXPECT_EQ(exp.target_rate.Get(), DataRate::KilobitsPerSec(300)); + EXPECT_EQ(*exp.max_buffer.GetOptional(), DataSize::Bytes(5)); + EXPECT_EQ(exp.period.Get(), TimeDelta::Millis(300)); +} +TEST(FieldTrialParserUnitsTest, ParsesDefaultUnitParameters) { + DummyExperiment exp("t:300,b:5,p:300"); + EXPECT_EQ(exp.target_rate.Get(), DataRate::KilobitsPerSec(300)); + EXPECT_EQ(*exp.max_buffer.GetOptional(), DataSize::Bytes(5)); + EXPECT_EQ(exp.period.Get(), TimeDelta::Millis(300)); +} +TEST(FieldTrialParserUnitsTest, ParsesInfinityParameter) { + DummyExperiment exp("t:inf,p:inf"); + EXPECT_EQ(exp.target_rate.Get(), DataRate::Infinity()); + EXPECT_EQ(exp.period.Get(), TimeDelta::PlusInfinity()); +} +TEST(FieldTrialParserUnitsTest, ParsesOtherUnitParameters) { + DummyExperiment exp("t:300bps,p:0.3 seconds,b:8 bytes"); + EXPECT_EQ(exp.target_rate.Get(), DataRate::BitsPerSec(300)); + EXPECT_EQ(*exp.max_buffer.GetOptional(), DataSize::Bytes(8)); + EXPECT_EQ(exp.period.Get(), TimeDelta::Millis(300)); +} +TEST(FieldTrialParserUnitsTest, IgnoresOutOfRange) { + FieldTrialConstrained rate("r", DataRate::KilobitsPerSec(30), + DataRate::KilobitsPerSec(10), + DataRate::KilobitsPerSec(100)); + FieldTrialConstrained delta("d", TimeDelta::Millis(30), + TimeDelta::Millis(10), + TimeDelta::Millis(100)); + FieldTrialConstrained size( + "s", DataSize::Bytes(30), DataSize::Bytes(10), DataSize::Bytes(100)); + ParseFieldTrial({&rate, &delta, &size}, "r:0,d:0,s:0"); + EXPECT_EQ(rate->kbps(), 30); + EXPECT_EQ(delta->ms(), 30); + EXPECT_EQ(size->bytes(), 30); + ParseFieldTrial({&rate, &delta, &size}, "r:300,d:300,s:300"); + EXPECT_EQ(rate->kbps(), 30); + EXPECT_EQ(delta->ms(), 30); + EXPECT_EQ(size->bytes(), 30); + ParseFieldTrial({&rate, &delta, &size}, "r:50,d:50,s:50"); + EXPECT_EQ(rate->kbps(), 50); + EXPECT_EQ(delta->ms(), 50); + EXPECT_EQ(size->bytes(), 50); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc new file mode 100644 index 0000000000..413e2a91d5 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc @@ -0,0 +1,39 @@ +/* + * 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/keyframe_interval_settings.h" + +#include "api/transport/field_trial_based_config.h" + +namespace webrtc { + +namespace { + +constexpr char kFieldTrialName[] = "WebRTC-KeyframeInterval"; + +} // namespace + +KeyframeIntervalSettings::KeyframeIntervalSettings( + const FieldTrialsView* const key_value_config) + : min_keyframe_send_interval_ms_("min_keyframe_send_interval_ms") { + ParseFieldTrial({&min_keyframe_send_interval_ms_}, + key_value_config->Lookup(kFieldTrialName)); +} + +KeyframeIntervalSettings KeyframeIntervalSettings::ParseFromFieldTrials() { + FieldTrialBasedConfig field_trial_config; + return KeyframeIntervalSettings(&field_trial_config); +} + +absl::optional KeyframeIntervalSettings::MinKeyframeSendIntervalMs() + const { + return min_keyframe_send_interval_ms_.GetOptional(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.h b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.h new file mode 100644 index 0000000000..aff7854516 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef RTC_BASE_EXPERIMENTS_KEYFRAME_INTERVAL_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_KEYFRAME_INTERVAL_SETTINGS_H_ + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +// TODO(bugs.webrtc.org/10427): Remove and replace with proper configuration +// parameter, or move to using FIR if intent is to avoid triggering multiple +// times to PLIs corresponding to the same request when RTT is large. +class KeyframeIntervalSettings final { + public: + static KeyframeIntervalSettings ParseFromFieldTrials(); + + // Sender side. + // The encoded keyframe send rate is <= 1/MinKeyframeSendIntervalMs(). + absl::optional MinKeyframeSendIntervalMs() const; + + private: + explicit KeyframeIntervalSettings(const FieldTrialsView* key_value_config); + + FieldTrialOptional min_keyframe_send_interval_ms_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_KEYFRAME_INTERVAL_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build new file mode 100644 index 0000000000..b8ece40f9b --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("keyframe_interval_settings_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_unittest.cc new file mode 100644 index 0000000000..25cebbcd70 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_unittest.cc @@ -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. + */ + +#include "rtc_base/experiments/keyframe_interval_settings.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +TEST(KeyframeIntervalSettingsTest, ParsesMinKeyframeSendIntervalMs) { + EXPECT_FALSE(KeyframeIntervalSettings::ParseFromFieldTrials() + .MinKeyframeSendIntervalMs()); + + test::ScopedFieldTrials field_trials( + "WebRTC-KeyframeInterval/min_keyframe_send_interval_ms:100/"); + EXPECT_EQ(KeyframeIntervalSettings::ParseFromFieldTrials() + .MinKeyframeSendIntervalMs(), + 100); +} + +TEST(KeyframeIntervalSettingsTest, DoesNotParseIncorrectValues) { + EXPECT_FALSE(KeyframeIntervalSettings::ParseFromFieldTrials() + .MinKeyframeSendIntervalMs()); + + test::ScopedFieldTrials field_trials( + "WebRTC-KeyframeInterval/min_keyframe_send_interval_ms:a/"); + EXPECT_FALSE(KeyframeIntervalSettings::ParseFromFieldTrials() + .MinKeyframeSendIntervalMs()); + EXPECT_FALSE(KeyframeIntervalSettings::ParseFromFieldTrials() + .MinKeyframeSendIntervalMs()); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc new file mode 100644 index 0000000000..f37c4e9c76 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc @@ -0,0 +1,114 @@ +/* + * 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/min_video_bitrate_experiment.h" + +#include + +#include "rtc_base/checks.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { + +const int kDefaultMinVideoBitrateBps = 30000; + +namespace { +const char kForcedFallbackFieldTrial[] = + "WebRTC-VP8-Forced-Fallback-Encoder-v2"; +const char kMinVideoBitrateExperiment[] = "WebRTC-Video-MinVideoBitrate"; + +absl::optional GetFallbackMinBpsFromFieldTrial(VideoCodecType type) { + if (type != kVideoCodecVP8) { + return absl::nullopt; + } + + if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial)) { + return absl::nullopt; + } + + const std::string group = + webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial); + if (group.empty()) { + return absl::nullopt; + } + + int min_pixels; // Ignored. + int max_pixels; // Ignored. + int min_bps; + if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels, + &min_bps) != 3) { + return absl::nullopt; + } + + if (min_bps <= 0) { + return absl::nullopt; + } + + return min_bps; +} +} // namespace + +absl::optional GetExperimentalMinVideoBitrate(VideoCodecType type) { + const absl::optional fallback_min_bitrate_bps = + GetFallbackMinBpsFromFieldTrial(type); + if (fallback_min_bitrate_bps) { + return DataRate::BitsPerSec(*fallback_min_bitrate_bps); + } + + if (webrtc::field_trial::IsEnabled(kMinVideoBitrateExperiment)) { + webrtc::FieldTrialFlag enabled("Enabled"); + + // Backwards-compatibility with an old experiment - a generic minimum which, + // if set, applies to all codecs. + webrtc::FieldTrialOptional min_video_bitrate("br"); + + // New experiment - per-codec minimum bitrate. + webrtc::FieldTrialOptional min_bitrate_vp8("vp8_br"); + webrtc::FieldTrialOptional min_bitrate_vp9("vp9_br"); + webrtc::FieldTrialOptional min_bitrate_av1("av1_br"); + webrtc::FieldTrialOptional min_bitrate_h264("h264_br"); + + webrtc::ParseFieldTrial( + {&enabled, &min_video_bitrate, &min_bitrate_vp8, &min_bitrate_vp9, + &min_bitrate_av1, &min_bitrate_h264}, + webrtc::field_trial::FindFullName(kMinVideoBitrateExperiment)); + + if (min_video_bitrate) { + if (min_bitrate_vp8 || min_bitrate_vp9 || min_bitrate_av1 || + min_bitrate_h264) { + // "br" is mutually-exclusive with the other configuration possibilites. + RTC_LOG(LS_WARNING) << "Self-contradictory experiment config."; + } + return *min_video_bitrate; + } + + switch (type) { + case kVideoCodecVP8: + return min_bitrate_vp8.GetOptional(); + case kVideoCodecVP9: + return min_bitrate_vp9.GetOptional(); + case kVideoCodecAV1: + return min_bitrate_av1.GetOptional(); + case kVideoCodecH264: + return min_bitrate_h264.GetOptional(); + case kVideoCodecGeneric: + case kVideoCodecMultiplex: + return absl::nullopt; + } + + RTC_DCHECK_NOTREACHED(); + } + + return absl::nullopt; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.h b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.h new file mode 100644 index 0000000000..9ea8783894 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.h @@ -0,0 +1,28 @@ +/* + * 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_MIN_VIDEO_BITRATE_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_MIN_VIDEO_BITRATE_EXPERIMENT_H_ + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/video/video_codec_type.h" + +namespace webrtc { + +extern const int kDefaultMinVideoBitrateBps; + +// Return the experiment-driven minimum video bitrate. +// If no experiment is effective, returns nullopt. +absl::optional GetExperimentalMinVideoBitrate(VideoCodecType type); + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_MIN_VIDEO_BITRATE_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build new file mode 100644 index 0000000000..0092a33c39 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("min_video_bitrate_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_unittest.cc new file mode 100644 index 0000000000..9792bad61c --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_unittest.cc @@ -0,0 +1,161 @@ +/* + * 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/min_video_bitrate_experiment.h" + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/video/video_codec_type.h" +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +TEST(GetExperimentalMinVideoBitrateTest, + NulloptForAllCodecsIfFieldTrialUndefined) { + test::ScopedFieldTrials field_trials(""); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::nullopt); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::nullopt); +} + +TEST(GetExperimentalMinVideoBitrateTest, + NulloptForAllCodecsIfFieldTrialDisabled) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/Disabled,br:123kbps/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::nullopt); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::nullopt); +} + +TEST(GetExperimentalMinVideoBitrateTest, BrForAllCodecsIfDefined) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/Enabled,br:123kbps/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::make_optional(DataRate::KilobitsPerSec(123))); +} + +TEST(GetExperimentalMinVideoBitrateTest, BrTrumpsSpecificCodecConfigs) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/" + "Enabled,br:123kbps,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::make_optional(DataRate::KilobitsPerSec(123))); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::make_optional(DataRate::KilobitsPerSec(123))); +} + +TEST(GetExperimentalMinVideoBitrateTest, + SpecificCodecConfigsIgnoredIfExpDisabled) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/" + "Disabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::nullopt); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::nullopt); +} + +TEST(GetExperimentalMinVideoBitrateTest, SpecificCodecConfigsUsedIfExpEnabled) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/" + "Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::make_optional(DataRate::KilobitsPerSec(100))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::make_optional(DataRate::KilobitsPerSec(200))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::make_optional(DataRate::KilobitsPerSec(300))); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::nullopt); +} + +TEST(GetExperimentalMinVideoBitrateTest, + Vp8BitrateValueTakenFromFallbackIfAvailable) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/" + "Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/" + "WebRTC-VP8-Forced-Fallback-Encoder-v2/" + "Enabled-444444,555555,666666/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8), + absl::make_optional(DataRate::BitsPerSec(666666))); +} + +TEST(GetExperimentalMinVideoBitrateTest, + NonVp8BitrateValuesTakenFromMinVideoBitrate) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-MinVideoBitrate/" + "Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/" + "WebRTC-VP8-Forced-Fallback-Encoder-v2/" + "Enabled-444444,555555,666666/"); + + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric), + absl::nullopt); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9), + absl::make_optional(DataRate::KilobitsPerSec(200))); + EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264), + absl::make_optional(DataRate::KilobitsPerSec(300))); + EXPECT_EQ( + GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex), + absl::nullopt); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc new file mode 100644 index 0000000000..ce817a0797 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc @@ -0,0 +1,49 @@ +/* + * Copyright 2018 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/normalize_simulcast_size_experiment.h" + +#include + +#include + +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { +namespace { +constexpr char kFieldTrial[] = "WebRTC-NormalizeSimulcastResolution"; +constexpr int kMinSetting = 0; +constexpr int kMaxSetting = 5; +} // namespace + +absl::optional NormalizeSimulcastSizeExperiment::GetBase2Exponent() { + if (!webrtc::field_trial::IsEnabled(kFieldTrial)) + return absl::nullopt; + + const std::string group = webrtc::field_trial::FindFullName(kFieldTrial); + if (group.empty()) + return absl::nullopt; + + int exponent; + if (sscanf(group.c_str(), "Enabled-%d", &exponent) != 1) { + RTC_LOG(LS_WARNING) << "No parameter provided."; + return absl::nullopt; + } + + if (exponent < kMinSetting || exponent > kMaxSetting) { + RTC_LOG(LS_WARNING) << "Unsupported exp value provided, value ignored."; + return absl::nullopt; + } + + return absl::optional(exponent); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.h b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.h new file mode 100644 index 0000000000..6b358202b2 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.h @@ -0,0 +1,25 @@ +/* + * Copyright 2018 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_NORMALIZE_SIMULCAST_SIZE_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_NORMALIZE_SIMULCAST_SIZE_EXPERIMENT_H_ + +#include "absl/types/optional.h" + +namespace webrtc { +class NormalizeSimulcastSizeExperiment { + public: + // Returns the base two exponent from field trial. + static absl::optional GetBase2Exponent(); +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_NORMALIZE_SIMULCAST_SIZE_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build new file mode 100644 index 0000000000..acf592c763 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("normalize_simulcast_size_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc new file mode 100644 index 0000000000..34e07427cf --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc @@ -0,0 +1,59 @@ +/* + * Copyright 2018 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/normalize_simulcast_size_experiment.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(NormalizeSimulcastSizeExperimentTest, GetExponent) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Enabled-2/"); + EXPECT_EQ(2, NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +TEST(NormalizeSimulcastSizeExperimentTest, GetExponentWithTwoParameters) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Enabled-3-4/"); + EXPECT_EQ(3, NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +TEST(NormalizeSimulcastSizeExperimentTest, GetExponentFailsIfNotEnabled) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Disabled/"); + EXPECT_FALSE(NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +TEST(NormalizeSimulcastSizeExperimentTest, + GetExponentFailsForInvalidFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Enabled-invalid/"); + EXPECT_FALSE(NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +TEST(NormalizeSimulcastSizeExperimentTest, + GetExponentFailsForNegativeOutOfBoundValue) { + // Supported range: [0, 5]. + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Enabled--1/"); + EXPECT_FALSE(NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +TEST(NormalizeSimulcastSizeExperimentTest, + GetExponentFailsForPositiveOutOfBoundValue) { + // Supported range: [0, 5]. + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-NormalizeSimulcastResolution/Enabled-6/"); + EXPECT_FALSE(NormalizeSimulcastSizeExperiment::GetBase2Exponent()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc new file mode 100644 index 0000000000..509ba91dc3 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc @@ -0,0 +1,82 @@ +/* + * 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/quality_rampup_experiment.h" + +#include + +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +QualityRampupExperiment::QualityRampupExperiment( + const FieldTrialsView* const key_value_config) + : min_pixels_("min_pixels"), + min_duration_ms_("min_duration_ms"), + max_bitrate_factor_("max_bitrate_factor") { + ParseFieldTrial( + {&min_pixels_, &min_duration_ms_, &max_bitrate_factor_}, + key_value_config->Lookup("WebRTC-Video-QualityRampupSettings")); +} + +QualityRampupExperiment QualityRampupExperiment::ParseSettings() { + FieldTrialBasedConfig field_trial_config; + return QualityRampupExperiment(&field_trial_config); +} + +absl::optional QualityRampupExperiment::MinPixels() const { + return min_pixels_.GetOptional(); +} + +absl::optional QualityRampupExperiment::MinDurationMs() const { + return min_duration_ms_.GetOptional(); +} + +absl::optional QualityRampupExperiment::MaxBitrateFactor() const { + return max_bitrate_factor_.GetOptional(); +} + +void QualityRampupExperiment::SetMaxBitrate(int pixels, + uint32_t max_bitrate_kbps) { + if (!min_pixels_ || pixels < min_pixels_.Value() || max_bitrate_kbps == 0) { + return; + } + max_bitrate_kbps_ = std::max(max_bitrate_kbps_.value_or(0), max_bitrate_kbps); +} + +bool QualityRampupExperiment::BwHigh(int64_t now_ms, + uint32_t available_bw_kbps) { + if (!min_pixels_ || !min_duration_ms_ || !max_bitrate_kbps_) { + return false; + } + + if (available_bw_kbps < + max_bitrate_kbps_.value() * MaxBitrateFactor().value_or(1)) { + start_ms_.reset(); + return false; + } + + if (!start_ms_) + start_ms_ = now_ms; + + return (now_ms - *start_ms_) >= min_duration_ms_.Value(); +} + +void QualityRampupExperiment::Reset() { + start_ms_.reset(); + max_bitrate_kbps_.reset(); +} + +bool QualityRampupExperiment::Enabled() const { + return min_pixels_ && min_duration_ms_; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.h b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.h new file mode 100644 index 0000000000..e8048a3c1c --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef RTC_BASE_EXPERIMENTS_QUALITY_RAMPUP_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_QUALITY_RAMPUP_EXPERIMENT_H_ + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class QualityRampupExperiment final { + public: + static QualityRampupExperiment ParseSettings(); + + absl::optional MinPixels() const; + absl::optional MinDurationMs() const; + absl::optional MaxBitrateFactor() const; + + // Sets the max bitrate and the frame size. + // The call has no effect if the frame size is less than `min_pixels_`. + void SetMaxBitrate(int pixels, uint32_t max_bitrate_kbps); + + // Returns true if the available bandwidth is a certain percentage + // (max_bitrate_factor_) above `max_bitrate_kbps_` for `min_duration_ms_`. + bool BwHigh(int64_t now_ms, uint32_t available_bw_kbps); + + void Reset(); + bool Enabled() const; + + private: + explicit QualityRampupExperiment( + const FieldTrialsView* const key_value_config); + + FieldTrialOptional min_pixels_; + FieldTrialOptional min_duration_ms_; + FieldTrialOptional max_bitrate_factor_; + + absl::optional start_ms_; + absl::optional max_bitrate_kbps_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_QUALITY_RAMPUP_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build new file mode 100644 index 0000000000..aa454826f6 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("quality_rampup_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_unittest.cc new file mode 100644 index 0000000000..b0ede34791 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_unittest.cc @@ -0,0 +1,139 @@ +/* + * 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/quality_rampup_experiment.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +class QualityRampupExperimentTest : public ::testing::Test { + protected: + int64_t NowMs() const { return current_ms_; } + int64_t AdvanceMs(int64_t delta_ms) { + current_ms_ += delta_ms; + return current_ms_; + } + int64_t current_ms_ = 2345; +}; + +TEST_F(QualityRampupExperimentTest, ValuesNotSetByDefault) { + const auto settings = QualityRampupExperiment::ParseSettings(); + EXPECT_FALSE(settings.MinPixels()); + EXPECT_FALSE(settings.MinDurationMs()); + EXPECT_FALSE(settings.MaxBitrateFactor()); +} + +TEST_F(QualityRampupExperimentTest, ParseMinPixels) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/min_pixels:10000/"); + EXPECT_EQ(10000, QualityRampupExperiment::ParseSettings().MinPixels()); +} + +TEST_F(QualityRampupExperimentTest, ParseMinDuration) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/min_duration_ms:987/"); + EXPECT_EQ(987, QualityRampupExperiment::ParseSettings().MinDurationMs()); +} + +TEST_F(QualityRampupExperimentTest, ParseMaxBitrateFactor) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/max_bitrate_factor:1.23/"); + EXPECT_EQ(1.23, QualityRampupExperiment::ParseSettings().MaxBitrateFactor()); +} + +TEST_F(QualityRampupExperimentTest, ReportsBwHighWhenDurationPassed) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/" + "min_pixels:10000,min_duration_ms:2000/"); + auto exp = QualityRampupExperiment::ParseSettings(); + EXPECT_EQ(10000, exp.MinPixels()); + EXPECT_EQ(2000, exp.MinDurationMs()); + + const uint32_t kMaxKbps = 800; + exp.SetMaxBitrate(/*pixels*/ 10000, kMaxKbps); + + const uint32_t kAvailableKbps = kMaxKbps; + EXPECT_FALSE(exp.BwHigh(NowMs(), kAvailableKbps)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000 - 1), kAvailableKbps)); + EXPECT_TRUE(exp.BwHigh(AdvanceMs(1), kAvailableKbps)); +} + +TEST_F(QualityRampupExperimentTest, UsesMaxSetBitrate) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/" + "min_pixels:10000,min_duration_ms:2000/"); + auto exp = QualityRampupExperiment::ParseSettings(); + + const uint32_t kMaxKbps = 800; + exp.SetMaxBitrate(/*pixels*/ 10000, kMaxKbps); + exp.SetMaxBitrate(/*pixels*/ 10000, kMaxKbps - 1); + + EXPECT_FALSE(exp.BwHigh(NowMs(), kMaxKbps - 1)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000), kMaxKbps - 1)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(1), kMaxKbps)); + EXPECT_TRUE(exp.BwHigh(AdvanceMs(2000), kMaxKbps)); +} + +TEST_F(QualityRampupExperimentTest, DoesNotReportBwHighIfBelowMinPixels) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/" + "min_pixels:10000,min_duration_ms:2000/"); + auto exp = QualityRampupExperiment::ParseSettings(); + + const uint32_t kMaxKbps = 800; + exp.SetMaxBitrate(/*pixels*/ 9999, kMaxKbps); + + const uint32_t kAvailableKbps = kMaxKbps; + EXPECT_FALSE(exp.BwHigh(NowMs(), kAvailableKbps)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000), kAvailableKbps)); +} + +TEST_F(QualityRampupExperimentTest, ReportsBwHighWithMaxBitrateFactor) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/" + "min_pixels:10000,min_duration_ms:2000,max_bitrate_factor:1.5/"); + auto exp = QualityRampupExperiment::ParseSettings(); + EXPECT_EQ(10000, exp.MinPixels()); + EXPECT_EQ(2000, exp.MinDurationMs()); + EXPECT_EQ(1.5, exp.MaxBitrateFactor()); + + const uint32_t kMaxKbps = 800; + exp.SetMaxBitrate(/*pixels*/ 10000, kMaxKbps); + + const uint32_t kAvailableKbps = kMaxKbps * 1.5; + EXPECT_FALSE(exp.BwHigh(NowMs(), kAvailableKbps - 1)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000), kAvailableKbps - 1)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(1), kAvailableKbps)); + EXPECT_TRUE(exp.BwHigh(AdvanceMs(2000), kAvailableKbps)); +} + +TEST_F(QualityRampupExperimentTest, ReportsBwHigh) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityRampupSettings/" + "min_pixels:10000,min_duration_ms:2000/"); + auto exp = QualityRampupExperiment::ParseSettings(); + + const uint32_t kMaxKbps = 800; + exp.SetMaxBitrate(/*pixels*/ 10000, kMaxKbps); + + const uint32_t kAvailableKbps = kMaxKbps; + EXPECT_FALSE(exp.BwHigh(NowMs(), kAvailableKbps)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000 - 1), kAvailableKbps)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(1), kAvailableKbps - 1)); // Below, reset. + EXPECT_FALSE(exp.BwHigh(AdvanceMs(1), kAvailableKbps)); + EXPECT_FALSE(exp.BwHigh(AdvanceMs(2000 - 1), kAvailableKbps)); + EXPECT_TRUE(exp.BwHigh(AdvanceMs(1), kAvailableKbps)); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc new file mode 100644 index 0000000000..85c99255ab --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc @@ -0,0 +1,102 @@ +/* + * 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/quality_scaler_settings.h" + +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/logging.h" + +namespace webrtc { +namespace { +const int kMinFrames = 10; +const double kMinScaleFactor = 0.01; +} // namespace + +QualityScalerSettings::QualityScalerSettings( + const FieldTrialsView* const key_value_config) + : sampling_period_ms_("sampling_period_ms"), + average_qp_window_("average_qp_window"), + min_frames_("min_frames"), + initial_scale_factor_("initial_scale_factor"), + scale_factor_("scale_factor"), + initial_bitrate_interval_ms_("initial_bitrate_interval_ms"), + initial_bitrate_factor_("initial_bitrate_factor") { + ParseFieldTrial( + {&sampling_period_ms_, &average_qp_window_, &min_frames_, + &initial_scale_factor_, &scale_factor_, &initial_bitrate_interval_ms_, + &initial_bitrate_factor_}, + key_value_config->Lookup("WebRTC-Video-QualityScalerSettings")); +} + +QualityScalerSettings QualityScalerSettings::ParseFromFieldTrials() { + FieldTrialBasedConfig field_trial_config; + return QualityScalerSettings(&field_trial_config); +} + +absl::optional QualityScalerSettings::SamplingPeriodMs() const { + if (sampling_period_ms_ && sampling_period_ms_.Value() <= 0) { + RTC_LOG(LS_WARNING) << "Unsupported sampling_period_ms value, ignored."; + return absl::nullopt; + } + return sampling_period_ms_.GetOptional(); +} + +absl::optional QualityScalerSettings::AverageQpWindow() const { + if (average_qp_window_ && average_qp_window_.Value() <= 0) { + RTC_LOG(LS_WARNING) << "Unsupported average_qp_window value, ignored."; + return absl::nullopt; + } + return average_qp_window_.GetOptional(); +} + +absl::optional QualityScalerSettings::MinFrames() const { + if (min_frames_ && min_frames_.Value() < kMinFrames) { + RTC_LOG(LS_WARNING) << "Unsupported min_frames value, ignored."; + return absl::nullopt; + } + return min_frames_.GetOptional(); +} + +absl::optional QualityScalerSettings::InitialScaleFactor() const { + if (initial_scale_factor_ && + initial_scale_factor_.Value() < kMinScaleFactor) { + RTC_LOG(LS_WARNING) << "Unsupported initial_scale_factor value, ignored."; + return absl::nullopt; + } + return initial_scale_factor_.GetOptional(); +} + +absl::optional QualityScalerSettings::ScaleFactor() const { + if (scale_factor_ && scale_factor_.Value() < kMinScaleFactor) { + RTC_LOG(LS_WARNING) << "Unsupported scale_factor value, ignored."; + return absl::nullopt; + } + return scale_factor_.GetOptional(); +} + +absl::optional QualityScalerSettings::InitialBitrateIntervalMs() const { + if (initial_bitrate_interval_ms_ && + initial_bitrate_interval_ms_.Value() < 0) { + RTC_LOG(LS_WARNING) << "Unsupported bitrate_interval value, ignored."; + return absl::nullopt; + } + return initial_bitrate_interval_ms_.GetOptional(); +} + +absl::optional QualityScalerSettings::InitialBitrateFactor() const { + if (initial_bitrate_factor_ && + initial_bitrate_factor_.Value() < kMinScaleFactor) { + RTC_LOG(LS_WARNING) << "Unsupported initial_bitrate_factor value, ignored."; + return absl::nullopt; + } + return initial_bitrate_factor_.GetOptional(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h new file mode 100644 index 0000000000..99827aac6b --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#ifndef RTC_BASE_EXPERIMENTS_QUALITY_SCALER_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_QUALITY_SCALER_SETTINGS_H_ + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class QualityScalerSettings final { + public: + static QualityScalerSettings ParseFromFieldTrials(); + + absl::optional SamplingPeriodMs() const; + absl::optional AverageQpWindow() const; + absl::optional MinFrames() const; + absl::optional InitialScaleFactor() const; + absl::optional ScaleFactor() const; + absl::optional InitialBitrateIntervalMs() const; + absl::optional InitialBitrateFactor() const; + + private: + explicit QualityScalerSettings(const FieldTrialsView* const key_value_config); + + FieldTrialOptional sampling_period_ms_; + FieldTrialOptional average_qp_window_; + FieldTrialOptional min_frames_; + FieldTrialOptional initial_scale_factor_; + FieldTrialOptional scale_factor_; + FieldTrialOptional initial_bitrate_interval_ms_; + FieldTrialOptional initial_bitrate_factor_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_QUALITY_SCALER_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build new file mode 100644 index 0000000000..c8c2708eb7 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("quality_scaler_settings_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc new file mode 100644 index 0000000000..9da770c1b5 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc @@ -0,0 +1,103 @@ +/* + * 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/quality_scaler_settings.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +TEST(QualityScalerSettingsTest, ValuesNotSetByDefault) { + const auto settings = QualityScalerSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings.MinFrames()); + EXPECT_FALSE(settings.InitialScaleFactor()); + EXPECT_FALSE(settings.ScaleFactor()); + EXPECT_FALSE(settings.InitialBitrateIntervalMs()); + EXPECT_FALSE(settings.InitialBitrateFactor()); +} + +TEST(QualityScalerSettingsTest, ParseMinFrames) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/min_frames:100/"); + EXPECT_EQ(100, QualityScalerSettings::ParseFromFieldTrials().MinFrames()); +} + +TEST(QualityScalerSettingsTest, ParseInitialScaleFactor) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/initial_scale_factor:1.5/"); + EXPECT_EQ(1.5, + QualityScalerSettings::ParseFromFieldTrials().InitialScaleFactor()); +} + +TEST(QualityScalerSettingsTest, ParseScaleFactor) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/scale_factor:1.1/"); + EXPECT_EQ(1.1, QualityScalerSettings::ParseFromFieldTrials().ScaleFactor()); +} + +TEST(QualityScalerSettingsTest, ParseInitialBitrateInterval) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/initial_bitrate_interval_ms:1000/"); + EXPECT_EQ( + 1000, + QualityScalerSettings::ParseFromFieldTrials().InitialBitrateIntervalMs()); +} + +TEST(QualityScalerSettingsTest, ParseInitialBitrateFactor) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/initial_bitrate_factor:0.75/"); + EXPECT_EQ( + 0.75, + QualityScalerSettings::ParseFromFieldTrials().InitialBitrateFactor()); +} + +TEST(QualityScalerSettingsTest, ParseAll) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/" + "min_frames:100,initial_scale_factor:1.5,scale_factor:0.9," + "initial_bitrate_interval_ms:5500,initial_bitrate_factor:0.7/"); + const auto settings = QualityScalerSettings::ParseFromFieldTrials(); + EXPECT_EQ(100, settings.MinFrames()); + EXPECT_EQ(1.5, settings.InitialScaleFactor()); + EXPECT_EQ(0.9, settings.ScaleFactor()); + EXPECT_EQ(5500, settings.InitialBitrateIntervalMs()); + EXPECT_EQ(0.7, settings.InitialBitrateFactor()); +} + +TEST(QualityScalerSettingsTest, DoesNotParseIncorrectValue) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/" + "min_frames:a,initial_scale_factor:b,scale_factor:c," + "initial_bitrate_interval_ms:d,initial_bitrate_factor:e/"); + const auto settings = QualityScalerSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings.MinFrames()); + EXPECT_FALSE(settings.InitialScaleFactor()); + EXPECT_FALSE(settings.ScaleFactor()); + EXPECT_FALSE(settings.InitialBitrateIntervalMs()); + EXPECT_FALSE(settings.InitialBitrateFactor()); +} + +TEST(QualityScalerSettingsTest, DoesNotReturnTooSmallValue) { + test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScalerSettings/" + "min_frames:0,initial_scale_factor:0.0,scale_factor:0.0," + "initial_bitrate_interval_ms:-1,initial_bitrate_factor:0.0/"); + const auto settings = QualityScalerSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings.MinFrames()); + EXPECT_FALSE(settings.InitialScaleFactor()); + EXPECT_FALSE(settings.ScaleFactor()); + EXPECT_FALSE(settings.InitialBitrateIntervalMs()); + EXPECT_FALSE(settings.InitialBitrateFactor()); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc new file mode 100644 index 0000000000..7d5722bbe3 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc @@ -0,0 +1,111 @@ +/* + * Copyright 2018 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/quality_scaling_experiment.h" + +#include + +#include + +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { +namespace { +constexpr char kFieldTrial[] = "WebRTC-Video-QualityScaling"; +constexpr int kMinQp = 1; +constexpr int kMaxVp8Qp = 127; +constexpr int kMaxVp9Qp = 255; +constexpr int kMaxH264Qp = 51; +constexpr int kMaxGenericQp = 255; + +#if !defined(WEBRTC_IOS) +constexpr char kDefaultQualityScalingSetttings[] = + "Enabled-29,95,149,205,24,37,26,36,0.9995,0.9999,1"; +#endif + +absl::optional GetThresholds(int low, + int high, + int max) { + if (low < kMinQp || high > max || high < low) + return absl::nullopt; + + RTC_LOG(LS_INFO) << "QP thresholds: low: " << low << ", high: " << high; + return absl::optional( + VideoEncoder::QpThresholds(low, high)); +} +} // namespace + +bool QualityScalingExperiment::Enabled() { +#if defined(WEBRTC_IOS) + return webrtc::field_trial::IsEnabled(kFieldTrial); +#else + return !webrtc::field_trial::IsDisabled(kFieldTrial); +#endif +} + +absl::optional +QualityScalingExperiment::ParseSettings() { + std::string group = webrtc::field_trial::FindFullName(kFieldTrial); + // TODO(http://crbug.com/webrtc/12401): Completely remove the experiment code + // after few releases. +#if !defined(WEBRTC_IOS) + if (group.empty()) + group = kDefaultQualityScalingSetttings; +#endif + Settings s; + if (sscanf(group.c_str(), "Enabled-%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%d", + &s.vp8_low, &s.vp8_high, &s.vp9_low, &s.vp9_high, &s.h264_low, + &s.h264_high, &s.generic_low, &s.generic_high, &s.alpha_high, + &s.alpha_low, &s.drop) != 11) { + RTC_LOG(LS_WARNING) << "Invalid number of parameters provided."; + return absl::nullopt; + } + return s; +} + +absl::optional +QualityScalingExperiment::GetQpThresholds(VideoCodecType codec_type) { + const auto settings = ParseSettings(); + if (!settings) + return absl::nullopt; + + switch (codec_type) { + case kVideoCodecVP8: + return GetThresholds(settings->vp8_low, settings->vp8_high, kMaxVp8Qp); + case kVideoCodecVP9: + return GetThresholds(settings->vp9_low, settings->vp9_high, kMaxVp9Qp); + case kVideoCodecH264: + return GetThresholds(settings->h264_low, settings->h264_high, kMaxH264Qp); + case kVideoCodecGeneric: + return GetThresholds(settings->generic_low, settings->generic_high, + kMaxGenericQp); + default: + return absl::nullopt; + } +} + +QualityScalingExperiment::Config QualityScalingExperiment::GetConfig() { + const auto settings = ParseSettings(); + if (!settings) + return Config(); + + Config config; + config.use_all_drop_reasons = settings->drop > 0; + + if (settings->alpha_high < 0 || settings->alpha_low < settings->alpha_high) { + RTC_LOG(LS_WARNING) << "Invalid alpha value provided, using default."; + return config; + } + config.alpha_high = settings->alpha_high; + config.alpha_low = settings->alpha_low; + return config; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h new file mode 100644 index 0000000000..31d8292b5c --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h @@ -0,0 +1,58 @@ +/* + * Copyright 2018 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_QUALITY_SCALING_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_QUALITY_SCALING_EXPERIMENT_H_ + +#include "absl/types/optional.h" +#include "api/video_codecs/video_encoder.h" + +namespace webrtc { +class QualityScalingExperiment { + public: + struct Settings { + int vp8_low; // VP8: low QP threshold. + int vp8_high; // VP8: high QP threshold. + int vp9_low; // VP9: low QP threshold. + int vp9_high; // VP9: high QP threshold. + int h264_low; // H264: low QP threshold. + int h264_high; // H264: high QP threshold. + int generic_low; // Generic: low QP threshold. + int generic_high; // Generic: high QP threshold. + float alpha_high; // `alpha_` for ExpFilter used when checking high QP. + float alpha_low; // `alpha_` for ExpFilter used when checking low QP. + int drop; // >0 sets `use_all_drop_reasons` to true. + }; + + // Used by QualityScaler. + struct Config { + float alpha_high = 0.9995f; + float alpha_low = 0.9999f; + // If set, all type of dropped frames are used. + // Otherwise only dropped frames by MediaOptimization are used. + bool use_all_drop_reasons = false; + }; + + // Returns true if the experiment is enabled. + static bool Enabled(); + + // Returns settings from field trial. + static absl::optional ParseSettings(); + + // Returns QpThresholds for the `codec_type`. + static absl::optional GetQpThresholds( + VideoCodecType codec_type); + + // Returns parsed values. If the parsing fails, default values are returned. + static Config GetConfig(); +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_QUALITY_SCALING_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build new file mode 100644 index 0000000000..2a84caa1a1 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("quality_scaling_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_unittest.cc new file mode 100644 index 0000000000..4507f1514f --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_unittest.cc @@ -0,0 +1,186 @@ +/* + * Copyright 2018 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/quality_scaling_experiment.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { +void ExpectEqualSettings(QualityScalingExperiment::Settings a, + QualityScalingExperiment::Settings b) { + EXPECT_EQ(a.vp8_low, b.vp8_low); + EXPECT_EQ(a.vp8_high, b.vp8_high); + EXPECT_EQ(a.vp9_low, b.vp9_low); + EXPECT_EQ(a.vp9_high, b.vp9_high); + EXPECT_EQ(a.h264_low, b.h264_low); + EXPECT_EQ(a.h264_high, b.h264_high); + EXPECT_EQ(a.generic_low, b.generic_low); + EXPECT_EQ(a.generic_high, b.generic_high); + EXPECT_EQ(a.alpha_high, b.alpha_high); + EXPECT_EQ(a.alpha_low, b.alpha_low); + EXPECT_EQ(a.drop, b.drop); +} + +void ExpectEqualConfig(QualityScalingExperiment::Config a, + QualityScalingExperiment::Config b) { + EXPECT_EQ(a.alpha_high, b.alpha_high); + EXPECT_EQ(a.alpha_low, b.alpha_low); + EXPECT_EQ(a.use_all_drop_reasons, b.use_all_drop_reasons); +} +} // namespace + +#if !defined(WEBRTC_IOS) +// TODO(bugs.webrtc.org/12401): investigate why QualityScaler kicks in on iOS. +TEST(QualityScalingExperimentTest, DefaultEnabledWithoutFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials(""); + EXPECT_TRUE(QualityScalingExperiment::Enabled()); +} +#else +TEST(QualityScalingExperimentTest, DefaultDisabledWithoutFieldTrialIOS) { + webrtc::test::ScopedFieldTrials field_trials(""); + EXPECT_FALSE(QualityScalingExperiment::Enabled()); +} +#endif + +TEST(QualityScalingExperimentTest, EnabledWithFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled/"); + EXPECT_TRUE(QualityScalingExperiment::Enabled()); +} + +TEST(QualityScalingExperimentTest, ParseSettings) { + const QualityScalingExperiment::Settings kExpected = {1, 2, 3, 4, 5, 6, + 7, 8, 0.9f, 0.99f, 1}; + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.9,0.99,1/"); + const auto settings = QualityScalingExperiment::ParseSettings(); + EXPECT_TRUE(settings); + ExpectEqualSettings(kExpected, *settings); +} + +#if !defined(WEBRTC_IOS) +// TODO(bugs.webrtc.org/12401): investigate why QualityScaler kicks in on iOS. +TEST(QualityScalingExperimentTest, ParseSettingsUsesDefaultsWithoutFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials(""); + // Uses some default hard coded values. + EXPECT_TRUE(QualityScalingExperiment::ParseSettings()); +} +#else +TEST(QualityScalingExperimentTest, ParseSettingsFailsWithoutFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials(""); + EXPECT_FALSE(QualityScalingExperiment::ParseSettings()); +} +#endif + +TEST(QualityScalingExperimentTest, ParseSettingsFailsWithInvalidFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-invalid/"); + EXPECT_FALSE(QualityScalingExperiment::ParseSettings()); +} + +TEST(QualityScalingExperimentTest, GetConfig) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.9,0.99,0/"); + const auto config = QualityScalingExperiment::GetConfig(); + EXPECT_EQ(0.9f, config.alpha_high); + EXPECT_EQ(0.99f, config.alpha_low); + EXPECT_FALSE(config.use_all_drop_reasons); +} + +TEST(QualityScalingExperimentTest, GetsDefaultConfigForInvalidFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-invalid/"); + const auto config = QualityScalingExperiment::GetConfig(); + ExpectEqualConfig(config, QualityScalingExperiment::Config()); +} + +TEST(QualityScalingExperimentTest, GetsDefaultAlphaForInvalidValue) { + QualityScalingExperiment::Config expected_config; + expected_config.use_all_drop_reasons = true; + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.99,0.9,1/"); + const auto config = QualityScalingExperiment::GetConfig(); + ExpectEqualConfig(config, expected_config); +} + +TEST(QualityScalingExperimentTest, GetVp8Thresholds) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,0,0,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecVP8); + EXPECT_TRUE(thresholds); + EXPECT_EQ(1, thresholds->low); + EXPECT_EQ(2, thresholds->high); +} + +TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidVp8Value) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-0,0,3,4,5,6,7,8,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecVP8); + EXPECT_FALSE(thresholds); +} + +TEST(QualityScalingExperimentTest, GetVp9Thresholds) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,0,0,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecVP9); + EXPECT_TRUE(thresholds); + EXPECT_EQ(3, thresholds->low); + EXPECT_EQ(4, thresholds->high); +} + +TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidVp9Value) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,0,0,5,6,7,8,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecVP9); + EXPECT_FALSE(thresholds); +} + +TEST(QualityScalingExperimentTest, GetH264Thresholds) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,0,0,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecH264); + EXPECT_TRUE(thresholds); + EXPECT_EQ(5, thresholds->low); + EXPECT_EQ(6, thresholds->high); +} + +TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidH264Value) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,0,0,7,8,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecH264); + EXPECT_FALSE(thresholds); +} + +TEST(QualityScalingExperimentTest, GetGenericThresholds) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,0,0,7,8,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecGeneric); + EXPECT_TRUE(thresholds); + EXPECT_EQ(7, thresholds->low); + EXPECT_EQ(8, thresholds->high); +} + +TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidGenericValue) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,0,0,0.9,0.99,1/"); + const auto thresholds = + QualityScalingExperiment::GetQpThresholds(kVideoCodecGeneric); + EXPECT_FALSE(thresholds); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc new file mode 100644 index 0000000000..84e7b1bcc1 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc @@ -0,0 +1,183 @@ +/* + * 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 "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 = 350; + +const int kDefaultMinPushbackTargetBitrateBps = 30000; + +const char kCongestionWindowDefaultFieldTrialString[] = + "QueueSize:350,MinBitrate:30000,DropFrame:true"; + +const char kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName[] = + "WebRTC-UseBaseHeavyVP8TL3RateAllocation"; + +bool IsEnabled(const FieldTrialsView* const key_value_config, + absl::string_view key) { + return absl::StartsWith(key_value_config->Lookup(key), "Enabled"); +} + +} // namespace + +constexpr char CongestionWindowConfig::kKey[]; + +std::unique_ptr 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 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, // + "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); +} + +RateControlSettings::RateControlSettings( + const FieldTrialsView* const key_value_config) { + std::string congestion_window_config = + key_value_config->Lookup(CongestionWindowConfig::kKey).empty() + ? kCongestionWindowDefaultFieldTrialString + : key_value_config->Lookup(CongestionWindowConfig::kKey); + congestion_window_config_ = + CongestionWindowConfig::Parse(congestion_window_config); + video_config_.vp8_base_heavy_tl3_alloc = IsEnabled( + key_value_config, kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName); + 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 FieldTrialsView* 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_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 +RateControlSettings::CongestionWindowInitialDataWindow() const { + return congestion_window_config_.initial_data_window; +} + +absl::optional RateControlSettings::GetPacingFactor() const { + return video_config_.pacing_factor; +} + +bool RateControlSettings::UseAlrProbing() const { + return video_config_.alr_probing; +} + +absl::optional 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 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::LibvpxVp9TrustedRateController() const { + return video_config_.trust_vp9; +} + +bool RateControlSettings::Vp8BaseHeavyTl3RateAllocation() const { + return video_config_.vp8_base_heavy_tl3_alloc; +} + +bool RateControlSettings::UseEncoderBitrateAdjuster() const { + return video_config_.bitrate_adjuster; +} + +bool RateControlSettings::BitrateAdjusterCanUseNetworkHeadroom() const { + return video_config_.adjuster_use_headroom; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.h b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.h new file mode 100644 index 0000000000..05e942d39f --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#ifndef RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_ +#define RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_ + +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "api/units/data_size.h" +#include "api/video_codecs/video_codec.h" +#include "rtc_base/experiments/struct_parameters_parser.h" +#include "video/config/video_encoder_config.h" + +namespace webrtc { + +struct CongestionWindowConfig { + static constexpr char kKey[] = "WebRTC-CongestionWindow"; + absl::optional queue_size_ms; + absl::optional min_bitrate_bps; + absl::optional initial_data_window; + bool drop_frame_only = false; + std::unique_ptr Parser(); + static CongestionWindowConfig Parse(absl::string_view config); +}; + +struct VideoRateControlConfig { + static constexpr char kKey[] = "WebRTC-VideoRateControl"; + absl::optional pacing_factor; + bool alr_probing = false; + absl::optional vp8_qp_max; + absl::optional vp8_min_pixels; + bool trust_vp8 = true; + bool trust_vp9 = true; + bool bitrate_adjuster = true; + bool adjuster_use_headroom = true; + bool vp8_s0_boost = false; + bool vp8_base_heavy_tl3_alloc = false; + + std::unique_ptr Parser(); +}; + +class RateControlSettings final { + public: + ~RateControlSettings(); + RateControlSettings(RateControlSettings&&); + + static RateControlSettings ParseFromFieldTrials(); + static RateControlSettings ParseFromKeyValueConfig( + const FieldTrialsView* const key_value_config); + + // When CongestionWindowPushback is enabled, the pacer is oblivious to + // the congestion window. The relation between outstanding data and + // the congestion window affects encoder allocations directly. + bool UseCongestionWindow() const; + int64_t GetCongestionWindowAdditionalTimeMs() const; + bool UseCongestionWindowPushback() const; + bool UseCongestionWindowDropFrameOnly() const; + uint32_t CongestionWindowMinPushbackTargetBitrateBps() const; + absl::optional CongestionWindowInitialDataWindow() const; + + absl::optional GetPacingFactor() const; + bool UseAlrProbing() const; + + absl::optional LibvpxVp8QpMax() const; + absl::optional LibvpxVp8MinPixels() const; + bool LibvpxVp8TrustedRateController() const; + bool Vp8BoostBaseLayerQuality() const; + bool Vp8DynamicRateSettings() const; + bool LibvpxVp9TrustedRateController() const; + bool Vp9DynamicRateSettings() const; + + bool Vp8BaseHeavyTl3RateAllocation() const; + + bool UseEncoderBitrateAdjuster() const; + bool BitrateAdjusterCanUseNetworkHeadroom() const; + + private: + explicit RateControlSettings(const FieldTrialsView* const key_value_config); + + CongestionWindowConfig congestion_window_config_; + VideoRateControlConfig video_config_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build new file mode 100644 index 0000000000..6cbe9e8474 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rate_control_settings_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_unittest.cc new file mode 100644 index 0000000000..91ebf531bd --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_unittest.cc @@ -0,0 +1,191 @@ +/* + * 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/rate_control_settings.h" + +#include "api/video_codecs/video_codec.h" +#include "test/field_trial.h" +#include "test/gtest.h" +#include "video/config/video_encoder_config.h" + +namespace webrtc { + +namespace { + +TEST(RateControlSettingsTest, CongestionWindow) { + EXPECT_TRUE( + RateControlSettings::ParseFromFieldTrials().UseCongestionWindow()); + + test::ScopedFieldTrials field_trials( + "WebRTC-CongestionWindow/QueueSize:100/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_after.UseCongestionWindow()); + EXPECT_EQ(settings_after.GetCongestionWindowAdditionalTimeMs(), 100); +} + +TEST(RateControlSettingsTest, CongestionWindowPushback) { + EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials() + .UseCongestionWindowPushback()); + + test::ScopedFieldTrials field_trials( + "WebRTC-CongestionWindow/QueueSize:100,MinBitrate:100000/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_after.UseCongestionWindowPushback()); + EXPECT_EQ(settings_after.CongestionWindowMinPushbackTargetBitrateBps(), + 100000u); +} + +TEST(RateControlSettingsTest, CongestionWindowPushbackDropframe) { + EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials() + .UseCongestionWindowPushback()); + + test::ScopedFieldTrials field_trials( + "WebRTC-CongestionWindow/" + "QueueSize:100,MinBitrate:100000,DropFrame:true/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_after.UseCongestionWindowPushback()); + EXPECT_EQ(settings_after.CongestionWindowMinPushbackTargetBitrateBps(), + 100000u); + EXPECT_TRUE(settings_after.UseCongestionWindowDropFrameOnly()); +} + +TEST(RateControlSettingsTest, CongestionWindowPushbackDefaultConfig) { + const RateControlSettings settings = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings.UseCongestionWindowPushback()); + EXPECT_EQ(settings.CongestionWindowMinPushbackTargetBitrateBps(), 30000u); + EXPECT_TRUE(settings.UseCongestionWindowDropFrameOnly()); +} + +TEST(RateControlSettingsTest, PacingFactor) { + EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().GetPacingFactor()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/pacing_factor:1.2/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + // Need to explicitly dereference the absl::optional + // for the EXPECT_DOUBLE_EQ to compile. + ASSERT_TRUE(settings_after.GetPacingFactor()); + EXPECT_DOUBLE_EQ(*settings_after.GetPacingFactor(), 1.2); +} + +TEST(RateControlSettingsTest, AlrProbing) { + EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().UseAlrProbing()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/alr_probing:1/"); + EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials().UseAlrProbing()); +} + +TEST(RateControlSettingsTest, LibvpxVp8QpMax) { + EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().LibvpxVp8QpMax()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/vp8_qp_max:50/"); + EXPECT_EQ(RateControlSettings::ParseFromFieldTrials().LibvpxVp8QpMax(), 50); +} + +TEST(RateControlSettingsTest, DoesNotGetTooLargeLibvpxVp8QpMaxValue) { + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/vp8_qp_max:70/"); + EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().LibvpxVp8QpMax()); +} + +TEST(RateControlSettingsTest, LibvpxVp8MinPixels) { + EXPECT_FALSE( + RateControlSettings::ParseFromFieldTrials().LibvpxVp8MinPixels()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/vp8_min_pixels:50000/"); + EXPECT_EQ(RateControlSettings::ParseFromFieldTrials().LibvpxVp8MinPixels(), + 50000); +} + +TEST(RateControlSettingsTest, DoesNotGetTooSmallLibvpxVp8MinPixelValue) { + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/vp8_min_pixels:0/"); + EXPECT_FALSE( + RateControlSettings::ParseFromFieldTrials().LibvpxVp8MinPixels()); +} + +TEST(RateControlSettingsTest, LibvpxTrustedRateController) { + const RateControlSettings settings_before = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_before.LibvpxVp8TrustedRateController()); + EXPECT_TRUE(settings_before.LibvpxVp9TrustedRateController()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/trust_vp8:0,trust_vp9:0/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings_after.LibvpxVp8TrustedRateController()); + EXPECT_FALSE(settings_after.LibvpxVp9TrustedRateController()); +} + +TEST(RateControlSettingsTest, Vp8BaseHeavyTl3RateAllocationLegacyKey) { + const RateControlSettings settings_before = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings_before.Vp8BaseHeavyTl3RateAllocation()); + + test::ScopedFieldTrials field_trials( + "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_after.Vp8BaseHeavyTl3RateAllocation()); +} + +TEST(RateControlSettingsTest, + Vp8BaseHeavyTl3RateAllocationVideoRateControlKey) { + const RateControlSettings settings_before = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings_before.Vp8BaseHeavyTl3RateAllocation()); + + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/vp8_base_heavy_tl3_alloc:1/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_TRUE(settings_after.Vp8BaseHeavyTl3RateAllocation()); +} + +TEST(RateControlSettingsTest, + Vp8BaseHeavyTl3RateAllocationVideoRateControlKeyOverridesLegacyKey) { + const RateControlSettings settings_before = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings_before.Vp8BaseHeavyTl3RateAllocation()); + + test::ScopedFieldTrials field_trials( + "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/WebRTC-VideoRateControl/" + "vp8_base_heavy_tl3_alloc:0/"); + const RateControlSettings settings_after = + RateControlSettings::ParseFromFieldTrials(); + EXPECT_FALSE(settings_after.Vp8BaseHeavyTl3RateAllocation()); +} + +TEST(RateControlSettingsTest, UseEncoderBitrateAdjuster) { + // Should be on by default. + EXPECT_TRUE( + RateControlSettings::ParseFromFieldTrials().UseEncoderBitrateAdjuster()); + + { + // Can be turned off via field trial. + test::ScopedFieldTrials field_trials( + "WebRTC-VideoRateControl/bitrate_adjuster:false/"); + EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials() + .UseEncoderBitrateAdjuster()); + } +} + +} // namespace + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc new file mode 100644 index 0000000000..b4c9c31d99 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc @@ -0,0 +1,65 @@ +/* + * Copyright 2018 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/rtt_mult_experiment.h" + +#include + +#include +#include + +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { + +namespace { +const char kRttMultExperiment[] = "WebRTC-RttMult"; +const float max_rtt_mult_setting = 1.0; +const float min_rtt_mult_setting = 0.0; +const float max_rtt_mult_add_cap_ms = 2000.0; +const float min_rtt_mult_add_cap_ms = 0.0; +} // namespace + +bool RttMultExperiment::RttMultEnabled() { + return field_trial::IsEnabled(kRttMultExperiment); +} + +absl::optional +RttMultExperiment::GetRttMultValue() { + if (!RttMultExperiment::RttMultEnabled()) + return absl::nullopt; + const std::string group = + webrtc::field_trial::FindFullName(kRttMultExperiment); + if (group.empty()) { + RTC_LOG(LS_WARNING) << "Could not find rtt_mult_experiment."; + return absl::nullopt; + } + + Settings s; + if (sscanf(group.c_str(), "Enabled-%f,%f", &s.rtt_mult_setting, + &s.rtt_mult_add_cap_ms) != 2) { + RTC_LOG(LS_WARNING) << "Invalid number of parameters provided."; + return absl::nullopt; + } + // Bounds check rtt_mult_setting and rtt_mult_add_cap_ms values. + s.rtt_mult_setting = std::min(s.rtt_mult_setting, max_rtt_mult_setting); + s.rtt_mult_setting = std::max(s.rtt_mult_setting, min_rtt_mult_setting); + s.rtt_mult_add_cap_ms = + std::min(s.rtt_mult_add_cap_ms, max_rtt_mult_add_cap_ms); + s.rtt_mult_add_cap_ms = + std::max(s.rtt_mult_add_cap_ms, min_rtt_mult_add_cap_ms); + RTC_LOG(LS_INFO) << "rtt_mult experiment: rtt_mult value = " + << s.rtt_mult_setting + << " rtt_mult addition cap = " << s.rtt_mult_add_cap_ms + << " ms."; + return s; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.h b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.h new file mode 100644 index 0000000000..a868e63e8d --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 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_RTT_MULT_EXPERIMENT_H_ +#define RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_ + +#include "absl/types/optional.h" + +namespace webrtc { + +class RttMultExperiment { + public: + struct Settings { + float rtt_mult_setting; // Jitter buffer size is increased by this factor + // times the estimated RTT. + float rtt_mult_add_cap_ms; // Jitter buffer size increase is capped by this + // value. + }; + + // Returns true if the experiment is enabled. + static bool RttMultEnabled(); + + // Returns rtt_mult value and rtt_mult addition cap value from field trial. + static absl::optional GetRttMultValue(); +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build new file mode 100644 index 0000000000..aea652b106 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtt_mult_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc new file mode 100644 index 0000000000..bb00f5ec34 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc @@ -0,0 +1,62 @@ +/* + * Copyright 2018 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/rtt_mult_experiment.h" + +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(RttMultExperimentTest, RttMultDisabledByDefault) { + EXPECT_FALSE(RttMultExperiment::RttMultEnabled()); +} + +TEST(RttMultExperimentTest, RttMultEnabledByFieldTrial) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enabled-0.60,100.0/"); + EXPECT_TRUE(RttMultExperiment::RttMultEnabled()); +} + +TEST(RttMultExperimentTest, RttMultTestValue) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enabled-0.60,100.0/"); + EXPECT_EQ(0.6f, RttMultExperiment::GetRttMultValue()->rtt_mult_setting); + EXPECT_EQ(100.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_add_cap_ms); +} + +TEST(RttMultExperimentTest, RttMultTestMalformedEnabled) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enable-0.60,100.0/"); + EXPECT_FALSE(RttMultExperiment::RttMultEnabled()); + EXPECT_FALSE(RttMultExperiment::GetRttMultValue()); +} + +TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsPositive) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enabled-1.5,2100.0/"); + EXPECT_EQ(1.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_setting); + EXPECT_EQ(2000.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_add_cap_ms); +} + +TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsNegative) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enabled--0.5,-100.0/"); + EXPECT_EQ(0.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_setting); + EXPECT_EQ(0.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_add_cap_ms); +} + +TEST(RttMultExperimentTest, RttMultTestMalformedValue) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-RttMult/Enabled-0.25,10a0.0/"); + EXPECT_NE(100.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_add_cap_ms); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc new file mode 100644 index 0000000000..fa04fa35b4 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc @@ -0,0 +1,63 @@ +/* + * 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" + +namespace webrtc { +namespace { +constexpr char kFieldTrialName[] = "WebRTC-StableTargetRate"; +} // namespace + +StableTargetRateExperiment::StableTargetRateExperiment( + const FieldTrialsView* const key_value_config, + double default_video_hysteresis, + double 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( + const StableTargetRateExperiment&) = default; +StableTargetRateExperiment::StableTargetRateExperiment( + StableTargetRateExperiment&&) = default; + +StableTargetRateExperiment StableTargetRateExperiment::ParseFromFieldTrials() { + FieldTrialBasedConfig config; + return ParseFromKeyValueConfig(&config); +} + +StableTargetRateExperiment StableTargetRateExperiment::ParseFromKeyValueConfig( + const FieldTrialsView* const key_value_config) { + return StableTargetRateExperiment(key_value_config, + /*default_video_hysteresis=*/1.2, + /*default_screenshare_hysteresis=*/1.35); +} + +bool StableTargetRateExperiment::IsEnabled() const { + return enabled_.Get(); +} + +double StableTargetRateExperiment::GetVideoHysteresisFactor() const { + return video_hysteresis_factor_.Get(); +} + +double StableTargetRateExperiment::GetScreenshareHysteresisFactor() const { + return screenshare_hysteresis_factor_.Get(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.h b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.h new file mode 100644 index 0000000000..be0f9da129 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.h @@ -0,0 +1,44 @@ +/* + * 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/field_trials_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +namespace webrtc { + +class StableTargetRateExperiment { + public: + StableTargetRateExperiment(const StableTargetRateExperiment&); + StableTargetRateExperiment(StableTargetRateExperiment&&); + static StableTargetRateExperiment ParseFromFieldTrials(); + static StableTargetRateExperiment ParseFromKeyValueConfig( + const FieldTrialsView* const key_value_config); + + bool IsEnabled() const; + double GetVideoHysteresisFactor() const; + double GetScreenshareHysteresisFactor() const; + + private: + explicit StableTargetRateExperiment( + const FieldTrialsView* const key_value_config, + double default_video_hysteresis, + double default_screenshare_hysteresis); + + FieldTrialParameter enabled_; + FieldTrialParameter video_hysteresis_factor_; + FieldTrialParameter screenshare_hysteresis_factor_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_STABLE_TARGET_RATE_EXPERIMENT_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build new file mode 100644 index 0000000000..c1854a7f4d --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("stable_target_rate_experiment_gn") diff --git a/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_unittest.cc new file mode 100644 index 0000000000..854398e910 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_unittest.cc @@ -0,0 +1,67 @@ +/* + * 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_EQ(config.GetVideoHysteresisFactor(), 1.2); + EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.35); +} + +TEST(StableBweExperimentTest, EnabledNoHysteresis) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-StableTargetRate/enabled:true/"); + + StableTargetRateExperiment config = + StableTargetRateExperiment::ParseFromFieldTrials(); + EXPECT_TRUE(config.IsEnabled()); + EXPECT_EQ(config.GetVideoHysteresisFactor(), 1.2); + EXPECT_EQ(config.GetScreenshareHysteresisFactor(), 1.35); +} + +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, 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 diff --git a/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc new file mode 100644 index 0000000000..011df3eaba --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc @@ -0,0 +1,135 @@ +/* + * 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/struct_parameters_parser.h" + +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/logging.h" + +namespace webrtc { +namespace { +size_t FindOrEnd(absl::string_view str, size_t start, char delimiter) { + size_t pos = str.find(delimiter, start); + pos = (pos == absl::string_view::npos) ? str.length() : pos; + return pos; +} +} // namespace + +namespace struct_parser_impl { +namespace { +inline void StringEncode(std::string* target, bool val) { + *target += rtc::ToString(val); +} +inline void StringEncode(std::string* target, double val) { + *target += rtc::ToString(val); +} +inline void StringEncode(std::string* target, int val) { + *target += rtc::ToString(val); +} +inline void StringEncode(std::string* target, unsigned val) { + *target += rtc::ToString(val); +} +inline void StringEncode(std::string* target, DataRate val) { + *target += webrtc::ToString(val); +} +inline void StringEncode(std::string* target, DataSize val) { + *target += webrtc::ToString(val); +} +inline void StringEncode(std::string* target, TimeDelta val) { + *target += webrtc::ToString(val); +} + +template +inline void StringEncode(std::string* sb, absl::optional val) { + if (val) + StringEncode(sb, *val); +} +} // namespace +template +bool TypedParser::Parse(absl::string_view src, void* target) { + auto parsed = ParseTypedParameter(std::string(src)); + if (parsed.has_value()) + *reinterpret_cast(target) = *parsed; + return parsed.has_value(); +} +template +void TypedParser::Encode(const void* src, std::string* target) { + StringEncode(target, *reinterpret_cast(src)); +} + +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser>; +template class TypedParser>; +template class TypedParser>; + +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser>; +template class TypedParser>; +template class TypedParser>; +} // namespace struct_parser_impl + +StructParametersParser::StructParametersParser( + std::vector members) + : members_(std::move(members)) {} + +void StructParametersParser::Parse(absl::string_view src) { + size_t i = 0; + while (i < src.length()) { + size_t val_end = FindOrEnd(src, i, ','); + size_t colon_pos = FindOrEnd(src, i, ':'); + size_t key_end = std::min(val_end, colon_pos); + size_t val_begin = key_end + 1u; + absl::string_view key(src.substr(i, key_end - i)); + absl::string_view opt_value; + if (val_end >= val_begin) + opt_value = src.substr(val_begin, val_end - val_begin); + i = val_end + 1u; + bool found = false; + for (auto& member : members_) { + if (key == member.key) { + found = true; + if (!member.parser.parse(opt_value, member.member_ptr)) { + RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key + << "' in trial: \"" << src << "\""; + } + break; + } + } + // "_" is be used to prefix keys that are part of the string for + // debugging purposes but not neccessarily used. + // e.g. WebRTC-Experiment/param: value, _DebuggingString + if (!found && (key.empty() || key[0] != '_')) { + RTC_LOG(LS_INFO) << "No field with key: '" << key + << "' (found in trial: \"" << src << "\")"; + } + } +} + +std::string StructParametersParser::Encode() const { + std::string res; + bool first = true; + for (const auto& member : members_) { + if (!first) + res += ","; + res += member.key; + res += ":"; + member.parser.encode(member.member_ptr, &res); + first = false; + } + return res; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.h b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.h new file mode 100644 index 0000000000..f5f8340209 --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.h @@ -0,0 +1,110 @@ +/* + * 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. + */ +#ifndef RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ +#define RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ + +#include +#include +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/experiments/field_trial_units.h" +#include "rtc_base/string_encode.h" + +namespace webrtc { +namespace struct_parser_impl { +struct TypedMemberParser { + public: + bool (*parse)(absl::string_view src, void* target); + void (*encode)(const void* src, std::string* target); +}; + +struct MemberParameter { + const char* key; + void* member_ptr; + TypedMemberParser parser; +}; + +template +class TypedParser { + public: + static bool Parse(absl::string_view src, void* target); + static void Encode(const void* src, std::string* target); +}; + +// Instantiated in cc file to avoid duplication during compile. Add additional +// parsers as needed. Generally, try to use these suggested types even if the +// context where the value is used might require a different type. For instance, +// a size_t representing a packet size should use an int parameter as there's no +// need to support packet sizes larger than INT32_MAX. +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser>; +extern template class TypedParser>; +extern template class TypedParser>; + +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser>; +extern template class TypedParser>; +extern template class TypedParser>; + +template +void AddMembers(MemberParameter* out, const char* key, T* member) { + *out = MemberParameter{ + key, member, + TypedMemberParser{&TypedParser::Parse, &TypedParser::Encode}}; +} + +template +void AddMembers(MemberParameter* out, + const char* key, + T* member, + Args... args) { + AddMembers(out, key, member); + AddMembers(++out, args...); +} +} // namespace struct_parser_impl + +class StructParametersParser { + public: + template + static std::unique_ptr Create(const char* first_key, + T* first_member, + Args... args) { + std::vector members( + sizeof...(args) / 2 + 1); + struct_parser_impl::AddMembers(&members.front(), std::move(first_key), + first_member, args...); + return absl::WrapUnique(new StructParametersParser(std::move(members))); + } + + void Parse(absl::string_view src); + std::string Encode() const; + + private: + explicit StructParametersParser( + std::vector members); + + std::vector members_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ diff --git a/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc new file mode 100644 index 0000000000..2f92b9fc6a --- /dev/null +++ b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc @@ -0,0 +1,67 @@ +/* + * 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/struct_parameters_parser.h" +#include "rtc_base/gunit.h" + +namespace webrtc { +namespace { +struct DummyConfig { + bool enabled = false; + double factor = 0.5; + int retries = 5; + unsigned size = 3; + bool ping = 0; + absl::optional duration; + absl::optional latency = TimeDelta::Millis(100); + std::unique_ptr Parser(); +}; + +std::unique_ptr DummyConfig::Parser() { + // The empty comments ensures that each pair is on a separate line. + return StructParametersParser::Create("e", &enabled, // + "f", &factor, // + "r", &retries, // + "s", &size, // + "p", &ping, // + "d", &duration, // + "l", &latency); +} +} // namespace + +TEST(StructParametersParserTest, ParsesValidParameters) { + DummyConfig exp; + exp.Parser()->Parse("e:1,f:-1.7,r:2,s:7,p:1,d:8,l:,"); + EXPECT_TRUE(exp.enabled); + EXPECT_EQ(exp.factor, -1.7); + EXPECT_EQ(exp.retries, 2); + EXPECT_EQ(exp.size, 7u); + EXPECT_EQ(exp.ping, true); + EXPECT_EQ(exp.duration.value().ms(), 8); + EXPECT_FALSE(exp.latency); +} + +TEST(StructParametersParserTest, UsesDefaults) { + DummyConfig exp; + exp.Parser()->Parse(""); + EXPECT_FALSE(exp.enabled); + EXPECT_EQ(exp.factor, 0.5); + EXPECT_EQ(exp.retries, 5); + EXPECT_EQ(exp.size, 3u); + EXPECT_EQ(exp.ping, false); +} + +TEST(StructParametersParserTest, EncodeAll) { + DummyConfig exp; + auto encoded = exp.Parser()->Encode(); + // All parameters are encoded. + EXPECT_EQ(encoded, "e:false,f:0.5,r:5,s:3,p:false,d:,l:100 ms"); +} + +} // namespace webrtc -- cgit v1.2.3