1 /*
2 * Copyright (c) 2012 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 // Unit tests for PacketBuffer class.
12
13 #include "modules/audio_coding/neteq/packet_buffer.h"
14
15 #include <memory>
16
17 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
18 #include "api/neteq/tick_timer.h"
19 #include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
20 #include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
21 #include "modules/audio_coding/neteq/packet.h"
22 #include "test/field_trial.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25
26 using ::testing::_;
27 using ::testing::InSequence;
28 using ::testing::MockFunction;
29 using ::testing::Return;
30 using ::testing::StrictMock;
31
32 namespace {
33 class MockEncodedAudioFrame : public webrtc::AudioDecoder::EncodedAudioFrame {
34 public:
35 MOCK_METHOD(size_t, Duration, (), (const, override));
36
37 MOCK_METHOD(bool, IsDtxPacket, (), (const, override));
38
39 MOCK_METHOD(absl::optional<DecodeResult>,
40 Decode,
41 (rtc::ArrayView<int16_t> decoded),
42 (const, override));
43 };
44
45 // Helper class to generate packets. Packets must be deleted by the user.
46 class PacketGenerator {
47 public:
48 PacketGenerator(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
~PacketGenerator()49 virtual ~PacketGenerator() {}
50 void Reset(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
51 webrtc::Packet NextPacket(
52 int payload_size_bytes,
53 std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame);
54
55 uint16_t seq_no_;
56 uint32_t ts_;
57 uint8_t pt_;
58 int frame_size_;
59 };
60
PacketGenerator(uint16_t seq_no,uint32_t ts,uint8_t pt,int frame_size)61 PacketGenerator::PacketGenerator(uint16_t seq_no,
62 uint32_t ts,
63 uint8_t pt,
64 int frame_size) {
65 Reset(seq_no, ts, pt, frame_size);
66 }
67
Reset(uint16_t seq_no,uint32_t ts,uint8_t pt,int frame_size)68 void PacketGenerator::Reset(uint16_t seq_no,
69 uint32_t ts,
70 uint8_t pt,
71 int frame_size) {
72 seq_no_ = seq_no;
73 ts_ = ts;
74 pt_ = pt;
75 frame_size_ = frame_size;
76 }
77
NextPacket(int payload_size_bytes,std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame)78 webrtc::Packet PacketGenerator::NextPacket(
79 int payload_size_bytes,
80 std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame) {
81 webrtc::Packet packet;
82 packet.sequence_number = seq_no_;
83 packet.timestamp = ts_;
84 packet.payload_type = pt_;
85 packet.payload.SetSize(payload_size_bytes);
86 ++seq_no_;
87 ts_ += frame_size_;
88 packet.frame = std::move(audio_frame);
89 return packet;
90 }
91
92 struct PacketsToInsert {
93 uint16_t sequence_number;
94 uint32_t timestamp;
95 uint8_t payload_type;
96 bool primary;
97 // Order of this packet to appear upon extraction, after inserting a series
98 // of packets. A negative number means that it should have been discarded
99 // before extraction.
100 int extract_order;
101 };
102
103 } // namespace
104
105 namespace webrtc {
106
107 // Start of test definitions.
108
TEST(PacketBuffer,CreateAndDestroy)109 TEST(PacketBuffer, CreateAndDestroy) {
110 TickTimer tick_timer;
111 PacketBuffer* buffer = new PacketBuffer(10, &tick_timer); // 10 packets.
112 EXPECT_TRUE(buffer->Empty());
113 delete buffer;
114 }
115
TEST(PacketBuffer,InsertPacket)116 TEST(PacketBuffer, InsertPacket) {
117 TickTimer tick_timer;
118 PacketBuffer buffer(10, &tick_timer); // 10 packets.
119 PacketGenerator gen(17u, 4711u, 0, 10);
120 StrictMock<MockStatisticsCalculator> mock_stats;
121 MockDecoderDatabase decoder_database;
122
123 const int payload_len = 100;
124 const Packet packet = gen.NextPacket(payload_len, nullptr);
125 EXPECT_EQ(0, buffer.InsertPacket(/*packet=*/packet.Clone(),
126 /*stats=*/&mock_stats,
127 /*last_decoded_length=*/payload_len,
128 /*sample_rate=*/10000,
129 /*target_level_ms=*/60,
130 /*decoder_database=*/decoder_database));
131 uint32_t next_ts;
132 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
133 EXPECT_EQ(4711u, next_ts);
134 EXPECT_FALSE(buffer.Empty());
135 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
136 const Packet* next_packet = buffer.PeekNextPacket();
137 EXPECT_EQ(packet, *next_packet); // Compare contents.
138 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
139
140 // Do not explicitly flush buffer or delete packet to test that it is deleted
141 // with the buffer. (Tested with Valgrind or similar tool.)
142 }
143
144 // Test to flush buffer.
TEST(PacketBuffer,FlushBuffer)145 TEST(PacketBuffer, FlushBuffer) {
146 TickTimer tick_timer;
147 PacketBuffer buffer(10, &tick_timer); // 10 packets.
148 PacketGenerator gen(0, 0, 0, 10);
149 const int payload_len = 10;
150 StrictMock<MockStatisticsCalculator> mock_stats;
151 MockDecoderDatabase decoder_database;
152
153 // Insert 10 small packets; should be ok.
154 for (int i = 0; i < 10; ++i) {
155 EXPECT_EQ(
156 PacketBuffer::kOK,
157 buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
158 /*stats=*/&mock_stats,
159 /*last_decoded_length=*/payload_len,
160 /*sample_rate=*/1000,
161 /*target_level_ms=*/60,
162 /*decoder_database=*/decoder_database));
163 }
164 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
165 EXPECT_FALSE(buffer.Empty());
166
167 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
168 buffer.Flush(&mock_stats);
169 // Buffer should delete the payloads itself.
170 EXPECT_EQ(0u, buffer.NumPacketsInBuffer());
171 EXPECT_TRUE(buffer.Empty());
172 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
173 }
174
175 // Test to fill the buffer over the limits, and verify that it flushes.
TEST(PacketBuffer,OverfillBuffer)176 TEST(PacketBuffer, OverfillBuffer) {
177 TickTimer tick_timer;
178 PacketBuffer buffer(10, &tick_timer); // 10 packets.
179 PacketGenerator gen(0, 0, 0, 10);
180 StrictMock<MockStatisticsCalculator> mock_stats;
181 MockDecoderDatabase decoder_database;
182
183 // Insert 10 small packets; should be ok.
184 const int payload_len = 10;
185 int i;
186 for (i = 0; i < 10; ++i) {
187 EXPECT_EQ(
188 PacketBuffer::kOK,
189 buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
190 /*stats=*/&mock_stats,
191 /*last_decoded_length=*/payload_len,
192 /*sample_rate=*/1000,
193 /*target_level_ms=*/60,
194 /*decoder_database=*/decoder_database));
195 }
196 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
197 uint32_t next_ts;
198 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
199 EXPECT_EQ(0u, next_ts); // Expect first inserted packet to be first in line.
200
201 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
202 const Packet packet = gen.NextPacket(payload_len, nullptr);
203 // Insert 11th packet; should flush the buffer and insert it after flushing.
204 EXPECT_EQ(PacketBuffer::kFlushed,
205 buffer.InsertPacket(/*packet=*/packet.Clone(),
206 /*stats=*/&mock_stats,
207 /*last_decoded_length=*/payload_len,
208 /*sample_rate=*/1000,
209 /*target_level_ms=*/60,
210 /*decoder_database=*/decoder_database));
211 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
212 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
213 // Expect last inserted packet to be first in line.
214 EXPECT_EQ(packet.timestamp, next_ts);
215
216 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
217 }
218
219 // Test a partial buffer flush.
TEST(PacketBuffer,PartialFlush)220 TEST(PacketBuffer, PartialFlush) {
221 // Use a field trial to configure smart flushing.
222 test::ScopedFieldTrials field_trials(
223 "WebRTC-Audio-NetEqSmartFlushing/enabled:true,"
224 "target_level_threshold_ms:0,target_level_multiplier:2/");
225 TickTimer tick_timer;
226 PacketBuffer buffer(10, &tick_timer); // 10 packets.
227 PacketGenerator gen(0, 0, 0, 10);
228 const int payload_len = 10;
229 StrictMock<MockStatisticsCalculator> mock_stats;
230 MockDecoderDatabase decoder_database;
231
232 // Insert 10 small packets; should be ok.
233 for (int i = 0; i < 10; ++i) {
234 EXPECT_EQ(
235 PacketBuffer::kOK,
236 buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
237 /*stats=*/&mock_stats,
238 /*last_decoded_length=*/payload_len,
239 /*sample_rate=*/1000,
240 /*target_level_ms=*/100,
241 /*decoder_database=*/decoder_database));
242 }
243 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
244 EXPECT_FALSE(buffer.Empty());
245
246 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(7);
247 buffer.PartialFlush(/*target_level_ms=*/30,
248 /*sample_rate=*/1000,
249 /*last_decoded_length=*/payload_len,
250 /*stats=*/&mock_stats);
251 // There should still be some packets left in the buffer.
252 EXPECT_EQ(3u, buffer.NumPacketsInBuffer());
253 EXPECT_FALSE(buffer.Empty());
254 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
255 }
256
257 // Test to fill the buffer over the limits, and verify that the smart flush
258 // functionality works as expected.
TEST(PacketBuffer,SmartFlushOverfillBuffer)259 TEST(PacketBuffer, SmartFlushOverfillBuffer) {
260 // Use a field trial to configure smart flushing.
261 test::ScopedFieldTrials field_trials(
262 "WebRTC-Audio-NetEqSmartFlushing/enabled:true,"
263 "target_level_threshold_ms:0,target_level_multiplier:2/");
264 TickTimer tick_timer;
265 PacketBuffer buffer(10, &tick_timer); // 10 packets.
266 PacketGenerator gen(0, 0, 0, 10);
267 StrictMock<MockStatisticsCalculator> mock_stats;
268 MockDecoderDatabase decoder_database;
269
270 // Insert 10 small packets; should be ok.
271 const int payload_len = 10;
272 int i;
273 for (i = 0; i < 10; ++i) {
274 EXPECT_EQ(
275 PacketBuffer::kOK,
276 buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
277 /*stats=*/&mock_stats,
278 /*last_decoded_length=*/payload_len,
279 /*sample_rate=*/1000,
280 /*target_level_ms=*/100,
281 /*decoder_database=*/decoder_database));
282 }
283 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
284 uint32_t next_ts;
285 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
286 EXPECT_EQ(0u, next_ts); // Expect first inserted packet to be first in line.
287
288 const Packet packet = gen.NextPacket(payload_len, nullptr);
289 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(6);
290 // Insert 11th packet; should cause a partial flush and insert the packet
291 // after flushing.
292 EXPECT_EQ(PacketBuffer::kPartialFlush,
293 buffer.InsertPacket(/*packet=*/packet.Clone(),
294 /*stats=*/&mock_stats,
295 /*last_decoded_length=*/payload_len,
296 /*sample_rate=*/1000,
297 /*target_level_ms=*/40,
298 /*decoder_database=*/decoder_database));
299 EXPECT_EQ(5u, buffer.NumPacketsInBuffer());
300 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
301 }
302
303 // Test inserting a list of packets.
TEST(PacketBuffer,InsertPacketList)304 TEST(PacketBuffer, InsertPacketList) {
305 TickTimer tick_timer;
306 PacketBuffer buffer(10, &tick_timer); // 10 packets.
307 PacketGenerator gen(0, 0, 0, 10);
308 PacketList list;
309 const int payload_len = 10;
310
311 // Insert 10 small packets.
312 for (int i = 0; i < 10; ++i) {
313 list.push_back(gen.NextPacket(payload_len, nullptr));
314 }
315
316 MockDecoderDatabase decoder_database;
317 auto factory = CreateBuiltinAudioDecoderFactory();
318 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
319 absl::nullopt, factory.get());
320 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
321 .WillRepeatedly(Return(&info));
322
323 StrictMock<MockStatisticsCalculator> mock_stats;
324
325 absl::optional<uint8_t> current_pt;
326 absl::optional<uint8_t> current_cng_pt;
327 EXPECT_EQ(
328 PacketBuffer::kOK,
329 buffer.InsertPacketList(/*packet_list=*/&list,
330 /*decoder_database=*/decoder_database,
331 /*current_rtp_payload_type=*/¤t_pt,
332 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
333 /*stats=*/&mock_stats,
334 /*last_decoded_length=*/payload_len,
335 /*sample_rate=*/1000,
336 /*target_level_ms=*/30));
337 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
338 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
339 EXPECT_EQ(0, current_pt); // Current payload type changed to 0.
340 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type not changed.
341
342 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
343 }
344
345 // Test inserting a list of packets. Last packet is of a different payload type.
346 // Expecting the buffer to flush.
347 // TODO(hlundin): Remove this test when legacy operation is no longer needed.
TEST(PacketBuffer,InsertPacketListChangePayloadType)348 TEST(PacketBuffer, InsertPacketListChangePayloadType) {
349 TickTimer tick_timer;
350 PacketBuffer buffer(10, &tick_timer); // 10 packets.
351 PacketGenerator gen(0, 0, 0, 10);
352 PacketList list;
353 const int payload_len = 10;
354
355 // Insert 10 small packets.
356 for (int i = 0; i < 10; ++i) {
357 list.push_back(gen.NextPacket(payload_len, nullptr));
358 }
359 // Insert 11th packet of another payload type (not CNG).
360 {
361 Packet packet = gen.NextPacket(payload_len, nullptr);
362 packet.payload_type = 1;
363 list.push_back(std::move(packet));
364 }
365
366 MockDecoderDatabase decoder_database;
367 auto factory = CreateBuiltinAudioDecoderFactory();
368 const DecoderDatabase::DecoderInfo info0(SdpAudioFormat("pcmu", 8000, 1),
369 absl::nullopt, factory.get());
370 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
371 .WillRepeatedly(Return(&info0));
372 const DecoderDatabase::DecoderInfo info1(SdpAudioFormat("pcma", 8000, 1),
373 absl::nullopt, factory.get());
374 EXPECT_CALL(decoder_database, GetDecoderInfo(1))
375 .WillRepeatedly(Return(&info1));
376
377 StrictMock<MockStatisticsCalculator> mock_stats;
378
379 absl::optional<uint8_t> current_pt;
380 absl::optional<uint8_t> current_cng_pt;
381 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
382 EXPECT_EQ(
383 PacketBuffer::kFlushed,
384 buffer.InsertPacketList(/*packet_list=*/&list,
385 /*decoder_database=*/decoder_database,
386 /*current_rtp_payload_type=*/¤t_pt,
387 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
388 /*stats=*/&mock_stats,
389 /*last_decoded_length=*/payload_len,
390 /*sample_rate=*/1000,
391 /*target_level_ms=*/30));
392 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
393 EXPECT_EQ(1u, buffer.NumPacketsInBuffer()); // Only the last packet.
394 EXPECT_EQ(1, current_pt); // Current payload type changed to 1.
395 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type not changed.
396
397 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
398 }
399
TEST(PacketBuffer,ExtractOrderRedundancy)400 TEST(PacketBuffer, ExtractOrderRedundancy) {
401 TickTimer tick_timer;
402 PacketBuffer buffer(100, &tick_timer); // 100 packets.
403 const int kPackets = 18;
404 const int kFrameSize = 10;
405 const int kPayloadLength = 10;
406
407 PacketsToInsert packet_facts[kPackets] = {
408 {0xFFFD, 0xFFFFFFD7, 0, true, 0}, {0xFFFE, 0xFFFFFFE1, 0, true, 1},
409 {0xFFFE, 0xFFFFFFD7, 1, false, -1}, {0xFFFF, 0xFFFFFFEB, 0, true, 2},
410 {0xFFFF, 0xFFFFFFE1, 1, false, -1}, {0x0000, 0xFFFFFFF5, 0, true, 3},
411 {0x0000, 0xFFFFFFEB, 1, false, -1}, {0x0001, 0xFFFFFFFF, 0, true, 4},
412 {0x0001, 0xFFFFFFF5, 1, false, -1}, {0x0002, 0x0000000A, 0, true, 5},
413 {0x0002, 0xFFFFFFFF, 1, false, -1}, {0x0003, 0x0000000A, 1, false, -1},
414 {0x0004, 0x0000001E, 0, true, 7}, {0x0004, 0x00000014, 1, false, 6},
415 {0x0005, 0x0000001E, 0, true, -1}, {0x0005, 0x00000014, 1, false, -1},
416 {0x0006, 0x00000028, 0, true, 8}, {0x0006, 0x0000001E, 1, false, -1},
417 };
418 MockDecoderDatabase decoder_database;
419
420 const size_t kExpectPacketsInBuffer = 9;
421
422 std::vector<Packet> expect_order(kExpectPacketsInBuffer);
423
424 PacketGenerator gen(0, 0, 0, kFrameSize);
425
426 StrictMock<MockStatisticsCalculator> mock_stats;
427
428 // Interleaving the EXPECT_CALL sequence with expectations on the MockFunction
429 // check ensures that exactly one call to PacketsDiscarded happens in each
430 // DiscardNextPacket call.
431 InSequence s;
432 MockFunction<void(int check_point_id)> check;
433 for (int i = 0; i < kPackets; ++i) {
434 gen.Reset(packet_facts[i].sequence_number, packet_facts[i].timestamp,
435 packet_facts[i].payload_type, kFrameSize);
436 Packet packet = gen.NextPacket(kPayloadLength, nullptr);
437 packet.priority.codec_level = packet_facts[i].primary ? 0 : 1;
438 if (packet_facts[i].extract_order < 0) {
439 if (packet.priority.codec_level > 0) {
440 EXPECT_CALL(mock_stats, SecondaryPacketsDiscarded(1));
441 } else {
442 EXPECT_CALL(mock_stats, PacketsDiscarded(1));
443 }
444 }
445 EXPECT_CALL(check, Call(i));
446 EXPECT_EQ(PacketBuffer::kOK,
447 buffer.InsertPacket(/*packet=*/packet.Clone(),
448 /*stats=*/&mock_stats,
449 /*last_decoded_length=*/kPayloadLength,
450 /*sample_rate=*/1000,
451 /*target_level_ms=*/60,
452 /*decoder_database=*/decoder_database));
453 if (packet_facts[i].extract_order >= 0) {
454 expect_order[packet_facts[i].extract_order] = std::move(packet);
455 }
456 check.Call(i);
457 }
458
459 EXPECT_EQ(kExpectPacketsInBuffer, buffer.NumPacketsInBuffer());
460
461 for (size_t i = 0; i < kExpectPacketsInBuffer; ++i) {
462 const absl::optional<Packet> packet = buffer.GetNextPacket();
463 EXPECT_EQ(packet, expect_order[i]); // Compare contents.
464 }
465 EXPECT_TRUE(buffer.Empty());
466 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
467 }
468
TEST(PacketBuffer,DiscardPackets)469 TEST(PacketBuffer, DiscardPackets) {
470 TickTimer tick_timer;
471 PacketBuffer buffer(100, &tick_timer); // 100 packets.
472 const uint16_t start_seq_no = 17;
473 const uint32_t start_ts = 4711;
474 const uint32_t ts_increment = 10;
475 PacketGenerator gen(start_seq_no, start_ts, 0, ts_increment);
476 PacketList list;
477 const int payload_len = 10;
478 StrictMock<MockStatisticsCalculator> mock_stats;
479 MockDecoderDatabase decoder_database;
480
481 constexpr int kTotalPackets = 10;
482 // Insert 10 small packets.
483 for (int i = 0; i < kTotalPackets; ++i) {
484 buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
485 /*stats=*/&mock_stats,
486 /*last_decoded_length=*/payload_len,
487 /*sample_rate=*/1000,
488 /*target_level_ms=*/60,
489 /*decoder_database=*/decoder_database);
490 }
491 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
492
493 uint32_t current_ts = start_ts;
494
495 // Discard them one by one and make sure that the right packets are at the
496 // front of the buffer.
497 constexpr int kDiscardPackets = 5;
498
499 // Interleaving the EXPECT_CALL sequence with expectations on the MockFunction
500 // check ensures that exactly one call to PacketsDiscarded happens in each
501 // DiscardNextPacket call.
502 InSequence s;
503 MockFunction<void(int check_point_id)> check;
504 for (int i = 0; i < kDiscardPackets; ++i) {
505 uint32_t ts;
506 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&ts));
507 EXPECT_EQ(current_ts, ts);
508 EXPECT_CALL(mock_stats, PacketsDiscarded(1));
509 EXPECT_CALL(check, Call(i));
510 EXPECT_EQ(PacketBuffer::kOK, buffer.DiscardNextPacket(&mock_stats));
511 current_ts += ts_increment;
512 check.Call(i);
513 }
514
515 constexpr int kRemainingPackets = kTotalPackets - kDiscardPackets;
516 // This will discard all remaining packets but one. The oldest packet is older
517 // than the indicated horizon_samples, and will thus be left in the buffer.
518 constexpr size_t kSkipPackets = 1;
519 EXPECT_CALL(mock_stats, PacketsDiscarded(1))
520 .Times(kRemainingPackets - kSkipPackets);
521 EXPECT_CALL(check, Call(17)); // Arbitrary id number.
522 buffer.DiscardOldPackets(start_ts + kTotalPackets * ts_increment,
523 kRemainingPackets * ts_increment, &mock_stats);
524 check.Call(17); // Same arbitrary id number.
525
526 EXPECT_EQ(kSkipPackets, buffer.NumPacketsInBuffer());
527 uint32_t ts;
528 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&ts));
529 EXPECT_EQ(current_ts, ts);
530
531 // Discard all remaining packets.
532 EXPECT_CALL(mock_stats, PacketsDiscarded(kSkipPackets));
533 buffer.DiscardAllOldPackets(start_ts + kTotalPackets * ts_increment,
534 &mock_stats);
535
536 EXPECT_TRUE(buffer.Empty());
537 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
538 }
539
TEST(PacketBuffer,Reordering)540 TEST(PacketBuffer, Reordering) {
541 TickTimer tick_timer;
542 PacketBuffer buffer(100, &tick_timer); // 100 packets.
543 const uint16_t start_seq_no = 17;
544 const uint32_t start_ts = 4711;
545 const uint32_t ts_increment = 10;
546 PacketGenerator gen(start_seq_no, start_ts, 0, ts_increment);
547 const int payload_len = 10;
548
549 // Generate 10 small packets and insert them into a PacketList. Insert every
550 // odd packet to the front, and every even packet to the back, thus creating
551 // a (rather strange) reordering.
552 PacketList list;
553 for (int i = 0; i < 10; ++i) {
554 Packet packet = gen.NextPacket(payload_len, nullptr);
555 if (i % 2) {
556 list.push_front(std::move(packet));
557 } else {
558 list.push_back(std::move(packet));
559 }
560 }
561
562 MockDecoderDatabase decoder_database;
563 auto factory = CreateBuiltinAudioDecoderFactory();
564 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
565 absl::nullopt, factory.get());
566 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
567 .WillRepeatedly(Return(&info));
568 absl::optional<uint8_t> current_pt;
569 absl::optional<uint8_t> current_cng_pt;
570
571 StrictMock<MockStatisticsCalculator> mock_stats;
572
573 EXPECT_EQ(
574 PacketBuffer::kOK,
575 buffer.InsertPacketList(/*packet_list=*/&list,
576 /*decoder_database=*/decoder_database,
577 /*current_rtp_payload_type=*/¤t_pt,
578 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
579 /*stats=*/&mock_stats,
580 /*last_decoded_length=*/payload_len,
581 /*sample_rate=*/1000,
582 /*target_level_ms=*/30));
583 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
584
585 // Extract them and make sure that come out in the right order.
586 uint32_t current_ts = start_ts;
587 for (int i = 0; i < 10; ++i) {
588 const absl::optional<Packet> packet = buffer.GetNextPacket();
589 ASSERT_TRUE(packet);
590 EXPECT_EQ(current_ts, packet->timestamp);
591 current_ts += ts_increment;
592 }
593 EXPECT_TRUE(buffer.Empty());
594
595 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
596 }
597
598 // The test first inserts a packet with narrow-band CNG, then a packet with
599 // wide-band speech. The expected behavior of the packet buffer is to detect a
600 // change in sample rate, even though no speech packet has been inserted before,
601 // and flush out the CNG packet.
TEST(PacketBuffer,CngFirstThenSpeechWithNewSampleRate)602 TEST(PacketBuffer, CngFirstThenSpeechWithNewSampleRate) {
603 TickTimer tick_timer;
604 PacketBuffer buffer(10, &tick_timer); // 10 packets.
605 const uint8_t kCngPt = 13;
606 const int kPayloadLen = 10;
607 const uint8_t kSpeechPt = 100;
608
609 MockDecoderDatabase decoder_database;
610 auto factory = CreateBuiltinAudioDecoderFactory();
611 const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 8000, 1),
612 absl::nullopt, factory.get());
613 EXPECT_CALL(decoder_database, GetDecoderInfo(kCngPt))
614 .WillRepeatedly(Return(&info_cng));
615 const DecoderDatabase::DecoderInfo info_speech(
616 SdpAudioFormat("l16", 16000, 1), absl::nullopt, factory.get());
617 EXPECT_CALL(decoder_database, GetDecoderInfo(kSpeechPt))
618 .WillRepeatedly(Return(&info_speech));
619
620 // Insert first packet, which is narrow-band CNG.
621 PacketGenerator gen(0, 0, kCngPt, 10);
622 PacketList list;
623 list.push_back(gen.NextPacket(kPayloadLen, nullptr));
624 absl::optional<uint8_t> current_pt;
625 absl::optional<uint8_t> current_cng_pt;
626
627 StrictMock<MockStatisticsCalculator> mock_stats;
628
629 EXPECT_EQ(
630 PacketBuffer::kOK,
631 buffer.InsertPacketList(/*packet_list=*/&list,
632 /*decoder_database=*/decoder_database,
633 /*current_rtp_payload_type=*/¤t_pt,
634 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
635 /*stats=*/&mock_stats,
636 /*last_decoded_length=*/kPayloadLen,
637 /*sample_rate=*/1000,
638 /*target_level_ms=*/30));
639 EXPECT_TRUE(list.empty());
640 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
641 ASSERT_TRUE(buffer.PeekNextPacket());
642 EXPECT_EQ(kCngPt, buffer.PeekNextPacket()->payload_type);
643 EXPECT_EQ(current_pt, absl::nullopt); // Current payload type not set.
644 EXPECT_EQ(kCngPt, current_cng_pt); // CNG payload type set.
645
646 // Insert second packet, which is wide-band speech.
647 {
648 Packet packet = gen.NextPacket(kPayloadLen, nullptr);
649 packet.payload_type = kSpeechPt;
650 list.push_back(std::move(packet));
651 }
652 // Expect the buffer to flush out the CNG packet, since it does not match the
653 // new speech sample rate.
654 EXPECT_CALL(mock_stats, PacketsDiscarded(1));
655 EXPECT_EQ(
656 PacketBuffer::kFlushed,
657 buffer.InsertPacketList(/*packet_list=*/&list,
658 /*decoder_database=*/decoder_database,
659 /*current_rtp_payload_type=*/¤t_pt,
660 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
661 /*stats=*/&mock_stats,
662 /*last_decoded_length=*/kPayloadLen,
663 /*sample_rate=*/1000,
664 /*target_level_ms=*/30));
665 EXPECT_TRUE(list.empty());
666 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
667 ASSERT_TRUE(buffer.PeekNextPacket());
668 EXPECT_EQ(kSpeechPt, buffer.PeekNextPacket()->payload_type);
669
670 EXPECT_EQ(kSpeechPt, current_pt); // Current payload type set.
671 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type reset.
672
673 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
674 }
675
TEST(PacketBuffer,Failures)676 TEST(PacketBuffer, Failures) {
677 const uint16_t start_seq_no = 17;
678 const uint32_t start_ts = 4711;
679 const uint32_t ts_increment = 10;
680 int payload_len = 100;
681 PacketGenerator gen(start_seq_no, start_ts, 0, ts_increment);
682 TickTimer tick_timer;
683 StrictMock<MockStatisticsCalculator> mock_stats;
684 MockDecoderDatabase decoder_database;
685
686 PacketBuffer* buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
687 {
688 Packet packet = gen.NextPacket(payload_len, nullptr);
689 packet.payload.Clear();
690 EXPECT_EQ(PacketBuffer::kInvalidPacket,
691 buffer->InsertPacket(/*packet=*/std::move(packet),
692 /*stats=*/&mock_stats,
693 /*last_decoded_length=*/payload_len,
694 /*sample_rate=*/1000,
695 /*target_level_ms=*/60,
696 /*decoder_database=*/decoder_database));
697 }
698 // Buffer should still be empty. Test all empty-checks.
699 uint32_t temp_ts;
700 EXPECT_EQ(PacketBuffer::kBufferEmpty, buffer->NextTimestamp(&temp_ts));
701 EXPECT_EQ(PacketBuffer::kBufferEmpty,
702 buffer->NextHigherTimestamp(0, &temp_ts));
703 EXPECT_EQ(NULL, buffer->PeekNextPacket());
704 EXPECT_FALSE(buffer->GetNextPacket());
705
706 // Discarding packets will not invoke mock_stats.PacketDiscarded() because the
707 // packet buffer is empty.
708 EXPECT_EQ(PacketBuffer::kBufferEmpty, buffer->DiscardNextPacket(&mock_stats));
709 buffer->DiscardAllOldPackets(0, &mock_stats);
710
711 // Insert one packet to make the buffer non-empty.
712 EXPECT_EQ(
713 PacketBuffer::kOK,
714 buffer->InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
715 /*stats=*/&mock_stats,
716 /*last_decoded_length=*/payload_len,
717 /*sample_rate=*/1000,
718 /*target_level_ms=*/60,
719 /*decoder_database=*/decoder_database));
720 EXPECT_EQ(PacketBuffer::kInvalidPointer, buffer->NextTimestamp(NULL));
721 EXPECT_EQ(PacketBuffer::kInvalidPointer,
722 buffer->NextHigherTimestamp(0, NULL));
723 delete buffer;
724
725 // Insert packet list of three packets, where the second packet has an invalid
726 // payload. Expect first packet to be inserted, and the remaining two to be
727 // discarded.
728 buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
729 PacketList list;
730 list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
731 {
732 Packet packet = gen.NextPacket(payload_len, nullptr);
733 packet.payload.Clear(); // Invalid.
734 list.push_back(std::move(packet));
735 }
736 list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
737 auto factory = CreateBuiltinAudioDecoderFactory();
738 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
739 absl::nullopt, factory.get());
740 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
741 .WillRepeatedly(Return(&info));
742 absl::optional<uint8_t> current_pt;
743 absl::optional<uint8_t> current_cng_pt;
744 EXPECT_EQ(
745 PacketBuffer::kInvalidPacket,
746 buffer->InsertPacketList(/*packet_list=*/&list,
747 /*decoder_database=*/decoder_database,
748 /*current_rtp_payload_type=*/¤t_pt,
749 /*current_cng_rtp_payload_type=*/¤t_cng_pt,
750 /*stats=*/&mock_stats,
751 /*last_decoded_length=*/payload_len,
752 /*sample_rate=*/1000,
753 /*target_level_ms=*/30));
754 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
755 EXPECT_EQ(1u, buffer->NumPacketsInBuffer());
756 delete buffer;
757 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
758 }
759
760 // Test packet comparison function.
761 // The function should return true if the first packet "goes before" the second.
TEST(PacketBuffer,ComparePackets)762 TEST(PacketBuffer, ComparePackets) {
763 PacketGenerator gen(0, 0, 0, 10);
764 Packet a(gen.NextPacket(10, nullptr)); // SN = 0, TS = 0.
765 Packet b(gen.NextPacket(10, nullptr)); // SN = 1, TS = 10.
766 EXPECT_FALSE(a == b);
767 EXPECT_TRUE(a != b);
768 EXPECT_TRUE(a < b);
769 EXPECT_FALSE(a > b);
770 EXPECT_TRUE(a <= b);
771 EXPECT_FALSE(a >= b);
772
773 // Testing wrap-around case; 'a' is earlier but has a larger timestamp value.
774 a.timestamp = 0xFFFFFFFF - 10;
775 EXPECT_FALSE(a == b);
776 EXPECT_TRUE(a != b);
777 EXPECT_TRUE(a < b);
778 EXPECT_FALSE(a > b);
779 EXPECT_TRUE(a <= b);
780 EXPECT_FALSE(a >= b);
781
782 // Test equal packets.
783 EXPECT_TRUE(a == a);
784 EXPECT_FALSE(a != a);
785 EXPECT_FALSE(a < a);
786 EXPECT_FALSE(a > a);
787 EXPECT_TRUE(a <= a);
788 EXPECT_TRUE(a >= a);
789
790 // Test equal timestamps but different sequence numbers (0 and 1).
791 a.timestamp = b.timestamp;
792 EXPECT_FALSE(a == b);
793 EXPECT_TRUE(a != b);
794 EXPECT_TRUE(a < b);
795 EXPECT_FALSE(a > b);
796 EXPECT_TRUE(a <= b);
797 EXPECT_FALSE(a >= b);
798
799 // Test equal timestamps but different sequence numbers (32767 and 1).
800 a.sequence_number = 0xFFFF;
801 EXPECT_FALSE(a == b);
802 EXPECT_TRUE(a != b);
803 EXPECT_TRUE(a < b);
804 EXPECT_FALSE(a > b);
805 EXPECT_TRUE(a <= b);
806 EXPECT_FALSE(a >= b);
807
808 // Test equal timestamps and sequence numbers, but differing priorities.
809 a.sequence_number = b.sequence_number;
810 a.priority = {1, 0};
811 b.priority = {0, 0};
812 // a after b
813 EXPECT_FALSE(a == b);
814 EXPECT_TRUE(a != b);
815 EXPECT_FALSE(a < b);
816 EXPECT_TRUE(a > b);
817 EXPECT_FALSE(a <= b);
818 EXPECT_TRUE(a >= b);
819
820 Packet c(gen.NextPacket(0, nullptr)); // SN = 2, TS = 20.
821 Packet d(gen.NextPacket(0, nullptr)); // SN = 3, TS = 20.
822 c.timestamp = b.timestamp;
823 d.timestamp = b.timestamp;
824 c.sequence_number = b.sequence_number;
825 d.sequence_number = b.sequence_number;
826 c.priority = {1, 1};
827 d.priority = {0, 1};
828 // c after d
829 EXPECT_FALSE(c == d);
830 EXPECT_TRUE(c != d);
831 EXPECT_FALSE(c < d);
832 EXPECT_TRUE(c > d);
833 EXPECT_FALSE(c <= d);
834 EXPECT_TRUE(c >= d);
835
836 // c after a
837 EXPECT_FALSE(c == a);
838 EXPECT_TRUE(c != a);
839 EXPECT_FALSE(c < a);
840 EXPECT_TRUE(c > a);
841 EXPECT_FALSE(c <= a);
842 EXPECT_TRUE(c >= a);
843
844 // c after b
845 EXPECT_FALSE(c == b);
846 EXPECT_TRUE(c != b);
847 EXPECT_FALSE(c < b);
848 EXPECT_TRUE(c > b);
849 EXPECT_FALSE(c <= b);
850 EXPECT_TRUE(c >= b);
851
852 // a after d
853 EXPECT_FALSE(a == d);
854 EXPECT_TRUE(a != d);
855 EXPECT_FALSE(a < d);
856 EXPECT_TRUE(a > d);
857 EXPECT_FALSE(a <= d);
858 EXPECT_TRUE(a >= d);
859
860 // d after b
861 EXPECT_FALSE(d == b);
862 EXPECT_TRUE(d != b);
863 EXPECT_FALSE(d < b);
864 EXPECT_TRUE(d > b);
865 EXPECT_FALSE(d <= b);
866 EXPECT_TRUE(d >= b);
867 }
868
TEST(PacketBuffer,GetSpanSamples)869 TEST(PacketBuffer, GetSpanSamples) {
870 constexpr size_t kFrameSizeSamples = 10;
871 constexpr int kPayloadSizeBytes = 1; // Does not matter to this test;
872 constexpr uint32_t kStartTimeStamp = 0xFFFFFFFE; // Close to wrap around.
873 constexpr int kSampleRateHz = 48000;
874 constexpr bool KCountDtxWaitingTime = false;
875 TickTimer tick_timer;
876 PacketBuffer buffer(3, &tick_timer);
877 PacketGenerator gen(0, kStartTimeStamp, 0, kFrameSizeSamples);
878 StrictMock<MockStatisticsCalculator> mock_stats;
879 MockDecoderDatabase decoder_database;
880
881 Packet packet_1 = gen.NextPacket(kPayloadSizeBytes, nullptr);
882
883 std::unique_ptr<MockEncodedAudioFrame> mock_audio_frame =
884 std::make_unique<MockEncodedAudioFrame>();
885 EXPECT_CALL(*mock_audio_frame, Duration())
886 .WillRepeatedly(Return(kFrameSizeSamples));
887 Packet packet_2 =
888 gen.NextPacket(kPayloadSizeBytes, std::move(mock_audio_frame));
889
890 RTC_DCHECK_GT(packet_1.timestamp,
891 packet_2.timestamp); // Tmestamp wrapped around.
892
893 EXPECT_EQ(PacketBuffer::kOK,
894 buffer.InsertPacket(/*packet=*/std::move(packet_1),
895 /*stats=*/&mock_stats,
896 /*last_decoded_length=*/kFrameSizeSamples,
897 /*sample_rate=*/1000,
898 /*target_level_ms=*/60,
899 /*decoder_database=*/decoder_database));
900
901 constexpr size_t kLastDecodedSizeSamples = 2;
902 // packet_1 has no access to duration, and relies last decoded duration as
903 // input.
904 EXPECT_EQ(kLastDecodedSizeSamples,
905 buffer.GetSpanSamples(kLastDecodedSizeSamples, kSampleRateHz,
906 KCountDtxWaitingTime));
907
908 EXPECT_EQ(PacketBuffer::kOK,
909 buffer.InsertPacket(/*packet=*/std::move(packet_2),
910 /*stats=*/&mock_stats,
911 /*last_decoded_length=*/kFrameSizeSamples,
912 /*sample_rate=*/1000,
913 /*target_level_ms=*/60,
914 /*decoder_database=*/decoder_database));
915
916 EXPECT_EQ(kFrameSizeSamples * 2,
917 buffer.GetSpanSamples(0, kSampleRateHz, KCountDtxWaitingTime));
918
919 // packet_2 has access to duration, and ignores last decoded duration as
920 // input.
921 EXPECT_EQ(kFrameSizeSamples * 2,
922 buffer.GetSpanSamples(kLastDecodedSizeSamples, kSampleRateHz,
923 KCountDtxWaitingTime));
924 }
925
926 namespace {
TestIsObsoleteTimestamp(uint32_t limit_timestamp)927 void TestIsObsoleteTimestamp(uint32_t limit_timestamp) {
928 // Check with zero horizon, which implies that the horizon is at 2^31, i.e.,
929 // half the timestamp range.
930 static const uint32_t kZeroHorizon = 0;
931 static const uint32_t k2Pow31Minus1 = 0x7FFFFFFF;
932 // Timestamp on the limit is not old.
933 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
934 limit_timestamp, limit_timestamp, kZeroHorizon));
935 // 1 sample behind is old.
936 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 1,
937 limit_timestamp, kZeroHorizon));
938 // 2^31 - 1 samples behind is old.
939 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - k2Pow31Minus1,
940 limit_timestamp, kZeroHorizon));
941 // 1 sample ahead is not old.
942 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
943 limit_timestamp + 1, limit_timestamp, kZeroHorizon));
944 // If |t1-t2|=2^31 and t1>t2, t2 is older than t1 but not the opposite.
945 uint32_t other_timestamp = limit_timestamp + (1 << 31);
946 uint32_t lowest_timestamp = std::min(limit_timestamp, other_timestamp);
947 uint32_t highest_timestamp = std::max(limit_timestamp, other_timestamp);
948 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(
949 lowest_timestamp, highest_timestamp, kZeroHorizon));
950 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
951 highest_timestamp, lowest_timestamp, kZeroHorizon));
952
953 // Fixed horizon at 10 samples.
954 static const uint32_t kHorizon = 10;
955 // Timestamp on the limit is not old.
956 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp,
957 limit_timestamp, kHorizon));
958 // 1 sample behind is old.
959 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 1,
960 limit_timestamp, kHorizon));
961 // 9 samples behind is old.
962 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 9,
963 limit_timestamp, kHorizon));
964 // 10 samples behind is not old.
965 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 10,
966 limit_timestamp, kHorizon));
967 // 2^31 - 1 samples behind is not old.
968 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
969 limit_timestamp - k2Pow31Minus1, limit_timestamp, kHorizon));
970 // 1 sample ahead is not old.
971 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp + 1,
972 limit_timestamp, kHorizon));
973 // 2^31 samples ahead is not old.
974 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp + (1 << 31),
975 limit_timestamp, kHorizon));
976 }
977 } // namespace
978
979 // Test the IsObsoleteTimestamp method with different limit timestamps.
TEST(PacketBuffer,IsObsoleteTimestamp)980 TEST(PacketBuffer, IsObsoleteTimestamp) {
981 TestIsObsoleteTimestamp(0);
982 TestIsObsoleteTimestamp(1);
983 TestIsObsoleteTimestamp(0xFFFFFFFF); // -1 in uint32_t.
984 TestIsObsoleteTimestamp(0x80000000); // 2^31.
985 TestIsObsoleteTimestamp(0x80000001); // 2^31 + 1.
986 TestIsObsoleteTimestamp(0x7FFFFFFF); // 2^31 - 1.
987 }
988
989 } // namespace webrtc
990