blob: 539a318fe1b2d636f7626cdcf53cd4e950758895 [file] [log] [blame]
/*
* 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 kWindowSizeMs = 1000;
class PacketArrivalHistoryTest : public testing::Test {
public:
PacketArrivalHistoryTest() : history_(kWindowSizeMs) {
history_.set_sample_rate(kFs);
}
void IncrementTime(int delta_ms) { time_ms_ += delta_ms; }
int InsertPacketAndGetDelay(int timestamp_delta_ms) {
uint32_t timestamp = timestamp_ + timestamp_delta_ms * kFsKhz;
if (timestamp_delta_ms > 0) {
timestamp_ = timestamp;
}
history_.Insert(timestamp, time_ms_);
EXPECT_EQ(history_.IsNewestRtpTimestamp(timestamp),
timestamp_delta_ms >= 0);
return history_.GetDelayMs(timestamp, time_ms_);
}
protected:
int64_t time_ms_ = 0;
PacketArrivalHistory history_;
uint32_t timestamp_ = 0x12345678;
};
TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
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(-2 * kFrameSizeMs), 60);
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(), 100);
}
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(), 80);
}
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(), 3 * 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(), 3 * kFrameSizeMs);
}
} // namespace
} // namespace webrtc