1 /*
2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/audio_coding/neteq/packet_arrival_history.h"
12
13 #include <cstdint>
14 #include <limits>
15
16 #include "test/gtest.h"
17
18 namespace webrtc {
19 namespace {
20
21 constexpr int kFs = 8000;
22 constexpr int kFsKhz = kFs / 1000;
23 constexpr int kFrameSizeMs = 20;
24 constexpr int kWindowSizeMs = 1000;
25
26 class PacketArrivalHistoryTest : public testing::Test {
27 public:
PacketArrivalHistoryTest()28 PacketArrivalHistoryTest() : history_(kWindowSizeMs) {
29 history_.set_sample_rate(kFs);
30 }
IncrementTime(int delta_ms)31 void IncrementTime(int delta_ms) { time_ms_ += delta_ms; }
InsertPacketAndGetDelay(int timestamp_delta_ms)32 int InsertPacketAndGetDelay(int timestamp_delta_ms) {
33 uint32_t timestamp = timestamp_ + timestamp_delta_ms * kFsKhz;
34 if (timestamp_delta_ms > 0) {
35 timestamp_ = timestamp;
36 }
37 history_.Insert(timestamp, time_ms_);
38 EXPECT_EQ(history_.IsNewestRtpTimestamp(timestamp),
39 timestamp_delta_ms >= 0);
40 return history_.GetDelayMs(timestamp, time_ms_);
41 }
42
43 protected:
44 int64_t time_ms_ = 0;
45 PacketArrivalHistory history_;
46 uint32_t timestamp_ = 0x12345678;
47 };
48
TEST_F(PacketArrivalHistoryTest,RelativeArrivalDelay)49 TEST_F(PacketArrivalHistoryTest, RelativeArrivalDelay) {
50 EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
51
52 IncrementTime(kFrameSizeMs);
53 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
54
55 IncrementTime(2 * kFrameSizeMs);
56 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
57
58 // Reordered packet.
59 EXPECT_EQ(InsertPacketAndGetDelay(-2 * kFrameSizeMs), 60);
60
61 IncrementTime(2 * kFrameSizeMs);
62 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 40);
63
64 // Move reference packet forward.
65 EXPECT_EQ(InsertPacketAndGetDelay(4 * kFrameSizeMs), 0);
66
67 IncrementTime(2 * kFrameSizeMs);
68 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
69
70 // Earlier packet is now more delayed due to the new reference packet.
71 EXPECT_EQ(history_.GetMaxDelayMs(), 100);
72 }
73
TEST_F(PacketArrivalHistoryTest,ReorderedPackets)74 TEST_F(PacketArrivalHistoryTest, ReorderedPackets) {
75 // Insert first packet.
76 EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
77
78 // Insert reordered packet.
79 EXPECT_EQ(InsertPacketAndGetDelay(-80), 80);
80
81 // Insert another reordered packet.
82 EXPECT_EQ(InsertPacketAndGetDelay(-kFrameSizeMs), 20);
83
84 // Insert the next packet in order and verify that the relative delay is
85 // estimated based on the first inserted packet.
86 IncrementTime(4 * kFrameSizeMs);
87 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 60);
88
89 EXPECT_EQ(history_.GetMaxDelayMs(), 80);
90 }
91
TEST_F(PacketArrivalHistoryTest,MaxHistorySize)92 TEST_F(PacketArrivalHistoryTest, MaxHistorySize) {
93 EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
94
95 IncrementTime(2 * kFrameSizeMs);
96 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 20);
97 EXPECT_EQ(history_.GetMaxDelayMs(), 20);
98
99 // Insert next packet with a timestamp difference larger than maximum history
100 // size. This removes the previously inserted packet from the history.
101 IncrementTime(kWindowSizeMs + kFrameSizeMs);
102 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs + kWindowSizeMs), 0);
103 EXPECT_EQ(history_.GetMaxDelayMs(), 0);
104 }
105
TEST_F(PacketArrivalHistoryTest,TimestampWraparound)106 TEST_F(PacketArrivalHistoryTest, TimestampWraparound) {
107 timestamp_ = std::numeric_limits<uint32_t>::max();
108 EXPECT_EQ(InsertPacketAndGetDelay(0), 0);
109
110 IncrementTime(2 * kFrameSizeMs);
111 // Insert timestamp that will wrap around.
112 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), kFrameSizeMs);
113
114 // Insert reordered packet before the wraparound.
115 EXPECT_EQ(InsertPacketAndGetDelay(-2 * kFrameSizeMs), 3 * kFrameSizeMs);
116
117 // Insert another in-order packet after the wraparound.
118 EXPECT_EQ(InsertPacketAndGetDelay(kFrameSizeMs), 0);
119
120 EXPECT_EQ(history_.GetMaxDelayMs(), 3 * kFrameSizeMs);
121 }
122
123 } // namespace
124 } // namespace webrtc
125