blob: 4286006b6e64105286187ac4fb49fb5b68c01793 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_coding/neteq/packet_buffer.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Ivo Creusen3ce44a32019-10-31 14:38:11 +010018#include "api/neteq/tick_timer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#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"
Ivo Creusen7b463c52020-11-25 11:32:40 +010022#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "test/gmock.h"
24#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000025
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000026using ::testing::_;
henrik.lundin63d146b2017-07-05 07:03:34 -070027using ::testing::InSequence;
28using ::testing::MockFunction;
Jonas Olssona4d87372019-07-05 19:08:33 +020029using ::testing::Return;
30using ::testing::StrictMock;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000031
Minyue Li3f2eeb82019-07-03 16:43:29 +020032namespace {
33class MockEncodedAudioFrame : public webrtc::AudioDecoder::EncodedAudioFrame {
34 public:
Danil Chapovalov704fb552020-05-18 15:10:15 +020035 MOCK_METHOD(size_t, Duration, (), (const, override));
Minyue Li3f2eeb82019-07-03 16:43:29 +020036
Danil Chapovalov704fb552020-05-18 15:10:15 +020037 MOCK_METHOD(bool, IsDtxPacket, (), (const, override));
Minyue Li3f2eeb82019-07-03 16:43:29 +020038
Danil Chapovalov704fb552020-05-18 15:10:15 +020039 MOCK_METHOD(absl::optional<DecodeResult>,
40 Decode,
41 (rtc::ArrayView<int16_t> decoded),
42 (const, override));
Minyue Li3f2eeb82019-07-03 16:43:29 +020043};
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000044
45// Helper class to generate packets. Packets must be deleted by the user.
46class PacketGenerator {
47 public:
48 PacketGenerator(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
49 virtual ~PacketGenerator() {}
minyue@webrtc.orgc8039072014-10-09 10:49:54 +000050 void Reset(uint16_t seq_no, uint32_t ts, uint8_t pt, int frame_size);
Minyue Li3f2eeb82019-07-03 16:43:29 +020051 webrtc::Packet NextPacket(
52 int payload_size_bytes,
53 std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000054
55 uint16_t seq_no_;
56 uint32_t ts_;
57 uint8_t pt_;
58 int frame_size_;
59};
60
Jonas Olssona4d87372019-07-05 19:08:33 +020061PacketGenerator::PacketGenerator(uint16_t seq_no,
62 uint32_t ts,
63 uint8_t pt,
minyue@webrtc.orgc8039072014-10-09 10:49:54 +000064 int frame_size) {
65 Reset(seq_no, ts, pt, frame_size);
66}
67
Jonas Olssona4d87372019-07-05 19:08:33 +020068void PacketGenerator::Reset(uint16_t seq_no,
69 uint32_t ts,
70 uint8_t pt,
minyue@webrtc.orgc8039072014-10-09 10:49:54 +000071 int frame_size) {
72 seq_no_ = seq_no;
73 ts_ = ts;
74 pt_ = pt;
75 frame_size_ = frame_size;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000076}
77
Minyue Li3f2eeb82019-07-03 16:43:29 +020078webrtc::Packet PacketGenerator::NextPacket(
79 int payload_size_bytes,
80 std::unique_ptr<webrtc::AudioDecoder::EncodedAudioFrame> audio_frame) {
81 webrtc::Packet packet;
ossua73f6c92016-10-24 08:25:28 -070082 packet.sequence_number = seq_no_;
83 packet.timestamp = ts_;
84 packet.payload_type = pt_;
85 packet.payload.SetSize(payload_size_bytes);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000086 ++seq_no_;
87 ts_ += frame_size_;
Minyue Li3f2eeb82019-07-03 16:43:29 +020088 packet.frame = std::move(audio_frame);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000089 return packet;
90}
91
minyue@webrtc.orgc8039072014-10-09 10:49:54 +000092struct 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};
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000102
Minyue Li3f2eeb82019-07-03 16:43:29 +0200103} // namespace
104
105namespace webrtc {
106
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000107// Start of test definitions.
108
109TEST(PacketBuffer, CreateAndDestroy) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700110 TickTimer tick_timer;
111 PacketBuffer* buffer = new PacketBuffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000112 EXPECT_TRUE(buffer->Empty());
113 delete buffer;
114}
115
116TEST(PacketBuffer, InsertPacket) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700117 TickTimer tick_timer;
118 PacketBuffer buffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119 PacketGenerator gen(17u, 4711u, 0, 10);
minyue-webrtc12d30842017-07-19 11:44:06 +0200120 StrictMock<MockStatisticsCalculator> mock_stats;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100121 MockDecoderDatabase decoder_database;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000122
123 const int payload_len = 100;
Minyue Li3f2eeb82019-07-03 16:43:29 +0200124 const Packet packet = gen.NextPacket(payload_len, nullptr);
Ivo Creusen7b463c52020-11-25 11:32:40 +0100125 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));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000131 uint32_t next_ts;
132 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
133 EXPECT_EQ(4711u, next_ts);
134 EXPECT_FALSE(buffer.Empty());
Peter Kastingdce40cf2015-08-24 14:52:23 -0700135 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
ossu7a377612016-10-18 04:06:13 -0700136 const Packet* next_packet = buffer.PeekNextPacket();
ossua73f6c92016-10-24 08:25:28 -0700137 EXPECT_EQ(packet, *next_packet); // Compare contents.
Ivo Creusen7b463c52020-11-25 11:32:40 +0100138 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000139
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.
145TEST(PacketBuffer, FlushBuffer) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700146 TickTimer tick_timer;
147 PacketBuffer buffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000148 PacketGenerator gen(0, 0, 0, 10);
149 const int payload_len = 10;
minyue-webrtc12d30842017-07-19 11:44:06 +0200150 StrictMock<MockStatisticsCalculator> mock_stats;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100151 MockDecoderDatabase decoder_database;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000152
153 // Insert 10 small packets; should be ok.
154 for (int i = 0; i < 10; ++i) {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200155 EXPECT_EQ(
156 PacketBuffer::kOK,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100157 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));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000163 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700164 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000165 EXPECT_FALSE(buffer.Empty());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000166
Ivo Creusen7b463c52020-11-25 11:32:40 +0100167 EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
168 buffer.Flush(&mock_stats);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000169 // Buffer should delete the payloads itself.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700170 EXPECT_EQ(0u, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171 EXPECT_TRUE(buffer.Empty());
Ivo Creusen7b463c52020-11-25 11:32:40 +0100172 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000173}
174
175// Test to fill the buffer over the limits, and verify that it flushes.
176TEST(PacketBuffer, OverfillBuffer) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700177 TickTimer tick_timer;
178 PacketBuffer buffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000179 PacketGenerator gen(0, 0, 0, 10);
minyue-webrtc12d30842017-07-19 11:44:06 +0200180 StrictMock<MockStatisticsCalculator> mock_stats;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100181 MockDecoderDatabase decoder_database;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000182
183 // Insert 10 small packets; should be ok.
184 const int payload_len = 10;
185 int i;
186 for (i = 0; i < 10; ++i) {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200187 EXPECT_EQ(
188 PacketBuffer::kOK,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100189 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.
220TEST(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.
259TEST(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));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700283 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000284 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
Minyue Li3f2eeb82019-07-03 16:43:29 +0200288 const Packet packet = gen.NextPacket(payload_len, nullptr);
Ivo Creusen7b463c52020-11-25 11:32:40 +0100289 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.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000301}
302
303// Test inserting a list of packets.
304TEST(PacketBuffer, InsertPacketList) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700305 TickTimer tick_timer;
306 PacketBuffer buffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000307 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) {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200313 list.push_back(gen.NextPacket(payload_len, nullptr));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000314 }
315
316 MockDecoderDatabase decoder_database;
henrik.lundinebd9fd72016-08-31 13:03:36 -0700317 auto factory = CreateBuiltinAudioDecoderFactory();
Niels Möller72899062019-01-11 09:36:13 +0100318 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200319 absl::nullopt, factory);
henrik.lundinebd9fd72016-08-31 13:03:36 -0700320 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
321 .WillRepeatedly(Return(&info));
minyue-webrtc12d30842017-07-19 11:44:06 +0200322
323 StrictMock<MockStatisticsCalculator> mock_stats;
324
Danil Chapovalovb6021232018-06-19 13:26:36 +0200325 absl::optional<uint8_t> current_pt;
326 absl::optional<uint8_t> current_cng_pt;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100327 EXPECT_EQ(
328 PacketBuffer::kOK,
329 buffer.InsertPacketList(/*packet_list=*/&list,
330 /*decoder_database=*/decoder_database,
331 /*current_rtp_payload_type=*/&current_pt,
332 /*current_cng_rtp_payload_type=*/&current_cng_pt,
333 /*stats=*/&mock_stats,
334 /*last_decoded_length=*/payload_len,
335 /*sample_rate=*/1000,
336 /*target_level_ms=*/30));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000337 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700338 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
Jonas Olssona4d87372019-07-05 19:08:33 +0200339 EXPECT_EQ(0, current_pt); // Current payload type changed to 0.
Danil Chapovalovb6021232018-06-19 13:26:36 +0200340 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type not changed.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000341
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000342 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.
348TEST(PacketBuffer, InsertPacketListChangePayloadType) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700349 TickTimer tick_timer;
350 PacketBuffer buffer(10, &tick_timer); // 10 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000351 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) {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200357 list.push_back(gen.NextPacket(payload_len, nullptr));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000358 }
359 // Insert 11th packet of another payload type (not CNG).
ossua73f6c92016-10-24 08:25:28 -0700360 {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200361 Packet packet = gen.NextPacket(payload_len, nullptr);
ossua73f6c92016-10-24 08:25:28 -0700362 packet.payload_type = 1;
363 list.push_back(std::move(packet));
364 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000365
366 MockDecoderDatabase decoder_database;
henrik.lundinebd9fd72016-08-31 13:03:36 -0700367 auto factory = CreateBuiltinAudioDecoderFactory();
Niels Möller72899062019-01-11 09:36:13 +0100368 const DecoderDatabase::DecoderInfo info0(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200369 absl::nullopt, factory);
henrik.lundinebd9fd72016-08-31 13:03:36 -0700370 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
371 .WillRepeatedly(Return(&info0));
Niels Möller72899062019-01-11 09:36:13 +0100372 const DecoderDatabase::DecoderInfo info1(SdpAudioFormat("pcma", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200373 absl::nullopt, factory);
henrik.lundinebd9fd72016-08-31 13:03:36 -0700374 EXPECT_CALL(decoder_database, GetDecoderInfo(1))
375 .WillRepeatedly(Return(&info1));
minyue-webrtc12d30842017-07-19 11:44:06 +0200376
377 StrictMock<MockStatisticsCalculator> mock_stats;
378
Danil Chapovalovb6021232018-06-19 13:26:36 +0200379 absl::optional<uint8_t> current_pt;
380 absl::optional<uint8_t> current_cng_pt;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100381 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=*/&current_pt,
387 /*current_cng_rtp_payload_type=*/&current_cng_pt,
388 /*stats=*/&mock_stats,
389 /*last_decoded_length=*/payload_len,
390 /*sample_rate=*/1000,
391 /*target_level_ms=*/30));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000392 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700393 EXPECT_EQ(1u, buffer.NumPacketsInBuffer()); // Only the last packet.
Jonas Olssona4d87372019-07-05 19:08:33 +0200394 EXPECT_EQ(1, current_pt); // Current payload type changed to 1.
Danil Chapovalovb6021232018-06-19 13:26:36 +0200395 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type not changed.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000396
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000397 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
398}
399
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000400TEST(PacketBuffer, ExtractOrderRedundancy) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700401 TickTimer tick_timer;
402 PacketBuffer buffer(100, &tick_timer); // 100 packets.
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000403 const int kPackets = 18;
404 const int kFrameSize = 10;
405 const int kPayloadLength = 10;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000406
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000407 PacketsToInsert packet_facts[kPackets] = {
Jonas Olssona4d87372019-07-05 19:08:33 +0200408 {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},
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000417 };
Ivo Creusen7b463c52020-11-25 11:32:40 +0100418 MockDecoderDatabase decoder_database;
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000419
Peter Kastingdce40cf2015-08-24 14:52:23 -0700420 const size_t kExpectPacketsInBuffer = 9;
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000421
ossua73f6c92016-10-24 08:25:28 -0700422 std::vector<Packet> expect_order(kExpectPacketsInBuffer);
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000423
424 PacketGenerator gen(0, 0, 0, kFrameSize);
425
minyue-webrtc12d30842017-07-19 11:44:06 +0200426 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;
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000433 for (int i = 0; i < kPackets; ++i) {
Jonas Olssona4d87372019-07-05 19:08:33 +0200434 gen.Reset(packet_facts[i].sequence_number, packet_facts[i].timestamp,
435 packet_facts[i].payload_type, kFrameSize);
Minyue Li3f2eeb82019-07-03 16:43:29 +0200436 Packet packet = gen.NextPacket(kPayloadLength, nullptr);
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200437 packet.priority.codec_level = packet_facts[i].primary ? 0 : 1;
minyue-webrtc12d30842017-07-19 11:44:06 +0200438 if (packet_facts[i].extract_order < 0) {
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200439 if (packet.priority.codec_level > 0) {
440 EXPECT_CALL(mock_stats, SecondaryPacketsDiscarded(1));
441 } else {
442 EXPECT_CALL(mock_stats, PacketsDiscarded(1));
443 }
minyue-webrtc12d30842017-07-19 11:44:06 +0200444 }
445 EXPECT_CALL(check, Call(i));
446 EXPECT_EQ(PacketBuffer::kOK,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100447 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));
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000453 if (packet_facts[i].extract_order >= 0) {
ossua73f6c92016-10-24 08:25:28 -0700454 expect_order[packet_facts[i].extract_order] = std::move(packet);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000455 }
minyue-webrtc12d30842017-07-19 11:44:06 +0200456 check.Call(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000457 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000458
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000459 EXPECT_EQ(kExpectPacketsInBuffer, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000460
Peter Kastingdce40cf2015-08-24 14:52:23 -0700461 for (size_t i = 0; i < kExpectPacketsInBuffer; ++i) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200462 const absl::optional<Packet> packet = buffer.GetNextPacket();
ossua73f6c92016-10-24 08:25:28 -0700463 EXPECT_EQ(packet, expect_order[i]); // Compare contents.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000464 }
minyue@webrtc.orgc8039072014-10-09 10:49:54 +0000465 EXPECT_TRUE(buffer.Empty());
Ivo Creusen7b463c52020-11-25 11:32:40 +0100466 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000467}
468
469TEST(PacketBuffer, DiscardPackets) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700470 TickTimer tick_timer;
471 PacketBuffer buffer(100, &tick_timer); // 100 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000472 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;
minyue-webrtc12d30842017-07-19 11:44:06 +0200478 StrictMock<MockStatisticsCalculator> mock_stats;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100479 MockDecoderDatabase decoder_database;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000480
minyue-webrtcfae474c2017-07-05 11:17:40 +0200481 constexpr int kTotalPackets = 10;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000482 // Insert 10 small packets.
minyue-webrtcfae474c2017-07-05 11:17:40 +0200483 for (int i = 0; i < kTotalPackets; ++i) {
Ivo Creusen7b463c52020-11-25 11:32:40 +0100484 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000490 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700491 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000492
minyue-webrtcfae474c2017-07-05 11:17:40 +0200493 uint32_t current_ts = start_ts;
494
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000495 // Discard them one by one and make sure that the right packets are at the
496 // front of the buffer.
minyue-webrtcfae474c2017-07-05 11:17:40 +0200497 constexpr int kDiscardPackets = 5;
henrik.lundin63d146b2017-07-05 07:03:34 -0700498
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;
minyue-webrtcfae474c2017-07-05 11:17:40 +0200504 for (int i = 0; i < kDiscardPackets; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000505 uint32_t ts;
506 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&ts));
507 EXPECT_EQ(current_ts, ts);
henrik.lundin63d146b2017-07-05 07:03:34 -0700508 EXPECT_CALL(mock_stats, PacketsDiscarded(1));
509 EXPECT_CALL(check, Call(i));
minyue-webrtcfae474c2017-07-05 11:17:40 +0200510 EXPECT_EQ(PacketBuffer::kOK, buffer.DiscardNextPacket(&mock_stats));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000511 current_ts += ts_increment;
henrik.lundin63d146b2017-07-05 07:03:34 -0700512 check.Call(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000513 }
minyue-webrtcfae474c2017-07-05 11:17:40 +0200514
515 constexpr int kRemainingPackets = kTotalPackets - kDiscardPackets;
henrik.lundin63d146b2017-07-05 07:03:34 -0700516 // 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;
minyue-webrtc0c3ca752017-08-23 15:59:38 +0200519 EXPECT_CALL(mock_stats, PacketsDiscarded(1))
520 .Times(kRemainingPackets - kSkipPackets);
henrik.lundin63d146b2017-07-05 07:03:34 -0700521 EXPECT_CALL(check, Call(17)); // Arbitrary id number.
minyue-webrtcfae474c2017-07-05 11:17:40 +0200522 buffer.DiscardOldPackets(start_ts + kTotalPackets * ts_increment,
523 kRemainingPackets * ts_increment, &mock_stats);
henrik.lundin63d146b2017-07-05 07:03:34 -0700524 check.Call(17); // Same arbitrary id number.
525
526 EXPECT_EQ(kSkipPackets, buffer.NumPacketsInBuffer());
minyue-webrtcfae474c2017-07-05 11:17:40 +0200527 uint32_t ts;
528 EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&ts));
529 EXPECT_EQ(current_ts, ts);
530
531 // Discard all remaining packets.
henrik.lundin63d146b2017-07-05 07:03:34 -0700532 EXPECT_CALL(mock_stats, PacketsDiscarded(kSkipPackets));
minyue-webrtcfae474c2017-07-05 11:17:40 +0200533 buffer.DiscardAllOldPackets(start_ts + kTotalPackets * ts_increment,
534 &mock_stats);
535
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000536 EXPECT_TRUE(buffer.Empty());
Ivo Creusen7b463c52020-11-25 11:32:40 +0100537 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000538}
539
540TEST(PacketBuffer, Reordering) {
henrik.lundin84f8cd62016-04-26 07:45:16 -0700541 TickTimer tick_timer;
542 PacketBuffer buffer(100, &tick_timer); // 100 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000543 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) {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200554 Packet packet = gen.NextPacket(payload_len, nullptr);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000555 if (i % 2) {
ossua73f6c92016-10-24 08:25:28 -0700556 list.push_front(std::move(packet));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000557 } else {
ossua73f6c92016-10-24 08:25:28 -0700558 list.push_back(std::move(packet));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000559 }
560 }
561
562 MockDecoderDatabase decoder_database;
henrik.lundinebd9fd72016-08-31 13:03:36 -0700563 auto factory = CreateBuiltinAudioDecoderFactory();
Niels Möller72899062019-01-11 09:36:13 +0100564 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200565 absl::nullopt, factory);
henrik.lundinebd9fd72016-08-31 13:03:36 -0700566 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
567 .WillRepeatedly(Return(&info));
Danil Chapovalovb6021232018-06-19 13:26:36 +0200568 absl::optional<uint8_t> current_pt;
569 absl::optional<uint8_t> current_cng_pt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000570
minyue-webrtc12d30842017-07-19 11:44:06 +0200571 StrictMock<MockStatisticsCalculator> mock_stats;
572
Ivo Creusen7b463c52020-11-25 11:32:40 +0100573 EXPECT_EQ(
574 PacketBuffer::kOK,
575 buffer.InsertPacketList(/*packet_list=*/&list,
576 /*decoder_database=*/decoder_database,
577 /*current_rtp_payload_type=*/&current_pt,
578 /*current_cng_rtp_payload_type=*/&current_cng_pt,
579 /*stats=*/&mock_stats,
580 /*last_decoded_length=*/payload_len,
581 /*sample_rate=*/1000,
582 /*target_level_ms=*/30));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700583 EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000584
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) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200588 const absl::optional<Packet> packet = buffer.GetNextPacket();
ossua73f6c92016-10-24 08:25:28 -0700589 ASSERT_TRUE(packet);
ossu7a377612016-10-18 04:06:13 -0700590 EXPECT_EQ(current_ts, packet->timestamp);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000591 current_ts += ts_increment;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000592 }
593 EXPECT_TRUE(buffer.Empty());
594
595 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
596}
597
henrik.lundin067d8552016-09-01 23:19:05 -0700598// 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.
602TEST(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();
Niels Möller72899062019-01-11 09:36:13 +0100611 const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200612 absl::nullopt, factory);
henrik.lundin067d8552016-09-01 23:19:05 -0700613 EXPECT_CALL(decoder_database, GetDecoderInfo(kCngPt))
614 .WillRepeatedly(Return(&info_cng));
Niels Möller72899062019-01-11 09:36:13 +0100615 const DecoderDatabase::DecoderInfo info_speech(
616 SdpAudioFormat("l16", 16000, 1), absl::nullopt, factory);
henrik.lundin067d8552016-09-01 23:19:05 -0700617 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;
Minyue Li3f2eeb82019-07-03 16:43:29 +0200623 list.push_back(gen.NextPacket(kPayloadLen, nullptr));
Danil Chapovalovb6021232018-06-19 13:26:36 +0200624 absl::optional<uint8_t> current_pt;
625 absl::optional<uint8_t> current_cng_pt;
minyue-webrtc12d30842017-07-19 11:44:06 +0200626
627 StrictMock<MockStatisticsCalculator> mock_stats;
628
Ivo Creusen7b463c52020-11-25 11:32:40 +0100629 EXPECT_EQ(
630 PacketBuffer::kOK,
631 buffer.InsertPacketList(/*packet_list=*/&list,
632 /*decoder_database=*/decoder_database,
633 /*current_rtp_payload_type=*/&current_pt,
634 /*current_cng_rtp_payload_type=*/&current_cng_pt,
635 /*stats=*/&mock_stats,
636 /*last_decoded_length=*/kPayloadLen,
637 /*sample_rate=*/1000,
638 /*target_level_ms=*/30));
henrik.lundin067d8552016-09-01 23:19:05 -0700639 EXPECT_TRUE(list.empty());
640 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
ossu7a377612016-10-18 04:06:13 -0700641 ASSERT_TRUE(buffer.PeekNextPacket());
642 EXPECT_EQ(kCngPt, buffer.PeekNextPacket()->payload_type);
Danil Chapovalovb6021232018-06-19 13:26:36 +0200643 EXPECT_EQ(current_pt, absl::nullopt); // Current payload type not set.
Jonas Olssona4d87372019-07-05 19:08:33 +0200644 EXPECT_EQ(kCngPt, current_cng_pt); // CNG payload type set.
henrik.lundin067d8552016-09-01 23:19:05 -0700645
646 // Insert second packet, which is wide-band speech.
ossua73f6c92016-10-24 08:25:28 -0700647 {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200648 Packet packet = gen.NextPacket(kPayloadLen, nullptr);
ossua73f6c92016-10-24 08:25:28 -0700649 packet.payload_type = kSpeechPt;
650 list.push_back(std::move(packet));
651 }
henrik.lundin067d8552016-09-01 23:19:05 -0700652 // Expect the buffer to flush out the CNG packet, since it does not match the
653 // new speech sample rate.
Ivo Creusen7b463c52020-11-25 11:32:40 +0100654 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=*/&current_pt,
660 /*current_cng_rtp_payload_type=*/&current_cng_pt,
661 /*stats=*/&mock_stats,
662 /*last_decoded_length=*/kPayloadLen,
663 /*sample_rate=*/1000,
664 /*target_level_ms=*/30));
henrik.lundin067d8552016-09-01 23:19:05 -0700665 EXPECT_TRUE(list.empty());
666 EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
ossu7a377612016-10-18 04:06:13 -0700667 ASSERT_TRUE(buffer.PeekNextPacket());
668 EXPECT_EQ(kSpeechPt, buffer.PeekNextPacket()->payload_type);
henrik.lundin067d8552016-09-01 23:19:05 -0700669
Jonas Olssona4d87372019-07-05 19:08:33 +0200670 EXPECT_EQ(kSpeechPt, current_pt); // Current payload type set.
Danil Chapovalovb6021232018-06-19 13:26:36 +0200671 EXPECT_EQ(absl::nullopt, current_cng_pt); // CNG payload type reset.
henrik.lundin067d8552016-09-01 23:19:05 -0700672
henrik.lundin067d8552016-09-01 23:19:05 -0700673 EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
674}
675
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000676TEST(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);
henrik.lundin84f8cd62016-04-26 07:45:16 -0700682 TickTimer tick_timer;
minyue-webrtc12d30842017-07-19 11:44:06 +0200683 StrictMock<MockStatisticsCalculator> mock_stats;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100684 MockDecoderDatabase decoder_database;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000685
henrik.lundin84f8cd62016-04-26 07:45:16 -0700686 PacketBuffer* buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
ossua73f6c92016-10-24 08:25:28 -0700687 {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200688 Packet packet = gen.NextPacket(payload_len, nullptr);
ossua73f6c92016-10-24 08:25:28 -0700689 packet.payload.Clear();
690 EXPECT_EQ(PacketBuffer::kInvalidPacket,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100691 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));
ossua73f6c92016-10-24 08:25:28 -0700697 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000698 // 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));
ossu7a377612016-10-18 04:06:13 -0700703 EXPECT_EQ(NULL, buffer->PeekNextPacket());
ossua73f6c92016-10-24 08:25:28 -0700704 EXPECT_FALSE(buffer->GetNextPacket());
minyue-webrtcfae474c2017-07-05 11:17:40 +0200705
minyue-webrtcfae474c2017-07-05 11:17:40 +0200706 // 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000710
711 // Insert one packet to make the buffer non-empty.
Minyue Li3f2eeb82019-07-03 16:43:29 +0200712 EXPECT_EQ(
713 PacketBuffer::kOK,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100714 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));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000720 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.
henrik.lundin84f8cd62016-04-26 07:45:16 -0700728 buffer = new PacketBuffer(100, &tick_timer); // 100 packets.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000729 PacketList list;
Minyue Li3f2eeb82019-07-03 16:43:29 +0200730 list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
ossua73f6c92016-10-24 08:25:28 -0700731 {
Minyue Li3f2eeb82019-07-03 16:43:29 +0200732 Packet packet = gen.NextPacket(payload_len, nullptr);
ossua73f6c92016-10-24 08:25:28 -0700733 packet.payload.Clear(); // Invalid.
734 list.push_back(std::move(packet));
735 }
Minyue Li3f2eeb82019-07-03 16:43:29 +0200736 list.push_back(gen.NextPacket(payload_len, nullptr)); // Valid packet.
henrik.lundinebd9fd72016-08-31 13:03:36 -0700737 auto factory = CreateBuiltinAudioDecoderFactory();
Niels Möller72899062019-01-11 09:36:13 +0100738 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200739 absl::nullopt, factory);
henrik.lundinebd9fd72016-08-31 13:03:36 -0700740 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
741 .WillRepeatedly(Return(&info));
Danil Chapovalovb6021232018-06-19 13:26:36 +0200742 absl::optional<uint8_t> current_pt;
743 absl::optional<uint8_t> current_cng_pt;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100744 EXPECT_EQ(
745 PacketBuffer::kInvalidPacket,
746 buffer->InsertPacketList(/*packet_list=*/&list,
747 /*decoder_database=*/decoder_database,
748 /*current_rtp_payload_type=*/&current_pt,
749 /*current_cng_rtp_payload_type=*/&current_cng_pt,
750 /*stats=*/&mock_stats,
751 /*last_decoded_length=*/payload_len,
752 /*sample_rate=*/1000,
753 /*target_level_ms=*/30));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000754 EXPECT_TRUE(list.empty()); // The PacketBuffer should have depleted the list.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700755 EXPECT_EQ(1u, buffer->NumPacketsInBuffer());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000756 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.
762TEST(PacketBuffer, ComparePackets) {
763 PacketGenerator gen(0, 0, 0, 10);
Minyue Li3f2eeb82019-07-03 16:43:29 +0200764 Packet a(gen.NextPacket(10, nullptr)); // SN = 0, TS = 0.
765 Packet b(gen.NextPacket(10, nullptr)); // SN = 1, TS = 10.
ossua73f6c92016-10-24 08:25:28 -0700766 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000772
773 // Testing wrap-around case; 'a' is earlier but has a larger timestamp value.
ossua73f6c92016-10-24 08:25:28 -0700774 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000781
782 // Test equal packets.
ossua73f6c92016-10-24 08:25:28 -0700783 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000789
790 // Test equal timestamps but different sequence numbers (0 and 1).
ossua73f6c92016-10-24 08:25:28 -0700791 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000798
799 // Test equal timestamps but different sequence numbers (32767 and 1).
ossua73f6c92016-10-24 08:25:28 -0700800 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000807
ossua70695a2016-09-22 02:06:28 -0700808 // Test equal timestamps and sequence numbers, but differing priorities.
ossua73f6c92016-10-24 08:25:28 -0700809 a.sequence_number = b.sequence_number;
810 a.priority = {1, 0};
811 b.priority = {0, 0};
ossua70695a2016-09-22 02:06:28 -0700812 // a after b
ossua73f6c92016-10-24 08:25:28 -0700813 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000819
Minyue Li3f2eeb82019-07-03 16:43:29 +0200820 Packet c(gen.NextPacket(0, nullptr)); // SN = 2, TS = 20.
821 Packet d(gen.NextPacket(0, nullptr)); // SN = 3, TS = 20.
ossua73f6c92016-10-24 08:25:28 -0700822 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};
ossua70695a2016-09-22 02:06:28 -0700828 // c after d
ossua73f6c92016-10-24 08:25:28 -0700829 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);
ossua70695a2016-09-22 02:06:28 -0700835
836 // c after a
ossua73f6c92016-10-24 08:25:28 -0700837 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);
ossua70695a2016-09-22 02:06:28 -0700843
844 // c after b
ossua73f6c92016-10-24 08:25:28 -0700845 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);
ossua70695a2016-09-22 02:06:28 -0700851
852 // a after d
ossua73f6c92016-10-24 08:25:28 -0700853 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);
ossua70695a2016-09-22 02:06:28 -0700859
860 // d after b
ossua73f6c92016-10-24 08:25:28 -0700861 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);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000867}
868
Minyue Li3f2eeb82019-07-03 16:43:29 +0200869TEST(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;
Ivo Creusen7b463c52020-11-25 11:32:40 +0100879 MockDecoderDatabase decoder_database;
Minyue Li3f2eeb82019-07-03 16:43:29 +0200880
881 Packet packet_1 = gen.NextPacket(kPayloadSizeBytes, nullptr);
882
883 std::unique_ptr<MockEncodedAudioFrame> mock_audio_frame =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200884 std::make_unique<MockEncodedAudioFrame>();
Minyue Li3f2eeb82019-07-03 16:43:29 +0200885 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,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100894 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));
Minyue Li3f2eeb82019-07-03 16:43:29 +0200900
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,
Ivo Creusen7b463c52020-11-25 11:32:40 +0100909 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));
Minyue Li3f2eeb82019-07-03 16:43:29 +0200915
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
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000926namespace {
927void 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.
Jonas Olssona4d87372019-07-05 19:08:33 +0200936 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 1,
937 limit_timestamp, kZeroHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000938 // 2^31 - 1 samples behind is old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200939 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - k2Pow31Minus1,
940 limit_timestamp, kZeroHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000941 // 1 sample ahead is not old.
942 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
943 limit_timestamp + 1, limit_timestamp, kZeroHorizon));
Cesar Magalhaesf69f1fb2015-05-30 17:49:18 +0200944 // 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));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000950 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(
Cesar Magalhaesf69f1fb2015-05-30 17:49:18 +0200951 highest_timestamp, lowest_timestamp, kZeroHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000952
953 // Fixed horizon at 10 samples.
954 static const uint32_t kHorizon = 10;
955 // Timestamp on the limit is not old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200956 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp,
957 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000958 // 1 sample behind is old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200959 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 1,
960 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000961 // 9 samples behind is old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200962 EXPECT_TRUE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 9,
963 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000964 // 10 samples behind is not old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200965 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp - 10,
966 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000967 // 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.
Jonas Olssona4d87372019-07-05 19:08:33 +0200971 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp + 1,
972 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000973 // 2^31 samples ahead is not old.
Jonas Olssona4d87372019-07-05 19:08:33 +0200974 EXPECT_FALSE(PacketBuffer::IsObsoleteTimestamp(limit_timestamp + (1 << 31),
975 limit_timestamp, kHorizon));
henrik.lundin@webrtc.org52b42cb2014-11-04 14:03:58 +0000976}
977} // namespace
978
979// Test the IsObsoleteTimestamp method with different limit timestamps.
980TEST(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}
Minyue Li3f2eeb82019-07-03 16:43:29 +0200988
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000989} // namespace webrtc