blob: a44f41ba4121b90270d60d4a2951b1c55036d299 [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"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000020
21namespace webrtc {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000022namespace {
23
24const int kNackThreshold = 3;
25const int kSampleRateHz = 16000;
26const int kPacketSizeMs = 30;
27const uint32_t kTimestampIncrement = 480; // 30 ms.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000028const int64_t kShortRoundTripTimeMs = 1;
turaj@webrtc.org7959e162013-09-12 18:30:26 +000029
30bool IsNackListCorrect(const std::vector<uint16_t>& nack_list,
31 const uint16_t* lost_sequence_numbers,
32 size_t num_lost_packets) {
33 if (nack_list.size() != num_lost_packets)
34 return false;
35
36 if (num_lost_packets == 0)
37 return true;
38
39 for (size_t k = 0; k < nack_list.size(); ++k) {
40 int seq_num = nack_list[k];
41 bool seq_num_matched = false;
42 for (size_t n = 0; n < num_lost_packets; ++n) {
43 if (seq_num == lost_sequence_numbers[n]) {
44 seq_num_matched = true;
45 break;
46 }
47 }
48 if (!seq_num_matched)
49 return false;
50 }
51 return true;
52}
53
54} // namespace
55
henrik.lundin91951862016-06-08 06:43:41 -070056TEST(NackTrackerTest, EmptyListWhenNoPacketLoss) {
57 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +000058 nack->UpdateSampleRate(kSampleRateHz);
59
60 int seq_num = 1;
61 uint32_t timestamp = 0;
62
63 std::vector<uint16_t> nack_list;
64 for (int n = 0; n < 100; n++) {
65 nack->UpdateLastReceivedPacket(seq_num, timestamp);
66 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
67 seq_num++;
68 timestamp += kTimestampIncrement;
69 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
70 EXPECT_TRUE(nack_list.empty());
71 }
72}
73
henrik.lundin91951862016-06-08 06:43:41 -070074TEST(NackTrackerTest, NoNackIfReorderWithinNackThreshold) {
75 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +000076 nack->UpdateSampleRate(kSampleRateHz);
77
78 int seq_num = 1;
79 uint32_t timestamp = 0;
80 std::vector<uint16_t> nack_list;
81
82 nack->UpdateLastReceivedPacket(seq_num, timestamp);
83 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
84 EXPECT_TRUE(nack_list.empty());
85 int num_late_packets = kNackThreshold + 1;
86
87 // Push in reverse order
88 while (num_late_packets > 0) {
henrik.lundin48ed9302015-10-29 05:36:24 -070089 nack->UpdateLastReceivedPacket(
90 seq_num + num_late_packets,
91 timestamp + num_late_packets * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000092 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
93 EXPECT_TRUE(nack_list.empty());
94 num_late_packets--;
95 }
96}
97
henrik.lundin91951862016-06-08 06:43:41 -070098TEST(NackTrackerTest, LatePacketsMovedToNackThenNackListDoesNotChange) {
henrik.lundin48ed9302015-10-29 05:36:24 -070099 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000100 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
henrik.lundin48ed9302015-10-29 05:36:24 -0700101 sizeof(kSequenceNumberLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000102
103 for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700104 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000105 nack->UpdateSampleRate(kSampleRateHz);
106
107 uint16_t sequence_num_lost_packets[kNumAllLostPackets];
108 for (int n = 0; n < kNumAllLostPackets; n++) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700109 sequence_num_lost_packets[n] =
110 kSequenceNumberLostPackets[n] +
111 k * 65531; // Have wrap around in sequence numbers for |k == 1|.
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000112 }
113 uint16_t seq_num = sequence_num_lost_packets[0] - 1;
114
115 uint32_t timestamp = 0;
116 std::vector<uint16_t> nack_list;
117
118 nack->UpdateLastReceivedPacket(seq_num, timestamp);
119 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
120 EXPECT_TRUE(nack_list.empty());
121
122 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
123 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
124 int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
125
126 for (int n = 0; n < kNackThreshold + 1; ++n) {
127 nack->UpdateLastReceivedPacket(seq_num, timestamp);
128 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
129 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
130 num_lost_packets));
131 seq_num++;
132 timestamp += kTimestampIncrement;
133 num_lost_packets++;
134 }
135
136 for (int n = 0; n < 100; ++n) {
137 nack->UpdateLastReceivedPacket(seq_num, timestamp);
138 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
139 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
140 kNumAllLostPackets));
141 seq_num++;
142 timestamp += kTimestampIncrement;
143 }
144 }
145}
146
henrik.lundin91951862016-06-08 06:43:41 -0700147TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700148 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000149 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
henrik.lundin48ed9302015-10-29 05:36:24 -0700150 sizeof(kSequenceNumberLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000151
152 for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700153 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000154 nack->UpdateSampleRate(kSampleRateHz);
155
156 uint16_t sequence_num_lost_packets[kNumAllLostPackets];
157 for (int n = 0; n < kNumAllLostPackets; ++n) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700158 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] +
159 k * 65531; // Wrap around for |k == 1|.
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000160 }
161
162 uint16_t seq_num = sequence_num_lost_packets[0] - 1;
163 uint32_t timestamp = 0;
164
165 nack->UpdateLastReceivedPacket(seq_num, timestamp);
166 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
167 EXPECT_TRUE(nack_list.empty());
168
169 size_t index_retransmitted_rtp = 0;
170 uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement;
171
172 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
173 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
174 size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
175 for (int n = 0; n < kNumAllLostPackets; ++n) {
176 // Number of lost packets does not change for the first
177 // |kNackThreshold + 1| packets, one is added to the list and one is
178 // removed. Thereafter, the list shrinks every iteration.
179 if (n >= kNackThreshold + 1)
180 num_lost_packets--;
181
182 nack->UpdateLastReceivedPacket(seq_num, timestamp);
183 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
184 EXPECT_TRUE(IsNackListCorrect(
185 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
186 num_lost_packets));
187 seq_num++;
188 timestamp += kTimestampIncrement;
189
190 // Retransmission of a lost RTP.
191 nack->UpdateLastReceivedPacket(
192 sequence_num_lost_packets[index_retransmitted_rtp],
193 timestamp_retransmitted_rtp);
194 index_retransmitted_rtp++;
195 timestamp_retransmitted_rtp += kTimestampIncrement;
196
197 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
198 EXPECT_TRUE(IsNackListCorrect(
199 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
200 num_lost_packets - 1)); // One less lost packet in the list.
201 }
202 ASSERT_TRUE(nack_list.empty());
203 }
204}
205
206// Assess if estimation of timestamps and time-to-play is correct. Introduce all
207// combinations that timestamps and sequence numbers might have wrap around.
henrik.lundin91951862016-06-08 06:43:41 -0700208TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700209 const uint16_t kLostPackets[] = {2, 3, 4, 5, 6, 7, 8,
210 9, 10, 11, 12, 13, 14, 15};
211 static const int kNumAllLostPackets =
212 sizeof(kLostPackets) / sizeof(kLostPackets[0]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000213
214 for (int k = 0; k < 4; ++k) {
henrik.lundin91951862016-06-08 06:43:41 -0700215 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000216 nack->UpdateSampleRate(kSampleRateHz);
217
218 // Sequence number wrap around if |k| is 2 or 3;
219 int seq_num_offset = (k < 2) ? 0 : 65531;
220
221 // Timestamp wrap around if |k| is 1 or 3.
henrik.lundin48ed9302015-10-29 05:36:24 -0700222 uint32_t timestamp_offset =
223 (k & 0x1) ? static_cast<uint32_t>(0xffffffff) - 6 : 0;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000224
225 uint32_t timestamp_lost_packets[kNumAllLostPackets];
226 uint16_t seq_num_lost_packets[kNumAllLostPackets];
227 for (int n = 0; n < kNumAllLostPackets; ++n) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700228 timestamp_lost_packets[n] =
229 timestamp_offset + kLostPackets[n] * kTimestampIncrement;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000230 seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n];
231 }
232
233 // We and to push two packets before lost burst starts.
234 uint16_t seq_num = seq_num_lost_packets[0] - 2;
235 uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement;
236
237 const uint16_t first_seq_num = seq_num;
238 const uint32_t first_timestamp = timestamp;
239
240 // Two consecutive packets to have a correct estimate of timestamp increase.
241 nack->UpdateLastReceivedPacket(seq_num, timestamp);
242 seq_num++;
243 timestamp += kTimestampIncrement;
244 nack->UpdateLastReceivedPacket(seq_num, timestamp);
245
246 // A packet after the last one which is supposed to be lost.
247 seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1;
henrik.lundin48ed9302015-10-29 05:36:24 -0700248 timestamp =
249 timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000250 nack->UpdateLastReceivedPacket(seq_num, timestamp);
251
henrik.lundin91951862016-06-08 06:43:41 -0700252 NackTracker::NackList nack_list = nack->GetNackList();
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000253 EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size());
254
255 // Pretend the first packet is decoded.
256 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
257 nack_list = nack->GetNackList();
258
henrik.lundin91951862016-06-08 06:43:41 -0700259 NackTracker::NackList::iterator it = nack_list.begin();
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000260 while (it != nack_list.end()) {
261 seq_num = it->first - seq_num_offset;
262 int index = seq_num - kLostPackets[0];
263 EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp);
264 EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms);
265 ++it;
266 }
267
268 // Pretend 10 ms is passed, and we had pulled audio from NetEq, it still
269 // reports the same sequence number as decoded, time-to-play should be
270 // updated by 10 ms.
271 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
272 nack_list = nack->GetNackList();
273 it = nack_list.begin();
274 while (it != nack_list.end()) {
275 seq_num = it->first - seq_num_offset;
276 int index = seq_num - kLostPackets[0];
277 EXPECT_EQ((index + 2) * kPacketSizeMs - 10, it->second.time_to_play_ms);
278 ++it;
279 }
280 }
281}
282
henrik.lundin91951862016-06-08 06:43:41 -0700283TEST(NackTrackerTest,
284 MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000285 for (int m = 0; m < 2; ++m) {
286 uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700287 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000288 nack->UpdateSampleRate(kSampleRateHz);
289
290 // Two consecutive packets to have a correct estimate of timestamp increase.
291 uint16_t seq_num = 0;
292 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700293 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000294 seq_num++;
295 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700296 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000297
298 // Skip 10 packets (larger than NACK threshold).
299 const int kNumLostPackets = 10;
300 seq_num += kNumLostPackets + 1;
301 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700302 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000303
304 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
305 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
306 EXPECT_EQ(kExpectedListSize, nack_list.size());
307
308 for (int k = 0; k < 2; ++k) {
309 // Decoding of the first and the second arrived packets.
310 for (int n = 0; n < kPacketSizeMs / 10; ++n) {
311 nack->UpdateLastDecodedPacket(seq_num_offset + k,
312 k * kTimestampIncrement);
313 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
314 EXPECT_EQ(kExpectedListSize, nack_list.size());
315 }
316 }
317
318 // Decoding of the last received packet.
319 nack->UpdateLastDecodedPacket(seq_num + seq_num_offset,
henrik.lundin48ed9302015-10-29 05:36:24 -0700320 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000321 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
322 EXPECT_TRUE(nack_list.empty());
323
324 // Make sure list of late packets is also empty. To check that, push few
325 // packets, if the late list is not empty its content will pop up in NACK
326 // list.
327 for (int n = 0; n < kNackThreshold + 10; ++n) {
328 seq_num++;
329 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
henrik.lundin48ed9302015-10-29 05:36:24 -0700330 seq_num * kTimestampIncrement);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000331 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
332 EXPECT_TRUE(nack_list.empty());
333 }
334 }
335}
336
henrik.lundin91951862016-06-08 06:43:41 -0700337TEST(NackTrackerTest, Reset) {
338 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000339 nack->UpdateSampleRate(kSampleRateHz);
340
341 // Two consecutive packets to have a correct estimate of timestamp increase.
342 uint16_t seq_num = 0;
343 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
344 seq_num++;
345 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
346
347 // Skip 10 packets (larger than NACK threshold).
348 const int kNumLostPackets = 10;
349 seq_num += kNumLostPackets + 1;
350 nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
351
352 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
353 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
354 EXPECT_EQ(kExpectedListSize, nack_list.size());
355
356 nack->Reset();
357 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
358 EXPECT_TRUE(nack_list.empty());
359}
360
henrik.lundin91951862016-06-08 06:43:41 -0700361TEST(NackTrackerTest, ListSizeAppliedFromBeginning) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000362 const size_t kNackListSize = 10;
363 for (int m = 0; m < 2; ++m) {
364 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700365 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000366 nack->UpdateSampleRate(kSampleRateHz);
367 nack->SetMaxNackListSize(kNackListSize);
368
369 uint16_t seq_num = seq_num_offset;
370 uint32_t timestamp = 0x12345678;
371 nack->UpdateLastReceivedPacket(seq_num, timestamp);
372
373 // Packet lost more than NACK-list size limit.
374 uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
375
376 seq_num += num_lost_packets + 1;
377 timestamp += (num_lost_packets + 1) * kTimestampIncrement;
378 nack->UpdateLastReceivedPacket(seq_num, timestamp);
379
380 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
381 EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size());
382 }
383}
384
henrik.lundin91951862016-06-08 06:43:41 -0700385TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000386 const size_t kNackListSize = 10;
387 for (int m = 0; m < 2; ++m) {
388 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
henrik.lundin91951862016-06-08 06:43:41 -0700389 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000390 nack->UpdateSampleRate(kSampleRateHz);
391
392 uint16_t seq_num = seq_num_offset;
393 uint32_t timestamp = 0x87654321;
394 nack->UpdateLastReceivedPacket(seq_num, timestamp);
395
396 // Packet lost more than NACK-list size limit.
397 uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
398
kwiberg2d0c3322016-02-14 09:28:33 -0800399 std::unique_ptr<uint16_t[]> seq_num_lost(new uint16_t[num_lost_packets]);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000400 for (int n = 0; n < num_lost_packets; ++n) {
401 seq_num_lost[n] = ++seq_num;
402 }
403
404 ++seq_num;
405 timestamp += (num_lost_packets + 1) * kTimestampIncrement;
406 nack->UpdateLastReceivedPacket(seq_num, timestamp);
407 size_t expected_size = num_lost_packets - kNackThreshold;
408
409 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
410 EXPECT_EQ(expected_size, nack_list.size());
411
412 nack->SetMaxNackListSize(kNackListSize);
413 expected_size = kNackListSize - kNackThreshold;
414 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
415 EXPECT_TRUE(IsNackListCorrect(
416 nack_list, &seq_num_lost[num_lost_packets - kNackListSize],
417 expected_size));
418
419 // NACK list does not change size but the content is changing. The oldest
420 // element is removed and one from late list is inserted.
421 size_t n;
422 for (n = 1; n <= static_cast<size_t>(kNackThreshold); ++n) {
423 ++seq_num;
424 timestamp += kTimestampIncrement;
425 nack->UpdateLastReceivedPacket(seq_num, timestamp);
426 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
427 EXPECT_TRUE(IsNackListCorrect(
428 nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
429 expected_size));
430 }
431
432 // NACK list should shrink.
433 for (; n < kNackListSize; ++n) {
434 ++seq_num;
435 timestamp += kTimestampIncrement;
436 nack->UpdateLastReceivedPacket(seq_num, timestamp);
437 --expected_size;
438 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
439 EXPECT_TRUE(IsNackListCorrect(
440 nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
441 expected_size));
442 }
443
444 // After this packet, NACK list should be empty.
445 ++seq_num;
446 timestamp += kTimestampIncrement;
447 nack->UpdateLastReceivedPacket(seq_num, timestamp);
448 nack_list = nack->GetNackList(kShortRoundTripTimeMs);
449 EXPECT_TRUE(nack_list.empty());
450 }
451}
452
henrik.lundin91951862016-06-08 06:43:41 -0700453TEST(NackTrackerTest, RoudTripTimeIsApplied) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000454 const int kNackListSize = 200;
henrik.lundin91951862016-06-08 06:43:41 -0700455 std::unique_ptr<NackTracker> nack(NackTracker::Create(kNackThreshold));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000456 nack->UpdateSampleRate(kSampleRateHz);
457 nack->SetMaxNackListSize(kNackListSize);
458
459 uint16_t seq_num = 0;
460 uint32_t timestamp = 0x87654321;
461 nack->UpdateLastReceivedPacket(seq_num, timestamp);
462
463 // Packet lost more than NACK-list size limit.
464 uint16_t kNumLostPackets = kNackThreshold + 5;
465
466 seq_num += (1 + kNumLostPackets);
467 timestamp += (1 + kNumLostPackets) * kTimestampIncrement;
468 nack->UpdateLastReceivedPacket(seq_num, timestamp);
469
470 // Expected time-to-play are:
471 // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ...
472 //
473 // sequence number: 1, 2, 3, 4, 5
474 // time-to-play: 20, 50, 80, 110, 140
475 //
476 std::vector<uint16_t> nack_list = nack->GetNackList(100);
477 ASSERT_EQ(2u, nack_list.size());
478 EXPECT_EQ(4, nack_list[0]);
479 EXPECT_EQ(5, nack_list[1]);
480}
481
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000482} // namespace webrtc