summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/experiments
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/rtc_base/experiments')
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/BUILD.gn302
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/DEPS8
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/OWNERS13
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/alr_experiment.cc98
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/alr_experiment.h48
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc487
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.h143
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc619
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.cc43
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings.h35
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_unittest.cc49
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.cc89
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h64
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_unittest.cc106
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc236
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h100
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_unittest.cc102
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_list.cc59
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_list.h226
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_list_unittest.cc141
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_parser.cc260
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_parser.h291
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build235
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc187
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_units.cc116
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_units.h41
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/field_trial_units_unittest.cc87
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.cc39
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings.h39
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_unittest.cc43
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc116
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.h28
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_unittest.cc161
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.cc49
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment.h25
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc59
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.cc82
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment.h53
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_unittest.cc139
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc96
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h44
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc100
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc117
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h61
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_unittest.cc186
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rate_control_settings.cc183
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rate_control_settings.h93
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rate_control_settings_unittest.cc191
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc39
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.h35
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc31
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.cc63
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment.h44
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build232
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_unittest.cc67
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc135
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser.h110
-rw-r--r--third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc68
71 files changed, 9929 insertions, 0 deletions
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..185d5931f7
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/BUILD.gn
@@ -0,0 +1,302 @@
+# 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",
+ ]
+ 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:field_trials_view",
+ "../../api/transport:field_trial_based_config",
+ "../../api/video_codecs:video_codecs_api",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings:strings",
+ "//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 <inttypes.h>
+#include <stdio.h>
+
+#include <string>
+
+#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>
+AlrExperimentSettings::CreateFromFieldTrial(absl::string_view experiment_name) {
+ return AlrExperimentSettings::CreateFromFieldTrial(FieldTrialBasedConfig(),
+ experiment_name);
+}
+
+absl::optional<AlrExperimentSettings>
+AlrExperimentSettings::CreateFromFieldTrial(
+ const FieldTrialsView& key_value_config,
+ absl::string_view experiment_name) {
+ absl::optional<AlrExperimentSettings> 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 <stdint.h>
+
+#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<AlrExperimentSettings> CreateFromFieldTrial(
+ absl::string_view experiment_name);
+ static absl::optional<AlrExperimentSettings> 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..4435f010b6
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/alr_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..1a269b4fa6
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings.cc
@@ -0,0 +1,487 @@
+/*
+ * 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 <limits>
+
+#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<BalancedDegradationSettings::Config> 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<BalancedDegradationSettings::Config>& 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<BalancedDegradationSettings::Config> GetValidOrDefault(
+ const std::vector<BalancedDegradationSettings::Config>& configs) {
+ if (IsValid(configs)) {
+ return configs;
+ }
+ return DefaultConfigs();
+}
+
+absl::optional<VideoEncoder::QpThresholds> GetThresholds(
+ VideoCodecType type,
+ const BalancedDegradationSettings::Config& config) {
+ absl::optional<int> low;
+ absl::optional<int> 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 kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use H264 QP thresholds for now.
+ 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>(
+ VideoEncoder::QpThresholds(*low, *high));
+ }
+ return absl::nullopt;
+}
+
+int GetFps(VideoCodecType type,
+ const absl::optional<BalancedDegradationSettings::Config>& config) {
+ if (!config.has_value()) {
+ return std::numeric_limits<int>::max();
+ }
+
+ absl::optional<int> fps;
+ switch (type) {
+ case kVideoCodecVP8:
+ fps = config->vp8.GetFps();
+ break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
+ 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<int>::max() : framerate;
+}
+
+absl::optional<int> GetKbps(
+ VideoCodecType type,
+ const absl::optional<BalancedDegradationSettings::Config>& config) {
+ if (!config.has_value())
+ return absl::nullopt;
+
+ absl::optional<int> kbps;
+ switch (type) {
+ case kVideoCodecVP8:
+ kbps = config->vp8.GetKbps();
+ break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
+ 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<int>(config->kbps) : absl::nullopt;
+}
+
+absl::optional<int> GetKbpsRes(
+ VideoCodecType type,
+ const absl::optional<BalancedDegradationSettings::Config>& config) {
+ if (!config.has_value())
+ return absl::nullopt;
+
+ absl::optional<int> kbps_res;
+ switch (type) {
+ case kVideoCodecVP8:
+ kbps_res = config->vp8.GetKbpsRes();
+ break;
+ case kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
+ 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<int>(config->kbps_res)
+ : absl::nullopt;
+}
+} // namespace
+
+absl::optional<int> BalancedDegradationSettings::CodecTypeSpecific::GetQpLow()
+ const {
+ return (qp_low > 0) ? absl::optional<int>(qp_low) : absl::nullopt;
+}
+
+absl::optional<int> BalancedDegradationSettings::CodecTypeSpecific::GetQpHigh()
+ const {
+ return (qp_high > 0) ? absl::optional<int>(qp_high) : absl::nullopt;
+}
+
+absl::optional<int> BalancedDegradationSettings::CodecTypeSpecific::GetFps()
+ const {
+ return (fps > 0) ? absl::optional<int>(fps) : absl::nullopt;
+}
+
+absl::optional<int> BalancedDegradationSettings::CodecTypeSpecific::GetKbps()
+ const {
+ return (kbps > 0) ? absl::optional<int>(kbps) : absl::nullopt;
+}
+
+absl::optional<int> BalancedDegradationSettings::CodecTypeSpecific::GetKbpsRes()
+ const {
+ return (kbps_res > 0) ? absl::optional<int>(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<Config> 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::Config>
+BalancedDegradationSettings::GetConfigs() const {
+ return configs_;
+}
+
+int BalancedDegradationSettings::MinFps(VideoCodecType type, int pixels) const {
+ return GetFps(type, GetMinFpsConfig(pixels));
+}
+
+absl::optional<BalancedDegradationSettings::Config>
+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::Config>
+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<int> 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<uint32_t>(min_kbps.value() * 1000);
+}
+
+bool BalancedDegradationSettings::CanAdaptUpResolution(
+ VideoCodecType type,
+ int pixels,
+ uint32_t bitrate_bps) const {
+ absl::optional<int> 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<uint32_t>(min_kbps.value() * 1000);
+}
+
+absl::optional<int> BalancedDegradationSettings::MinFpsDiff(int pixels) const {
+ for (const auto& config : configs_) {
+ if (pixels <= config.pixels) {
+ return (config.fps_diff > kNoFpsDiff)
+ ? absl::optional<int>(config.fps_diff)
+ : absl::nullopt;
+ }
+ }
+ return absl::nullopt;
+}
+
+absl::optional<VideoEncoder::QpThresholds>
+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..2bca73dfb9
--- /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 <vector>
+
+#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<int> GetQpLow() const;
+ absl::optional<int> GetQpHigh() const;
+ absl::optional<int> GetFps() const;
+ absl::optional<int> GetKbps() const;
+ absl::optional<int> 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<Config> 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<int> MinFpsDiff(int pixels) const;
+
+ // Gets QpThresholds for the codec `type` based on `pixels`.
+ absl::optional<VideoEncoder::QpThresholds> GetQpThresholds(
+ VideoCodecType type,
+ int pixels) const;
+
+ private:
+ absl::optional<Config> GetMinFpsConfig(int pixels) const;
+ absl::optional<Config> GetMaxFpsConfig(int pixels) const;
+ Config GetConfig(int pixels) const;
+
+ std::vector<Config> 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..cbbb32ab70
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..996c06f8f2
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/balanced_degradation_settings_unittest.cc
@@ -0,0 +1,619 @@
+/*
+ * 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 <limits>
+
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+#include "test/scoped_key_value_config.h"
+
+namespace webrtc {
+namespace {
+
+void VerifyIsDefault(
+ const std::vector<BalancedDegradationSettings::Config>& 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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<uint32_t>
+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<uint32_t> BitrateStateUpdateInterval() const;
+
+ private:
+ explicit BandwidthQualityScalerSettings(
+ const FieldTrialsView* const key_value_config);
+
+ FieldTrialOptional<uint32_t> 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..95a92d20e1
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/bandwidth_quality_scaler_settings_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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 <stdio.h>
+
+#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<CpuSpeedExperiment::Config> GetValidOrEmpty(
+ const std::vector<CpuSpeedExperiment::Config>& 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<CpuSpeedExperiment::Config>& configs) {
+ for (const auto& config : configs) {
+ if (config.cpu_speed_le_cores == 0)
+ return false;
+ }
+ return true;
+}
+} // namespace
+
+CpuSpeedExperiment::CpuSpeedExperiment() : cores_("cores") {
+ FieldTrialStructList<Config> 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<int> 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<int>(config.cpu_speed_le_cores)
+ : absl::optional<int>(config.cpu_speed);
+ }
+ return absl::optional<int>(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..24ec0c0ec6
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment.h
@@ -0,0 +1,64 @@
+/*
+ * 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 <vector>
+
+#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<int> GetValue(int pixels, int num_cores) const;
+
+ private:
+ std::vector<Config> configs_;
+
+ // Threshold for when to use `cpu_speed_le_cores`.
+ FieldTrialOptional<int> 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..5151c986c4
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/cpu_speed_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..136201d261
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.cc
@@ -0,0 +1,236 @@
+/*
+ * 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 <stdio.h>
+
+#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<VideoEncoder::ResolutionBitrateLimits> ToResolutionBitrateLimits(
+ const std::vector<EncoderInfoSettings::BitrateLimit>& limits) {
+ std::vector<VideoEncoder::ResolutionBitrateLimits> 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<VideoEncoder::ResolutionBitrateLimits>
+EncoderInfoSettings::GetDefaultSinglecastBitrateLimits(
+ VideoCodecType codec_type) {
+ if (codec_type == kVideoCodecAV1) {
+ // AV1 singlecast max bitrate limits are higher than AV1 SVC max limits.
+ // This is because in singlecast we normally have just one receiver, BWE is
+ // known end-to-end and the encode target bitrate guarantees delivery of
+ // video.
+ // The min bitrate limits are not used in singlecast (used in SVC/simulcast
+ // to de-/activate spatial layers) and are set to zero. Send resolution in
+ // singlecast is assumed to be regulated by QP-based quality scaler.
+ return {{320 * 180, 0, 0, 256000},
+ {480 * 270, 176000, 0, 384000},
+ {640 * 360, 256000, 0, 512000},
+ {960 * 540, 384000, 0, 1024000},
+ {1280 * 720, 576000, 0, 1536000}};
+ }
+
+ if (codec_type == kVideoCodecVP9) {
+ // VP9 singlecast bitrate limits are derived ~directly from VP9 SVC bitrate
+ // limits. The current max limits are unnecessarily too strict for
+ // singlecast, where BWE is known end-to-end, especially for low
+ // resolutions.
+ 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}};
+ }
+
+ // VP8 and other codecs.
+ 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<VideoEncoder::ResolutionBitrateLimits>
+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<VideoEncoder::ResolutionBitrateLimits>
+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<VideoEncoder::ResolutionBitrateLimits>
+EncoderInfoSettings::GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
+ absl::optional<int> frame_size_pixels,
+ const std::vector<VideoEncoder::ResolutionBitrateLimits>&
+ resolution_bitrate_limits) {
+ if (!frame_size_pixels.has_value() || frame_size_pixels.value() <= 0) {
+ return absl::nullopt;
+ }
+
+ std::vector<VideoEncoder::ResolutionBitrateLimits> 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<int>(
+ 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<int>(
+ 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<BitrateLimit> 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<uint32_t> 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") {}
+
+LibaomAv1EncoderInfoSettings::LibaomAv1EncoderInfoSettings()
+ : EncoderInfoSettings("WebRTC-Av1-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..416bf6be7a
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings.h
@@ -0,0 +1,100 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#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<uint32_t> requested_resolution_alignment() const;
+ bool apply_alignment_to_all_simulcast_layers() const {
+ return apply_alignment_to_all_simulcast_layers_.Get();
+ }
+ std::vector<VideoEncoder::ResolutionBitrateLimits> resolution_bitrate_limits()
+ const {
+ return resolution_bitrate_limits_;
+ }
+
+ static std::vector<VideoEncoder::ResolutionBitrateLimits>
+ GetDefaultSinglecastBitrateLimits(VideoCodecType codec_type);
+
+ static absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ GetDefaultSinglecastBitrateLimitsForResolution(VideoCodecType codec_type,
+ int frame_size_pixels);
+
+ static std::vector<VideoEncoder::ResolutionBitrateLimits>
+ GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted();
+
+ static absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
+ absl::optional<int> frame_size_pixels,
+ const std::vector<VideoEncoder::ResolutionBitrateLimits>&
+ resolution_bitrate_limits);
+
+ protected:
+ explicit EncoderInfoSettings(absl::string_view name);
+
+ private:
+ FieldTrialOptional<uint32_t> requested_resolution_alignment_;
+ FieldTrialFlag apply_alignment_to_all_simulcast_layers_;
+ std::vector<VideoEncoder::ResolutionBitrateLimits> 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 {}
+};
+
+// EncoderInfo settings for LibaomAv1Encoder.
+class LibaomAv1EncoderInfoSettings : public EncoderInfoSettings {
+ public:
+ LibaomAv1EncoderInfoSettings();
+ ~LibaomAv1EncoderInfoSettings() 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..b7a699fe03
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/encoder_info_settings_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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<std::string> str_value) {
+ RTC_DCHECK_NOTREACHED();
+ return true;
+}
+
+int FieldTrialStructListBase::ValidateAndGetLength() {
+ int length = -1;
+ for (std::unique_ptr<FieldTrialListWrapper>& 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..63403cc51d
--- /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 <initializer_list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#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<T> 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 <typename T>
+class FieldTrialList : public FieldTrialListBase {
+ public:
+ explicit FieldTrialList(absl::string_view key) : FieldTrialList(key, {}) {}
+ FieldTrialList(absl::string_view key, std::initializer_list<T> default_values)
+ : FieldTrialListBase(key), values_(default_values) {}
+
+ std::vector<T> Get() const { return values_; }
+ operator std::vector<T>() const { return Get(); }
+ typename std::vector<T>::const_reference operator[](size_t index) const {
+ return values_[index];
+ }
+ const std::vector<T>* operator->() const { return &values_; }
+
+ protected:
+ bool Parse(absl::optional<std::string> str_value) override {
+ parse_got_called_ = true;
+
+ if (!str_value) {
+ values_.clear();
+ return true;
+ }
+
+ std::vector<T> new_values_;
+
+ for (const absl::string_view token : rtc::split(str_value.value(), '|')) {
+ absl::optional<T> value = ParseTypedParameter<T>(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<T> 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 <typename T>
+struct LambdaTypeTraits : public LambdaTypeTraits<decltype(&T::operator())> {};
+
+template <typename ClassType, typename RetType, typename SourceType>
+struct LambdaTypeTraits<RetType* (ClassType::*)(SourceType*) const> {
+ using ret = RetType;
+ using src = SourceType;
+};
+
+template <typename T>
+struct TypedFieldTrialListWrapper : FieldTrialListWrapper {
+ public:
+ TypedFieldTrialListWrapper(absl::string_view key,
+ std::function<void(void*, T)> 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<T> list_;
+ std::function<void(void*, T)> sink_;
+};
+
+} // namespace field_trial_list_impl
+
+template <typename F,
+ typename Traits = typename field_trial_list_impl::LambdaTypeTraits<F>>
+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<typename Traits::src*>(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<FieldTrialListWrapper*> 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<FieldTrialListWrapper>(*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<std::string> str_value) override;
+
+ std::vector<std::unique_ptr<FieldTrialListWrapper>> sub_lists_;
+};
+
+template <typename S>
+class FieldTrialStructList : public FieldTrialStructListBase {
+ public:
+ FieldTrialStructList(std::initializer_list<FieldTrialListWrapper*> l,
+ std::initializer_list<S> default_list)
+ : FieldTrialStructListBase(l), values_(default_list) {}
+
+ std::vector<S> Get() const { return values_; }
+ operator std::vector<S>() const { return Get(); }
+ const S& operator[](size_t index) const { return values_[index]; }
+ const std::vector<S>* operator->() const { return &values_; }
+
+ protected:
+ void ParseDone() override {
+ int length = ValidateAndGetLength();
+
+ if (length == -1)
+ return;
+
+ std::vector<S> new_values(length, S());
+
+ for (std::unique_ptr<FieldTrialListWrapper>& 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<S> 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<int> 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<std::string> 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<Garment> 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<Garment> 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<Garment> 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<Garment> 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<Garment> 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 <inttypes.h>
+
+#include <algorithm>
+#include <map>
+#include <type_traits>
+#include <utility>
+
+#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<FieldTrialParameterInterface*> fields,
+ absl::string_view trial_string) {
+ std::map<absl::string_view, FieldTrialParameterInterface*> 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<std::string> 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<bool> ParseTypedParameter<bool>(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<double> ParseTypedParameter<double>(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<int> ParseTypedParameter<int>(absl::string_view str) {
+ int64_t value;
+ if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) {
+ if (rtc::IsValueInRangeForNumericType<int, int64_t>(value)) {
+ return static_cast<int>(value);
+ }
+ }
+ return absl::nullopt;
+}
+
+template <>
+absl::optional<unsigned> ParseTypedParameter<unsigned>(absl::string_view str) {
+ int64_t value;
+ if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) {
+ if (rtc::IsValueInRangeForNumericType<unsigned, int64_t>(value)) {
+ return static_cast<unsigned>(value);
+ }
+ }
+ return absl::nullopt;
+}
+
+template <>
+absl::optional<std::string> ParseTypedParameter<std::string>(
+ absl::string_view str) {
+ return std::string(str);
+}
+
+template <>
+absl::optional<absl::optional<bool>> ParseTypedParameter<absl::optional<bool>>(
+ absl::string_view str) {
+ return ParseOptionalParameter<bool>(str);
+}
+template <>
+absl::optional<absl::optional<int>> ParseTypedParameter<absl::optional<int>>(
+ absl::string_view str) {
+ return ParseOptionalParameter<int>(str);
+}
+template <>
+absl::optional<absl::optional<unsigned>>
+ParseTypedParameter<absl::optional<unsigned>>(absl::string_view str) {
+ return ParseOptionalParameter<unsigned>(str);
+}
+template <>
+absl::optional<absl::optional<double>>
+ParseTypedParameter<absl::optional<double>>(absl::string_view str) {
+ return ParseOptionalParameter<double>(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<std::string> str_value) {
+ // Only set the flag if there is no argument provided.
+ if (str_value) {
+ absl::optional<bool> opt_value = ParseTypedParameter<bool>(*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<std::string, int> 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<std::string> str_value) {
+ if (str_value) {
+ auto it = enum_mapping_.find(*str_value);
+ if (it != enum_mapping_.end()) {
+ value_ = it->second;
+ return true;
+ }
+ absl::optional<int> value = ParseTypedParameter<int>(*str_value);
+ if (value.has_value() &&
+ (valid_values_.find(*value) != valid_values_.end())) {
+ value_ = *value;
+ return true;
+ }
+ }
+ return false;
+}
+
+template class FieldTrialParameter<bool>;
+template class FieldTrialParameter<double>;
+template class FieldTrialParameter<int>;
+template class FieldTrialParameter<unsigned>;
+template class FieldTrialParameter<std::string>;
+
+template class FieldTrialConstrained<double>;
+template class FieldTrialConstrained<int>;
+template class FieldTrialConstrained<unsigned>;
+
+template class FieldTrialOptional<double>;
+template class FieldTrialOptional<int>;
+template class FieldTrialOptional<unsigned>;
+template class FieldTrialOptional<bool>;
+template class FieldTrialOptional<std::string>;
+
+} // 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 <stdint.h>
+
+#include <initializer_list>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#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<FieldTrialParameterInterface*> fields,
+ absl::string_view trial_string);
+ void MarkAsUsed() { used_ = true; }
+ virtual bool Parse(absl::optional<std::string> str_value) = 0;
+
+ virtual void ParseDone() {}
+
+ std::vector<FieldTrialParameterInterface*> 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<FieldTrialParameterInterface*> 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 <typename T>
+absl::optional<T> ParseTypedParameter(absl::string_view);
+
+// This class uses the ParseTypedParameter function to implement a parameter
+// implementation with an enforced default value.
+template <typename T>
+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<std::string> str_value) override {
+ if (str_value) {
+ absl::optional<T> value = ParseTypedParameter<T>(*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 <typename T>
+class FieldTrialConstrained : public FieldTrialParameterInterface {
+ public:
+ FieldTrialConstrained(absl::string_view key,
+ T default_value,
+ absl::optional<T> lower_limit,
+ absl::optional<T> 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<std::string> str_value) override {
+ if (str_value) {
+ absl::optional<T> value = ParseTypedParameter<T>(*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<T> lower_limit_;
+ absl::optional<T> upper_limit_;
+};
+
+class AbstractFieldTrialEnum : public FieldTrialParameterInterface {
+ public:
+ AbstractFieldTrialEnum(absl::string_view key,
+ int default_value,
+ std::map<std::string, int> mapping);
+ ~AbstractFieldTrialEnum() override;
+ AbstractFieldTrialEnum(const AbstractFieldTrialEnum&);
+
+ protected:
+ bool Parse(absl::optional<std::string> str_value) override;
+
+ protected:
+ int value_;
+ std::map<std::string, int> enum_mapping_;
+ std::set<int> 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 <typename T>
+class FieldTrialEnum : public AbstractFieldTrialEnum {
+ public:
+ FieldTrialEnum(absl::string_view key,
+ T default_value,
+ std::map<std::string, T> mapping)
+ : AbstractFieldTrialEnum(key,
+ static_cast<int>(default_value),
+ ToIntMap(mapping)) {}
+ T Get() const { return static_cast<T>(value_); }
+ operator T() const { return Get(); }
+
+ private:
+ static std::map<std::string, int> ToIntMap(std::map<std::string, T> mapping) {
+ std::map<std::string, int> res;
+ for (const auto& it : mapping)
+ res[it.first] = static_cast<int>(it.second);
+ return res;
+ }
+};
+
+// This class uses the ParseTypedParameter function to implement an optional
+// parameter implementation that can default to absl::nullopt.
+template <typename T>
+class FieldTrialOptional : public FieldTrialParameterInterface {
+ public:
+ explicit FieldTrialOptional(absl::string_view key)
+ : FieldTrialParameterInterface(key) {}
+ FieldTrialOptional(absl::string_view key, absl::optional<T> default_value)
+ : FieldTrialParameterInterface(key), value_(default_value) {}
+ absl::optional<T> 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<std::string> str_value) override {
+ if (str_value) {
+ absl::optional<T> value = ParseTypedParameter<T>(*str_value);
+ if (!value.has_value())
+ return false;
+ value_ = value.value();
+ } else {
+ value_ = absl::nullopt;
+ }
+ return true;
+ }
+
+ private:
+ absl::optional<T> value_;
+};
+
+// Equivalent to a FieldTrialParameter<bool> 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<std::string> str_value) override;
+
+ private:
+ bool value_;
+};
+
+template <typename T>
+absl::optional<absl::optional<T>> ParseOptionalParameter(
+ absl::string_view str) {
+ if (str.empty())
+ return absl::optional<T>();
+ auto parsed = ParseTypedParameter<T>(str);
+ if (parsed.has_value())
+ return parsed;
+ return absl::nullopt;
+}
+
+template <>
+absl::optional<bool> ParseTypedParameter<bool>(absl::string_view str);
+template <>
+absl::optional<double> ParseTypedParameter<double>(absl::string_view str);
+template <>
+absl::optional<int> ParseTypedParameter<int>(absl::string_view str);
+template <>
+absl::optional<unsigned> ParseTypedParameter<unsigned>(absl::string_view str);
+template <>
+absl::optional<std::string> ParseTypedParameter<std::string>(
+ absl::string_view str);
+
+template <>
+absl::optional<absl::optional<bool>> ParseTypedParameter<absl::optional<bool>>(
+ absl::string_view str);
+template <>
+absl::optional<absl::optional<int>> ParseTypedParameter<absl::optional<int>>(
+ absl::string_view str);
+template <>
+absl::optional<absl::optional<unsigned>>
+ParseTypedParameter<absl::optional<unsigned>>(absl::string_view str);
+template <>
+absl::optional<absl::optional<double>>
+ParseTypedParameter<absl::optional<double>>(absl::string_view str);
+
+// Accepts true, false, else parsed with sscanf %i, true if != 0.
+extern template class FieldTrialParameter<bool>;
+// Interpreted using sscanf %lf.
+extern template class FieldTrialParameter<double>;
+// Interpreted using sscanf %i.
+extern template class FieldTrialParameter<int>;
+// Interpreted using sscanf %u.
+extern template class FieldTrialParameter<unsigned>;
+// Using the given value as is.
+extern template class FieldTrialParameter<std::string>;
+
+extern template class FieldTrialConstrained<double>;
+extern template class FieldTrialConstrained<int>;
+extern template class FieldTrialConstrained<unsigned>;
+
+extern template class FieldTrialOptional<double>;
+extern template class FieldTrialOptional<int>;
+extern template class FieldTrialOptional<unsigned>;
+extern template class FieldTrialOptional<bool>;
+extern template class FieldTrialOptional<std::string>;
+
+} // 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..ea63aafc99
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_gn/moz.build
@@ -0,0 +1,235 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..73d115357f
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/field_trial_parser_unittest.cc
@@ -0,0 +1,187 @@
+/*
+ * 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<double> factor = FieldTrialParameter<double>("f", 0.5);
+ FieldTrialParameter<int> retries = FieldTrialParameter<int>("r", 5);
+ FieldTrialParameter<unsigned> size = FieldTrialParameter<unsigned>("s", 3);
+ FieldTrialParameter<bool> ping = FieldTrialParameter<bool>("p", 0);
+ FieldTrialParameter<std::string> hash =
+ FieldTrialParameter<std::string>("h", "a80");
+
+ DummyExperiment()
+ : DummyExperiment([] {
+ field_trial::FieldTrialsAllowedInScopeForTesting k{
+ {kDummyExperiment}};
+ return 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> 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<double> low("low", 10, absl::nullopt, 100);
+ FieldTrialConstrained<double> 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<unsigned> size("size", 5, 1, 10);
+ ParseFieldTrial({&size}, "size:0");
+ EXPECT_EQ(size.Get(), 5u);
+}
+TEST(FieldTrialParserTest, ReadsValuesFromFieldWithoutKey) {
+ FieldTrialFlag enabled("Enabled");
+ FieldTrialParameter<int> req("", 10);
+ ParseFieldTrial({&enabled, &req}, "Enabled,20");
+ EXPECT_EQ(req.Get(), 20);
+ ParseFieldTrial({&req}, "30");
+ EXPECT_EQ(req.Get(), 30);
+}
+TEST(FieldTrialParserTest, ParsesOptionalParameters) {
+ FieldTrialOptional<int> 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<unsigned> 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<std::string> 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<CustomEnum> 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 <stdio.h>
+
+#include <limits>
+#include <string>
+
+#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<ValueWithUnit> ParseValueWithUnit(absl::string_view str) {
+ if (str == "inf") {
+ return ValueWithUnit{std::numeric_limits<double>::infinity(), ""};
+ } else if (str == "-inf") {
+ return ValueWithUnit{-std::numeric_limits<double>::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<DataRate> ParseTypedParameter<DataRate>(absl::string_view str) {
+ absl::optional<ValueWithUnit> 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<DataSize> ParseTypedParameter<DataSize>(absl::string_view str) {
+ absl::optional<ValueWithUnit> result = ParseValueWithUnit(str);
+ if (result) {
+ if (result->unit.empty() || result->unit == "bytes")
+ return DataSize::Bytes(result->value);
+ }
+ return absl::nullopt;
+}
+
+template <>
+absl::optional<TimeDelta> ParseTypedParameter<TimeDelta>(
+ absl::string_view str) {
+ absl::optional<ValueWithUnit> 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<absl::optional<DataRate>>
+ParseTypedParameter<absl::optional<DataRate>>(absl::string_view str) {
+ return ParseOptionalParameter<DataRate>(str);
+}
+template <>
+absl::optional<absl::optional<DataSize>>
+ParseTypedParameter<absl::optional<DataSize>>(absl::string_view str) {
+ return ParseOptionalParameter<DataSize>(str);
+}
+template <>
+absl::optional<absl::optional<TimeDelta>>
+ParseTypedParameter<absl::optional<TimeDelta>>(absl::string_view str) {
+ return ParseOptionalParameter<TimeDelta>(str);
+}
+
+template class FieldTrialParameter<DataRate>;
+template class FieldTrialParameter<DataSize>;
+template class FieldTrialParameter<TimeDelta>;
+
+template class FieldTrialConstrained<DataRate>;
+template class FieldTrialConstrained<DataSize>;
+template class FieldTrialConstrained<TimeDelta>;
+
+template class FieldTrialOptional<DataRate>;
+template class FieldTrialOptional<DataSize>;
+template class FieldTrialOptional<TimeDelta>;
+} // 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<DataRate> ParseTypedParameter<DataRate>(absl::string_view str);
+template <>
+absl::optional<DataSize> ParseTypedParameter<DataSize>(absl::string_view str);
+template <>
+absl::optional<TimeDelta> ParseTypedParameter<TimeDelta>(absl::string_view str);
+
+extern template class FieldTrialParameter<DataRate>;
+extern template class FieldTrialParameter<DataSize>;
+extern template class FieldTrialParameter<TimeDelta>;
+
+extern template class FieldTrialConstrained<DataRate>;
+extern template class FieldTrialConstrained<DataSize>;
+extern template class FieldTrialConstrained<TimeDelta>;
+
+extern template class FieldTrialOptional<DataRate>;
+extern template class FieldTrialOptional<DataSize>;
+extern template class FieldTrialOptional<TimeDelta>;
+} // 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 <string>
+
+#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<DataRate> target_rate =
+ FieldTrialParameter<DataRate>("t", DataRate::KilobitsPerSec(100));
+ FieldTrialParameter<TimeDelta> period =
+ FieldTrialParameter<TimeDelta>("p", TimeDelta::Millis(100));
+ FieldTrialOptional<DataSize> max_buffer =
+ FieldTrialOptional<DataSize>("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<DataRate> rate("r", DataRate::KilobitsPerSec(30),
+ DataRate::KilobitsPerSec(10),
+ DataRate::KilobitsPerSec(100));
+ FieldTrialConstrained<TimeDelta> delta("d", TimeDelta::Millis(30),
+ TimeDelta::Millis(10),
+ TimeDelta::Millis(100));
+ FieldTrialConstrained<DataSize> 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<int> 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<int> MinKeyframeSendIntervalMs() const;
+
+ private:
+ explicit KeyframeIntervalSettings(const FieldTrialsView* key_value_config);
+
+ FieldTrialOptional<int> 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..3857bc9451
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/keyframe_interval_settings_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..f9e7613a15
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment.cc
@@ -0,0 +1,116 @@
+/*
+ * 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 <string>
+
+#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<int> 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<DataRate> GetExperimentalMinVideoBitrate(VideoCodecType type) {
+ const absl::optional<int> 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<webrtc::DataRate> min_video_bitrate("br");
+
+ // New experiment - per-codec minimum bitrate.
+ webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_vp8("vp8_br");
+ webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_vp9("vp9_br");
+ webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_av1("av1_br");
+ webrtc::FieldTrialOptional<webrtc::DataRate> 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 kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use VP9 bitrate limits for now.
+ 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<DataRate> 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..5f811a6c6d
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/min_video_bitrate_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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 <stdio.h>
+
+#include <string>
+
+#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<int> 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<int>(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<int> 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..68ad8a0f14
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/normalize_simulcast_size_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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 <algorithm>
+
+#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<int> QualityRampupExperiment::MinPixels() const {
+ return min_pixels_.GetOptional();
+}
+
+absl::optional<int> QualityRampupExperiment::MinDurationMs() const {
+ return min_duration_ms_.GetOptional();
+}
+
+absl::optional<double> 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<int> MinPixels() const;
+ absl::optional<int> MinDurationMs() const;
+ absl::optional<double> 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<int> min_pixels_;
+ FieldTrialOptional<int> min_duration_ms_;
+ FieldTrialOptional<double> max_bitrate_factor_;
+
+ absl::optional<int64_t> start_ms_;
+ absl::optional<uint32_t> 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..c4b1f5bc22
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_rampup_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..24da211d89
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.cc
@@ -0,0 +1,96 @@
+/*
+ * 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/field_trials_view.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace {
+const int kMinFrames = 10;
+const double kMinScaleFactor = 0.01;
+} // namespace
+
+QualityScalerSettings::QualityScalerSettings(
+ const FieldTrialsView& field_trials)
+ : 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_},
+ field_trials.Lookup("WebRTC-Video-QualityScalerSettings"));
+}
+
+absl::optional<int> 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<int> 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<int> 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<double> 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<double> 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<int> 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<double> 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..1085816697
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings.h
@@ -0,0 +1,44 @@
+/*
+ * 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:
+ explicit QualityScalerSettings(const FieldTrialsView& field_trials);
+
+ absl::optional<int> SamplingPeriodMs() const;
+ absl::optional<int> AverageQpWindow() const;
+ absl::optional<int> MinFrames() const;
+ absl::optional<double> InitialScaleFactor() const;
+ absl::optional<double> ScaleFactor() const;
+ absl::optional<int> InitialBitrateIntervalMs() const;
+ absl::optional<double> InitialBitrateFactor() const;
+
+ private:
+ FieldTrialOptional<int> sampling_period_ms_;
+ FieldTrialOptional<int> average_qp_window_;
+ FieldTrialOptional<int> min_frames_;
+ FieldTrialOptional<double> initial_scale_factor_;
+ FieldTrialOptional<double> scale_factor_;
+ FieldTrialOptional<int> initial_bitrate_interval_ms_;
+ FieldTrialOptional<double> 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..298ca9297c
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..578fe97b03
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaler_settings_unittest.cc
@@ -0,0 +1,100 @@
+/*
+ * 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/gtest.h"
+#include "test/scoped_key_value_config.h"
+
+namespace webrtc {
+namespace {
+
+TEST(QualityScalerSettingsTest, ValuesNotSetByDefault) {
+ webrtc::test::ScopedKeyValueConfig field_trials("");
+ const auto settings = QualityScalerSettings(field_trials);
+ EXPECT_FALSE(settings.MinFrames());
+ EXPECT_FALSE(settings.InitialScaleFactor());
+ EXPECT_FALSE(settings.ScaleFactor());
+ EXPECT_FALSE(settings.InitialBitrateIntervalMs());
+ EXPECT_FALSE(settings.InitialBitrateFactor());
+}
+
+TEST(QualityScalerSettingsTest, ParseMinFrames) {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScalerSettings/min_frames:100/");
+ EXPECT_EQ(100, QualityScalerSettings(field_trials).MinFrames());
+}
+
+TEST(QualityScalerSettingsTest, ParseInitialScaleFactor) {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScalerSettings/initial_scale_factor:1.5/");
+ EXPECT_EQ(1.5, QualityScalerSettings(field_trials).InitialScaleFactor());
+}
+
+TEST(QualityScalerSettingsTest, ParseScaleFactor) {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScalerSettings/scale_factor:1.1/");
+ EXPECT_EQ(1.1, QualityScalerSettings(field_trials).ScaleFactor());
+}
+
+TEST(QualityScalerSettingsTest, ParseInitialBitrateInterval) {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScalerSettings/initial_bitrate_interval_ms:1000/");
+ EXPECT_EQ(1000,
+ QualityScalerSettings(field_trials).InitialBitrateIntervalMs());
+}
+
+TEST(QualityScalerSettingsTest, ParseInitialBitrateFactor) {
+ test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScalerSettings/initial_bitrate_factor:0.75/");
+ EXPECT_EQ(0.75, QualityScalerSettings(field_trials).InitialBitrateFactor());
+}
+
+TEST(QualityScalerSettingsTest, ParseAll) {
+ test::ScopedKeyValueConfig 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(field_trials);
+ 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::ScopedKeyValueConfig 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(field_trials);
+ EXPECT_FALSE(settings.MinFrames());
+ EXPECT_FALSE(settings.InitialScaleFactor());
+ EXPECT_FALSE(settings.ScaleFactor());
+ EXPECT_FALSE(settings.InitialBitrateIntervalMs());
+ EXPECT_FALSE(settings.InitialBitrateFactor());
+}
+
+TEST(QualityScalerSettingsTest, DoesNotReturnTooSmallValue) {
+ test::ScopedKeyValueConfig 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(field_trials);
+ 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..ee3d7c0320
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.cc
@@ -0,0 +1,117 @@
+/*
+ * 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 <stdio.h>
+
+#include <string>
+
+#include "absl/strings/match.h"
+#include "api/field_trials_view.h"
+#include "api/transport/field_trial_based_config.h"
+#include "rtc_base/logging.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<VideoEncoder::QpThresholds> 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>(
+ VideoEncoder::QpThresholds(low, high));
+}
+} // namespace
+
+bool QualityScalingExperiment::Enabled(const FieldTrialsView& field_trials) {
+#if defined(WEBRTC_IOS)
+ return absl::StartsWith(field_trials.Lookup(kFieldTrial), "Enabled");
+#else
+ return !absl::StartsWith(field_trials.Lookup(kFieldTrial), "Disabled");
+#endif
+}
+
+absl::optional<QualityScalingExperiment::Settings>
+QualityScalingExperiment::ParseSettings(const FieldTrialsView& field_trials) {
+ std::string group = field_trials.Lookup(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<VideoEncoder::QpThresholds>
+QualityScalingExperiment::GetQpThresholds(VideoCodecType codec_type,
+ const FieldTrialsView& field_trials) {
+ const auto settings = ParseSettings(field_trials);
+ 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 kVideoCodecH265:
+ // TODO(bugs.webrtc.org/13485): Use H264 QP thresholds for now.
+ 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 FieldTrialsView& field_trials) {
+ const auto settings = ParseSettings(field_trials);
+ 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..bd24c06e55
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment.h
@@ -0,0 +1,61 @@
+/*
+ * 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/field_trials_view.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(const FieldTrialsView& field_trials);
+
+ // Returns settings from field trial.
+ static absl::optional<Settings> ParseSettings(
+ const FieldTrialsView& field_trials);
+
+ // Returns QpThresholds for the `codec_type`.
+ static absl::optional<VideoEncoder::QpThresholds> GetQpThresholds(
+ VideoCodecType codec_type,
+ const FieldTrialsView& field_trials);
+
+ // Returns parsed values. If the parsing fails, default values are returned.
+ static Config GetConfig(const FieldTrialsView& field_trials);
+};
+
+} // 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..d606a38148
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/quality_scaling_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..0c1450557a
--- /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/gtest.h"
+#include "test/scoped_key_value_config.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::ScopedKeyValueConfig field_trials("");
+ EXPECT_TRUE(QualityScalingExperiment::Enabled(field_trials));
+}
+#else
+TEST(QualityScalingExperimentTest, DefaultDisabledWithoutFieldTrialIOS) {
+ webrtc::test::ScopedKeyValueConfig field_trials("");
+ EXPECT_FALSE(QualityScalingExperiment::Enabled(field_trials));
+}
+#endif
+
+TEST(QualityScalingExperimentTest, EnabledWithFieldTrial) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled/");
+ EXPECT_TRUE(QualityScalingExperiment::Enabled(field_trials));
+}
+
+TEST(QualityScalingExperimentTest, ParseSettings) {
+ const QualityScalingExperiment::Settings kExpected = {1, 2, 3, 4, 5, 6,
+ 7, 8, 0.9f, 0.99f, 1};
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.9,0.99,1/");
+ const auto settings = QualityScalingExperiment::ParseSettings(field_trials);
+ 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::ScopedKeyValueConfig field_trials("");
+ // Uses some default hard coded values.
+ EXPECT_TRUE(QualityScalingExperiment::ParseSettings(field_trials));
+}
+#else
+TEST(QualityScalingExperimentTest, ParseSettingsFailsWithoutFieldTrial) {
+ webrtc::test::ScopedKeyValueConfig field_trials("");
+ EXPECT_FALSE(QualityScalingExperiment::ParseSettings(field_trials));
+}
+#endif
+
+TEST(QualityScalingExperimentTest, ParseSettingsFailsWithInvalidFieldTrial) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled-invalid/");
+ EXPECT_FALSE(QualityScalingExperiment::ParseSettings(field_trials));
+}
+
+TEST(QualityScalingExperimentTest, GetConfig) {
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.9,0.99,0/");
+ const auto config = QualityScalingExperiment::GetConfig(field_trials);
+ 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::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled-invalid/");
+ const auto config = QualityScalingExperiment::GetConfig(field_trials);
+ ExpectEqualConfig(config, QualityScalingExperiment::Config());
+}
+
+TEST(QualityScalingExperimentTest, GetsDefaultAlphaForInvalidValue) {
+ QualityScalingExperiment::Config expected_config;
+ expected_config.use_all_drop_reasons = true;
+ webrtc::test::ScopedKeyValueConfig field_trials(
+ "WebRTC-Video-QualityScaling/Enabled-1,2,3,4,5,6,7,8,0.99,0.9,1/");
+ const auto config = QualityScalingExperiment::GetConfig(field_trials);
+ ExpectEqualConfig(config, expected_config);
+}
+
+TEST(QualityScalingExperimentTest, GetVp8Thresholds) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_TRUE(thresholds);
+ EXPECT_EQ(1, thresholds->low);
+ EXPECT_EQ(2, thresholds->high);
+}
+
+TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidVp8Value) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_FALSE(thresholds);
+}
+
+TEST(QualityScalingExperimentTest, GetVp9Thresholds) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_TRUE(thresholds);
+ EXPECT_EQ(3, thresholds->low);
+ EXPECT_EQ(4, thresholds->high);
+}
+
+TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidVp9Value) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_FALSE(thresholds);
+}
+
+TEST(QualityScalingExperimentTest, GetH264Thresholds) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_TRUE(thresholds);
+ EXPECT_EQ(5, thresholds->low);
+ EXPECT_EQ(6, thresholds->high);
+}
+
+TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidH264Value) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_FALSE(thresholds);
+}
+
+TEST(QualityScalingExperimentTest, GetGenericThresholds) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ EXPECT_TRUE(thresholds);
+ EXPECT_EQ(7, thresholds->low);
+ EXPECT_EQ(8, thresholds->high);
+}
+
+TEST(QualityScalingExperimentTest, GetThresholdsFailsForInvalidGenericValue) {
+ webrtc::test::ScopedKeyValueConfig 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, field_trials);
+ 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 <inttypes.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "absl/strings/match.h"
+#include "api/transport/field_trial_based_config.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kDefaultAcceptedQueueMs = 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<StructParametersParser> CongestionWindowConfig::Parser() {
+ return StructParametersParser::Create("QueueSize", &queue_size_ms, //
+ "MinBitrate", &min_bitrate_bps,
+ "InitWin", &initial_data_window,
+ "DropFrame", &drop_frame_only);
+}
+
+// static
+CongestionWindowConfig CongestionWindowConfig::Parse(absl::string_view config) {
+ CongestionWindowConfig res;
+ res.Parser()->Parse(config);
+ return res;
+}
+
+constexpr char VideoRateControlConfig::kKey[];
+
+std::unique_ptr<StructParametersParser> VideoRateControlConfig::Parser() {
+ // The empty comments ensures that each pair is on a separate line.
+ return StructParametersParser::Create(
+ "pacing_factor", &pacing_factor, //
+ "alr_probing", &alr_probing, //
+ "vp8_qp_max", &vp8_qp_max, //
+ "vp8_min_pixels", &vp8_min_pixels, //
+ "trust_vp8", &trust_vp8, //
+ "trust_vp9", &trust_vp9, //
+ "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<bool>(congestion_window_config_.queue_size_ms);
+}
+
+int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
+ return congestion_window_config_.queue_size_ms.value_or(
+ kDefaultAcceptedQueueMs);
+}
+
+bool RateControlSettings::UseCongestionWindowPushback() const {
+ return congestion_window_config_.queue_size_ms &&
+ congestion_window_config_.min_bitrate_bps;
+}
+
+bool RateControlSettings::UseCongestionWindowDropFrameOnly() const {
+ return congestion_window_config_.drop_frame_only;
+}
+
+uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
+ const {
+ return congestion_window_config_.min_bitrate_bps.value_or(
+ kDefaultMinPushbackTargetBitrateBps);
+}
+
+absl::optional<DataSize>
+RateControlSettings::CongestionWindowInitialDataWindow() const {
+ return congestion_window_config_.initial_data_window;
+}
+
+absl::optional<double> RateControlSettings::GetPacingFactor() const {
+ return video_config_.pacing_factor;
+}
+
+bool RateControlSettings::UseAlrProbing() const {
+ return video_config_.alr_probing;
+}
+
+absl::optional<int> RateControlSettings::LibvpxVp8QpMax() const {
+ if (video_config_.vp8_qp_max &&
+ (*video_config_.vp8_qp_max < 0 || *video_config_.vp8_qp_max > 63)) {
+ RTC_LOG(LS_WARNING) << "Unsupported vp8_qp_max_ value, ignored.";
+ return absl::nullopt;
+ }
+ return video_config_.vp8_qp_max;
+}
+
+absl::optional<int> RateControlSettings::LibvpxVp8MinPixels() const {
+ if (video_config_.vp8_min_pixels && *video_config_.vp8_min_pixels < 1) {
+ return absl::nullopt;
+ }
+ return video_config_.vp8_min_pixels;
+}
+
+bool RateControlSettings::LibvpxVp8TrustedRateController() const {
+ return video_config_.trust_vp8;
+}
+
+bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
+ return video_config_.vp8_s0_boost;
+}
+
+bool RateControlSettings::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<int> queue_size_ms;
+ absl::optional<int> min_bitrate_bps;
+ absl::optional<DataSize> initial_data_window;
+ bool drop_frame_only = false;
+ std::unique_ptr<StructParametersParser> Parser();
+ static CongestionWindowConfig Parse(absl::string_view config);
+};
+
+struct VideoRateControlConfig {
+ static constexpr char kKey[] = "WebRTC-VideoRateControl";
+ absl::optional<double> pacing_factor;
+ bool alr_probing = false;
+ absl::optional<int> vp8_qp_max;
+ absl::optional<int> 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<StructParametersParser> 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<DataSize> CongestionWindowInitialDataWindow() const;
+
+ absl::optional<double> GetPacingFactor() const;
+ bool UseAlrProbing() const;
+
+ absl::optional<int> LibvpxVp8QpMax() const;
+ absl::optional<int> 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..be85251358
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/rate_control_settings_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..e15b928937
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment.cc
@@ -0,0 +1,39 @@
+/*
+ * 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 <stdio.h>
+
+#include <algorithm>
+#include <string>
+
+#include "rtc_base/logging.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+const char kRttMultExperiment[] = "WebRTC-RttMult";
+} // namespace
+
+bool RttMultExperiment::RttMultEnabled() {
+ return !field_trial::IsDisabled(kRttMultExperiment);
+}
+
+absl::optional<RttMultExperiment::Settings>
+RttMultExperiment::GetRttMultValue() {
+ if (!RttMultExperiment::RttMultEnabled()) {
+ return absl::nullopt;
+ }
+ return RttMultExperiment::Settings{.rtt_mult_setting = 0.9,
+ .rtt_mult_add_cap_ms = 200.0};
+}
+
+} // 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<RttMultExperiment::Settings> 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..7229d639e8
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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..a6798a1411
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/rtt_mult_experiment_unittest.cc
@@ -0,0 +1,31 @@
+/*
+ * 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, RttMultEnabledByDefault) {
+ EXPECT_TRUE(RttMultExperiment::RttMultEnabled());
+ ASSERT_TRUE(RttMultExperiment::GetRttMultValue());
+ EXPECT_EQ(0.9f, RttMultExperiment::GetRttMultValue()->rtt_mult_setting);
+ EXPECT_EQ(200.0f, RttMultExperiment::GetRttMultValue()->rtt_mult_add_cap_ms);
+}
+
+TEST(RttMultExperimentTest, RttMultDisabledByFieldTrial) {
+ webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Disabled/");
+ EXPECT_FALSE(RttMultExperiment::RttMultEnabled());
+ EXPECT_FALSE(RttMultExperiment::GetRttMultValue());
+}
+
+} // 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<bool> enabled_;
+ FieldTrialParameter<double> video_hysteresis_factor_;
+ FieldTrialParameter<double> 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..d031f8ace4
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/stable_target_rate_experiment_gn/moz.build
@@ -0,0 +1,232 @@
+# 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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_ENABLE_LIBEVENT"] = 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["RTC_ENABLE_WIN_WGC"] = True
+ 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 += [
+ "crypt32",
+ "iphlpapi",
+ "secur32",
+ "winmm"
+ ]
+
+if CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["TARGET_CPU"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["TARGET_CPU"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["TARGET_CPU"] == "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["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "arm":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "x86_64":
+
+ 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 <algorithm>
+
+#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 <typename T>
+inline void StringEncode(std::string* sb, absl::optional<T> val) {
+ if (val)
+ StringEncode(sb, *val);
+}
+} // namespace
+template <typename T>
+bool TypedParser<T>::Parse(absl::string_view src, void* target) {
+ auto parsed = ParseTypedParameter<T>(std::string(src));
+ if (parsed.has_value())
+ *reinterpret_cast<T*>(target) = *parsed;
+ return parsed.has_value();
+}
+template <typename T>
+void TypedParser<T>::Encode(const void* src, std::string* target) {
+ StringEncode(target, *reinterpret_cast<const T*>(src));
+}
+
+template class TypedParser<bool>;
+template class TypedParser<double>;
+template class TypedParser<int>;
+template class TypedParser<unsigned>;
+template class TypedParser<absl::optional<double>>;
+template class TypedParser<absl::optional<int>>;
+template class TypedParser<absl::optional<unsigned>>;
+
+template class TypedParser<DataRate>;
+template class TypedParser<DataSize>;
+template class TypedParser<TimeDelta>;
+template class TypedParser<absl::optional<DataRate>>;
+template class TypedParser<absl::optional<DataSize>>;
+template class TypedParser<absl::optional<TimeDelta>>;
+} // namespace struct_parser_impl
+
+StructParametersParser::StructParametersParser(
+ std::vector<struct_parser_impl::MemberParameter> 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 <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#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 <typename T>
+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<bool>;
+extern template class TypedParser<double>;
+extern template class TypedParser<int>;
+extern template class TypedParser<unsigned>;
+extern template class TypedParser<absl::optional<double>>;
+extern template class TypedParser<absl::optional<int>>;
+extern template class TypedParser<absl::optional<unsigned>>;
+
+extern template class TypedParser<DataRate>;
+extern template class TypedParser<DataSize>;
+extern template class TypedParser<TimeDelta>;
+extern template class TypedParser<absl::optional<DataRate>>;
+extern template class TypedParser<absl::optional<DataSize>>;
+extern template class TypedParser<absl::optional<TimeDelta>>;
+
+template <typename T>
+void AddMembers(MemberParameter* out, const char* key, T* member) {
+ *out = MemberParameter{
+ key, member,
+ TypedMemberParser{&TypedParser<T>::Parse, &TypedParser<T>::Encode}};
+}
+
+template <typename T, typename... Args>
+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 <typename T, typename... Args>
+ static std::unique_ptr<StructParametersParser> Create(const char* first_key,
+ T* first_member,
+ Args... args) {
+ std::vector<struct_parser_impl::MemberParameter> 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<struct_parser_impl::MemberParameter> members);
+
+ std::vector<struct_parser_impl::MemberParameter> 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..0824bd3b27
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/experiments/struct_parameters_parser_unittest.cc
@@ -0,0 +1,68 @@
+/*
+ * 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<TimeDelta> duration;
+ absl::optional<TimeDelta> latency = TimeDelta::Millis(100);
+ std::unique_ptr<StructParametersParser> Parser();
+};
+
+std::unique_ptr<StructParametersParser> 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