From 01ab7d501be1e6701e0f4e924ebc78c3bd11753b Mon Sep 17 00:00:00 2001 From: Jakob Ivarsson Date: Wed, 25 May 2022 21:06:14 +0200 Subject: [PATCH] Use packet arrival history in delay manager. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It replaces the relative arrival delay tracker which is equivalent. This results in a slight bit-exactness change but nothing that should affect quality. Bug: webrtc:13322 Change-Id: I6ed5d6fdfa724859122928a8838acce27ac2e5d0 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/263380 Commit-Queue: Jakob Ivarsson‎ Reviewed-by: Minyue Li Cr-Commit-Position: refs/heads/main@{#37004} --- modules/audio_coding/BUILD.gn | 3 - modules/audio_coding/neteq/decision_logic.cc | 26 +++--- modules/audio_coding/neteq/decision_logic.h | 1 - modules/audio_coding/neteq/delay_manager.cc | 26 +----- modules/audio_coding/neteq/delay_manager.h | 16 ++-- .../neteq/delay_manager_unittest.cc | 38 +++------ modules/audio_coding/neteq/neteq_unittest.cc | 4 +- .../neteq/packet_arrival_history.cc | 22 ++++- .../neteq/packet_arrival_history.h | 9 +- .../neteq/packet_arrival_history_unittest.cc | 2 + .../neteq/relative_arrival_delay_tracker.cc | 83 ------------------ .../neteq/relative_arrival_delay_tracker.h | 61 -------------- ...relative_arrival_delay_tracker_unittest.cc | 84 ------------------- 13 files changed, 62 insertions(+), 313 deletions(-) delete mode 100644 modules/audio_coding/neteq/relative_arrival_delay_tracker.cc delete mode 100644 modules/audio_coding/neteq/relative_arrival_delay_tracker.h delete mode 100644 modules/audio_coding/neteq/relative_arrival_delay_tracker_unittest.cc diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 7af05f9cb2..30d6c8ccf7 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -986,8 +986,6 @@ rtc_library("neteq") { "neteq/random_vector.h", "neteq/red_payload_splitter.cc", "neteq/red_payload_splitter.h", - "neteq/relative_arrival_delay_tracker.cc", - "neteq/relative_arrival_delay_tracker.h", "neteq/reorder_optimizer.cc", "neteq/reorder_optimizer.h", "neteq/statistics_calculator.cc", @@ -2037,7 +2035,6 @@ if (rtc_include_tests) { "neteq/post_decode_vad_unittest.cc", "neteq/random_vector_unittest.cc", "neteq/red_payload_splitter_unittest.cc", - "neteq/relative_arrival_delay_tracker_unittest.cc", "neteq/reorder_optimizer_unittest.cc", "neteq/statistics_calculator_unittest.cc", "neteq/sync_buffer_unittest.cc", diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc index 1a5aa26e02..3a656a7f43 100644 --- a/modules/audio_coding/neteq/decision_logic.cc +++ b/modules/audio_coding/neteq/decision_logic.cc @@ -12,6 +12,7 @@ #include +#include #include #include @@ -106,7 +107,6 @@ void DecisionLogic::SoftReset() { packet_length_samples_ = 0; sample_memory_ = 0; prev_time_scale_ = false; - last_pack_cng_or_dtmf_ = true; timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1); time_stretched_cn_samples_ = 0; @@ -239,11 +239,7 @@ absl::optional DecisionLogic::PacketArrived( bool should_update_stats, const PacketArrivedInfo& info) { buffer_flush_ = buffer_flush_ || info.buffer_flush; - if (info.is_cng_or_dtmf) { - last_pack_cng_or_dtmf_ = true; - return absl::nullopt; - } - if (!should_update_stats) { + if (!should_update_stats || info.is_cng_or_dtmf) { return absl::nullopt; } if (info.packet_length_samples > 0 && fs_hz > 0 && @@ -251,12 +247,18 @@ absl::optional DecisionLogic::PacketArrived( packet_length_samples_ = info.packet_length_samples; delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz); } - packet_arrival_history_.Insert( - info.main_timestamp, tick_timer_->ticks() * tick_timer_->ms_per_tick()); - auto relative_delay = delay_manager_->Update( - info.main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_); - last_pack_cng_or_dtmf_ = false; - return relative_delay; + int64_t time_now_ms = tick_timer_->ticks() * tick_timer_->ms_per_tick(); + packet_arrival_history_.Insert(info.main_timestamp, time_now_ms); + if (packet_arrival_history_.size() < 2) { + // No meaningful delay estimate unless at least 2 packets have arrived. + return absl::nullopt; + } + int arrival_delay_ms = + packet_arrival_history_.GetDelayMs(info.main_timestamp, time_now_ms); + bool reordered = + !packet_arrival_history_.IsNewestRtpTimestamp(info.main_timestamp); + delay_manager_->Update(arrival_delay_ms, reordered); + return arrival_delay_ms; } void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) { diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h index a0f590e884..1e7c9fe08f 100644 --- a/modules/audio_coding/neteq/decision_logic.h +++ b/modules/audio_coding/neteq/decision_logic.h @@ -191,7 +191,6 @@ class DecisionLogic : public NetEqController { std::unique_ptr timescale_countdown_; int num_consecutive_expands_ = 0; int time_stretched_cn_samples_ = 0; - bool last_pack_cng_or_dtmf_ = true; bool buffer_flush_ = false; int last_playout_delay_ms_ = 0; }; diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc index 8db7448225..ba8f706c64 100644 --- a/modules/audio_coding/neteq/delay_manager.cc +++ b/modules/audio_coding/neteq/delay_manager.cc @@ -51,7 +51,6 @@ DelayManager::Config::Config() { "forget_factor", &forget_factor, // "start_forget_weight", &start_forget_weight, // "resample_interval_ms", &resample_interval_ms, // - "max_history_ms", &max_history_ms, // "use_reorder_optimizer", &use_reorder_optimizer, // "reorder_forget_factor", &reorder_forget_factor, // "ms_per_loss_percent", &ms_per_loss_percent) @@ -66,7 +65,6 @@ void DelayManager::Config::Log() { << " start_forget_weight=" << start_forget_weight.value_or(0) << " resample_interval_ms=" << resample_interval_ms.value_or(0) - << " max_history_ms=" << max_history_ms << " use_reorder_optimizer=" << use_reorder_optimizer << " reorder_forget_factor=" << reorder_forget_factor << " ms_per_loss_percent=" << ms_per_loss_percent; @@ -80,7 +78,6 @@ DelayManager::DelayManager(const Config& config, const TickTimer* tick_timer) config.start_forget_weight, config.resample_interval_ms), reorder_optimizer_(MaybeCreateReorderOptimizer(config)), - relative_arrival_delay_tracker_(tick_timer, config.max_history_ms), base_minimum_delay_ms_(config.base_minimum_delay_ms), effective_minimum_delay_ms_(config.base_minimum_delay_ms), minimum_delay_ms_(0), @@ -93,27 +90,14 @@ DelayManager::DelayManager(const Config& config, const TickTimer* tick_timer) DelayManager::~DelayManager() {} -absl::optional DelayManager::Update(uint32_t timestamp, - int sample_rate_hz, - bool reset) { - if (reset) { - relative_arrival_delay_tracker_.Reset(); - } - absl::optional relative_delay = - relative_arrival_delay_tracker_.Update(timestamp, sample_rate_hz); - if (!relative_delay) { - return absl::nullopt; - } - - bool reordered = - relative_arrival_delay_tracker_.newest_timestamp() != timestamp; +void DelayManager::Update(int arrival_delay_ms, bool reordered) { if (!reorder_optimizer_ || !reordered) { - underrun_optimizer_.Update(*relative_delay); + underrun_optimizer_.Update(arrival_delay_ms); } target_level_ms_ = underrun_optimizer_.GetOptimalDelayMs().value_or(kStartDelayMs); if (reorder_optimizer_) { - reorder_optimizer_->Update(*relative_delay, reordered, target_level_ms_); + reorder_optimizer_->Update(arrival_delay_ms, reordered, target_level_ms_); target_level_ms_ = std::max( target_level_ms_, reorder_optimizer_->GetOptimalDelayMs().value_or(0)); } @@ -126,11 +110,8 @@ absl::optional DelayManager::Update(uint32_t timestamp, target_level_ms_ = std::min( target_level_ms_, 3 * max_packets_in_buffer_ * packet_len_ms_ / 4); } - - return relative_delay; } - int DelayManager::SetPacketAudioLength(int length_ms) { if (length_ms <= 0) { RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms; @@ -143,7 +124,6 @@ int DelayManager::SetPacketAudioLength(int length_ms) { void DelayManager::Reset() { packet_len_ms_ = 0; underrun_optimizer_.Reset(); - relative_arrival_delay_tracker_.Reset(); target_level_ms_ = kStartDelayMs; if (reorder_optimizer_) { reorder_optimizer_->Reset(); diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h index 56d108ad11..1c4fe423b0 100644 --- a/modules/audio_coding/neteq/delay_manager.h +++ b/modules/audio_coding/neteq/delay_manager.h @@ -19,7 +19,6 @@ #include "absl/types/optional.h" #include "api/neteq/tick_timer.h" #include "modules/audio_coding/neteq/histogram.h" -#include "modules/audio_coding/neteq/relative_arrival_delay_tracker.h" #include "modules/audio_coding/neteq/reorder_optimizer.h" #include "modules/audio_coding/neteq/underrun_optimizer.h" @@ -36,7 +35,6 @@ class DelayManager { double forget_factor = 0.983; absl::optional start_forget_weight = 2; absl::optional resample_interval_ms = 500; - int max_history_ms = 2000; bool use_reorder_optimizer = true; double reorder_forget_factor = 0.9993; @@ -54,14 +52,11 @@ class DelayManager { DelayManager(const DelayManager&) = delete; DelayManager& operator=(const DelayManager&) = delete; - // Updates the delay manager with a new incoming packet, with `timestamp` from - // the RTP header. This updates the statistics and a new target buffer level - // is calculated. Returns the relative delay if it can be calculated. If - // `reset` is true, restarts the relative arrival delay calculation from this - // packet. - virtual absl::optional Update(uint32_t timestamp, - int sample_rate_hz, - bool reset = false); + // Updates the delay manager that a new packet arrived with delay + // `arrival_delay_ms`. This updates the statistics and a new target buffer + // level is calculated. The `reordered` flag indicates if the packet was + // reordered. + virtual void Update(int arrival_delay_ms, bool reordered); // Resets all state. virtual void Reset(); @@ -105,7 +100,6 @@ class DelayManager { const int max_packets_in_buffer_; UnderrunOptimizer underrun_optimizer_; std::unique_ptr reorder_optimizer_; - RelativeArrivalDelayTracker relative_arrival_delay_tracker_; int base_minimum_delay_ms_; int effective_minimum_delay_ms_; // Used as lower bound for target delay. diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc index fafcffb58d..da5f53188c 100644 --- a/modules/audio_coding/neteq/delay_manager_unittest.cc +++ b/modules/audio_coding/neteq/delay_manager_unittest.cc @@ -30,9 +30,7 @@ namespace webrtc { namespace { constexpr int kMaxNumberOfPackets = 200; constexpr int kTimeStepMs = 10; -constexpr int kFs = 8000; constexpr int kFrameSizeMs = 20; -constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000; constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs; } // namespace @@ -41,25 +39,22 @@ class DelayManagerTest : public ::testing::Test { protected: DelayManagerTest(); virtual void SetUp(); - absl::optional InsertNextPacket(); + void Update(int delay); void IncreaseTime(int inc_ms); TickTimer tick_timer_; DelayManager dm_; - uint32_t ts_; }; DelayManagerTest::DelayManagerTest() - : dm_(DelayManager::Config(), &tick_timer_), ts_(0x12345678) {} + : dm_(DelayManager::Config(), &tick_timer_) {} void DelayManagerTest::SetUp() { dm_.SetPacketAudioLength(kFrameSizeMs); } -absl::optional DelayManagerTest::InsertNextPacket() { - auto relative_delay = dm_.Update(ts_, kFs); - ts_ += kTsIncrement; - return relative_delay; +void DelayManagerTest::Update(int delay) { + dm_.Update(delay, false); } void DelayManagerTest::IncreaseTime(int inc_ms) { @@ -75,28 +70,28 @@ TEST_F(DelayManagerTest, CreateAndDestroy) { TEST_F(DelayManagerTest, UpdateNormal) { for (int i = 0; i < 50; ++i) { - InsertNextPacket(); + Update(0); IncreaseTime(kFrameSizeMs); } EXPECT_EQ(20, dm_.TargetDelayMs()); } TEST_F(DelayManagerTest, MaxDelay) { - InsertNextPacket(); + Update(0); const int kMaxDelayMs = 60; EXPECT_GT(dm_.TargetDelayMs(), kMaxDelayMs); EXPECT_TRUE(dm_.SetMaximumDelay(kMaxDelayMs)); - InsertNextPacket(); + Update(0); EXPECT_EQ(kMaxDelayMs, dm_.TargetDelayMs()); } TEST_F(DelayManagerTest, MinDelay) { - InsertNextPacket(); + Update(0); int kMinDelayMs = 7 * kFrameSizeMs; EXPECT_LT(dm_.TargetDelayMs(), kMinDelayMs); dm_.SetMinimumDelay(kMinDelayMs); IncreaseTime(kFrameSizeMs); - InsertNextPacket(); + Update(0); EXPECT_EQ(kMinDelayMs, dm_.TargetDelayMs()); } @@ -220,7 +215,7 @@ TEST_F(DelayManagerTest, MinimumDelayMemorization) { TEST_F(DelayManagerTest, BaseMinimumDelay) { // First packet arrival. - InsertNextPacket(); + Update(0); constexpr int kBaseMinimumDelayMs = 7 * kFrameSizeMs; EXPECT_LT(dm_.TargetDelayMs(), kBaseMinimumDelayMs); @@ -228,14 +223,12 @@ TEST_F(DelayManagerTest, BaseMinimumDelay) { EXPECT_EQ(dm_.GetBaseMinimumDelay(), kBaseMinimumDelayMs); IncreaseTime(kFrameSizeMs); - InsertNextPacket(); + Update(0); EXPECT_EQ(dm_.GetBaseMinimumDelay(), kBaseMinimumDelayMs); EXPECT_EQ(kBaseMinimumDelayMs, dm_.TargetDelayMs()); } TEST_F(DelayManagerTest, Failures) { - // Wrong sample rate. - EXPECT_EQ(absl::nullopt, dm_.Update(0, -1)); // Wrong packet size. EXPECT_EQ(-1, dm_.SetPacketAudioLength(0)); EXPECT_EQ(-1, dm_.SetPacketAudioLength(-1)); @@ -250,13 +243,4 @@ TEST_F(DelayManagerTest, Failures) { EXPECT_FALSE(dm_.SetMaximumDelay(60)); } -TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) { - EXPECT_EQ(absl::nullopt, InsertNextPacket()); - IncreaseTime(kFrameSizeMs); - EXPECT_EQ(0, InsertNextPacket()); - IncreaseTime(2 * kFrameSizeMs); - - EXPECT_EQ(20, InsertNextPacket()); -} - } // namespace webrtc diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc index f387b15be6..43333c2891 100644 --- a/modules/audio_coding/neteq/neteq_unittest.cc +++ b/modules/audio_coding/neteq/neteq_unittest.cc @@ -57,10 +57,10 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) { webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); const std::string output_checksum = - "5e56fabfacd6fa202f3a00bcb4e034d6d817e6b3"; + "dee7a10ab92526876a70a85bc48a4906901af3df"; const std::string network_stats_checksum = - "dfbf60f913a25a1f2f1066f85b4b08c24eed0ef2"; + "911dbf5fd97f48d25b8f0967286eb73c9d6f6158"; DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum, absl::GetFlag(FLAGS_gen_ref)); diff --git a/modules/audio_coding/neteq/packet_arrival_history.cc b/modules/audio_coding/neteq/packet_arrival_history.cc index c579fe1061..7196a6e393 100644 --- a/modules/audio_coding/neteq/packet_arrival_history.cc +++ b/modules/audio_coding/neteq/packet_arrival_history.cc @@ -23,12 +23,16 @@ PacketArrivalHistory::PacketArrivalHistory(int window_size_ms) void PacketArrivalHistory::Insert(uint32_t rtp_timestamp, int64_t arrival_time_ms) { RTC_DCHECK(sample_rate_khz_ > 0); - int64_t unwrapped_rtp_timestamp_ms = - timestamp_unwrapper_.Unwrap(rtp_timestamp) / sample_rate_khz_; - history_.emplace_back(unwrapped_rtp_timestamp_ms, arrival_time_ms); + int64_t unwrapped_rtp_timestamp = timestamp_unwrapper_.Unwrap(rtp_timestamp); + if (!newest_rtp_timestamp_ || + unwrapped_rtp_timestamp > *newest_rtp_timestamp_) { + newest_rtp_timestamp_ = unwrapped_rtp_timestamp; + } + history_.emplace_back(unwrapped_rtp_timestamp / sample_rate_khz_, + arrival_time_ms); MaybeUpdateCachedArrivals(history_.back()); while (history_.front().rtp_timestamp_ms + window_size_ms_ < - unwrapped_rtp_timestamp_ms) { + unwrapped_rtp_timestamp / sample_rate_khz_) { if (&history_.front() == min_packet_arrival_) { min_packet_arrival_ = nullptr; } @@ -59,6 +63,7 @@ void PacketArrivalHistory::Reset() { min_packet_arrival_ = nullptr; max_packet_arrival_ = nullptr; timestamp_unwrapper_ = TimestampUnwrapper(); + newest_rtp_timestamp_ = absl::nullopt; } int PacketArrivalHistory::GetDelayMs(uint32_t rtp_timestamp, @@ -78,6 +83,15 @@ int PacketArrivalHistory::GetMaxDelayMs() const { return GetPacketArrivalDelayMs(*max_packet_arrival_); } +bool PacketArrivalHistory::IsNewestRtpTimestamp(uint32_t rtp_timestamp) const { + if (!newest_rtp_timestamp_) { + return false; + } + int64_t unwrapped_rtp_timestamp = + timestamp_unwrapper_.UnwrapWithoutUpdate(rtp_timestamp); + return unwrapped_rtp_timestamp == *newest_rtp_timestamp_; +} + int PacketArrivalHistory::GetPacketArrivalDelayMs( const PacketArrival& packet_arrival) const { if (!min_packet_arrival_) { diff --git a/modules/audio_coding/neteq/packet_arrival_history.h b/modules/audio_coding/neteq/packet_arrival_history.h index 29e257d256..79fc9176bc 100644 --- a/modules/audio_coding/neteq/packet_arrival_history.h +++ b/modules/audio_coding/neteq/packet_arrival_history.h @@ -13,8 +13,8 @@ #include #include -#include +#include "absl/types/optional.h" #include "api/neteq/tick_timer.h" #include "modules/include/module_common_types_public.h" @@ -34,17 +34,21 @@ class PacketArrivalHistory { // `(time_ms - p.arrival_time_ms) - (rtp_timestamp - p.rtp_timestamp)` // where `p` is chosen as the packet arrival in the history that maximizes the // delay. - int GetDelayMs(uint32_t rtp_timestamp, int64_t times_ms) const; + int GetDelayMs(uint32_t rtp_timestamp, int64_t time_ms) const; // Get the maximum packet arrival delay observed in the history. int GetMaxDelayMs() const; + bool IsNewestRtpTimestamp(uint32_t rtp_timestamp) const; + void Reset(); void set_sample_rate(int sample_rate) { sample_rate_khz_ = sample_rate / 1000; } + size_t size() const { return history_.size(); } + private: struct PacketArrival { PacketArrival(int64_t rtp_timestamp_ms, int64_t arrival_time_ms) @@ -69,6 +73,7 @@ class PacketArrivalHistory { const PacketArrival* max_packet_arrival_ = nullptr; const int window_size_ms_; TimestampUnwrapper timestamp_unwrapper_; + absl::optional newest_rtp_timestamp_; int sample_rate_khz_ = 0; }; diff --git a/modules/audio_coding/neteq/packet_arrival_history_unittest.cc b/modules/audio_coding/neteq/packet_arrival_history_unittest.cc index 4d61de70ce..286a7acb2c 100644 --- a/modules/audio_coding/neteq/packet_arrival_history_unittest.cc +++ b/modules/audio_coding/neteq/packet_arrival_history_unittest.cc @@ -35,6 +35,8 @@ class PacketArrivalHistoryTest : public testing::Test { timestamp_ = timestamp; } history_.Insert(timestamp, time_ms_); + EXPECT_EQ(history_.IsNewestRtpTimestamp(timestamp), + timestamp_delta_ms >= 0); return history_.GetDelayMs(timestamp, time_ms_); } diff --git a/modules/audio_coding/neteq/relative_arrival_delay_tracker.cc b/modules/audio_coding/neteq/relative_arrival_delay_tracker.cc deleted file mode 100644 index b50ac80bab..0000000000 --- a/modules/audio_coding/neteq/relative_arrival_delay_tracker.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_coding/neteq/relative_arrival_delay_tracker.h" - -#include - -#include "modules/include/module_common_types_public.h" - -namespace webrtc { - -absl::optional RelativeArrivalDelayTracker::Update(uint32_t timestamp, - int sample_rate_hz) { - if (sample_rate_hz <= 0) { - return absl::nullopt; - } - if (!last_timestamp_) { - // Restart relative delay esimation from this packet. - delay_history_.clear(); - packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); - newest_timestamp_ = timestamp; - last_timestamp_ = timestamp; - return absl::nullopt; - } - - const int expected_iat_ms = - 1000ll * static_cast(timestamp - *last_timestamp_) / - sample_rate_hz; - const int iat_ms = packet_iat_stopwatch_->ElapsedMs(); - const int iat_delay_ms = iat_ms - expected_iat_ms; - UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz); - int relative_delay = CalculateRelativePacketArrivalDelay(); - - packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch(); - last_timestamp_ = timestamp; - if (IsNewerTimestamp(timestamp, *newest_timestamp_)) { - newest_timestamp_ = timestamp; - } - - return relative_delay; -} - -void RelativeArrivalDelayTracker::Reset() { - delay_history_.clear(); - packet_iat_stopwatch_.reset(); - newest_timestamp_ = absl::nullopt; - last_timestamp_ = absl::nullopt; -} - -void RelativeArrivalDelayTracker::UpdateDelayHistory(int iat_delay_ms, - uint32_t timestamp, - int sample_rate_hz) { - PacketDelay delay; - delay.iat_delay_ms = iat_delay_ms; - delay.timestamp = timestamp; - delay_history_.push_back(delay); - while (static_cast(timestamp - delay_history_.front().timestamp) > - max_history_ms_ * sample_rate_hz / 1000) { - delay_history_.pop_front(); - } -} - -int RelativeArrivalDelayTracker::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 (const PacketDelay& delay : delay_history_) { - relative_delay += delay.iat_delay_ms; - relative_delay = std::max(relative_delay, 0); - } - return relative_delay; -} - -} // namespace webrtc diff --git a/modules/audio_coding/neteq/relative_arrival_delay_tracker.h b/modules/audio_coding/neteq/relative_arrival_delay_tracker.h deleted file mode 100644 index fed56be2b6..0000000000 --- a/modules/audio_coding/neteq/relative_arrival_delay_tracker.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_CODING_NETEQ_RELATIVE_ARRIVAL_DELAY_TRACKER_H_ -#define MODULES_AUDIO_CODING_NETEQ_RELATIVE_ARRIVAL_DELAY_TRACKER_H_ - -#include -#include - -#include "absl/types/optional.h" -#include "api/neteq/tick_timer.h" - -namespace webrtc { - -class RelativeArrivalDelayTracker { - public: - RelativeArrivalDelayTracker(const TickTimer* tick_timer, int max_history_ms) - : tick_timer_(tick_timer), max_history_ms_(max_history_ms) {} - - absl::optional Update(uint32_t timestamp, int sample_rate_hz); - - void Reset(); - - absl::optional newest_timestamp() const { - return newest_timestamp_; - } - - private: - // Updates `delay_history_`. - void UpdateDelayHistory(int iat_delay_ms, - uint32_t timestamp, - int sample_rate_hz); - - // Calculate relative packet arrival delay from `delay_history_`. - int CalculateRelativePacketArrivalDelay() const; - - const TickTimer* tick_timer_; - const int max_history_ms_; - - struct PacketDelay { - int iat_delay_ms; - uint32_t timestamp; - }; - std::deque delay_history_; - - absl::optional newest_timestamp_; - absl::optional last_timestamp_; - - std::unique_ptr - packet_iat_stopwatch_; // Time elapsed since last packet. -}; - -} // namespace webrtc -#endif // MODULES_AUDIO_CODING_NETEQ_RELATIVE_ARRIVAL_DELAY_TRACKER_H_ diff --git a/modules/audio_coding/neteq/relative_arrival_delay_tracker_unittest.cc b/modules/audio_coding/neteq/relative_arrival_delay_tracker_unittest.cc deleted file mode 100644 index b4e9456e62..0000000000 --- a/modules/audio_coding/neteq/relative_arrival_delay_tracker_unittest.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_coding/neteq/relative_arrival_delay_tracker.h" - -#include "test/gtest.h" - -namespace webrtc { - -namespace { -constexpr int kMaxHistoryMs = 2000; -constexpr int kFs = 8000; -constexpr int kFrameSizeMs = 20; -constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000; -constexpr uint32_t kTs = 0x12345678; -} // namespace - -TEST(RelativeArrivalDelayTrackerTest, RelativeArrivalDelay) { - TickTimer tick_timer; - RelativeArrivalDelayTracker tracker(&tick_timer, kMaxHistoryMs); - - EXPECT_FALSE(tracker.Update(kTs, kFs)); - - tick_timer.Increment(kFrameSizeMs / tick_timer.ms_per_tick()); - EXPECT_EQ(tracker.Update(kTs + kTsIncrement, kFs), 0); - - tick_timer.Increment(2 * kFrameSizeMs / tick_timer.ms_per_tick()); - EXPECT_EQ(tracker.Update(kTs + 2 * kTsIncrement, kFs), 20); - - EXPECT_EQ(tracker.Update(kTs, kFs), 60); // Reordered, 60ms delayed. - - tick_timer.Increment(2 * kFrameSizeMs / tick_timer.ms_per_tick()); - EXPECT_EQ(tracker.Update(kTs + 3 * kTsIncrement, kFs), 40); -} - -TEST(RelativeArrivalDelayTrackerTest, ReorderedPackets) { - TickTimer tick_timer; - RelativeArrivalDelayTracker tracker(&tick_timer, kMaxHistoryMs); - - // Insert first packet. - EXPECT_FALSE(tracker.Update(kTs, kFs)); - - // Insert reordered packet. - EXPECT_EQ(tracker.Update(kTs - 4 * kTsIncrement, kFs), 80); - EXPECT_EQ(tracker.newest_timestamp(), kTs); - - // Insert another reordered packet. - EXPECT_EQ(tracker.Update(kTs - kTsIncrement, kFs), 20); - EXPECT_EQ(tracker.newest_timestamp(), kTs); - - // Insert the next packet in order and verify that the relative delay is - // estimated based on the first inserted packet. - tick_timer.Increment(4 * kFrameSizeMs / tick_timer.ms_per_tick()); - EXPECT_EQ(tracker.Update(kTs + kTsIncrement, kFs), 60); - EXPECT_EQ(tracker.newest_timestamp(), kTs + kTsIncrement); -} - -TEST(RelativeArrivalDelayTrackerTest, MaxDelayHistory) { - TickTimer tick_timer; - RelativeArrivalDelayTracker tracker(&tick_timer, kMaxHistoryMs); - - EXPECT_FALSE(tracker.Update(kTs, kFs)); - - // Insert 20 ms iat delay in the delay history. - tick_timer.Increment(2 * kFrameSizeMs / tick_timer.ms_per_tick()); - EXPECT_EQ(tracker.Update(kTs + kTsIncrement, kFs), 20); - - // Insert next packet with a timestamp difference larger than maximum history - // size. This removes the previously inserted iat delay from the history. - tick_timer.Increment((kMaxHistoryMs + kFrameSizeMs) / - tick_timer.ms_per_tick()); - EXPECT_EQ( - tracker.Update(kTs + 2 * kTsIncrement + kFs * kMaxHistoryMs / 1000, kFs), - 0); -} - -} // namespace webrtc