diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc index 6147cacb4a..1c7ad19025 100644 --- a/modules/audio_coding/neteq/delay_manager.cc +++ b/modules/audio_coding/neteq/delay_manager.cc @@ -19,6 +19,7 @@ #include "absl/memory/memory.h" #include "modules/audio_coding/neteq/delay_peak_detector.h" +#include "modules/audio_coding/neteq/histogram.h" #include "modules/include/module_common_types_public.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" @@ -39,6 +40,15 @@ constexpr int kIatFactor = 32745; // 0.9993 in Q15. constexpr int kMaxIat = 64; // Max inter-arrival time to register. constexpr int kMaxReorderedPackets = 10; // Max number of consecutive reordered packets. +constexpr int kMaxHistoryPackets = + 100; // Max number of packets used to calculate relative packet arrival + // delay. +constexpr int kDelayBuckets = 100; +constexpr int kBucketSizeMs = 20; + +int PercentileToQuantile(double percentile) { + return static_cast((1 << 30) * percentile / 100.0 + 0.5); +} absl::optional GetForcedLimitProbability() { constexpr char kForceTargetDelayPercentileFieldTrial[] = @@ -52,7 +62,7 @@ absl::optional GetForcedLimitProbability() { 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) * percentile / 100.0 + 0.5)); // in Q30. + PercentileToQuantile(percentile)); // in Q30. } else { RTC_LOG(LS_WARNING) << "Invalid parameter for " << kForceTargetDelayPercentileFieldTrial @@ -62,19 +72,54 @@ absl::optional GetForcedLimitProbability() { return absl::nullopt; } +struct DelayHistogramConfig { + int quantile = 1020054733; // 0.95 in Q30. + int forget_factor = 32745; // 0.9993 in Q15. +}; + +absl::optional GetDelayHistogramConfig() { + constexpr char kDelayHistogramFieldTrial[] = + "WebRTC-Audio-NetEqDelayHistogram"; + const bool use_new_delay_manager = + webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial); + if (use_new_delay_manager) { + const auto field_trial_string = + webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial); + DelayHistogramConfig config; + double percentile = -1.0; + double forget_factor = -1.0; + if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf", &percentile, + &forget_factor) == 2 && + percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 && + forget_factor <= 1.0) { + config.quantile = PercentileToQuantile(percentile); + config.forget_factor = (1 << 15) * forget_factor; + } + RTC_LOG(LS_INFO) << "Delay histogram config:" + << " quantile=" << config.quantile + << " forget_factor=" << config.forget_factor; + return absl::make_optional(config); + } + return absl::nullopt; +} + } // namespace namespace webrtc { DelayManager::DelayManager(size_t max_packets_in_buffer, int base_minimum_delay_ms, + int histogram_quantile, + HistogramMode histogram_mode, bool enable_rtx_handling, DelayPeakDetector* peak_detector, const TickTimer* tick_timer, - std::unique_ptr iat_histogram) + std::unique_ptr histogram) : first_packet_received_(false), max_packets_in_buffer_(max_packets_in_buffer), - iat_histogram_(std::move(iat_histogram)), + histogram_(std::move(histogram)), + histogram_quantile_(histogram_quantile), + histogram_mode_(histogram_mode), tick_timer_(tick_timer), base_minimum_delay_ms_(base_minimum_delay_ms), effective_minimum_delay_ms_(base_minimum_delay_ms), @@ -92,10 +137,9 @@ DelayManager::DelayManager(size_t max_packets_in_buffer, last_pack_cng_or_dtmf_(1), frame_length_change_experiment_( field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")), - forced_limit_probability_(GetForcedLimitProbability()), enable_rtx_handling_(enable_rtx_handling) { assert(peak_detector); // Should never be NULL. - RTC_CHECK(iat_histogram_); + RTC_CHECK(histogram_); RTC_DCHECK_GE(base_minimum_delay_ms_, 0); Reset(); @@ -107,10 +151,24 @@ std::unique_ptr DelayManager::Create( bool enable_rtx_handling, DelayPeakDetector* peak_detector, const TickTimer* tick_timer) { + int quantile; + std::unique_ptr histogram; + HistogramMode mode; + auto delay_histogram_config = GetDelayHistogramConfig(); + if (delay_histogram_config) { + DelayHistogramConfig config = delay_histogram_config.value(); + quantile = config.quantile; + histogram = + absl::make_unique(kDelayBuckets, config.forget_factor); + mode = RELATIVE_ARRIVAL_DELAY; + } else { + quantile = GetForcedLimitProbability().value_or(kLimitProbability); + histogram = absl::make_unique(kMaxIat + 1, kIatFactor); + mode = INTER_ARRIVAL_TIME; + } return absl::make_unique( - max_packets_in_buffer, base_minimum_delay_ms, enable_rtx_handling, - peak_detector, tick_timer, - absl::make_unique(kMaxIat + 1, kIatFactor)); + max_packets_in_buffer, base_minimum_delay_ms, quantile, mode, + enable_rtx_handling, peak_detector, tick_timer, std::move(histogram)); } DelayManager::~DelayManager() {} @@ -149,30 +207,57 @@ int DelayManager::Update(uint16_t sequence_number, bool reordered = false; if (packet_len_ms > 0) { // Cannot update statistics unless |packet_len_ms| is valid. - // Calculate inter-arrival time (IAT) in integer "packet times" - // (rounding down). This is the value added to the inter-arrival time - // histogram. - int iat_packets = packet_iat_stopwatch_->ElapsedMs() / packet_len_ms; - if (streaming_mode_) { UpdateCumulativeSums(packet_len_ms, sequence_number); } + // Inter-arrival time (IAT) in integer "packet times" (rounding down). This + // is the value added to the inter-arrival time histogram. + int iat_ms = packet_iat_stopwatch_->ElapsedMs(); + int iat_packets = iat_ms / packet_len_ms; // Check for discontinuous packet sequence and re-ordering. if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) { // Compensate for gap in the sequence numbers. Reduce IAT with the // expected extra time due to lost packets, but ensure that the IAT is // not negative. - iat_packets -= static_cast(sequence_number - last_seq_no_ - 1); + int packet_offset = + static_cast(sequence_number - last_seq_no_ - 1); + iat_packets -= packet_offset; iat_packets = std::max(iat_packets, 0); + iat_ms -= packet_offset * packet_len_ms; + iat_ms = std::max(iat_ms, 0); } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) { - iat_packets += static_cast(last_seq_no_ + 1 - sequence_number); + int packet_offset = + static_cast(last_seq_no_ + 1 - sequence_number); + iat_packets += packet_offset; + iat_ms += packet_offset * packet_len_ms; reordered = true; } - // Saturate IAT at maximum value. - iat_packets = std::min(iat_packets, iat_histogram_->NumBuckets() - 1); - iat_histogram_->Add(iat_packets); + switch (histogram_mode_) { + case RELATIVE_ARRIVAL_DELAY: { + int iat_delay = iat_ms - packet_len_ms; + int relative_delay; + if (reordered) { + relative_delay = std::max(iat_delay, 0); + } else { + UpdateDelayHistory(iat_delay); + relative_delay = CalculateRelativePacketArrivalDelay(); + } + const int index = relative_delay / kBucketSizeMs; + if (index < histogram_->NumBuckets()) { + // Maximum delay to register is 2000 ms. + histogram_->Add(index); + } + break; + } + case INTER_ARRIVAL_TIME: { + // Saturate IAT at maximum value. + iat_packets = std::min(iat_packets, histogram_->NumBuckets() - 1); + histogram_->Add(iat_packets); + break; + } + } // Calculate new |target_level_| based on updated statistics. target_level_ = CalculateTargetLevel(iat_packets, reordered); if (streaming_mode_) { @@ -195,6 +280,26 @@ int DelayManager::Update(uint16_t sequence_number, return 0; } +void DelayManager::UpdateDelayHistory(int iat_delay) { + delay_history_.push_back(iat_delay); + if (delay_history_.size() > kMaxHistoryPackets) { + delay_history_.pop_front(); + } +} + +int DelayManager::CalculateRelativePacketArrivalDelay() const { + // This effectively calculates arrival delay of a packet relative to the + // packet preceding the history window. If the arrival delay ever becomes + // smaller than zero, it means the reference packet is invalid, and we + // move the reference. + int relative_delay = 0; + for (int delay : delay_history_) { + relative_delay += delay; + relative_delay = std::max(relative_delay, 0); + } + return relative_delay; +} + void DelayManager::UpdateCumulativeSums(int packet_len_ms, uint16_t sequence_number) { // Calculate IAT in Q8, including fractions of a packet (i.e., more @@ -252,21 +357,30 @@ void DelayManager::LimitTargetLevel() { } int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) { - int limit_probability = forced_limit_probability_.value_or(kLimitProbability); + int limit_probability = histogram_quantile_; if (streaming_mode_) { limit_probability = kLimitProbabilityStreaming; } - // Calculate target buffer level from inter-arrival time histogram. - // This is the base value for the target buffer level. - int target_level = iat_histogram_->Quantile(limit_probability); - base_target_level_ = target_level; - - // Update detector for delay peaks. - bool delay_peak_found = - peak_detector_.Update(iat_packets, reordered, target_level); - if (delay_peak_found) { - target_level = std::max(target_level, peak_detector_.MaxPeakHeight()); + int bucket_index = histogram_->Quantile(limit_probability); + int target_level; + switch (histogram_mode_) { + case RELATIVE_ARRIVAL_DELAY: { + target_level = 1 + bucket_index * kBucketSizeMs / packet_len_ms_; + base_target_level_ = target_level; + break; + } + case INTER_ARRIVAL_TIME: { + target_level = bucket_index; + base_target_level_ = target_level; + // Update detector for delay peaks. + bool delay_peak_found = + peak_detector_.Update(iat_packets, reordered, target_level); + if (delay_peak_found) { + target_level = std::max(target_level, peak_detector_.MaxPeakHeight()); + } + break; + } } // Sanity check. |target_level| must be strictly positive. @@ -281,9 +395,10 @@ int DelayManager::SetPacketAudioLength(int length_ms) { RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms; return -1; } - if (frame_length_change_experiment_ && packet_len_ms_ != length_ms && + if (histogram_mode_ == INTER_ARRIVAL_TIME && + frame_length_change_experiment_ && packet_len_ms_ != length_ms && packet_len_ms_ > 0) { - iat_histogram_->Scale(packet_len_ms_, length_ms); + histogram_->Scale(packet_len_ms_, length_ms); } packet_len_ms_ = length_ms; @@ -297,7 +412,7 @@ void DelayManager::Reset() { packet_len_ms_ = 0; // Packet size unknown. streaming_mode_ = false; peak_detector_.Reset(); - iat_histogram_->Reset(); + histogram_->Reset(); base_target_level_ = 4; target_level_ = base_target_level_ << 8; packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); @@ -310,12 +425,12 @@ void DelayManager::Reset() { double DelayManager::EstimatedClockDriftPpm() const { double sum = 0.0; // Calculate the expected value based on the probabilities in - // |iat_histogram_|. - auto buckets = iat_histogram_->buckets(); + // |histogram_|. + auto buckets = histogram_->buckets(); for (size_t i = 0; i < buckets.size(); ++i) { sum += static_cast(buckets[i]) * i; } - // The probabilities in |iat_histogram_| are in Q30. Divide by 1 << 30 to + // The probabilities in |histogram_| are in Q30. Divide by 1 << 30 to // convert to Q0; subtract the nominal inter-arrival time (1) to make a zero // clockdrift represent as 0; mulitply by 1000000 to produce parts-per-million // (ppm). diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h index 4f2cb859a7..11dfeb9355 100644 --- a/modules/audio_coding/neteq/delay_manager.h +++ b/modules/audio_coding/neteq/delay_manager.h @@ -13,8 +13,8 @@ #include // Provide access to size_t. +#include #include -#include #include "absl/types/optional.h" #include "modules/audio_coding/neteq/histogram.h" @@ -28,12 +28,19 @@ class DelayPeakDetector; class DelayManager { public: + enum HistogramMode { + INTER_ARRIVAL_TIME, + RELATIVE_ARRIVAL_DELAY, + }; + DelayManager(size_t max_packets_in_buffer, int base_minimum_delay_ms, + int histogram_quantile, + HistogramMode histogram_mode, bool enable_rtx_handling, DelayPeakDetector* peak_detector, const TickTimer* tick_timer, - std::unique_ptr iat_histogram); + std::unique_ptr histogram); // Create a DelayManager object. Notify the delay manager that the packet // buffer can hold no more than |max_packets_in_buffer| packets (i.e., this @@ -116,16 +123,16 @@ class DelayManager { virtual int last_pack_cng_or_dtmf() const; virtual void set_last_pack_cng_or_dtmf(int value); - // This accessor is only intended for testing purposes. - const absl::optional& forced_limit_probability_for_test() const { - return forced_limit_probability_; - } - // This accessor is only intended for testing purposes. int effective_minimum_delay_ms_for_test() const { return effective_minimum_delay_ms_; } + // This accessor is only intended for testing purposes. + HistogramMode histogram_mode() const { return histogram_mode_; } + int histogram_quantile() const { return histogram_quantile_; } + int histogram_forget_factor() const { return histogram_->forget_factor(); } + private: // Provides value which minimum delay can't exceed based on current buffer // size and given |maximum_delay_ms_|. Lower bound is a constant 0. @@ -134,6 +141,12 @@ class DelayManager { // Provides 75% of currently possible maximum buffer size in milliseconds. int MaxBufferTimeQ75() const; + // Updates |delay_history_|. + void UpdateDelayHistory(int iat_delay); + + // Calculate relative packet arrival delay from |delay_history_|. + int CalculateRelativePacketArrivalDelay() const; + // Updates |iat_cumulative_sum_| and |max_iat_cumulative_sum_|. (These are // used by the streaming mode.) This method is called by Update(). void UpdateCumulativeSums(int packet_len_ms, uint16_t sequence_number); @@ -157,7 +170,9 @@ class DelayManager { bool first_packet_received_; const size_t max_packets_in_buffer_; // Capacity of the packet buffer. - std::unique_ptr iat_histogram_; + std::unique_ptr histogram_; + const int histogram_quantile_; + const HistogramMode histogram_mode_; const TickTimer* tick_timer_; int base_minimum_delay_ms_; // Provides delay which is used by LimitTargetLevel as lower bound on target @@ -185,9 +200,9 @@ class DelayManager { DelayPeakDetector& peak_detector_; int last_pack_cng_or_dtmf_; const bool frame_length_change_experiment_; - const absl::optional forced_limit_probability_; const bool enable_rtx_handling_; int num_reordered_packets_ = 0; // Number of consecutive reordered packets. + std::deque delay_history_; 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 b3797e2e80..7b573240d3 100644 --- a/modules/audio_coding/neteq/delay_manager_unittest.cc +++ b/modules/audio_coding/neteq/delay_manager_unittest.cc @@ -25,19 +25,24 @@ namespace webrtc { +namespace { +constexpr int kMaxNumberOfPackets = 240; +constexpr int kMinDelayMs = 0; +constexpr int kTimeStepMs = 10; +constexpr int kFs = 8000; +constexpr int kFrameSizeMs = 20; +constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000; +constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs; +constexpr int kDefaultHistogramQuantile = 1020054733; +constexpr int kMaxIat = 64; +constexpr int kForgetFactor = 32745; +} // namespace + using ::testing::Return; using ::testing::_; class DelayManagerTest : public ::testing::Test { protected: - static const int kMaxNumberOfPackets = 240; - static const int kMinDelayMs = 0; - static const int kTimeStepMs = 10; - static const int kFs = 8000; - static const int kFrameSizeMs = 20; - static const int kTsIncrement = kFrameSizeMs * kFs / 1000; - static const int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs; - DelayManagerTest(); virtual void SetUp(); virtual void TearDown(); @@ -49,11 +54,13 @@ class DelayManagerTest : public ::testing::Test { std::unique_ptr dm_; TickTimer tick_timer_; MockDelayPeakDetector detector_; - bool use_mock_histogram_ = false; MockHistogram* mock_histogram_; uint16_t seq_no_; uint32_t ts_; bool enable_rtx_handling_ = false; + bool use_mock_histogram_ = false; + DelayManager::HistogramMode histogram_mode_ = + DelayManager::HistogramMode::INTER_ARRIVAL_TIME; }; DelayManagerTest::DelayManagerTest() @@ -68,18 +75,17 @@ void DelayManagerTest::SetUp() { void DelayManagerTest::RecreateDelayManager() { EXPECT_CALL(detector_, Reset()).Times(1); - std::unique_ptr histogram; - static const int kMaxIat = 64; - static const int kForgetFactor = 32745; if (use_mock_histogram_) { mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor); - histogram.reset(mock_histogram_); + std::unique_ptr histogram(mock_histogram_); + dm_ = absl::make_unique( + kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile, + histogram_mode_, enable_rtx_handling_, &detector_, &tick_timer_, + std::move(histogram)); } else { - histogram = absl::make_unique(kMaxIat, kForgetFactor); + dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs, + enable_rtx_handling_, &detector_, &tick_timer_); } - dm_.reset(new DelayManager(kMaxNumberOfPackets, kMinDelayMs, - enable_rtx_handling_, &detector_, &tick_timer_, - std::move(histogram))); } void DelayManagerTest::SetPacketAudioLength(int lengt_ms) { @@ -577,8 +583,7 @@ TEST_F(DelayManagerTest, TargetDelayGreaterThanOne) { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-0/"); RecreateDelayManager(); - EXPECT_EQ(absl::make_optional(0), - dm_->forced_limit_probability_for_test()); + EXPECT_EQ(0, dm_->histogram_quantile()); SetPacketAudioLength(kFrameSizeMs); // First packet arrival. @@ -599,33 +604,109 @@ TEST_F(DelayManagerTest, ForcedTargetDelayPercentile) { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-95/"); RecreateDelayManager(); - EXPECT_EQ(absl::make_optional(1020054733), - dm_->forced_limit_probability_for_test()); // 1/20 in Q30 + EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile()); } { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/"); RecreateDelayManager(); - EXPECT_EQ(absl::make_optional(1073204953), - dm_->forced_limit_probability_for_test()); // 1/2000 in Q30 + EXPECT_EQ(1073204953, dm_->histogram_quantile()); // 0.9995 in Q30. } { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Disabled/"); RecreateDelayManager(); - EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile()); } { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled--1/"); - EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile()); } { test::ScopedFieldTrials field_trial( "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-100.1/"); RecreateDelayManager(); - EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test()); + EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile()); } } +TEST_F(DelayManagerTest, DelayHistogramFieldTrial) { + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/"); + RecreateDelayManager(); + EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY, + dm_->histogram_mode()); + EXPECT_EQ(1030792151, dm_->histogram_quantile()); // 0.96 in Q30. + EXPECT_EQ(32702, dm_->histogram_forget_factor()); // 0.998 in Q15. + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqDelayHistogram/Enabled-97.5-0.998/"); + RecreateDelayManager(); + EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY, + dm_->histogram_mode()); + EXPECT_EQ(1046898278, dm_->histogram_quantile()); // 0.975 in Q30. + EXPECT_EQ(32702, dm_->histogram_forget_factor()); // 0.998 in Q15. + } + { + // NetEqDelayHistogram should take precedence over + // NetEqForceTargetDelayPercentile. + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/" + "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/"); + RecreateDelayManager(); + EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY, + dm_->histogram_mode()); + EXPECT_EQ(1030792151, dm_->histogram_quantile()); // 0.96 in Q30. + EXPECT_EQ(32702, dm_->histogram_forget_factor()); // 0.998 in Q15. + } + { + // Invalid parameters. + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqDelayHistogram/Enabled-96/"); + RecreateDelayManager(); + EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY, + dm_->histogram_mode()); + EXPECT_EQ(kDefaultHistogramQuantile, + dm_->histogram_quantile()); // 0.95 in Q30. + EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor()); // 0.9993 in Q15. + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqDelayHistogram/Disabled/"); + RecreateDelayManager(); + EXPECT_EQ(DelayManager::HistogramMode::INTER_ARRIVAL_TIME, + dm_->histogram_mode()); + EXPECT_EQ(kDefaultHistogramQuantile, + dm_->histogram_quantile()); // 0.95 in Q30. + EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor()); // 0.9993 in Q15. + } +} + +TEST_F(DelayManagerTest, RelativeArrivalDelayMode) { + histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY; + use_mock_histogram_ = true; + RecreateDelayManager(); + + SetPacketAudioLength(kFrameSizeMs); + InsertNextPacket(); + + IncreaseTime(kFrameSizeMs); + EXPECT_CALL(*mock_histogram_, Add(0)); // Not delayed. + InsertNextPacket(); + + IncreaseTime(2 * kFrameSizeMs); + EXPECT_CALL(*mock_histogram_, Add(1)); // 20ms delayed. + EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs)); + + IncreaseTime(2 * kFrameSizeMs); + EXPECT_CALL(*mock_histogram_, Add(2)); // 40ms delayed. + EXPECT_EQ(0, dm_->Update(seq_no_ + 1, ts_ + kTsIncrement, kFs)); + + EXPECT_CALL(*mock_histogram_, Add(1)); // Reordered, 20ms delayed. + EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs)); +} + } // namespace webrtc diff --git a/modules/audio_coding/neteq/histogram.h b/modules/audio_coding/neteq/histogram.h index 66b4fe9d0c..fc8f612ac8 100644 --- a/modules/audio_coding/neteq/histogram.h +++ b/modules/audio_coding/neteq/histogram.h @@ -43,6 +43,8 @@ class Histogram { // Returns the probability for each bucket in Q30. std::vector buckets() const { return buckets_; } + int forget_factor() const { return base_forget_factor_; } + // Made public for testing. static std::vector ScaleBuckets(const std::vector& buckets, int old_bucket_width, diff --git a/modules/audio_coding/neteq/mock/mock_delay_manager.h b/modules/audio_coding/neteq/mock/mock_delay_manager.h index fa07e20bb4..63dd5751d1 100644 --- a/modules/audio_coding/neteq/mock/mock_delay_manager.h +++ b/modules/audio_coding/neteq/mock/mock_delay_manager.h @@ -23,12 +23,16 @@ class MockDelayManager : public DelayManager { public: MockDelayManager(size_t max_packets_in_buffer, int base_min_target_delay_ms, + int histogram_quantile, + HistogramMode histogram_mode, bool enable_rtx_handling, DelayPeakDetector* peak_detector, const TickTimer* tick_timer, std::unique_ptr histogram) : DelayManager(max_packets_in_buffer, base_min_target_delay_ms, + histogram_quantile, + histogram_mode, enable_rtx_handling, peak_detector, tick_timer, diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc index e7552c1066..86fbe9c75c 100644 --- a/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -97,7 +97,8 @@ class NetEqImplTest : public ::testing::Test { if (use_mock_delay_manager_) { std::unique_ptr mock(new MockDelayManager( - config_.max_packets_in_buffer, config_.min_delay_ms, + config_.max_packets_in_buffer, config_.min_delay_ms, 1020054733, + DelayManager::HistogramMode::INTER_ARRIVAL_TIME, config_.enable_rtx_handling, delay_peak_detector_, tick_timer_, absl::make_unique(50, 32745))); mock_delay_manager_ = mock.get();