Use packet arrival history in delay manager.

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‎ <jakobi@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37004}
This commit is contained in:
Jakob Ivarsson
2022-05-25 21:06:14 +02:00
committed by WebRTC LUCI CQ
parent c1fb359b2a
commit 01ab7d501b
13 changed files with 62 additions and 313 deletions

View File

@ -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",

View File

@ -12,6 +12,7 @@
#include <stdio.h>
#include <cstdint>
#include <memory>
#include <string>
@ -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<int> 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<int> 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) {

View File

@ -191,7 +191,6 @@ class DecisionLogic : public NetEqController {
std::unique_ptr<TickTimer::Countdown> 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;
};

View File

@ -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<int> DelayManager::Update(uint32_t timestamp,
int sample_rate_hz,
bool reset) {
if (reset) {
relative_arrival_delay_tracker_.Reset();
}
absl::optional<int> 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<int> 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();

View File

@ -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<double> start_forget_weight = 2;
absl::optional<int> 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<int> 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<ReorderOptimizer> reorder_optimizer_;
RelativeArrivalDelayTracker relative_arrival_delay_tracker_;
int base_minimum_delay_ms_;
int effective_minimum_delay_ms_; // Used as lower bound for target delay.

View File

@ -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<int> 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<int> 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

View File

@ -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));

View File

@ -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_) {

View File

@ -13,8 +13,8 @@
#include <cstdint>
#include <deque>
#include <memory>
#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<int64_t> newest_rtp_timestamp_;
int sample_rate_khz_ = 0;
};

View File

@ -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_);
}

View File

@ -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 <algorithm>
#include "modules/include/module_common_types_public.h"
namespace webrtc {
absl::optional<int> 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<int32_t>(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<int32_t>(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

View File

@ -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 <deque>
#include <memory>
#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<int> Update(uint32_t timestamp, int sample_rate_hz);
void Reset();
absl::optional<uint32_t> 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<PacketDelay> delay_history_;
absl::optional<uint32_t> newest_timestamp_;
absl::optional<uint32_t> last_timestamp_;
std::unique_ptr<TickTimer::Stopwatch>
packet_iat_stopwatch_; // Time elapsed since last packet.
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_RELATIVE_ARRIVAL_DELAY_TRACKER_H_

View File

@ -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