From 002fbb8c7dee94484c4b2164e861cfb481211ecf Mon Sep 17 00:00:00 2001 From: Minyue Li Date: Thu, 4 Oct 2018 11:31:03 +0200 Subject: [PATCH] Adding field trial to force target level percentile in NetEQ. Bug: webrtc:9822 Change-Id: I636f75de10851729825311ee5783e836f3b583cd Reviewed-on: https://webrtc-review.googlesource.com/c/101220 Commit-Queue: Minyue Li Reviewed-by: Henrik Lundin Cr-Commit-Position: refs/heads/master@{#24975} --- modules/audio_coding/neteq/delay_manager.cc | 41 ++++++++++- modules/audio_coding/neteq/delay_manager.h | 16 ++--- .../neteq/delay_manager_unittest.cc | 69 +++++++++++++++++-- 3 files changed, 111 insertions(+), 15 deletions(-) diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc index 84d457c6a0..e5eb592efa 100644 --- a/modules/audio_coding/neteq/delay_manager.cc +++ b/modules/audio_coding/neteq/delay_manager.cc @@ -23,6 +23,41 @@ #include "rtc_base/numerics/safe_conversions.h" #include "system_wrappers/include/field_trial.h" +namespace { + +constexpr int kLimitProbability = 53687091; // 1/20 in Q30. +constexpr int kLimitProbabilityStreaming = 536871; // 1/2000 in Q30. +constexpr int kMaxStreamingPeakPeriodMs = 600000; // 10 minutes in ms. +constexpr int kCumulativeSumDrift = 2; // Drift term for cumulative sum + // |iat_cumulative_sum_|. +// Steady-state forgetting factor for |iat_vector_|, 0.9993 in Q15. +constexpr int kIatFactor_ = 32745; +constexpr int kMaxIat = 64; // Max inter-arrival time to register. + +absl::optional GetForcedLimitProbability() { + constexpr char kForceTargetDelayPercentileFieldTrial[] = + "WebRTC-Audio-NetEqForceTargetDelayPercentile"; + const bool use_forced_target_delay_percentile = + webrtc::field_trial::IsEnabled(kForceTargetDelayPercentileFieldTrial); + if (use_forced_target_delay_percentile) { + const std::string field_trial_string = webrtc::field_trial::FindFullName( + kForceTargetDelayPercentileFieldTrial); + double percentile = -1.0; + if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 && + percentile >= 0.0 && percentile <= 100.0) { + return absl::make_optional(static_cast( + (1 << 30) * (100.0 - percentile) / 100.0 + 0.5)); // in Q30. + } else { + RTC_LOG(LS_WARNING) << "Invalid parameter for " + << kForceTargetDelayPercentileFieldTrial + << ", ignored."; + } + } + return absl::nullopt; +} + +} // namespace + namespace webrtc { DelayManager::DelayManager(size_t max_packets_in_buffer, @@ -46,8 +81,10 @@ DelayManager::DelayManager(size_t max_packets_in_buffer, peak_detector_(*peak_detector), last_pack_cng_or_dtmf_(1), frame_length_change_experiment_( - field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) { + field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")), + forced_limit_probability_(GetForcedLimitProbability()) { assert(peak_detector); // Should never be NULL. + Reset(); } @@ -253,7 +290,7 @@ void DelayManager::LimitTargetLevel() { } int DelayManager::CalculateTargetLevel(int iat_packets) { - int limit_probability = kLimitProbability; + int limit_probability = forced_limit_probability_.value_or(kLimitProbability); if (streaming_mode_) { limit_probability = kLimitProbabilityStreaming; } diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h index 00e39af6a5..cd5fc09031 100644 --- a/modules/audio_coding/neteq/delay_manager.h +++ b/modules/audio_coding/neteq/delay_manager.h @@ -16,6 +16,7 @@ #include #include +#include "absl/types/optional.h" #include "modules/audio_coding/neteq/tick_timer.h" #include "rtc_base/constructormagic.h" @@ -114,16 +115,12 @@ class DelayManager { virtual int last_pack_cng_or_dtmf() const; virtual void set_last_pack_cng_or_dtmf(int value); - private: - static const int kLimitProbability = 53687091; // 1/20 in Q30. - static const int kLimitProbabilityStreaming = 536871; // 1/2000 in Q30. - static const int kMaxStreamingPeakPeriodMs = 600000; // 10 minutes in ms. - static const int kCumulativeSumDrift = 2; // Drift term for cumulative sum - // |iat_cumulative_sum_|. - // Steady-state forgetting factor for |iat_vector_|, 0.9993 in Q15. - static const int kIatFactor_ = 32745; - static const int kMaxIat = 64; // Max inter-arrival time to register. + // This accessor is only intended for testing purposes. + const absl::optional& forced_limit_probability_for_test() const { + return forced_limit_probability_; + } + private: // Sets |iat_vector_| to the default start distribution and sets the // |base_target_level_| and |target_level_| to the corresponding values. void ResetHistogram(); @@ -168,6 +165,7 @@ class DelayManager { DelayPeakDetector& peak_detector_; int last_pack_cng_or_dtmf_; const bool frame_length_change_experiment_; + const absl::optional forced_limit_probability_; RTC_DISALLOW_COPY_AND_ASSIGN(DelayManager); }; diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc index 6afed661f9..e4e865fe46 100644 --- a/modules/audio_coding/neteq/delay_manager_unittest.cc +++ b/modules/audio_coding/neteq/delay_manager_unittest.cc @@ -15,6 +15,7 @@ #include #include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h" +#include "test/field_trial.h" #include "test/gmock.h" #include "test/gtest.h" @@ -34,11 +35,12 @@ class DelayManagerTest : public ::testing::Test { DelayManagerTest(); virtual void SetUp(); virtual void TearDown(); + void RecreateDelayManager(); void SetPacketAudioLength(int lengt_ms); void InsertNextPacket(); void IncreaseTime(int inc_ms); - DelayManager* dm_; + std::unique_ptr dm_; TickTimer tick_timer_; MockDelayPeakDetector detector_; uint16_t seq_no_; @@ -46,11 +48,15 @@ class DelayManagerTest : public ::testing::Test { }; DelayManagerTest::DelayManagerTest() - : dm_(NULL), detector_(&tick_timer_), seq_no_(0x1234), ts_(0x12345678) {} + : dm_(nullptr), detector_(&tick_timer_), seq_no_(0x1234), ts_(0x12345678) {} void DelayManagerTest::SetUp() { + RecreateDelayManager(); +} + +void DelayManagerTest::RecreateDelayManager() { EXPECT_CALL(detector_, Reset()).Times(1); - dm_ = new DelayManager(kMaxNumberOfPackets, &detector_, &tick_timer_); + dm_.reset(new DelayManager(kMaxNumberOfPackets, &detector_, &tick_timer_)); } void DelayManagerTest::SetPacketAudioLength(int lengt_ms) { @@ -71,7 +77,6 @@ void DelayManagerTest::IncreaseTime(int inc_ms) { } void DelayManagerTest::TearDown() { EXPECT_CALL(detector_, Die()); - delete dm_; } TEST_F(DelayManagerTest, CreateAndDestroy) { @@ -326,6 +331,61 @@ TEST_F(DelayManagerTest, Failures) { EXPECT_FALSE(dm_->SetMaximumDelay(60)); } +TEST_F(DelayManagerTest, TargetDelayGreaterThanOne) { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-0/"); + RecreateDelayManager(); + EXPECT_EQ(absl::make_optional(1 << 30), + dm_->forced_limit_probability_for_test()); + + SetPacketAudioLength(kFrameSizeMs); + // First packet arrival. + InsertNextPacket(); + // Advance time by one frame size. + IncreaseTime(kFrameSizeMs); + // Second packet arrival. + // Expect detector update method to be called once with inter-arrival time + // equal to 1 packet. + EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false)); + InsertNextPacket(); + constexpr int kExpectedTarget = 1; + EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel()); // In Q8. +} + +TEST_F(DelayManagerTest, ForcedTargetDelayPercentile) { + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-95/"); + RecreateDelayManager(); + EXPECT_EQ(absl::make_optional(53687091), + dm_->forced_limit_probability_for_test()); // 1/20 in Q30 + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/"); + RecreateDelayManager(); + EXPECT_EQ(absl::make_optional(536871), + dm_->forced_limit_probability_for_test()); // 1/2000 in Q30 + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Disabled/"); + RecreateDelayManager(); + EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled--1/"); + EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-100.1/"); + RecreateDelayManager(); + EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + } +} + // Test if the histogram is stretched correctly if the packet size is decreased. TEST(DelayManagerIATScalingTest, StretchTest) { using IATVector = DelayManager::IATVector; @@ -437,4 +497,5 @@ TEST(DelayManagerIATScalingTest, OverflowTest) { scaled_iat = DelayManager::ScaleHistogram(iat, 20, 60); EXPECT_EQ(scaled_iat, expected_result); } + } // namespace webrtc