Source code
Revision control
Copy as Markdown
Other Tools
/*
* Copyright (c) 2022 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/packet_arrival_history.h"
#include <cstdint>
#include <limits>
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr int kFs = 8000;
constexpr int kFsKhz = kFs / 1000;
constexpr int kFrameSizeMs = 20;
constexpr int kFrameSizeSamples = kFrameSizeMs * kFsKhz;
constexpr int kWindowSizeMs = 1000;
class PacketArrivalHistoryTest : public testing::Test {
public:
PacketArrivalHistoryTest() : history_(&tick_timer_, kWindowSizeMs) {
history_.set_sample_rate(kFs);
}
void IncrementTime(int delta_ms) {
tick_timer_.Increment(delta_ms / tick_timer_.ms_per_tick());
}
int InsertPacketAndGetDelay(int timestamp_delta_ms) {
uint32_t timestamp = timestamp_ + timestamp_delta_ms * kFsKhz;
if (timestamp_delta_ms > 0) {
timestamp_ = timestamp;
}
EXPECT_TRUE(history_.Insert(timestamp, kFrameSizeSamples));
EXPECT_EQ(history_.IsNewestRtpTimestamp(timestamp),
timestamp_delta_ms >= 0);
return history_.GetDelayMs(timestamp);
}
protected:
TickTimer tick_timer_;
PacketArrivalHistory history_;
uint32_t timestamp_ = 0x12345678;
};
TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
// Insert first packet.
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
IncrementTime(kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
IncrementTime(2 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
// Reordered packet.
EXPECT_EQ(InsertPacketAndGetDelay(-3 * kFrameSizeMs), 80);
IncrementTime(2 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 40);
// Move reference packet forward.
EXPECT_EQ(InsertPacketAndGetDelay(4 * kFrameSizeMs), 0);
IncrementTime(2 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
// Earlier packet is now more delayed due to the new reference packet.
EXPECT_EQ(history_.GetMaxDelayMs(), 80);
}
TEST_F(PacketArrivalHistoryTest, ReorderedPackets) {
// Insert first packet.
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
// Insert reordered packet.
EXPECT_EQ(InsertPacketAndGetDelay(-80), 80);
// Insert another reordered packet.
EXPECT_EQ(InsertPacketAndGetDelay(-kFrameSizeMs), 20);
// Insert the next packet in order and verify that the relative delay is
// estimated based on the first inserted packet.
IncrementTime(4 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 60);
EXPECT_EQ(history_.GetMaxDelayMs(), 60);
}
TEST_F(PacketArrivalHistoryTest, MaxHistorySize) {
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
IncrementTime(2 * kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
EXPECT_EQ(history_.GetMaxDelayMs(), 20);
// Insert next packet with a timestamp difference larger than maximum history
// size. This removes the previously inserted packet from the history.
IncrementTime(kWindowSizeMs + kFrameSizeMs);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs + kWindowSizeMs), 0);
EXPECT_EQ(history_.GetMaxDelayMs(), 0);
}
TEST_F(PacketArrivalHistoryTest, TimestampWraparound) {
timestamp_ = std::numeric_limits<uint32_t>::max();
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
IncrementTime(2 * kFrameSizeMs);
// Insert timestamp that will wrap around.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), kFrameSizeMs);
// Insert reordered packet before the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(-2 * kFrameSizeMs), 3 * kFrameSizeMs);
// Insert another in-order packet after the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
EXPECT_EQ(history_.GetMaxDelayMs(), kFrameSizeMs);
}
TEST_F(PacketArrivalHistoryTest, TimestampWraparoundBackwards) {
timestamp_ = 0;
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
IncrementTime(2 * kFrameSizeMs);
// Insert timestamp that will wrap around.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), kFrameSizeMs);
// Insert reordered packet before the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(-2 * kFrameSizeMs), 3 * kFrameSizeMs);
// Insert another in-order packet after the wraparound.
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
EXPECT_EQ(history_.GetMaxDelayMs(), kFrameSizeMs);
}
TEST_F(PacketArrivalHistoryTest, OldPacketShouldNotBeInserted) {
// Insert first packet as reference.
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
// Insert packet with timestamp older than the window size compared to the
// first packet.
EXPECT_FALSE(history_.Insert(timestamp_ - kWindowSizeMs * kFsKhz - 1,
kFrameSizeSamples));
}
TEST_F(PacketArrivalHistoryTest, DuplicatePacketShouldNotBeInserted) {
// Insert first packet as reference.
uint32_t first_timestamp = timestamp_;
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
// Same timestamp as the first packet.
EXPECT_FALSE(history_.Insert(first_timestamp, kFrameSizeSamples));
}
TEST_F(PacketArrivalHistoryTest, OverlappingPacketShouldNotBeInserted) {
// Insert first packet as reference.
EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
// 10 ms overlap with the previous packet.
EXPECT_FALSE(history_.Insert(timestamp_ + kFrameSizeSamples / 2,
kFrameSizeSamples / 2));
}
} // namespace
} // namespace webrtc