diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 14a1bdc0e5..ec00aad4d8 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -951,8 +951,6 @@ rtc_library("neteq") { "neteq/decoder_database.h", "neteq/delay_manager.cc", "neteq/delay_manager.h", - "neteq/delay_peak_detector.cc", - "neteq/delay_peak_detector.h", "neteq/dsp_helper.cc", "neteq/dsp_helper.h", "neteq/dtmf_buffer.cc", @@ -2027,7 +2025,6 @@ if (rtc_include_tests) { "neteq/decision_logic_unittest.cc", "neteq/decoder_database_unittest.cc", "neteq/delay_manager_unittest.cc", - "neteq/delay_peak_detector_unittest.cc", "neteq/dsp_helper_unittest.cc", "neteq/dtmf_buffer_unittest.cc", "neteq/dtmf_tone_generator_unittest.cc", @@ -2035,7 +2032,6 @@ if (rtc_include_tests) { "neteq/histogram_unittest.cc", "neteq/merge_unittest.cc", "neteq/mock/mock_decoder_database.h", - "neteq/mock/mock_delay_peak_detector.h", "neteq/mock/mock_dtmf_buffer.h", "neteq/mock/mock_dtmf_tone_generator.h", "neteq/mock/mock_expand.h", diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc index 5c746ad96f..b223b2da36 100644 --- a/modules/audio_coding/neteq/decision_logic.cc +++ b/modules/audio_coding/neteq/decision_logic.cc @@ -33,11 +33,9 @@ constexpr int kDefaultTargetLevelWindowMs = 100; namespace webrtc { DecisionLogic::DecisionLogic(NetEqController::Config config) - : delay_peak_detector_(config.tick_timer, config.enable_rtx_handling), - delay_manager_(DelayManager::Create(config.max_packets_in_buffer, + : delay_manager_(DelayManager::Create(config.max_packets_in_buffer, config.base_min_delay_ms, config.enable_rtx_handling, - &delay_peak_detector_, config.tick_timer)), tick_timer_(config.tick_timer), disallow_time_stretching_(!config.allow_time_stretching), diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h index 899f930862..5f1a414019 100644 --- a/modules/audio_coding/neteq/decision_logic.h +++ b/modules/audio_coding/neteq/decision_logic.h @@ -16,7 +16,6 @@ #include "api/neteq/tick_timer.h" #include "modules/audio_coding/neteq/buffer_level_filter.h" #include "modules/audio_coding/neteq/delay_manager.h" -#include "modules/audio_coding/neteq/delay_peak_detector.h" #include "rtc_base/constructor_magic.h" #include "rtc_base/experiments/field_trial_parser.h" @@ -97,7 +96,7 @@ class DecisionLogic : public NetEqController { int GetBaseMinimumDelay() const override { return delay_manager_->GetBaseMinimumDelay(); } - bool PeakFound() const override { return delay_manager_->PeakFound(); } + bool PeakFound() const override { return false; } int GetFilteredBufferLevel() const override { return buffer_level_filter_.filtered_current_level(); @@ -172,7 +171,6 @@ class DecisionLogic : public NetEqController { // Checks if num_consecutive_expands_ >= kMaxWaitForPacket. bool MaxWaitForPacket() const; - DelayPeakDetector delay_peak_detector_; std::unique_ptr delay_manager_; BufferLevelFilter buffer_level_filter_; const TickTimer* tick_timer_; diff --git a/modules/audio_coding/neteq/decision_logic_unittest.cc b/modules/audio_coding/neteq/decision_logic_unittest.cc index d1dd1239ab..a5b6712e73 100644 --- a/modules/audio_coding/neteq/decision_logic_unittest.cc +++ b/modules/audio_coding/neteq/decision_logic_unittest.cc @@ -17,7 +17,6 @@ #include "modules/audio_coding/neteq/buffer_level_filter.h" #include "modules/audio_coding/neteq/decoder_database.h" #include "modules/audio_coding/neteq/delay_manager.h" -#include "modules/audio_coding/neteq/delay_peak_detector.h" #include "modules/audio_coding/neteq/packet_buffer.h" #include "modules/audio_coding/neteq/statistics_calculator.h" #include "test/gtest.h" diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc index 727c522989..0df55c67cd 100644 --- a/modules/audio_coding/neteq/delay_manager.cc +++ b/modules/audio_coding/neteq/delay_manager.cc @@ -19,7 +19,6 @@ #include #include -#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" @@ -103,16 +102,13 @@ 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 histogram) : first_packet_received_(false), max_packets_in_buffer_(max_packets_in_buffer), 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), @@ -123,13 +119,9 @@ DelayManager::DelayManager(size_t max_packets_in_buffer, last_timestamp_(0), minimum_delay_ms_(0), maximum_delay_ms_(0), - peak_detector_(*peak_detector), last_pack_cng_or_dtmf_(1), - frame_length_change_experiment_( - field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")), enable_rtx_handling_(enable_rtx_handling), extra_delay_ms_(GetExtraDelayMs()) { - assert(peak_detector); // Should never be NULL. RTC_CHECK(histogram_); RTC_DCHECK_GE(base_minimum_delay_ms_, 0); @@ -140,16 +132,14 @@ std::unique_ptr DelayManager::Create( size_t max_packets_in_buffer, int base_minimum_delay_ms, bool enable_rtx_handling, - DelayPeakDetector* peak_detector, const TickTimer* tick_timer) { - const HistogramMode mode = RELATIVE_ARRIVAL_DELAY; DelayHistogramConfig config = GetDelayHistogramConfig(); const int quantile = config.quantile; std::unique_ptr histogram = std::make_unique( kDelayBuckets, config.forget_factor, config.start_forget_weight); return std::make_unique( - max_packets_in_buffer, base_minimum_delay_ms, quantile, mode, - enable_rtx_handling, peak_detector, tick_timer, std::move(histogram)); + max_packets_in_buffer, base_minimum_delay_ms, quantile, + enable_rtx_handling, tick_timer, std::move(histogram)); } DelayManager::~DelayManager() {} @@ -193,19 +183,16 @@ absl::optional DelayManager::Update(uint16_t 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. int packet_offset = static_cast(sequence_number - last_seq_no_ - 1); - iat_packets -= packet_offset; iat_ms -= packet_offset * packet_len_ms; } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) { int packet_offset = static_cast(last_seq_no_ + 1 - sequence_number); - iat_packets += packet_offset; iat_ms += packet_offset * packet_len_ms; reordered = true; } @@ -218,25 +205,13 @@ absl::optional DelayManager::Update(uint16_t sequence_number, relative_delay = CalculateRelativePacketArrivalDelay(); } - switch (histogram_mode_) { - case RELATIVE_ARRIVAL_DELAY: { - const int index = relative_delay.value() / kBucketSizeMs; - if (index < histogram_->NumBuckets()) { - // Maximum delay to register is 2000 ms. - histogram_->Add(index); - } - break; - } - case INTER_ARRIVAL_TIME: { - // Saturate IAT between 0 and maximum value. - iat_packets = - std::max(std::min(iat_packets, histogram_->NumBuckets() - 1), 0); - histogram_->Add(iat_packets); - break; - } + const int index = relative_delay.value() / kBucketSizeMs; + if (index < histogram_->NumBuckets()) { + // Maximum delay to register is 2000 ms. + histogram_->Add(index); } // Calculate new |target_level_| based on updated statistics. - target_level_ = CalculateTargetLevel(iat_packets, reordered); + target_level_ = CalculateTargetLevel(); LimitTargetLevel(); } // End if (packet_len_ms > 0). @@ -310,32 +285,15 @@ void DelayManager::LimitTargetLevel() { target_level_ = std::max(target_level_, 1 << 8); } -int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) { +int DelayManager::CalculateTargetLevel() { int limit_probability = histogram_quantile_; int bucket_index = histogram_->Quantile(limit_probability); - int target_level; - switch (histogram_mode_) { - case RELATIVE_ARRIVAL_DELAY: { - target_level = 1; - if (packet_len_ms_ > 0) { - target_level += bucket_index * kBucketSizeMs / packet_len_ms_; - } - base_target_level_ = target_level; - break; - } - case INTER_ARRIVAL_TIME: { - target_level = std::max(bucket_index, 1); - 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; - } + int target_level = 1; + if (packet_len_ms_ > 0) { + target_level += bucket_index * kBucketSizeMs / packet_len_ms_; } + base_target_level_ = target_level; // Sanity check. |target_level| must be strictly positive. target_level = std::max(target_level, 1); @@ -353,14 +311,8 @@ int DelayManager::SetPacketAudioLength(int length_ms) { RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms; return -1; } - if (histogram_mode_ == INTER_ARRIVAL_TIME && - frame_length_change_experiment_ && packet_len_ms_ != length_ms && - packet_len_ms_ > 0) { - histogram_->Scale(packet_len_ms_, length_ms); - } packet_len_ms_ = length_ms; - peak_detector_.SetPacketAudioLength(packet_len_ms_); packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); last_pack_cng_or_dtmf_ = 1; // TODO(hlundin): Legacy. Remove? return 0; @@ -368,7 +320,6 @@ int DelayManager::SetPacketAudioLength(int length_ms) { void DelayManager::Reset() { packet_len_ms_ = 0; // Packet size unknown. - peak_detector_.Reset(); histogram_->Reset(); delay_history_.clear(); base_target_level_ = 4; @@ -377,10 +328,6 @@ void DelayManager::Reset() { last_pack_cng_or_dtmf_ = 1; } -bool DelayManager::PeakFound() const { - return peak_detector_.peak_found(); -} - void DelayManager::ResetPacketIatCount() { packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); } diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h index c4404472cb..d7bea9e168 100644 --- a/modules/audio_coding/neteq/delay_manager.h +++ b/modules/audio_coding/neteq/delay_manager.h @@ -23,22 +23,12 @@ namespace webrtc { -// Forward declaration. -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 histogram); @@ -50,7 +40,6 @@ class DelayManager { static std::unique_ptr Create(size_t max_packets_in_buffer, int base_minimum_delay_ms, bool enable_rtx_handling, - DelayPeakDetector* peak_detector, const TickTimer* tick_timer); virtual ~DelayManager(); @@ -68,7 +57,7 @@ class DelayManager { // Sets target_level_ (in Q8) and returns the same value. Also calculates // and updates base_target_level_, which is the target buffer level before // taking delay peaks into account. - virtual int CalculateTargetLevel(int iat_packets, bool reordered); + virtual int CalculateTargetLevel(); // Notifies the DelayManager of how much audio data is carried in each packet. // The method updates the DelayPeakDetector too, and resets the inter-arrival @@ -78,11 +67,6 @@ class DelayManager { // Resets the DelayManager and the associated DelayPeakDetector. virtual void Reset(); - // Returns true if peak-mode is active. That is, delay peaks were observed - // recently. This method simply asks for the same information from the - // DelayPeakDetector object. - virtual bool PeakFound() const; - // Reset the inter-arrival time counter to 0. virtual void ResetPacketIatCount(); @@ -122,7 +106,6 @@ class DelayManager { } // These accessors are only intended for testing purposes. - HistogramMode histogram_mode() const { return histogram_mode_; } int histogram_quantile() const { return histogram_quantile_; } Histogram* histogram() const { return histogram_.get(); } @@ -163,7 +146,6 @@ class DelayManager { const size_t max_packets_in_buffer_; // Capacity of the packet buffer. 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 @@ -183,9 +165,7 @@ class DelayManager { uint32_t last_timestamp_; // Timestamp for the last received packet. int minimum_delay_ms_; // Externally set minimum delay. int maximum_delay_ms_; // Externally set maximum allowed delay. - DelayPeakDetector& peak_detector_; int last_pack_cng_or_dtmf_; - const bool frame_length_change_experiment_; const bool enable_rtx_handling_; int num_reordered_packets_ = 0; // Number of consecutive reordered packets. diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc index 7abc3fbcfb..d60dbeb755 100644 --- a/modules/audio_coding/neteq/delay_manager_unittest.cc +++ b/modules/audio_coding/neteq/delay_manager_unittest.cc @@ -17,7 +17,6 @@ #include #include "modules/audio_coding/neteq/histogram.h" -#include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h" #include "modules/audio_coding/neteq/mock/mock_histogram.h" #include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h" #include "rtc_base/checks.h" @@ -47,7 +46,6 @@ class DelayManagerTest : public ::testing::Test { protected: DelayManagerTest(); virtual void SetUp(); - virtual void TearDown(); void RecreateDelayManager(); void SetPacketAudioLength(int lengt_ms); absl::optional InsertNextPacket(); @@ -56,19 +54,15 @@ class DelayManagerTest : public ::testing::Test { std::unique_ptr dm_; TickTimer tick_timer_; MockStatisticsCalculator stats_; - MockDelayPeakDetector detector_; 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::RELATIVE_ARRIVAL_DELAY; }; DelayManagerTest::DelayManagerTest() : dm_(nullptr), - detector_(&tick_timer_, false), seq_no_(0x1234), ts_(0x12345678) {} @@ -77,22 +71,19 @@ void DelayManagerTest::SetUp() { } void DelayManagerTest::RecreateDelayManager() { - EXPECT_CALL(detector_, Reset()).Times(1); if (use_mock_histogram_) { mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor); std::unique_ptr histogram(mock_histogram_); dm_ = std::make_unique( kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile, - histogram_mode_, enable_rtx_handling_, &detector_, &tick_timer_, - std::move(histogram)); + enable_rtx_handling_, &tick_timer_, std::move(histogram)); } else { dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs, - enable_rtx_handling_, &detector_, &tick_timer_); + enable_rtx_handling_, &tick_timer_); } } void DelayManagerTest::SetPacketAudioLength(int lengt_ms) { - EXPECT_CALL(detector_, SetPacketAudioLength(lengt_ms)); dm_->SetPacketAudioLength(lengt_ms); } @@ -109,10 +100,6 @@ void DelayManagerTest::IncreaseTime(int inc_ms) { } } -void DelayManagerTest::TearDown() { - EXPECT_CALL(detector_, Die()); -} - TEST_F(DelayManagerTest, CreateAndDestroy) { // Nothing to do here. The test fixture creates and destroys the DelayManager // object. @@ -120,23 +107,10 @@ TEST_F(DelayManagerTest, CreateAndDestroy) { TEST_F(DelayManagerTest, SetPacketAudioLength) { const int kLengthMs = 30; - // Expect DelayManager to pass on the new length to the detector object. - EXPECT_CALL(detector_, SetPacketAudioLength(kLengthMs)).Times(1); EXPECT_EQ(0, dm_->SetPacketAudioLength(kLengthMs)); EXPECT_EQ(-1, dm_->SetPacketAudioLength(-1)); // Illegal parameter value. } -TEST_F(DelayManagerTest, PeakFound) { - // Expect DelayManager to pass on the question to the detector. - // Call twice, and let the detector return true the first time and false the - // second time. - EXPECT_CALL(detector_, peak_found()) - .WillOnce(Return(true)) - .WillOnce(Return(false)); - EXPECT_TRUE(dm_->PeakFound()); - EXPECT_FALSE(dm_->PeakFound()); -} - TEST_F(DelayManagerTest, UpdateNormal) { SetPacketAudioLength(kFrameSizeMs); // First packet arrival. @@ -495,8 +469,6 @@ 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, @@ -507,8 +479,6 @@ TEST_F(DelayManagerTest, DelayHistogramFieldTrial) { 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, @@ -536,8 +506,7 @@ TEST_F(DelayManagerTest, DelayHistogramFieldTrial) { } } -TEST_F(DelayManagerTest, RelativeArrivalDelayMode) { - histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY; +TEST_F(DelayManagerTest, RelativeArrivalDelay) { use_mock_histogram_ = true; RecreateDelayManager(); @@ -561,7 +530,6 @@ TEST_F(DelayManagerTest, RelativeArrivalDelayMode) { } TEST_F(DelayManagerTest, MaxDelayHistory) { - histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY; use_mock_histogram_ = true; RecreateDelayManager(); diff --git a/modules/audio_coding/neteq/delay_peak_detector.cc b/modules/audio_coding/neteq/delay_peak_detector.cc deleted file mode 100644 index 5669d72960..0000000000 --- a/modules/audio_coding/neteq/delay_peak_detector.cc +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2012 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 "modules/audio_coding/neteq/delay_peak_detector.h" - -#include - -#include "rtc_base/checks.h" -#include "system_wrappers/include/field_trial.h" - -namespace webrtc { - -// The DelayPeakDetector keeps track of severe inter-arrival times, called -// delay peaks. When a peak is observed, the "height" (the time elapsed since -// the previous packet arrival) and the peak "period" (the time since the last -// observed peak) is recorded in a vector. When enough peaks have been observed, -// peak-mode is engaged and the DelayManager asks the DelayPeakDetector for -// the worst peak height. - -DelayPeakDetector::~DelayPeakDetector() = default; - -DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer, - bool ignore_reordered_packets) - : peak_found_(false), - peak_detection_threshold_(0), - tick_timer_(tick_timer), - ignore_reordered_packets_(ignore_reordered_packets), - frame_length_change_experiment_( - field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) { - RTC_DCHECK(!peak_period_stopwatch_); -} - -void DelayPeakDetector::Reset() { - peak_period_stopwatch_.reset(); - peak_found_ = false; - peak_history_.clear(); -} - -// Calculates the threshold in number of packets. -void DelayPeakDetector::SetPacketAudioLength(int length_ms) { - if (length_ms > 0) { - if (frame_length_change_experiment_) { - peak_detection_threshold_ = std::max(2, kPeakHeightMs / length_ms); - } else { - peak_detection_threshold_ = kPeakHeightMs / length_ms; - } - } - if (frame_length_change_experiment_) { - peak_history_.clear(); - } -} - -bool DelayPeakDetector::peak_found() { - return peak_found_; -} - -int DelayPeakDetector::MaxPeakHeight() const { - int max_height = -1; // Returns -1 for an empty history. - std::list::const_iterator it; - for (it = peak_history_.begin(); it != peak_history_.end(); ++it) { - max_height = std::max(max_height, it->peak_height_packets); - } - return max_height; -} - -uint64_t DelayPeakDetector::MaxPeakPeriod() const { - auto max_period_element = std::max_element( - peak_history_.begin(), peak_history_.end(), - [](Peak a, Peak b) { return a.period_ms < b.period_ms; }); - if (max_period_element == peak_history_.end()) { - return 0; // |peak_history_| is empty. - } - RTC_DCHECK_GT(max_period_element->period_ms, 0); - return max_period_element->period_ms; -} - -bool DelayPeakDetector::Update(int inter_arrival_time, - bool reordered, - int target_level) { - if (ignore_reordered_packets_ && reordered) { - return CheckPeakConditions(); - } - if (inter_arrival_time > target_level + peak_detection_threshold_ || - inter_arrival_time > 2 * target_level) { - // A delay peak is observed. - if (!peak_period_stopwatch_) { - // This is the first peak. Reset the period counter. - peak_period_stopwatch_ = tick_timer_->GetNewStopwatch(); - } else if (peak_period_stopwatch_->ElapsedMs() > 0) { - if (peak_period_stopwatch_->ElapsedMs() <= kMaxPeakPeriodMs) { - // This is not the first peak, and the period is valid. - // Store peak data in the vector. - Peak peak_data; - peak_data.period_ms = peak_period_stopwatch_->ElapsedMs(); - peak_data.peak_height_packets = inter_arrival_time; - peak_history_.push_back(peak_data); - while (peak_history_.size() > kMaxNumPeaks) { - // Delete the oldest data point. - peak_history_.pop_front(); - } - peak_period_stopwatch_ = tick_timer_->GetNewStopwatch(); - } else if (peak_period_stopwatch_->ElapsedMs() <= 2 * kMaxPeakPeriodMs) { - // Invalid peak due to too long period. Reset period counter and start - // looking for next peak. - peak_period_stopwatch_ = tick_timer_->GetNewStopwatch(); - } else { - // More than 2 times the maximum period has elapsed since the last peak - // was registered. It seams that the network conditions have changed. - // Reset the peak statistics. - Reset(); - } - } - } - return CheckPeakConditions(); -} - -bool DelayPeakDetector::CheckPeakConditions() { - size_t s = peak_history_.size(); - if (s >= kMinPeaksToTrigger && - peak_period_stopwatch_->ElapsedMs() <= 2 * MaxPeakPeriod()) { - peak_found_ = true; - } else { - peak_found_ = false; - } - return peak_found_; -} -} // namespace webrtc diff --git a/modules/audio_coding/neteq/delay_peak_detector.h b/modules/audio_coding/neteq/delay_peak_detector.h deleted file mode 100644 index dce8bb4d6e..0000000000 --- a/modules/audio_coding/neteq/delay_peak_detector.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 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 MODULES_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_ -#define MODULES_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_ - -#include -#include - -#include -#include - -#include "api/neteq/tick_timer.h" -#include "rtc_base/constructor_magic.h" - -namespace webrtc { - -class DelayPeakDetector { - public: - DelayPeakDetector(const TickTimer* tick_timer, bool ignore_reordered_packets); - virtual ~DelayPeakDetector(); - virtual void Reset(); - - // Notifies the DelayPeakDetector of how much audio data is carried in each - // packet. - virtual void SetPacketAudioLength(int length_ms); - - // Returns true if peak-mode is active. That is, delay peaks were observed - // recently. - virtual bool peak_found(); - - // Calculates and returns the maximum delay peak height. Returns -1 if no - // delay peaks have been observed recently. The unit is number of packets. - virtual int MaxPeakHeight() const; - - // Calculates and returns the maximum delay peak distance in ms (strictly - // larger than 0), or 0 if no delay peaks have been observed recently. - virtual uint64_t MaxPeakPeriod() const; - - // Updates the DelayPeakDetector with a new inter-arrival time (in packets), - // the current target buffer level (needed to decide if a peak is observed or - // not) and if the new inter-arrival time includes a compensation for - // reordering. Returns true if peak-mode is active, false if not. - virtual bool Update(int inter_arrival_time, bool reordered, int target_level); - - private: - static const size_t kMaxNumPeaks = 8; - static const size_t kMinPeaksToTrigger = 2; - static const int kPeakHeightMs = 78; - static const int kMaxPeakPeriodMs = 10000; - - typedef struct { - uint64_t period_ms; - int peak_height_packets; - } Peak; - - bool CheckPeakConditions(); - - std::list peak_history_; - bool peak_found_; - int peak_detection_threshold_; - const TickTimer* tick_timer_; - std::unique_ptr peak_period_stopwatch_; - const bool ignore_reordered_packets_; - const bool frame_length_change_experiment_; - - RTC_DISALLOW_COPY_AND_ASSIGN(DelayPeakDetector); -}; - -} // namespace webrtc -#endif // MODULES_AUDIO_CODING_NETEQ_DELAY_PEAK_DETECTOR_H_ diff --git a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc b/modules/audio_coding/neteq/delay_peak_detector_unittest.cc deleted file mode 100644 index 6590dc281e..0000000000 --- a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2012 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. - */ - -// Unit tests for DelayPeakDetector class. - -#include "modules/audio_coding/neteq/delay_peak_detector.h" - -#include "test/gtest.h" - -namespace webrtc { - -TEST(DelayPeakDetector, CreateAndDestroy) { - TickTimer tick_timer; - DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer, false); - EXPECT_FALSE(detector->peak_found()); - delete detector; -} - -TEST(DelayPeakDetector, EmptyHistory) { - TickTimer tick_timer; - DelayPeakDetector detector(&tick_timer, false); - EXPECT_EQ(-1, detector.MaxPeakHeight()); - EXPECT_EQ(0u, detector.MaxPeakPeriod()); -} - -// Inject a series of packet arrivals into the detector. Three of the packets -// have suffered delays. After the third delay peak, peak-mode is expected to -// start. This should then continue until it is disengaged due to lack of peaks. -TEST(DelayPeakDetector, TriggerPeakMode) { - TickTimer tick_timer; - DelayPeakDetector detector(&tick_timer, false); - const int kPacketSizeMs = 30; - detector.SetPacketAudioLength(kPacketSizeMs); - - // Load up normal arrival times; 0 ms, 30 ms, 60 ms, 90 ms, ... - const int kNumPackets = 1000; - int arrival_times_ms[kNumPackets]; - for (int i = 0; i < kNumPackets; ++i) { - arrival_times_ms[i] = i * kPacketSizeMs; - } - - // Delay three packets. - const int kPeakDelayMs = 100; - // First delay peak. - arrival_times_ms[100] += kPeakDelayMs; - // Second delay peak. - arrival_times_ms[200] += kPeakDelayMs; - // Third delay peak. Trigger peak-mode after this packet. - arrival_times_ms[400] += kPeakDelayMs; - // The second peak period is the longest, 200 packets. - const uint64_t kWorstPeakPeriod = 200 * kPacketSizeMs; - int peak_mode_start_ms = arrival_times_ms[400]; - // Expect to disengage after no peaks are observed for two period times. - int peak_mode_end_ms = peak_mode_start_ms + 2 * kWorstPeakPeriod; - - // Load into detector. - int time = 0; - int next = 1; // Start with the second packet to get a proper IAT. - while (next < kNumPackets) { - while (next < kNumPackets && arrival_times_ms[next] <= time) { - int iat_packets = - (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs; - const int kTargetBufferLevel = 1; // Define peaks to be iat > 2. - if (time < peak_mode_start_ms || time > peak_mode_end_ms) { - EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel)); - } else { - EXPECT_TRUE(detector.Update(iat_packets, false, kTargetBufferLevel)); - EXPECT_EQ(kWorstPeakPeriod, detector.MaxPeakPeriod()); - EXPECT_EQ(kPeakDelayMs / kPacketSizeMs + 1, detector.MaxPeakHeight()); - } - ++next; - } - tick_timer.Increment(); - time += 10; // Increase time 10 ms. - } -} - -// Same test as TriggerPeakMode, but with base target buffer level increased to -// 2, in order to raise the bar for delay peaks to inter-arrival times > 4. -// The delay pattern has peaks with delay = 3, thus should not trigger. -TEST(DelayPeakDetector, DoNotTriggerPeakMode) { - TickTimer tick_timer; - DelayPeakDetector detector(&tick_timer, false); - const int kPacketSizeMs = 30; - detector.SetPacketAudioLength(kPacketSizeMs); - - // Load up normal arrival times; 0 ms, 30 ms, 60 ms, 90 ms, ... - const int kNumPackets = 1000; - int arrival_times_ms[kNumPackets]; - for (int i = 0; i < kNumPackets; ++i) { - arrival_times_ms[i] = i * kPacketSizeMs; - } - - // Delay three packets. - const int kPeakDelayMs = 100; - // First delay peak. - arrival_times_ms[100] += kPeakDelayMs; - // Second delay peak. - arrival_times_ms[200] += kPeakDelayMs; - // Third delay peak. - arrival_times_ms[400] += kPeakDelayMs; - - // Load into detector. - int time = 0; - int next = 1; // Start with the second packet to get a proper IAT. - while (next < kNumPackets) { - while (next < kNumPackets && arrival_times_ms[next] <= time) { - int iat_packets = - (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs; - const int kTargetBufferLevel = 2; // Define peaks to be iat > 4. - EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel)); - ++next; - } - tick_timer.Increment(); - time += 10; // Increase time 10 ms. - } -} - -// In situations with reordered packets, the DelayPeakDetector may be updated -// back-to-back (i.e., without the tick_timer moving) but still with non-zero -// inter-arrival time. This test is to make sure that this does not cause -// problems. -TEST(DelayPeakDetector, ZeroDistancePeaks) { - TickTimer tick_timer; - DelayPeakDetector detector(&tick_timer, false); - const int kPacketSizeMs = 30; - detector.SetPacketAudioLength(kPacketSizeMs); - - const int kTargetBufferLevel = 2; // Define peaks to be iat > 4. - const int kInterArrivalTime = - 3 * kTargetBufferLevel; // Above peak threshold. - EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel)); - tick_timer.Increment(); - EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel)); - // The following would fail if there were non-zero time between the updates. - EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel)); -} - -TEST(DelayPeakDetector, IgnoreReorderedPacket) { - TickTimer tick_timer; - DelayPeakDetector detector(&tick_timer, true); - - const int kTargetBufferLevel = 2; // Define peaks to be iat > 4. - const int kInterArrivalTime = - 3 * kTargetBufferLevel; // Above peak threshold. - EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel)); - tick_timer.Increment(); - EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel)); - tick_timer.Increment(); - // The following would fail if the packet was not reordered. - EXPECT_FALSE(detector.Update(kInterArrivalTime, true, kTargetBufferLevel)); -} - -} // namespace webrtc diff --git a/modules/audio_coding/neteq/histogram.cc b/modules/audio_coding/neteq/histogram.cc index d0da16bdf2..15a2394eb0 100644 --- a/modules/audio_coding/neteq/histogram.cc +++ b/modules/audio_coding/neteq/histogram.cc @@ -146,58 +146,4 @@ int Histogram::NumBuckets() const { return buckets_.size(); } -void Histogram::Scale(int old_bucket_width, int new_bucket_width) { - buckets_ = ScaleBuckets(buckets_, old_bucket_width, new_bucket_width); -} - -std::vector Histogram::ScaleBuckets(const std::vector& buckets, - int old_bucket_width, - int new_bucket_width) { - RTC_DCHECK_GT(old_bucket_width, 0); - RTC_DCHECK_GT(new_bucket_width, 0); - RTC_DCHECK_EQ(old_bucket_width % 10, 0); - RTC_DCHECK_EQ(new_bucket_width % 10, 0); - std::vector new_histogram(buckets.size(), 0); - int64_t acc = 0; - int time_counter = 0; - size_t new_histogram_idx = 0; - for (size_t i = 0; i < buckets.size(); i++) { - acc += buckets[i]; - time_counter += old_bucket_width; - // The bins should be scaled, to ensure the histogram still sums to one. - const int64_t scaled_acc = acc * new_bucket_width / time_counter; - int64_t actually_used_acc = 0; - while (time_counter >= new_bucket_width) { - const int64_t old_histogram_val = new_histogram[new_histogram_idx]; - new_histogram[new_histogram_idx] = - rtc::saturated_cast(old_histogram_val + scaled_acc); - actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val; - new_histogram_idx = - std::min(new_histogram_idx + 1, new_histogram.size() - 1); - time_counter -= new_bucket_width; - } - // Only subtract the part that was succesfully written to the new histogram. - acc -= actually_used_acc; - } - // If there is anything left in acc (due to rounding errors), add it to the - // last bin. If we cannot add everything to the last bin we need to add as - // much as possible to the bins after the last bin (this is only possible - // when compressing a histogram). - while (acc > 0 && new_histogram_idx < new_histogram.size()) { - const int64_t old_histogram_val = new_histogram[new_histogram_idx]; - new_histogram[new_histogram_idx] = - rtc::saturated_cast(old_histogram_val + acc); - acc -= new_histogram[new_histogram_idx] - old_histogram_val; - new_histogram_idx++; - } - RTC_DCHECK_EQ(buckets.size(), new_histogram.size()); - if (acc == 0) { - // If acc is non-zero, we were not able to add everything to the new - // histogram, so this check will not hold. - RTC_DCHECK_EQ(accumulate(buckets.begin(), buckets.end(), 0ll), - accumulate(new_histogram.begin(), new_histogram.end(), 0ll)); - } - return new_histogram; -} - } // namespace webrtc diff --git a/modules/audio_coding/neteq/histogram.h b/modules/audio_coding/neteq/histogram.h index 7eb90d97a3..0567e3f183 100644 --- a/modules/audio_coding/neteq/histogram.h +++ b/modules/audio_coding/neteq/histogram.h @@ -38,20 +38,12 @@ class Histogram { // distribution. virtual int Quantile(int probability); - // Apply compression or stretching to the histogram. - virtual void Scale(int old_bucket_width, int new_bucket_width); - // Returns the number of buckets in the histogram. virtual int NumBuckets() const; // Returns the probability for each bucket in Q30. std::vector buckets() const { return buckets_; } - // Made public for testing. - static std::vector ScaleBuckets(const std::vector& buckets, - int old_bucket_width, - int new_bucket_width); - // Accessors only intended for testing purposes. int base_forget_factor_for_testing() const { return base_forget_factor_; } int forget_factor_for_testing() const { return forget_factor_; } diff --git a/modules/audio_coding/neteq/histogram_unittest.cc b/modules/audio_coding/neteq/histogram_unittest.cc index 4df8b488b3..e30a2956dc 100644 --- a/modules/audio_coding/neteq/histogram_unittest.cc +++ b/modules/audio_coding/neteq/histogram_unittest.cc @@ -59,116 +59,6 @@ TEST(HistogramTest, ForgetFactor) { } } -// Test if the histogram is scaled correctly if the bucket width is decreased. -TEST(HistogramTest, DownScale) { - // Test a straightforward 60 to 20 change. - std::vector buckets = {12, 0, 0, 0, 0, 0}; - std::vector expected_result = {4, 4, 4, 0, 0, 0}; - std::vector stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20); - EXPECT_EQ(stretched_buckets, expected_result); - - // Test an example where the last bin in the stretched histogram should - // contain the sum of the elements that don't fit into the new histogram. - buckets = {18, 15, 12, 9, 6, 3, 0}; - expected_result = {6, 6, 6, 5, 5, 5, 30}; - stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20); - EXPECT_EQ(stretched_buckets, expected_result); - - // Test a 120 to 60 change. - buckets = {18, 16, 14, 4, 0}; - expected_result = {9, 9, 8, 8, 18}; - stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 60); - EXPECT_EQ(stretched_buckets, expected_result); - - // Test a 120 to 20 change. - buckets = {19, 12, 0, 0, 0, 0, 0, 0}; - expected_result = {3, 3, 3, 3, 3, 3, 2, 11}; - stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 20); - EXPECT_EQ(stretched_buckets, expected_result); - - // Test a 70 to 40 change. - buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0}; - expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22}; - stretched_buckets = Histogram::ScaleBuckets(buckets, 70, 40); - EXPECT_EQ(stretched_buckets, expected_result); - - // Test a 30 to 20 change. - buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0}; - expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11}; - stretched_buckets = Histogram::ScaleBuckets(buckets, 30, 20); - EXPECT_EQ(stretched_buckets, expected_result); -} - -// Test if the histogram is scaled correctly if the bucket width is increased. -TEST(HistogramTest, UpScale) { - // Test a 20 to 60 change. - std::vector buckets = {12, 11, 10, 3, 2, 1}; - std::vector expected_result = {33, 6, 0, 0, 0, 0}; - std::vector compressed_buckets = - Histogram::ScaleBuckets(buckets, 20, 60); - EXPECT_EQ(compressed_buckets, expected_result); - - // Test a 60 to 120 change. - buckets = {18, 16, 14, 4, 1}; - expected_result = {34, 18, 1, 0, 0}; - compressed_buckets = Histogram::ScaleBuckets(buckets, 60, 120); - EXPECT_EQ(compressed_buckets, expected_result); - - // Test a 20 to 120 change. - buckets = {18, 12, 5, 4, 4, 3, 5, 1}; - expected_result = {46, 6, 0, 0, 0, 0, 0, 0}; - compressed_buckets = Histogram::ScaleBuckets(buckets, 20, 120); - EXPECT_EQ(compressed_buckets, expected_result); - - // Test a 70 to 80 change. - buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3}; - expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0}; - compressed_buckets = Histogram::ScaleBuckets(buckets, 70, 80); - EXPECT_EQ(compressed_buckets, expected_result); - - // Test a 50 to 110 change. - buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3}; - expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0}; - compressed_buckets = Histogram::ScaleBuckets(buckets, 50, 110); - EXPECT_EQ(compressed_buckets, expected_result); -} - -// Test if the histogram scaling function handles overflows correctly. -TEST(HistogramTest, OverflowTest) { - // Test a upscale operation that can cause overflow. - std::vector buckets = {733544448, 0, 0, 0, 0, 0, 0, - 340197376, 0, 0, 0, 0, 0, 0}; - std::vector expected_result = {733544448, 340197376, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0}; - std::vector scaled_buckets = Histogram::ScaleBuckets(buckets, 10, 60); - EXPECT_EQ(scaled_buckets, expected_result); - - buckets = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764, - 114119, 2072996, 0, 2149354, 0}; - expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0, - 0, 0, 0, 0, 0}; - scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60); - EXPECT_EQ(scaled_buckets, expected_result); - - // In this test case we will not be able to add everything to the final bin in - // the scaled histogram. Check that the last bin doesn't overflow. - buckets = {2000000000, 2000000000, 2000000000, - 2000000000, 2000000000, 2000000000}; - expected_result = {666666666, 666666666, 666666666, - 666666667, 666666667, 2147483647}; - scaled_buckets = Histogram::ScaleBuckets(buckets, 60, 20); - EXPECT_EQ(scaled_buckets, expected_result); - - // In this test case we will not be able to add enough to each of the bins, - // so the values should be smeared out past the end of the normal range. - buckets = {2000000000, 2000000000, 2000000000, - 2000000000, 2000000000, 2000000000}; - expected_result = {2147483647, 2147483647, 2147483647, - 2147483647, 2147483647, 1262581765}; - scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60); - EXPECT_EQ(scaled_buckets, expected_result); -} - TEST(HistogramTest, ReachSteadyStateForgetFactor) { static constexpr int kSteadyStateForgetFactor = (1 << 15) * 0.9993; Histogram histogram(100, kSteadyStateForgetFactor, 1.0); diff --git a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h b/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h deleted file mode 100644 index 1613f4ca74..0000000000 --- a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012 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 MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_ -#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_ - -#include "modules/audio_coding/neteq/delay_peak_detector.h" -#include "test/gmock.h" - -namespace webrtc { - -class MockDelayPeakDetector : public DelayPeakDetector { - public: - MockDelayPeakDetector(const TickTimer* tick_timer, - bool ignore_reordered_packets) - : DelayPeakDetector(tick_timer, ignore_reordered_packets) {} - virtual ~MockDelayPeakDetector() { Die(); } - MOCK_METHOD0(Die, void()); - MOCK_METHOD0(Reset, void()); - MOCK_METHOD1(SetPacketAudioLength, void(int length_ms)); - MOCK_METHOD0(peak_found, bool()); - MOCK_CONST_METHOD0(MaxPeakHeight, int()); - MOCK_CONST_METHOD0(MaxPeakPeriod, uint64_t()); - MOCK_METHOD3(Update, - bool(int inter_arrival_time, bool reordered, int target_level)); -}; - -} // namespace webrtc - -#endif // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_PEAK_DETECTOR_H_