Revert of Enable trendline experiment and bayesian bitrate estimator experiment by default. (patchset #6 id:100001 of https://codereview.webrtc.org/2777333003/ )
Reason for revert:
API changes in webrtc/sdk/objc/Framework/Headers/WebRTC/RTCFieldTrials.h broke internal project
Original issue's description:
> Enable trendline experiment and bayesian bitrate estimator experiment by default.
>
> BUG=webrtc:6566, webrtc:7415
>
> Review-Url: https://codereview.webrtc.org/2777333003
> Cr-Commit-Position: refs/heads/master@{#17491}
> Committed: https://chromium.googlesource.com/external/webrtc/+/27925de9512c67c9934ba535dc83ffe04ed999fe
TBR=terelius@webrtc.org,stefan@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:6566, webrtc:7415
Review-Url: https://codereview.webrtc.org/2791743002
Cr-Original-Commit-Position: refs/heads/master@{#17495}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 029f7cccf44da11559cdb5e74bf83b42ee98b039
diff --git a/call/rampup_tests.cc b/call/rampup_tests.cc
index 6c3cce6..0a2a738 100644
--- a/call/rampup_tests.cc
+++ b/call/rampup_tests.cc
@@ -417,9 +417,8 @@
rtx,
red,
report_perf_stats),
- link_rates_({4 * GetExpectedHighBitrate() / (3 * 1000),
- kLowBandwidthLimitBps / 1000,
- 4 * GetExpectedHighBitrate() / (3 * 1000), 0}),
+ link_rates_({GetHighLinkCapacity(), kLowBandwidthLimitBps / 1000,
+ GetHighLinkCapacity(), 0}),
test_state_(kFirstRampup),
next_state_(kTransitionToNextState),
state_start_ms_(clock_->TimeInMilliseconds()),
@@ -489,6 +488,10 @@
return expected_bitrate_bps;
}
+int RampUpDownUpTester::GetHighLinkCapacity() const {
+ return 4 * GetExpectedHighBitrate() / (3 * 1000);
+}
+
size_t RampUpDownUpTester::GetFecBytes() const {
size_t flex_fec_bytes = 0;
if (num_flexfec_streams_ > 0) {
diff --git a/examples/objc/AppRTCMobile/ios/ARDAppDelegate.m b/examples/objc/AppRTCMobile/ios/ARDAppDelegate.m
index 07c83a0..c26f052 100644
--- a/examples/objc/AppRTCMobile/ios/ARDAppDelegate.m
+++ b/examples/objc/AppRTCMobile/ios/ARDAppDelegate.m
@@ -26,6 +26,7 @@
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *fieldTrials = @{
+ kRTCFieldTrialImprovedBitrateEstimateKey: kRTCFieldTrialEnabledValue,
kRTCFieldTrialH264HighProfileKey: kRTCFieldTrialEnabledValue,
};
RTCInitFieldTrialDictionary(fieldTrials);
diff --git a/modules/congestion_controller/delay_based_bwe.cc b/modules/congestion_controller/delay_based_bwe.cc
index 042d7fa..e8d9d21 100644
--- a/modules/congestion_controller/delay_based_bwe.cc
+++ b/modules/congestion_controller/delay_based_bwe.cc
@@ -42,12 +42,86 @@
constexpr int kRateWindowMs = 150;
// Parameters for linear least squares fit of regression line to noisy data.
-constexpr size_t kDefaultTrendlineWindowSize = 20;
+constexpr size_t kDefaultTrendlineWindowSize = 15;
constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
constexpr double kDefaultTrendlineThresholdGain = 4.0;
+// Parameters for Theil-Sen robust fitting of line to noisy data.
+constexpr size_t kDefaultMedianSlopeWindowSize = 20;
+constexpr double kDefaultMedianSlopeThresholdGain = 4.0;
+
constexpr int kMaxConsecutiveFailedLookups = 5;
+const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate";
+const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter";
+const char kBweMedianSlopeFilterExperiment[] = "WebRTC-BweMedianSlopeFilter";
+
+bool BitrateEstimateExperimentIsEnabled() {
+ return webrtc::field_trial::IsEnabled(kBitrateEstimateExperiment);
+}
+
+bool TrendlineFilterExperimentIsEnabled() {
+ std::string experiment_string =
+ webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
+ // The experiment is enabled iff the field trial string begins with "Enabled".
+ return experiment_string.find("Enabled") == 0;
+}
+
+bool MedianSlopeFilterExperimentIsEnabled() {
+ std::string experiment_string =
+ webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
+ // The experiment is enabled iff the field trial string begins with "Enabled".
+ return experiment_string.find("Enabled") == 0;
+}
+
+bool ReadTrendlineFilterExperimentParameters(size_t* window_size,
+ double* smoothing_coef,
+ double* threshold_gain) {
+ RTC_DCHECK(TrendlineFilterExperimentIsEnabled());
+ RTC_DCHECK(!MedianSlopeFilterExperimentIsEnabled());
+ RTC_DCHECK(window_size != nullptr);
+ RTC_DCHECK(smoothing_coef != nullptr);
+ RTC_DCHECK(threshold_gain != nullptr);
+ std::string experiment_string =
+ webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
+ int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf,%lf",
+ window_size, smoothing_coef, threshold_gain);
+ if (parsed_values == 3) {
+ RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
+ RTC_CHECK(0 <= *smoothing_coef && *smoothing_coef <= 1)
+ << "Coefficient needs to be between 0 and 1 for weighted average.";
+ RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
+ return true;
+ }
+ LOG(LS_WARNING) << "Failed to parse parameters for BweTrendlineFilter "
+ "experiment from field trial string. Using default.";
+ *window_size = kDefaultTrendlineWindowSize;
+ *smoothing_coef = kDefaultTrendlineSmoothingCoeff;
+ *threshold_gain = kDefaultTrendlineThresholdGain;
+ return false;
+}
+
+bool ReadMedianSlopeFilterExperimentParameters(size_t* window_size,
+ double* threshold_gain) {
+ RTC_DCHECK(!TrendlineFilterExperimentIsEnabled());
+ RTC_DCHECK(MedianSlopeFilterExperimentIsEnabled());
+ RTC_DCHECK(window_size != nullptr);
+ RTC_DCHECK(threshold_gain != nullptr);
+ std::string experiment_string =
+ webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
+ int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf",
+ window_size, threshold_gain);
+ if (parsed_values == 2) {
+ RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
+ RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
+ return true;
+ }
+ LOG(LS_WARNING) << "Failed to parse parameters for BweMedianSlopeFilter "
+ "experiment from field trial string. Using default.";
+ *window_size = kDefaultMedianSlopeWindowSize;
+ *threshold_gain = kDefaultMedianSlopeThresholdGain;
+ return false;
+}
class PacketFeedbackComparator {
public:
@@ -79,9 +153,19 @@
current_win_ms_(0),
prev_time_ms_(-1),
bitrate_estimate_(-1.0f),
- bitrate_estimate_var_(50.0f) {}
+ bitrate_estimate_var_(50.0f),
+ old_estimator_(kBitrateWindowMs, 8000),
+ in_experiment_(BitrateEstimateExperimentIsEnabled()) {}
void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) {
+ if (!in_experiment_) {
+ old_estimator_.Update(bytes, now_ms);
+ rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms);
+ bitrate_estimate_ = -1.0f;
+ if (rate)
+ bitrate_estimate_ = *rate / 1000.0f;
+ return;
+ }
int rate_window_ms = kRateWindowMs;
// We use a larger window at the beginning to get a more stable sample that
// we can use to initialize the estimate.
@@ -147,9 +231,12 @@
}
DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
- : event_log_(event_log),
+ : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()),
+ in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()),
+ event_log_(event_log),
clock_(clock),
inter_arrival_(),
+ kalman_estimator_(),
trendline_estimator_(),
detector_(),
receiver_incoming_bitrate_(),
@@ -161,10 +248,29 @@
trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
probing_interval_estimator_(&rate_control_),
+ median_slope_window_size_(kDefaultMedianSlopeWindowSize),
+ median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain),
consecutive_delayed_feedbacks_(0),
last_logged_bitrate_(0),
last_logged_state_(kBwNormal) {
- LOG(LS_INFO) << "Using Trendline filter for delay change estimation.";
+ if (in_trendline_experiment_) {
+ ReadTrendlineFilterExperimentParameters(&trendline_window_size_,
+ &trendline_smoothing_coeff_,
+ &trendline_threshold_gain_);
+ LOG(LS_INFO) << "Trendline filter experiment enabled with parameters "
+ << trendline_window_size_ << ',' << trendline_smoothing_coeff_
+ << ',' << trendline_threshold_gain_;
+ }
+ if (in_median_slope_experiment_) {
+ ReadMedianSlopeFilterExperimentParameters(&median_slope_window_size_,
+ &median_slope_threshold_gain_);
+ LOG(LS_INFO) << "Median-slope filter experiment enabled with parameters "
+ << median_slope_window_size_ << ','
+ << median_slope_threshold_gain_;
+ }
+ if (!in_trendline_experiment_ && !in_median_slope_experiment_) {
+ LOG(LS_INFO) << "No overuse experiment enabled. Using Kalman filter.";
+ }
network_thread_.DetachFromThread();
}
@@ -237,9 +343,12 @@
inter_arrival_.reset(
new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
kTimestampToMs, true));
+ kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
trendline_estimator_.reset(new TrendlineEstimator(
trendline_window_size_, trendline_smoothing_coeff_,
trendline_threshold_gain_));
+ median_slope_estimator_.reset(new MedianSlopeEstimator(
+ median_slope_window_size_, median_slope_threshold_gain_));
}
last_seen_packet_ms_ = now_ms;
@@ -261,11 +370,26 @@
now_ms, packet_feedback.payload_size,
&ts_delta, &t_delta, &size_delta)) {
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
- trendline_estimator_->Update(t_delta, ts_delta_ms,
- packet_feedback.arrival_time_ms);
- detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
- trendline_estimator_->num_of_deltas(),
- packet_feedback.arrival_time_ms);
+ if (in_trendline_experiment_) {
+ trendline_estimator_->Update(t_delta, ts_delta_ms,
+ packet_feedback.arrival_time_ms);
+ detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
+ trendline_estimator_->num_of_deltas(),
+ packet_feedback.arrival_time_ms);
+ } else if (in_median_slope_experiment_) {
+ median_slope_estimator_->Update(t_delta, ts_delta_ms,
+ packet_feedback.arrival_time_ms);
+ detector_.Detect(median_slope_estimator_->trendline_slope(), ts_delta_ms,
+ median_slope_estimator_->num_of_deltas(),
+ packet_feedback.arrival_time_ms);
+ } else {
+ kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta,
+ detector_.State(),
+ packet_feedback.arrival_time_ms);
+ detector_.Detect(kalman_estimator_->offset(), ts_delta_ms,
+ kalman_estimator_->num_of_deltas(),
+ packet_feedback.arrival_time_ms);
+ }
}
int probing_bps = 0;
diff --git a/modules/congestion_controller/delay_based_bwe.h b/modules/congestion_controller/delay_based_bwe.h
index b43f920..5ae60f7 100644
--- a/modules/congestion_controller/delay_based_bwe.h
+++ b/modules/congestion_controller/delay_based_bwe.h
@@ -17,6 +17,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/rate_statistics.h"
#include "webrtc/base/thread_checker.h"
#include "webrtc/modules/congestion_controller/median_slope_estimator.h"
#include "webrtc/modules/congestion_controller/probe_bitrate_estimator.h"
@@ -76,6 +77,8 @@
int64_t prev_time_ms_;
float bitrate_estimate_;
float bitrate_estimate_var_;
+ RateStatistics old_estimator_;
+ const bool in_experiment_;
};
Result IncomingPacketFeedback(const PacketFeedback& packet_feedback);
@@ -86,12 +89,16 @@
int64_t now_ms,
rtc::Optional<uint32_t> acked_bitrate_bps,
uint32_t* target_bitrate_bps);
+ const bool in_trendline_experiment_;
+ const bool in_median_slope_experiment_;
rtc::ThreadChecker network_thread_;
RtcEventLog* const event_log_;
const Clock* const clock_;
std::unique_ptr<InterArrival> inter_arrival_;
+ std::unique_ptr<OveruseEstimator> kalman_estimator_;
std::unique_ptr<TrendlineEstimator> trendline_estimator_;
+ std::unique_ptr<MedianSlopeEstimator> median_slope_estimator_;
OveruseDetector detector_;
BitrateEstimator receiver_incoming_bitrate_;
int64_t last_update_ms_;
@@ -103,6 +110,8 @@
double trendline_smoothing_coeff_;
double trendline_threshold_gain_;
ProbingIntervalEstimator probing_interval_estimator_;
+ size_t median_slope_window_size_;
+ double median_slope_threshold_gain_;
int consecutive_delayed_feedbacks_;
uint32_t last_logged_bitrate_;
BandwidthUsage last_logged_state_;
diff --git a/modules/congestion_controller/delay_based_bwe_unittest.cc b/modules/congestion_controller/delay_based_bwe_unittest.cc
index 44407b3..559179e 100644
--- a/modules/congestion_controller/delay_based_bwe_unittest.cc
+++ b/modules/congestion_controller/delay_based_bwe_unittest.cc
@@ -119,7 +119,7 @@
TEST_F(DelayBasedBweTest, GetProbingInterval) {
int64_t default_interval_ms = bitrate_estimator_->GetProbingIntervalMs();
EXPECT_GT(default_interval_ms, 0);
- CapacityDropTestHelper(1, true, 333, 0);
+ CapacityDropTestHelper(1, true, 567, 0);
int64_t interval_ms = bitrate_estimator_->GetProbingIntervalMs();
EXPECT_GT(interval_ms, 0);
EXPECT_NE(interval_ms, default_interval_ms);
@@ -132,25 +132,27 @@
TEST_F(DelayBasedBweTest, RateIncreaseReordering) {
RateIncreaseReorderingTestHelper(674840);
}
+
TEST_F(DelayBasedBweTest, RateIncreaseRtpTimestamps) {
- RateIncreaseRtpTimestampsTestHelper(1288);
+ RateIncreaseRtpTimestampsTestHelper(1240);
}
TEST_F(DelayBasedBweTest, CapacityDropOneStream) {
- CapacityDropTestHelper(1, false, 333, 0);
+ CapacityDropTestHelper(1, false, 567, 0);
}
TEST_F(DelayBasedBweTest, CapacityDropPosOffsetChange) {
- CapacityDropTestHelper(1, false, 867, 30000);
+ CapacityDropTestHelper(1, false, 200, 30000);
}
TEST_F(DelayBasedBweTest, CapacityDropNegOffsetChange) {
- CapacityDropTestHelper(1, false, 867, -30000);
+ CapacityDropTestHelper(1, false, 733, -30000);
}
TEST_F(DelayBasedBweTest, CapacityDropOneStreamWrap) {
- CapacityDropTestHelper(1, true, 333, 0);
+ CapacityDropTestHelper(1, true, 567, 0);
}
+
TEST_F(DelayBasedBweTest, TestTimestampGrouping) {
TestTimestampGroupingTestHelper();
}
@@ -170,4 +172,97 @@
TestWrappingHelper(10 * 64);
}
+class DelayBasedBweExperimentTest : public DelayBasedBweTest {
+ public:
+ DelayBasedBweExperimentTest()
+ : override_field_trials_("WebRTC-ImprovedBitrateEstimate/Enabled/") {
+ bitrate_estimator_.reset(new DelayBasedBwe(nullptr, &clock_));
+ }
+
+ private:
+ test::ScopedFieldTrials override_field_trials_;
+};
+
+TEST_F(DelayBasedBweExperimentTest, RateIncreaseRtpTimestamps) {
+ RateIncreaseRtpTimestampsTestHelper(1288);
+}
+
+TEST_F(DelayBasedBweExperimentTest, CapacityDropOneStream) {
+ CapacityDropTestHelper(1, false, 333, 0);
+}
+
+TEST_F(DelayBasedBweExperimentTest, CapacityDropPosOffsetChange) {
+ CapacityDropTestHelper(1, false, 300, 30000);
+}
+
+TEST_F(DelayBasedBweExperimentTest, CapacityDropNegOffsetChange) {
+ CapacityDropTestHelper(1, false, 300, -30000);
+}
+
+TEST_F(DelayBasedBweExperimentTest, CapacityDropOneStreamWrap) {
+ CapacityDropTestHelper(1, true, 333, 0);
+}
+
+class DelayBasedBweTrendlineExperimentTest : public DelayBasedBweTest {
+ public:
+ DelayBasedBweTrendlineExperimentTest()
+ : override_field_trials_("WebRTC-BweTrendlineFilter/Enabled-15,0.9,4/") {
+ bitrate_estimator_.reset(new DelayBasedBwe(nullptr, &clock_));
+ }
+
+ private:
+ test::ScopedFieldTrials override_field_trials_;
+};
+
+TEST_F(DelayBasedBweTrendlineExperimentTest, RateIncreaseRtpTimestamps) {
+ RateIncreaseRtpTimestampsTestHelper(1240);
+}
+
+TEST_F(DelayBasedBweTrendlineExperimentTest, CapacityDropOneStream) {
+ CapacityDropTestHelper(1, false, 600, 0);
+}
+
+TEST_F(DelayBasedBweTrendlineExperimentTest, CapacityDropPosOffsetChange) {
+ CapacityDropTestHelper(1, false, 600, 30000);
+}
+
+TEST_F(DelayBasedBweTrendlineExperimentTest, CapacityDropNegOffsetChange) {
+ CapacityDropTestHelper(1, false, 1267, -30000);
+}
+
+TEST_F(DelayBasedBweTrendlineExperimentTest, CapacityDropOneStreamWrap) {
+ CapacityDropTestHelper(1, true, 600, 0);
+}
+
+class DelayBasedBweMedianSlopeExperimentTest : public DelayBasedBweTest {
+ public:
+ DelayBasedBweMedianSlopeExperimentTest()
+ : override_field_trials_("WebRTC-BweMedianSlopeFilter/Enabled-20,4/") {
+ bitrate_estimator_.reset(new DelayBasedBwe(nullptr, &clock_));
+ }
+
+ private:
+ test::ScopedFieldTrials override_field_trials_;
+};
+
+TEST_F(DelayBasedBweMedianSlopeExperimentTest, RateIncreaseRtpTimestamps) {
+ RateIncreaseRtpTimestampsTestHelper(1240);
+}
+
+TEST_F(DelayBasedBweMedianSlopeExperimentTest, CapacityDropOneStream) {
+ CapacityDropTestHelper(1, false, 600, 0);
+}
+
+TEST_F(DelayBasedBweMedianSlopeExperimentTest, CapacityDropPosOffsetChange) {
+ CapacityDropTestHelper(1, false, 600, 30000);
+}
+
+TEST_F(DelayBasedBweMedianSlopeExperimentTest, CapacityDropNegOffsetChange) {
+ CapacityDropTestHelper(1, false, 1267, -30000);
+}
+
+TEST_F(DelayBasedBweMedianSlopeExperimentTest, CapacityDropOneStreamWrap) {
+ CapacityDropTestHelper(1, true, 600, 0);
+}
+
} // namespace webrtc
diff --git a/modules/congestion_controller/delay_based_bwe_unittest_helper.cc b/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
index e7a98c3..c87439e 100644
--- a/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
+++ b/modules/congestion_controller/delay_based_bwe_unittest_helper.cc
@@ -411,7 +411,7 @@
uint32_t bitrate_bps = SteadyStateRun(
kDefaultSsrc, steady_state_time * kFramerate, kStartBitrate,
kMinExpectedBitrate, kMaxExpectedBitrate, kInitialCapacityBps);
- EXPECT_NEAR(kInitialCapacityBps, bitrate_bps, 180000u);
+ EXPECT_NEAR(kInitialCapacityBps, bitrate_bps, 130000u);
bitrate_observer_.Reset();
// Add an offset to make sure the BWE can handle it.
@@ -492,7 +492,7 @@
clock_.AdvanceTimeMilliseconds(silence_time_s * 1000);
send_time_ms += silence_time_s * 1000;
- for (size_t i = 0; i < 23; ++i) {
+ for (size_t i = 0; i < 22; ++i) {
IncomingFeedback(clock_.TimeInMilliseconds(), send_time_ms,
sequence_number++, 1000);
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
diff --git a/sdk/objc/Framework/Classes/RTCFieldTrials.mm b/sdk/objc/Framework/Classes/RTCFieldTrials.mm
index 25d651f..5e1ee0a 100644
--- a/sdk/objc/Framework/Classes/RTCFieldTrials.mm
+++ b/sdk/objc/Framework/Classes/RTCFieldTrials.mm
@@ -20,6 +20,9 @@
NSString * const kRTCFieldTrialSendSideBweWithOverheadKey = @"WebRTC-SendSideBwe-WithOverhead";
NSString * const kRTCFieldTrialFlexFec03AdvertisedKey = @"WebRTC-FlexFEC-03-Advertised";
NSString * const kRTCFieldTrialFlexFec03Key = @"WebRTC-FlexFEC-03";
+NSString * const kRTCFieldTrialImprovedBitrateEstimateKey = @"WebRTC-ImprovedBitrateEstimate";
+NSString * const kRTCFieldTrialMedianSlopeFilterKey = @"WebRTC-BweMedianSlopeFilter";
+NSString * const kRTCFieldTrialTrendlineFilterKey = @"WebRTC-BweTrendlineFilter";
NSString * const kRTCFieldTrialH264HighProfileKey = @"WebRTC-H264HighProfile";
NSString * const kRTCFieldTrialEnabledValue = @"Enabled";
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCFieldTrials.h b/sdk/objc/Framework/Headers/WebRTC/RTCFieldTrials.h
index 85430b7..a9d6806 100644
--- a/sdk/objc/Framework/Headers/WebRTC/RTCFieldTrials.h
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCFieldTrials.h
@@ -17,11 +17,23 @@
RTC_EXTERN NSString * const kRTCFieldTrialSendSideBweWithOverheadKey;
RTC_EXTERN NSString * const kRTCFieldTrialFlexFec03AdvertisedKey;
RTC_EXTERN NSString * const kRTCFieldTrialFlexFec03Key;
+RTC_EXTERN NSString * const kRTCFieldTrialImprovedBitrateEstimateKey;
RTC_EXTERN NSString * const kRTCFieldTrialH264HighProfileKey;
/** The valid value for field trials above. */
RTC_EXTERN NSString * const kRTCFieldTrialEnabledValue;
+/** Use a string returned by RTCFieldTrialMedianSlopeFilterValue as the value. */
+RTC_EXTERN NSString * const kRTCFieldTrialMedianSlopeFilterKey;
+RTC_EXTERN NSString *RTCFieldTrialMedianSlopeFilterValue(
+ size_t windowSize, double thresholdGain);
+
+/** Use a string returned by RTCFieldTrialTrendlineFilterValue as the value. */
+RTC_EXTERN NSString * const kRTCFieldTrialTrendlineFilterKey;
+/** Returns a valid value for kRTCFieldTrialTrendlineFilterKey. */
+RTC_EXTERN NSString *RTCFieldTrialTrendlineFilterValue(
+ size_t windowSize, double smoothingCoeff, double thresholdGain);
+
/** Initialize field trials using a dictionary mapping field trial keys to their values. See above
* for valid keys and values.
* Must be called before any other call into WebRTC. See: