OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_coding/main/acm2/nack.h" | 11 #include "webrtc/modules/audio_coding/neteq/nack.h" |
12 | 12 |
13 #include <stdint.h> | 13 #include <stdint.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 | 16 |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 #include "webrtc/base/scoped_ptr.h" | 18 #include "webrtc/base/scoped_ptr.h" |
19 #include "webrtc/typedefs.h" | 19 #include "webrtc/typedefs.h" |
20 #include "webrtc/modules/audio_coding/main/include/audio_coding_module_typedefs.
h" | 20 #include "webrtc/modules/audio_coding/main/include/audio_coding_module_typedefs.
h" |
21 | 21 |
22 namespace webrtc { | 22 namespace webrtc { |
23 | |
24 namespace acm2 { | |
25 | |
26 namespace { | 23 namespace { |
27 | 24 |
28 const int kNackThreshold = 3; | 25 const int kNackThreshold = 3; |
29 const int kSampleRateHz = 16000; | 26 const int kSampleRateHz = 16000; |
30 const int kPacketSizeMs = 30; | 27 const int kPacketSizeMs = 30; |
31 const uint32_t kTimestampIncrement = 480; // 30 ms. | 28 const uint32_t kTimestampIncrement = 480; // 30 ms. |
32 const int64_t kShortRoundTripTimeMs = 1; | 29 const int64_t kShortRoundTripTimeMs = 1; |
33 | 30 |
34 bool IsNackListCorrect(const std::vector<uint16_t>& nack_list, | 31 bool IsNackListCorrect(const std::vector<uint16_t>& nack_list, |
35 const uint16_t* lost_sequence_numbers, | 32 const uint16_t* lost_sequence_numbers, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 uint32_t timestamp = 0; | 80 uint32_t timestamp = 0; |
84 std::vector<uint16_t> nack_list; | 81 std::vector<uint16_t> nack_list; |
85 | 82 |
86 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 83 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
87 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 84 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
88 EXPECT_TRUE(nack_list.empty()); | 85 EXPECT_TRUE(nack_list.empty()); |
89 int num_late_packets = kNackThreshold + 1; | 86 int num_late_packets = kNackThreshold + 1; |
90 | 87 |
91 // Push in reverse order | 88 // Push in reverse order |
92 while (num_late_packets > 0) { | 89 while (num_late_packets > 0) { |
93 nack->UpdateLastReceivedPacket(seq_num + num_late_packets, timestamp + | 90 nack->UpdateLastReceivedPacket( |
94 num_late_packets * kTimestampIncrement); | 91 seq_num + num_late_packets, |
| 92 timestamp + num_late_packets * kTimestampIncrement); |
95 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 93 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
96 EXPECT_TRUE(nack_list.empty()); | 94 EXPECT_TRUE(nack_list.empty()); |
97 num_late_packets--; | 95 num_late_packets--; |
98 } | 96 } |
99 } | 97 } |
100 | 98 |
101 TEST(NackTest, LatePacketsMovedToNackThenNackListDoesNotChange) { | 99 TEST(NackTest, LatePacketsMovedToNackThenNackListDoesNotChange) { |
102 const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; | 100 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9}; |
103 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / | 101 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / |
104 sizeof(kSequenceNumberLostPackets[0]); | 102 sizeof(kSequenceNumberLostPackets[0]); |
105 | 103 |
106 for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around. | 104 for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around. |
107 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); | 105 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); |
108 nack->UpdateSampleRate(kSampleRateHz); | 106 nack->UpdateSampleRate(kSampleRateHz); |
109 | 107 |
110 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; | 108 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; |
111 for (int n = 0; n < kNumAllLostPackets; n++) { | 109 for (int n = 0; n < kNumAllLostPackets; n++) { |
112 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k * | 110 sequence_num_lost_packets[n] = |
113 65531; // Have wrap around in sequence numbers for |k == 1|. | 111 kSequenceNumberLostPackets[n] + |
| 112 k * 65531; // Have wrap around in sequence numbers for |k == 1|. |
114 } | 113 } |
115 uint16_t seq_num = sequence_num_lost_packets[0] - 1; | 114 uint16_t seq_num = sequence_num_lost_packets[0] - 1; |
116 | 115 |
117 uint32_t timestamp = 0; | 116 uint32_t timestamp = 0; |
118 std::vector<uint16_t> nack_list; | 117 std::vector<uint16_t> nack_list; |
119 | 118 |
120 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 119 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
121 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 120 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
122 EXPECT_TRUE(nack_list.empty()); | 121 EXPECT_TRUE(nack_list.empty()); |
123 | 122 |
(...skipping 16 matching lines...) Expand all Loading... |
140 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 139 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
141 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, | 140 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, |
142 kNumAllLostPackets)); | 141 kNumAllLostPackets)); |
143 seq_num++; | 142 seq_num++; |
144 timestamp += kTimestampIncrement; | 143 timestamp += kTimestampIncrement; |
145 } | 144 } |
146 } | 145 } |
147 } | 146 } |
148 | 147 |
149 TEST(NackTest, ArrivedPacketsAreRemovedFromNackList) { | 148 TEST(NackTest, ArrivedPacketsAreRemovedFromNackList) { |
150 const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; | 149 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9}; |
151 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / | 150 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / |
152 sizeof(kSequenceNumberLostPackets[0]); | 151 sizeof(kSequenceNumberLostPackets[0]); |
153 | 152 |
154 for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around. | 153 for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around. |
155 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); | 154 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); |
156 nack->UpdateSampleRate(kSampleRateHz); | 155 nack->UpdateSampleRate(kSampleRateHz); |
157 | 156 |
158 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; | 157 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; |
159 for (int n = 0; n < kNumAllLostPackets; ++n) { | 158 for (int n = 0; n < kNumAllLostPackets; ++n) { |
160 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k * | 159 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + |
161 65531; // Wrap around for |k == 1|. | 160 k * 65531; // Wrap around for |k == 1|. |
162 } | 161 } |
163 | 162 |
164 uint16_t seq_num = sequence_num_lost_packets[0] - 1; | 163 uint16_t seq_num = sequence_num_lost_packets[0] - 1; |
165 uint32_t timestamp = 0; | 164 uint32_t timestamp = 0; |
166 | 165 |
167 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 166 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
168 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 167 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
169 EXPECT_TRUE(nack_list.empty()); | 168 EXPECT_TRUE(nack_list.empty()); |
170 | 169 |
171 size_t index_retransmitted_rtp = 0; | 170 size_t index_retransmitted_rtp = 0; |
(...skipping 29 matching lines...) Expand all Loading... |
201 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], | 200 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], |
202 num_lost_packets - 1)); // One less lost packet in the list. | 201 num_lost_packets - 1)); // One less lost packet in the list. |
203 } | 202 } |
204 ASSERT_TRUE(nack_list.empty()); | 203 ASSERT_TRUE(nack_list.empty()); |
205 } | 204 } |
206 } | 205 } |
207 | 206 |
208 // Assess if estimation of timestamps and time-to-play is correct. Introduce all | 207 // Assess if estimation of timestamps and time-to-play is correct. Introduce all |
209 // combinations that timestamps and sequence numbers might have wrap around. | 208 // combinations that timestamps and sequence numbers might have wrap around. |
210 TEST(NackTest, EstimateTimestampAndTimeToPlay) { | 209 TEST(NackTest, EstimateTimestampAndTimeToPlay) { |
211 const uint16_t kLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, | 210 const uint16_t kLostPackets[] = {2, 3, 4, 5, 6, 7, 8, |
212 11, 12, 13, 14, 15 }; | 211 9, 10, 11, 12, 13, 14, 15}; |
213 static const int kNumAllLostPackets = sizeof(kLostPackets) / | 212 static const int kNumAllLostPackets = |
214 sizeof(kLostPackets[0]); | 213 sizeof(kLostPackets) / sizeof(kLostPackets[0]); |
215 | |
216 | 214 |
217 for (int k = 0; k < 4; ++k) { | 215 for (int k = 0; k < 4; ++k) { |
218 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); | 216 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); |
219 nack->UpdateSampleRate(kSampleRateHz); | 217 nack->UpdateSampleRate(kSampleRateHz); |
220 | 218 |
221 // Sequence number wrap around if |k| is 2 or 3; | 219 // Sequence number wrap around if |k| is 2 or 3; |
222 int seq_num_offset = (k < 2) ? 0 : 65531; | 220 int seq_num_offset = (k < 2) ? 0 : 65531; |
223 | 221 |
224 // Timestamp wrap around if |k| is 1 or 3. | 222 // Timestamp wrap around if |k| is 1 or 3. |
225 uint32_t timestamp_offset = (k & 0x1) ? | 223 uint32_t timestamp_offset = |
226 static_cast<uint32_t>(0xffffffff) - 6 : 0; | 224 (k & 0x1) ? static_cast<uint32_t>(0xffffffff) - 6 : 0; |
227 | 225 |
228 uint32_t timestamp_lost_packets[kNumAllLostPackets]; | 226 uint32_t timestamp_lost_packets[kNumAllLostPackets]; |
229 uint16_t seq_num_lost_packets[kNumAllLostPackets]; | 227 uint16_t seq_num_lost_packets[kNumAllLostPackets]; |
230 for (int n = 0; n < kNumAllLostPackets; ++n) { | 228 for (int n = 0; n < kNumAllLostPackets; ++n) { |
231 timestamp_lost_packets[n] = timestamp_offset + kLostPackets[n] * | 229 timestamp_lost_packets[n] = |
232 kTimestampIncrement; | 230 timestamp_offset + kLostPackets[n] * kTimestampIncrement; |
233 seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n]; | 231 seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n]; |
234 } | 232 } |
235 | 233 |
236 // We and to push two packets before lost burst starts. | 234 // We and to push two packets before lost burst starts. |
237 uint16_t seq_num = seq_num_lost_packets[0] - 2; | 235 uint16_t seq_num = seq_num_lost_packets[0] - 2; |
238 uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement; | 236 uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement; |
239 | 237 |
240 const uint16_t first_seq_num = seq_num; | 238 const uint16_t first_seq_num = seq_num; |
241 const uint32_t first_timestamp = timestamp; | 239 const uint32_t first_timestamp = timestamp; |
242 | 240 |
243 // Two consecutive packets to have a correct estimate of timestamp increase. | 241 // Two consecutive packets to have a correct estimate of timestamp increase. |
244 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 242 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
245 seq_num++; | 243 seq_num++; |
246 timestamp += kTimestampIncrement; | 244 timestamp += kTimestampIncrement; |
247 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 245 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
248 | 246 |
249 // A packet after the last one which is supposed to be lost. | 247 // A packet after the last one which is supposed to be lost. |
250 seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1; | 248 seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1; |
251 timestamp = timestamp_lost_packets[kNumAllLostPackets - 1] + | 249 timestamp = |
252 kTimestampIncrement; | 250 timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement; |
253 nack->UpdateLastReceivedPacket(seq_num, timestamp); | 251 nack->UpdateLastReceivedPacket(seq_num, timestamp); |
254 | 252 |
255 Nack::NackList nack_list = nack->GetNackList(); | 253 Nack::NackList nack_list = nack->GetNackList(); |
256 EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size()); | 254 EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size()); |
257 | 255 |
258 // Pretend the first packet is decoded. | 256 // Pretend the first packet is decoded. |
259 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp); | 257 nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp); |
260 nack_list = nack->GetNackList(); | 258 nack_list = nack->GetNackList(); |
261 | 259 |
262 Nack::NackList::iterator it = nack_list.begin(); | 260 Nack::NackList::iterator it = nack_list.begin(); |
(...skipping 22 matching lines...) Expand all Loading... |
285 | 283 |
286 TEST(NackTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) { | 284 TEST(NackTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) { |
287 for (int m = 0; m < 2; ++m) { | 285 for (int m = 0; m < 2; ++m) { |
288 uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if |m| is 1. | 286 uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if |m| is 1. |
289 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); | 287 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); |
290 nack->UpdateSampleRate(kSampleRateHz); | 288 nack->UpdateSampleRate(kSampleRateHz); |
291 | 289 |
292 // Two consecutive packets to have a correct estimate of timestamp increase. | 290 // Two consecutive packets to have a correct estimate of timestamp increase. |
293 uint16_t seq_num = 0; | 291 uint16_t seq_num = 0; |
294 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, | 292 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, |
295 seq_num * kTimestampIncrement); | 293 seq_num * kTimestampIncrement); |
296 seq_num++; | 294 seq_num++; |
297 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, | 295 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, |
298 seq_num * kTimestampIncrement); | 296 seq_num * kTimestampIncrement); |
299 | 297 |
300 // Skip 10 packets (larger than NACK threshold). | 298 // Skip 10 packets (larger than NACK threshold). |
301 const int kNumLostPackets = 10; | 299 const int kNumLostPackets = 10; |
302 seq_num += kNumLostPackets + 1; | 300 seq_num += kNumLostPackets + 1; |
303 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, | 301 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, |
304 seq_num * kTimestampIncrement); | 302 seq_num * kTimestampIncrement); |
305 | 303 |
306 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold; | 304 const size_t kExpectedListSize = kNumLostPackets - kNackThreshold; |
307 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 305 std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
308 EXPECT_EQ(kExpectedListSize, nack_list.size()); | 306 EXPECT_EQ(kExpectedListSize, nack_list.size()); |
309 | 307 |
310 for (int k = 0; k < 2; ++k) { | 308 for (int k = 0; k < 2; ++k) { |
311 // Decoding of the first and the second arrived packets. | 309 // Decoding of the first and the second arrived packets. |
312 for (int n = 0; n < kPacketSizeMs / 10; ++n) { | 310 for (int n = 0; n < kPacketSizeMs / 10; ++n) { |
313 nack->UpdateLastDecodedPacket(seq_num_offset + k, | 311 nack->UpdateLastDecodedPacket(seq_num_offset + k, |
314 k * kTimestampIncrement); | 312 k * kTimestampIncrement); |
315 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 313 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
316 EXPECT_EQ(kExpectedListSize, nack_list.size()); | 314 EXPECT_EQ(kExpectedListSize, nack_list.size()); |
317 } | 315 } |
318 } | 316 } |
319 | 317 |
320 // Decoding of the last received packet. | 318 // Decoding of the last received packet. |
321 nack->UpdateLastDecodedPacket(seq_num + seq_num_offset, | 319 nack->UpdateLastDecodedPacket(seq_num + seq_num_offset, |
322 seq_num * kTimestampIncrement); | 320 seq_num * kTimestampIncrement); |
323 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 321 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
324 EXPECT_TRUE(nack_list.empty()); | 322 EXPECT_TRUE(nack_list.empty()); |
325 | 323 |
326 // Make sure list of late packets is also empty. To check that, push few | 324 // Make sure list of late packets is also empty. To check that, push few |
327 // packets, if the late list is not empty its content will pop up in NACK | 325 // packets, if the late list is not empty its content will pop up in NACK |
328 // list. | 326 // list. |
329 for (int n = 0; n < kNackThreshold + 10; ++n) { | 327 for (int n = 0; n < kNackThreshold + 10; ++n) { |
330 seq_num++; | 328 seq_num++; |
331 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, | 329 nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, |
332 seq_num * kTimestampIncrement); | 330 seq_num * kTimestampIncrement); |
333 nack_list = nack->GetNackList(kShortRoundTripTimeMs); | 331 nack_list = nack->GetNackList(kShortRoundTripTimeMs); |
334 EXPECT_TRUE(nack_list.empty()); | 332 EXPECT_TRUE(nack_list.empty()); |
335 } | 333 } |
336 } | 334 } |
337 } | 335 } |
338 | 336 |
339 TEST(NackTest, Reset) { | 337 TEST(NackTest, Reset) { |
340 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); | 338 rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold)); |
341 nack->UpdateSampleRate(kSampleRateHz); | 339 nack->UpdateSampleRate(kSampleRateHz); |
342 | 340 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 // | 472 // |
475 // sequence number: 1, 2, 3, 4, 5 | 473 // sequence number: 1, 2, 3, 4, 5 |
476 // time-to-play: 20, 50, 80, 110, 140 | 474 // time-to-play: 20, 50, 80, 110, 140 |
477 // | 475 // |
478 std::vector<uint16_t> nack_list = nack->GetNackList(100); | 476 std::vector<uint16_t> nack_list = nack->GetNackList(100); |
479 ASSERT_EQ(2u, nack_list.size()); | 477 ASSERT_EQ(2u, nack_list.size()); |
480 EXPECT_EQ(4, nack_list[0]); | 478 EXPECT_EQ(4, nack_list[0]); |
481 EXPECT_EQ(5, nack_list[1]); | 479 EXPECT_EQ(5, nack_list[1]); |
482 } | 480 } |
483 | 481 |
484 } // namespace acm2 | |
485 | |
486 } // namespace webrtc | 482 } // namespace webrtc |
OLD | NEW |