blob: a3d1800a707e2c1342373e7c0160a39a3a478bde [file] [log] [blame]
turaj@webrtc.org7959e162013-09-12 18:30:26 +00001/*
2 * Copyright (c) 2013 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/nack_tracker.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000012
13#include <stdint.h>
14
15#include <algorithm>
kwiberg2d0c3322016-02-14 09:28:33 -080016#include <memory>
turaj@webrtc.org7959e162013-09-12 18:30:26 +000017
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
19#include "test/gtest.h"
20#include "typedefs.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000021
22namespace webrtc {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000023namespace {
24
25const int kNackThreshold = 3;
26const int kSampleRateHz = 16000;
27const int kPacketSizeMs = 30;
28const uint32_t kTimestampIncrement = 480; // 30 ms.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000029const int64_t kShortRoundTripTimeMs = 1;
turaj@webrtc.org7959e162013-09-12 18:30:26 +000030
31bool IsNackListCorrect(const std::vector<uint16_t>& nack_list,
32 const uint16_t* lost_sequence_numbers,
33 size_t num_lost_packets) {
34 if (nack_list.size() != num_lost_packets)
35 return false;
36
37 if (num_lost_packets == 0)
38 return true;
39
40 for (size_t k = 0; k < nack_list.size(); ++k) {
41 int seq_num = nack_list[k];
42 bool seq_num_matched = false;
43 for (size_t n = 0; n < num_lost_packets; ++n) {
44 if (seq_num == lost_sequence_numbers[n]) {
45 seq_num_matched = true;
46 break;
47 }
48 }
49 if (!seq_num_matched)
50 return false;
51 }
52 return true;
53}
54
55} // namespace
56
henrik.lundin91951862016-06-08 06:43:41 -070057TEST(NackTrackerTest, EmptyListWhenNoPacketLoss) {
58 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +000059 nack->UpdateSampleRate(kSampleRateHz);
60
61 int seq_num = 1;
62 uint32_t timestamp = 0;
63
64 std::vector<uint16_t> nack_list;
65 for (int n = 0; n < 100; n++) {
66 nack->UpdateLastReceivedPacket(seq_num, timestamp);
67 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
68 seq_num++;
69 timestamp += kTimestampIncrement;
70 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
71 EXPECT_TRUE(nack_list.empty());
72 }
73}
74
henrik.lundin91951862016-06-08 06:43:41 -070075TEST(NackTrackerTest, NoNackIfReorderWithinNackThreshold) {
76 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +000077 nack->UpdateSampleRate(kSampleRateHz);
78
79 int seq_num = 1;
80 uint32_t timestamp = 0;
81 std::vector<uint16_t> nack_list;
82
83 nack->UpdateLastReceivedPacket(seq_num, timestamp);
84 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
85 EXPECT_TRUE(nack_list.empty());
86 int num_late_packets = kNackThreshold + 1;
87
88 // Push in reverse order
89 while (num_late_packets > 0) {
henrik.lundin48ed9302015-10-29 05:36:24 -070090 nack->UpdateLastReceivedPacket(
91 seq_num + num_late_packets,
92 timestamp + num_late_packets * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000093 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
94 EXPECT_TRUE(nack_list.empty());
95 num_late_packets--;
96 }
97}
98
henrik.lundin91951862016-06-08 06:43:41 -070099TEST(NackTrackerTest, LatePacketsMovedToNackThenNackListDoesNotChange) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700100 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000101 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
henrik.lundin48ed9302015-10-29 05:36:24 -0700102 sizeof(kSequenceNumberLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000103
104 for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700105 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000106 nack->UpdateSampleRate(kSampleRateHz);
107
108 uint16_t sequence_num_lost_packets[kNumAllLostPackets];
109 for (int n = 0; n < kNumAllLostPackets; n++) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700110 sequence_num_lost_packets[n] =
111 kSequenceNumberLostPackets[n] +
112 k * 65531; // Have wrap around in sequence numbers for |k == 1|.
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000113 }
114 uint16_t seq_num = sequence_num_lost_packets[0] - 1;
115
116 uint32_t timestamp = 0;
117 std::vector<uint16_t> nack_list;
118
119 nack->UpdateLastReceivedPacket(seq_num, timestamp);
120 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
121 EXPECT_TRUE(nack_list.empty());
122
123 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
124 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
125 int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
126
127 for (int n = 0; n < kNackThreshold + 1; ++n) {
128 nack->UpdateLastReceivedPacket(seq_num, timestamp);
129 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
130 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
131 num_lost_packets));
132 seq_num++;
133 timestamp += kTimestampIncrement;
134 num_lost_packets++;
135 }
136
137 for (int n = 0; n < 100; ++n) {
138 nack->UpdateLastReceivedPacket(seq_num, timestamp);
139 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
140 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
141 kNumAllLostPackets));
142 seq_num++;
143 timestamp += kTimestampIncrement;
144 }
145 }
146}
147
henrik.lundin91951862016-06-08 06:43:41 -0700148TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700149 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000150 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
henrik.lundin48ed9302015-10-29 05:36:24 -0700151 sizeof(kSequenceNumberLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000152
153 for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700154 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000155 nack->UpdateSampleRate(kSampleRateHz);
156
157 uint16_t sequence_num_lost_packets[kNumAllLostPackets];
158 for (int n = 0; n < kNumAllLostPackets; ++n) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700159 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] +
160 k * 65531; // Wrap around for |k == 1|.
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000161 }
162
163 uint16_t seq_num = sequence_num_lost_packets[0] - 1;
164 uint32_t timestamp = 0;
165
166 nack->UpdateLastReceivedPacket(seq_num, timestamp);
167 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
168 EXPECT_TRUE(nack_list.empty());
169
170 size_t index_retransmitted_rtp = 0;
171 uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement;
172
173 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
174 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
175 size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
176 for (int n = 0; n < kNumAllLostPackets; ++n) {
177 // Number of lost packets does not change for the first
178 // |kNackThreshold + 1| packets, one is added to the list and one is
179 // removed. Thereafter, the list shrinks every iteration.
180 if (n >= kNackThreshold + 1)
181 num_lost_packets--;
182
183 nack->UpdateLastReceivedPacket(seq_num, timestamp);
184 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
185 EXPECT_TRUE(IsNackListCorrect(
186 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
187 num_lost_packets));
188 seq_num++;
189 timestamp += kTimestampIncrement;
190
191 // Retransmission of a lost RTP.
192 nack->UpdateLastReceivedPacket(
193 sequence_num_lost_packets[index_retransmitted_rtp],
194 timestamp_retransmitted_rtp);
195 index_retransmitted_rtp++;
196 timestamp_retransmitted_rtp += kTimestampIncrement;
197
198 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
199 EXPECT_TRUE(IsNackListCorrect(
200 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
201 num_lost_packets - 1)); // One less lost packet in the list.
202 }
203 ASSERT_TRUE(nack_list.empty());
204 }
205}
206
207// Assess if estimation of timestamps and time-to-play is correct. Introduce all
208// combinations that timestamps and sequence numbers might have wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700209TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700210 const uint16_t kLostPackets[] = {2, 3, 4, 5, 6, 7, 8,
211 9, 10, 11, 12, 13, 14, 15};
212 static const int kNumAllLostPackets =
213 sizeof(kLostPackets) / sizeof(kLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000214
215 for (int k = 0; k < 4; ++k) {
henrik.lundin91951862016-06-08 06:43:41 -0700216 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000217 nack->UpdateSampleRate(kSampleRateHz);
218
219 // Sequence number wrap around if |k| is 2 or 3;
220 int seq_num_offset = (k < 2) ? 0 : 65531;
221
222 // Timestamp wrap around if |k| is 1 or 3.
henrik.lundin48ed9302015-10-29 05:36:24 -0700223 uint32_t timestamp_offset =
224 (k & 0x1) ? static_cast<uint32_t>(0xffffffff) - 6 : 0;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000225
226 uint32_t timestamp_lost_packets[kNumAllLostPackets];
227 uint16_t seq_num_lost_packets[kNumAllLostPackets];
228 for (int n = 0; n < kNumAllLostPackets; ++n) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700229 timestamp_lost_packets[n] =
230 timestamp_offset + kLostPackets[n] * kTimestampIncrement;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000231 seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n];
232 }
233
234 // We and to push two packets before lost burst starts.
235 uint16_t seq_num = seq_num_lost_packets[0] - 2;
236 uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement;
237
238 const uint16_t first_seq_num = seq_num;
239 const uint32_t first_timestamp = timestamp;
240
241 // Two consecutive packets to have a correct estimate of timestamp increase.
242 nack->UpdateLastReceivedPacket(seq_num, timestamp);
243 seq_num++;
244 timestamp += kTimestampIncrement;
245 nack->UpdateLastReceivedPacket(seq_num, timestamp);
246
247 // A packet after the last one which is supposed to be lost.
248 seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1;
henrik.lundin48ed9302015-10-29 05:36:24 -0700249 timestamp =
250 timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000251 nack->UpdateLastReceivedPacket(seq_num, timestamp);
252
henrik.lundin91951862016-06-08 06:43:41 -0700253 NackTracker::NackList nack_list = nack->GetNackList();
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000254 EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size());
255
256 // Pretend the first packet is decoded.
257 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
258 nack_list = nack->GetNackList();
259
henrik.lundin91951862016-06-08 06:43:41 -0700260 NackTracker::NackList::iterator it = nack_list.begin();
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000261 while (it != nack_list.end()) {
262 seq_num = it->first - seq_num_offset;
263 int index = seq_num - kLostPackets[0];
264 EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp);
265 EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms);
266 ++it;
267 }
268
269 // Pretend 10 ms is passed, and we had pulled audio from NetEq, it still
270 // reports the same sequence number as decoded, time-to-play should be
271 // updated by 10 ms.
272 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
273 nack_list = nack->GetNackList();
274 it = nack_list.begin();
275 while (it != nack_list.end()) {
276 seq_num = it->first - seq_num_offset;
277 int index = seq_num - kLostPackets[0];
278 EXPECT_EQ((index + 2) * kPacketSizeMs - 10, it->second.time_to_play_ms);
279 ++it;
280 }
281 }
282}
283
henrik.lundin91951862016-06-08 06:43:41 -0700284TEST(NackTrackerTest,
285 MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000286 for (int m = 0; m < 2; ++m) {
287 uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700288 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000289 nack->UpdateSampleRate(kSampleRateHz);
290
291 // Two consecutive packets to have a correct estimate of timestamp increase.
292 uint16_t seq_num = 0;
293 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700294 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000295 seq_num++;
296 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700297 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000298
299 // Skip 10 packets (larger than NACK threshold).
300 const int kNumLostPackets = 10;
301 seq_num += kNumLostPackets + 1;
302 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700303 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000304
305 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
306 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
307 EXPECT_EQ(kExpectedListSize, nack_list.size());
308
309 for (int k = 0; k < 2; ++k) {
310 // Decoding of the first and the second arrived packets.
311 for (int n = 0; n < kPacketSizeMs / 10; ++n) {
312 nack->UpdateLastDecodedPacket(seq_num_offset + k,
313 k * kTimestampIncrement);
314 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
315 EXPECT_EQ(kExpectedListSize, nack_list.size());
316 }
317 }
318
319 // Decoding of the last received packet.
320 nack->UpdateLastDecodedPacket(seq_num + seq_num_offset,
henrik.lundin48ed9302015-10-29 05:36:24 -0700321 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000322 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
323 EXPECT_TRUE(nack_list.empty());
324
325 // Make sure list of late packets is also empty. To check that, push few
326 // packets, if the late list is not empty its content will pop up in NACK
327 // list.
328 for (int n = 0; n < kNackThreshold + 10; ++n) {
329 seq_num++;
330 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700331 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000332 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
333 EXPECT_TRUE(nack_list.empty());
334 }
335 }
336}
337
henrik.lundin91951862016-06-08 06:43:41 -0700338TEST(NackTrackerTest, Reset) {
339 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000340 nack->UpdateSampleRate(kSampleRateHz);
341
342 // Two consecutive packets to have a correct estimate of timestamp increase.
343 uint16_t seq_num = 0;
344 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
345 seq_num++;
346 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
347
348 // Skip 10 packets (larger than NACK threshold).
349 const int kNumLostPackets = 10;
350 seq_num += kNumLostPackets + 1;
351 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
352
353 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
354 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
355 EXPECT_EQ(kExpectedListSize, nack_list.size());
356
357 nack->Reset();
358 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
359 EXPECT_TRUE(nack_list.empty());
360}
361
henrik.lundin91951862016-06-08 06:43:41 -0700362TEST(NackTrackerTest, ListSizeAppliedFromBeginning) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000363 const size_t kNackListSize = 10;
364 for (int m = 0; m < 2; ++m) {
365 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700366 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000367 nack->UpdateSampleRate(kSampleRateHz);
368 nack->SetMaxNackListSize(kNackListSize);
369
370 uint16_t seq_num = seq_num_offset;
371 uint32_t timestamp = 0x12345678;
372 nack->UpdateLastReceivedPacket(seq_num, timestamp);
373
374 // Packet lost more than NACK-list size limit.
375 uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
376
377 seq_num += num_lost_packets + 1;
378 timestamp += (num_lost_packets + 1) * kTimestampIncrement;
379 nack->UpdateLastReceivedPacket(seq_num, timestamp);
380
381 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
382 EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size());
383 }
384}
385
henrik.lundin91951862016-06-08 06:43:41 -0700386TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000387 const size_t kNackListSize = 10;
388 for (int m = 0; m < 2; ++m) {
389 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700390 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000391 nack->UpdateSampleRate(kSampleRateHz);
392
393 uint16_t seq_num = seq_num_offset;
394 uint32_t timestamp = 0x87654321;
395 nack->UpdateLastReceivedPacket(seq_num, timestamp);
396
397 // Packet lost more than NACK-list size limit.
398 uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
399
kwiberg2d0c3322016-02-14 09:28:33 -0800400 std::unique_ptr<uint16_t[]> seq_num_lost(new uint16_t[num_lost_packets]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000401 for (int n = 0; n < num_lost_packets; ++n) {
402 seq_num_lost[n] = ++seq_num;
403 }
404
405 ++seq_num;
406 timestamp += (num_lost_packets + 1) * kTimestampIncrement;
407 nack->UpdateLastReceivedPacket(seq_num, timestamp);
408 size_t expected_size = num_lost_packets - kNackThreshold;
409
410 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
411 EXPECT_EQ(expected_size, nack_list.size());
412
413 nack->SetMaxNackListSize(kNackListSize);
414 expected_size = kNackListSize - kNackThreshold;
415 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
416 EXPECT_TRUE(IsNackListCorrect(
417 nack_list, &seq_num_lost[num_lost_packets - kNackListSize],
418 expected_size));
419
420 // NACK list does not change size but the content is changing. The oldest
421 // element is removed and one from late list is inserted.
422 size_t n;
423 for (n = 1; n <= static_cast<size_t>(kNackThreshold); ++n) {
424 ++seq_num;
425 timestamp += kTimestampIncrement;
426 nack->UpdateLastReceivedPacket(seq_num, timestamp);
427 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
428 EXPECT_TRUE(IsNackListCorrect(
429 nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
430 expected_size));
431 }
432
433 // NACK list should shrink.
434 for (; n < kNackListSize; ++n) {
435 ++seq_num;
436 timestamp += kTimestampIncrement;
437 nack->UpdateLastReceivedPacket(seq_num, timestamp);
438 --expected_size;
439 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
440 EXPECT_TRUE(IsNackListCorrect(
441 nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
442 expected_size));
443 }
444
445 // After this packet, NACK list should be empty.
446 ++seq_num;
447 timestamp += kTimestampIncrement;
448 nack->UpdateLastReceivedPacket(seq_num, timestamp);
449 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
450 EXPECT_TRUE(nack_list.empty());
451 }
452}
453
henrik.lundin91951862016-06-08 06:43:41 -0700454TEST(NackTrackerTest, RoudTripTimeIsApplied) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000455 const int kNackListSize = 200;
henrik.lundin91951862016-06-08 06:43:41 -0700456 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000457 nack->UpdateSampleRate(kSampleRateHz);
458 nack->SetMaxNackListSize(kNackListSize);
459
460 uint16_t seq_num = 0;
461 uint32_t timestamp = 0x87654321;
462 nack->UpdateLastReceivedPacket(seq_num, timestamp);
463
464 // Packet lost more than NACK-list size limit.
465 uint16_t kNumLostPackets = kNackThreshold + 5;
466
467 seq_num += (1 + kNumLostPackets);
468 timestamp += (1 + kNumLostPackets) * kTimestampIncrement;
469 nack->UpdateLastReceivedPacket(seq_num, timestamp);
470
471 // Expected time-to-play are:
472 // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ...
473 //
474 // sequence number: 1, 2, 3, 4, 5
475 // time-to-play: 20, 50, 80, 110, 140
476 //
477 std::vector<uint16_t> nack_list = nack->GetNackList(100);
478 ASSERT_EQ(2u, nack_list.size());
479 EXPECT_EQ(4, nack_list[0]);
480 EXPECT_EQ(5, nack_list[1]);
481}
482
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000483} // namespace webrtc