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 PayloadSplitter class.
12
13 #include "webrtc/modules/audio_coding/neteq/payload_splitter.h"
14
15 #include <assert.h>
16
17 #include <utility> // pair
18
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "webrtc/base/scoped_ptr.h"
21 #include "webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h"
22 #include "webrtc/modules/audio_coding/neteq/packet.h"
23
24 using ::testing::Return;
25 using ::testing::ReturnNull;
26
27 namespace webrtc {
28
29 static const int kRedPayloadType = 100;
30 static const size_t kPayloadLength = 10;
31 static const size_t kRedHeaderLength = 4; // 4 bytes RED header.
32 static const uint16_t kSequenceNumber = 0;
33 static const uint32_t kBaseTimestamp = 0x12345678;
34
35 // A possible Opus packet that contains FEC is the following.
36 // The frame is 20 ms in duration.
37 //
38 // 0 1 2 3
39 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 // |0|0|0|0|1|0|0|0|x|1|x|x|x|x|x|x|x| |
42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
43 // | Compressed frame 1 (N-2 bytes)... :
44 // : |
45 // | |
46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
CreateOpusFecPayload(uint8_t * payload,size_t payload_length,uint8_t payload_value)47 void CreateOpusFecPayload(uint8_t* payload, size_t payload_length,
48 uint8_t payload_value) {
49 if (payload_length < 2) {
50 return;
51 }
52 payload[0] = 0x08;
53 payload[1] = 0x40;
54 memset(&payload[2], payload_value, payload_length - 2);
55 }
56
57 // RED headers (according to RFC 2198):
58 //
59 // 0 1 2 3
60 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
61 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 // |F| block PT | timestamp offset | block length |
63 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 //
65 // Last RED header:
66 // 0 1 2 3 4 5 6 7
67 // +-+-+-+-+-+-+-+-+
68 // |0| Block PT |
69 // +-+-+-+-+-+-+-+-+
70
71 // Creates a RED packet, with |num_payloads| payloads, with payload types given
72 // by the values in array |payload_types| (which must be of length
73 // |num_payloads|). Each redundant payload is |timestamp_offset| samples
74 // "behind" the the previous payload.
CreateRedPayload(size_t num_payloads,uint8_t * payload_types,int timestamp_offset,bool embed_opus_fec=false)75 Packet* CreateRedPayload(size_t num_payloads,
76 uint8_t* payload_types,
77 int timestamp_offset,
78 bool embed_opus_fec = false) {
79 Packet* packet = new Packet;
80 packet->header.payloadType = kRedPayloadType;
81 packet->header.timestamp = kBaseTimestamp;
82 packet->header.sequenceNumber = kSequenceNumber;
83 packet->payload_length = (kPayloadLength + 1) +
84 (num_payloads - 1) * (kPayloadLength + kRedHeaderLength);
85 uint8_t* payload = new uint8_t[packet->payload_length];
86 uint8_t* payload_ptr = payload;
87 for (size_t i = 0; i < num_payloads; ++i) {
88 // Write the RED headers.
89 if (i == num_payloads - 1) {
90 // Special case for last payload.
91 *payload_ptr = payload_types[i] & 0x7F; // F = 0;
92 ++payload_ptr;
93 break;
94 }
95 *payload_ptr = payload_types[i] & 0x7F;
96 // Not the last block; set F = 1.
97 *payload_ptr |= 0x80;
98 ++payload_ptr;
99 int this_offset = (num_payloads - i - 1) * timestamp_offset;
100 *payload_ptr = this_offset >> 6;
101 ++payload_ptr;
102 assert(kPayloadLength <= 1023); // Max length described by 10 bits.
103 *payload_ptr = ((this_offset & 0x3F) << 2) | (kPayloadLength >> 8);
104 ++payload_ptr;
105 *payload_ptr = kPayloadLength & 0xFF;
106 ++payload_ptr;
107 }
108 for (size_t i = 0; i < num_payloads; ++i) {
109 // Write |i| to all bytes in each payload.
110 if (embed_opus_fec) {
111 CreateOpusFecPayload(payload_ptr, kPayloadLength,
112 static_cast<uint8_t>(i));
113 } else {
114 memset(payload_ptr, static_cast<int>(i), kPayloadLength);
115 }
116 payload_ptr += kPayloadLength;
117 }
118 packet->payload = payload;
119 return packet;
120 }
121
122 // Create a packet with all payload bytes set to |payload_value|.
CreatePacket(uint8_t payload_type,size_t payload_length,uint8_t payload_value,bool opus_fec=false)123 Packet* CreatePacket(uint8_t payload_type, size_t payload_length,
124 uint8_t payload_value, bool opus_fec = false) {
125 Packet* packet = new Packet;
126 packet->header.payloadType = payload_type;
127 packet->header.timestamp = kBaseTimestamp;
128 packet->header.sequenceNumber = kSequenceNumber;
129 packet->payload_length = payload_length;
130 uint8_t* payload = new uint8_t[packet->payload_length];
131 packet->payload = payload;
132 if (opus_fec) {
133 CreateOpusFecPayload(packet->payload, packet->payload_length,
134 payload_value);
135 } else {
136 memset(payload, payload_value, payload_length);
137 }
138 return packet;
139 }
140
141 // Checks that |packet| has the attributes given in the remaining parameters.
VerifyPacket(const Packet * packet,size_t payload_length,uint8_t payload_type,uint16_t sequence_number,uint32_t timestamp,uint8_t payload_value,bool primary=true)142 void VerifyPacket(const Packet* packet,
143 size_t payload_length,
144 uint8_t payload_type,
145 uint16_t sequence_number,
146 uint32_t timestamp,
147 uint8_t payload_value,
148 bool primary = true) {
149 EXPECT_EQ(payload_length, packet->payload_length);
150 EXPECT_EQ(payload_type, packet->header.payloadType);
151 EXPECT_EQ(sequence_number, packet->header.sequenceNumber);
152 EXPECT_EQ(timestamp, packet->header.timestamp);
153 EXPECT_EQ(primary, packet->primary);
154 ASSERT_FALSE(packet->payload == NULL);
155 for (size_t i = 0; i < packet->payload_length; ++i) {
156 EXPECT_EQ(payload_value, packet->payload[i]);
157 }
158 }
159
160 // Start of test definitions.
161
TEST(PayloadSplitter,CreateAndDestroy)162 TEST(PayloadSplitter, CreateAndDestroy) {
163 PayloadSplitter* splitter = new PayloadSplitter;
164 delete splitter;
165 }
166
167 // Packet A is split into A1 and A2.
TEST(RedPayloadSplitter,OnePacketTwoPayloads)168 TEST(RedPayloadSplitter, OnePacketTwoPayloads) {
169 uint8_t payload_types[] = {0, 0};
170 const int kTimestampOffset = 160;
171 Packet* packet = CreateRedPayload(2, payload_types, kTimestampOffset);
172 PacketList packet_list;
173 packet_list.push_back(packet);
174 PayloadSplitter splitter;
175 EXPECT_EQ(PayloadSplitter::kOK, splitter.SplitRed(&packet_list));
176 ASSERT_EQ(2u, packet_list.size());
177 // Check first packet. The first in list should always be the primary payload.
178 packet = packet_list.front();
179 VerifyPacket(packet, kPayloadLength, payload_types[1], kSequenceNumber,
180 kBaseTimestamp, 1, true);
181 delete [] packet->payload;
182 delete packet;
183 packet_list.pop_front();
184 // Check second packet.
185 packet = packet_list.front();
186 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber,
187 kBaseTimestamp - kTimestampOffset, 0, false);
188 delete [] packet->payload;
189 delete packet;
190 }
191
192 // Packets A and B are not split at all. Only the RED header in each packet is
193 // removed.
TEST(RedPayloadSplitter,TwoPacketsOnePayload)194 TEST(RedPayloadSplitter, TwoPacketsOnePayload) {
195 uint8_t payload_types[] = {0};
196 const int kTimestampOffset = 160;
197 // Create first packet, with a single RED payload.
198 Packet* packet = CreateRedPayload(1, payload_types, kTimestampOffset);
199 PacketList packet_list;
200 packet_list.push_back(packet);
201 // Create second packet, with a single RED payload.
202 packet = CreateRedPayload(1, payload_types, kTimestampOffset);
203 // Manually change timestamp and sequence number of second packet.
204 packet->header.timestamp += kTimestampOffset;
205 packet->header.sequenceNumber++;
206 packet_list.push_back(packet);
207 PayloadSplitter splitter;
208 EXPECT_EQ(PayloadSplitter::kOK, splitter.SplitRed(&packet_list));
209 ASSERT_EQ(2u, packet_list.size());
210 // Check first packet.
211 packet = packet_list.front();
212 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber,
213 kBaseTimestamp, 0, true);
214 delete [] packet->payload;
215 delete packet;
216 packet_list.pop_front();
217 // Check second packet.
218 packet = packet_list.front();
219 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber + 1,
220 kBaseTimestamp + kTimestampOffset, 0, true);
221 delete [] packet->payload;
222 delete packet;
223 }
224
225 // Packets A and B are split into packets A1, A2, A3, B1, B2, B3, with
226 // attributes as follows:
227 //
228 // A1* A2 A3 B1* B2 B3
229 // Payload type 0 1 2 0 1 2
230 // Timestamp b b-o b-2o b+o b b-o
231 // Sequence number 0 0 0 1 1 1
232 //
233 // b = kBaseTimestamp, o = kTimestampOffset, * = primary.
TEST(RedPayloadSplitter,TwoPacketsThreePayloads)234 TEST(RedPayloadSplitter, TwoPacketsThreePayloads) {
235 uint8_t payload_types[] = {2, 1, 0}; // Primary is the last one.
236 const int kTimestampOffset = 160;
237 // Create first packet, with 3 RED payloads.
238 Packet* packet = CreateRedPayload(3, payload_types, kTimestampOffset);
239 PacketList packet_list;
240 packet_list.push_back(packet);
241 // Create first packet, with 3 RED payloads.
242 packet = CreateRedPayload(3, payload_types, kTimestampOffset);
243 // Manually change timestamp and sequence number of second packet.
244 packet->header.timestamp += kTimestampOffset;
245 packet->header.sequenceNumber++;
246 packet_list.push_back(packet);
247 PayloadSplitter splitter;
248 EXPECT_EQ(PayloadSplitter::kOK, splitter.SplitRed(&packet_list));
249 ASSERT_EQ(6u, packet_list.size());
250 // Check first packet, A1.
251 packet = packet_list.front();
252 VerifyPacket(packet, kPayloadLength, payload_types[2], kSequenceNumber,
253 kBaseTimestamp, 2, true);
254 delete [] packet->payload;
255 delete packet;
256 packet_list.pop_front();
257 // Check second packet, A2.
258 packet = packet_list.front();
259 VerifyPacket(packet, kPayloadLength, payload_types[1], kSequenceNumber,
260 kBaseTimestamp - kTimestampOffset, 1, false);
261 delete [] packet->payload;
262 delete packet;
263 packet_list.pop_front();
264 // Check third packet, A3.
265 packet = packet_list.front();
266 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber,
267 kBaseTimestamp - 2 * kTimestampOffset, 0, false);
268 delete [] packet->payload;
269 delete packet;
270 packet_list.pop_front();
271 // Check fourth packet, B1.
272 packet = packet_list.front();
273 VerifyPacket(packet, kPayloadLength, payload_types[2], kSequenceNumber + 1,
274 kBaseTimestamp + kTimestampOffset, 2, true);
275 delete [] packet->payload;
276 delete packet;
277 packet_list.pop_front();
278 // Check fifth packet, B2.
279 packet = packet_list.front();
280 VerifyPacket(packet, kPayloadLength, payload_types[1], kSequenceNumber + 1,
281 kBaseTimestamp, 1, false);
282 delete [] packet->payload;
283 delete packet;
284 packet_list.pop_front();
285 // Check sixth packet, B3.
286 packet = packet_list.front();
287 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber + 1,
288 kBaseTimestamp - kTimestampOffset, 0, false);
289 delete [] packet->payload;
290 delete packet;
291 }
292
293 // Creates a list with 4 packets with these payload types:
294 // 0 = CNGnb
295 // 1 = PCMu
296 // 2 = DTMF (AVT)
297 // 3 = iLBC
298 // We expect the method CheckRedPayloads to discard the iLBC packet, since it
299 // is a non-CNG, non-DTMF payload of another type than the first speech payload
300 // found in the list (which is PCMu).
TEST(RedPayloadSplitter,CheckRedPayloads)301 TEST(RedPayloadSplitter, CheckRedPayloads) {
302 PacketList packet_list;
303 for (uint8_t i = 0; i <= 3; ++i) {
304 // Create packet with payload type |i|, payload length 10 bytes, all 0.
305 Packet* packet = CreatePacket(i, 10, 0);
306 packet_list.push_back(packet);
307 }
308
309 // Use a real DecoderDatabase object here instead of a mock, since it is
310 // easier to just register the payload types and let the actual implementation
311 // do its job.
312 DecoderDatabase decoder_database;
313 decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb, "cng-nb");
314 decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu");
315 decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT, "avt");
316 decoder_database.RegisterPayload(3, NetEqDecoder::kDecoderILBC, "ilbc");
317
318 PayloadSplitter splitter;
319 splitter.CheckRedPayloads(&packet_list, decoder_database);
320
321 ASSERT_EQ(3u, packet_list.size()); // Should have dropped the last packet.
322 // Verify packets. The loop verifies that payload types 0, 1, and 2 are in the
323 // list.
324 for (int i = 0; i <= 2; ++i) {
325 Packet* packet = packet_list.front();
326 VerifyPacket(packet, 10, i, kSequenceNumber, kBaseTimestamp, 0, true);
327 delete [] packet->payload;
328 delete packet;
329 packet_list.pop_front();
330 }
331 EXPECT_TRUE(packet_list.empty());
332 }
333
334 // Packet A is split into A1, A2 and A3. But the length parameter is off, so
335 // the last payloads should be discarded.
TEST(RedPayloadSplitter,WrongPayloadLength)336 TEST(RedPayloadSplitter, WrongPayloadLength) {
337 uint8_t payload_types[] = {0, 0, 0};
338 const int kTimestampOffset = 160;
339 Packet* packet = CreateRedPayload(3, payload_types, kTimestampOffset);
340 // Manually tamper with the payload length of the packet.
341 // This is one byte too short for the second payload (out of three).
342 // We expect only the first payload to be returned.
343 packet->payload_length -= kPayloadLength + 1;
344 PacketList packet_list;
345 packet_list.push_back(packet);
346 PayloadSplitter splitter;
347 EXPECT_EQ(PayloadSplitter::kRedLengthMismatch,
348 splitter.SplitRed(&packet_list));
349 ASSERT_EQ(1u, packet_list.size());
350 // Check first packet.
351 packet = packet_list.front();
352 VerifyPacket(packet, kPayloadLength, payload_types[0], kSequenceNumber,
353 kBaseTimestamp - 2 * kTimestampOffset, 0, false);
354 delete [] packet->payload;
355 delete packet;
356 packet_list.pop_front();
357 }
358
359 // Test that iSAC, iSAC-swb, RED, DTMF, CNG, and "Arbitrary" payloads do not
360 // get split.
TEST(AudioPayloadSplitter,NonSplittable)361 TEST(AudioPayloadSplitter, NonSplittable) {
362 // Set up packets with different RTP payload types. The actual values do not
363 // matter, since we are mocking the decoder database anyway.
364 PacketList packet_list;
365 for (uint8_t i = 0; i < 6; ++i) {
366 // Let the payload type be |i|, and the payload value 10 * |i|.
367 packet_list.push_back(CreatePacket(i, kPayloadLength, 10 * i));
368 }
369
370 MockDecoderDatabase decoder_database;
371 // Tell the mock decoder database to return DecoderInfo structs with different
372 // codec types.
373 // Use scoped pointers to avoid having to delete them later.
374 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info0(
375 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISAC, 16000, NULL,
376 false));
377 EXPECT_CALL(decoder_database, GetDecoderInfo(0))
378 .WillRepeatedly(Return(info0.get()));
379 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info1(
380 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderISACswb, 32000,
381 NULL, false));
382 EXPECT_CALL(decoder_database, GetDecoderInfo(1))
383 .WillRepeatedly(Return(info1.get()));
384 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info2(
385 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderRED, 8000, NULL,
386 false));
387 EXPECT_CALL(decoder_database, GetDecoderInfo(2))
388 .WillRepeatedly(Return(info2.get()));
389 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info3(
390 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderAVT, 8000, NULL,
391 false));
392 EXPECT_CALL(decoder_database, GetDecoderInfo(3))
393 .WillRepeatedly(Return(info3.get()));
394 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info4(
395 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderCNGnb, 8000, NULL,
396 false));
397 EXPECT_CALL(decoder_database, GetDecoderInfo(4))
398 .WillRepeatedly(Return(info4.get()));
399 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info5(
400 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderArbitrary, 8000,
401 NULL, false));
402 EXPECT_CALL(decoder_database, GetDecoderInfo(5))
403 .WillRepeatedly(Return(info5.get()));
404
405 PayloadSplitter splitter;
406 EXPECT_EQ(0, splitter.SplitAudio(&packet_list, decoder_database));
407 EXPECT_EQ(6u, packet_list.size());
408
409 // Check that all payloads are intact.
410 uint8_t payload_type = 0;
411 PacketList::iterator it = packet_list.begin();
412 while (it != packet_list.end()) {
413 VerifyPacket((*it), kPayloadLength, payload_type, kSequenceNumber,
414 kBaseTimestamp, 10 * payload_type);
415 ++payload_type;
416 delete [] (*it)->payload;
417 delete (*it);
418 it = packet_list.erase(it);
419 }
420
421 // The destructor is called when decoder_database goes out of scope.
422 EXPECT_CALL(decoder_database, Die());
423 }
424
425 // Test unknown payload type.
TEST(AudioPayloadSplitter,UnknownPayloadType)426 TEST(AudioPayloadSplitter, UnknownPayloadType) {
427 PacketList packet_list;
428 static const uint8_t kPayloadType = 17; // Just a random number.
429 size_t kPayloadLengthBytes = 4711; // Random number.
430 packet_list.push_back(CreatePacket(kPayloadType, kPayloadLengthBytes, 0));
431
432 MockDecoderDatabase decoder_database;
433 // Tell the mock decoder database to return NULL when asked for decoder info.
434 // This signals that the decoder database does not recognize the payload type.
435 EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
436 .WillRepeatedly(ReturnNull());
437
438 PayloadSplitter splitter;
439 EXPECT_EQ(PayloadSplitter::kUnknownPayloadType,
440 splitter.SplitAudio(&packet_list, decoder_database));
441 EXPECT_EQ(1u, packet_list.size());
442
443
444 // Delete the packets and payloads to avoid having the test leak memory.
445 PacketList::iterator it = packet_list.begin();
446 while (it != packet_list.end()) {
447 delete [] (*it)->payload;
448 delete (*it);
449 it = packet_list.erase(it);
450 }
451
452 // The destructor is called when decoder_database goes out of scope.
453 EXPECT_CALL(decoder_database, Die());
454 }
455
456 class SplitBySamplesTest : public ::testing::TestWithParam<NetEqDecoder> {
457 protected:
SetUp()458 virtual void SetUp() {
459 decoder_type_ = GetParam();
460 switch (decoder_type_) {
461 case NetEqDecoder::kDecoderPCMu:
462 case NetEqDecoder::kDecoderPCMa:
463 bytes_per_ms_ = 8;
464 samples_per_ms_ = 8;
465 break;
466 case NetEqDecoder::kDecoderPCMu_2ch:
467 case NetEqDecoder::kDecoderPCMa_2ch:
468 bytes_per_ms_ = 2 * 8;
469 samples_per_ms_ = 8;
470 break;
471 case NetEqDecoder::kDecoderG722:
472 bytes_per_ms_ = 8;
473 samples_per_ms_ = 16;
474 break;
475 case NetEqDecoder::kDecoderPCM16B:
476 bytes_per_ms_ = 16;
477 samples_per_ms_ = 8;
478 break;
479 case NetEqDecoder::kDecoderPCM16Bwb:
480 bytes_per_ms_ = 32;
481 samples_per_ms_ = 16;
482 break;
483 case NetEqDecoder::kDecoderPCM16Bswb32kHz:
484 bytes_per_ms_ = 64;
485 samples_per_ms_ = 32;
486 break;
487 case NetEqDecoder::kDecoderPCM16Bswb48kHz:
488 bytes_per_ms_ = 96;
489 samples_per_ms_ = 48;
490 break;
491 case NetEqDecoder::kDecoderPCM16B_2ch:
492 bytes_per_ms_ = 2 * 16;
493 samples_per_ms_ = 8;
494 break;
495 case NetEqDecoder::kDecoderPCM16Bwb_2ch:
496 bytes_per_ms_ = 2 * 32;
497 samples_per_ms_ = 16;
498 break;
499 case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
500 bytes_per_ms_ = 2 * 64;
501 samples_per_ms_ = 32;
502 break;
503 case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch:
504 bytes_per_ms_ = 2 * 96;
505 samples_per_ms_ = 48;
506 break;
507 case NetEqDecoder::kDecoderPCM16B_5ch:
508 bytes_per_ms_ = 5 * 16;
509 samples_per_ms_ = 8;
510 break;
511 default:
512 assert(false);
513 break;
514 }
515 }
516 size_t bytes_per_ms_;
517 int samples_per_ms_;
518 NetEqDecoder decoder_type_;
519 };
520
521 // Test splitting sample-based payloads.
TEST_P(SplitBySamplesTest,PayloadSizes)522 TEST_P(SplitBySamplesTest, PayloadSizes) {
523 PacketList packet_list;
524 static const uint8_t kPayloadType = 17; // Just a random number.
525 for (int payload_size_ms = 10; payload_size_ms <= 60; payload_size_ms += 10) {
526 // The payload values are set to be the same as the payload_size, so that
527 // one can distinguish from which packet the split payloads come from.
528 size_t payload_size_bytes = payload_size_ms * bytes_per_ms_;
529 packet_list.push_back(CreatePacket(kPayloadType, payload_size_bytes,
530 payload_size_ms));
531 }
532
533 MockDecoderDatabase decoder_database;
534 // Tell the mock decoder database to return DecoderInfo structs with different
535 // codec types.
536 // Use scoped pointers to avoid having to delete them later.
537 // (Sample rate is set to 8000 Hz, but does not matter.)
538 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info(
539 new DecoderDatabase::DecoderInfo(decoder_type_, 8000, NULL, false));
540 EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
541 .WillRepeatedly(Return(info.get()));
542
543 PayloadSplitter splitter;
544 EXPECT_EQ(0, splitter.SplitAudio(&packet_list, decoder_database));
545 // The payloads are expected to be split as follows:
546 // 10 ms -> 10 ms
547 // 20 ms -> 20 ms
548 // 30 ms -> 30 ms
549 // 40 ms -> 20 + 20 ms
550 // 50 ms -> 25 + 25 ms
551 // 60 ms -> 30 + 30 ms
552 int expected_size_ms[] = {10, 20, 30, 20, 20, 25, 25, 30, 30};
553 int expected_payload_value[] = {10, 20, 30, 40, 40, 50, 50, 60, 60};
554 int expected_timestamp_offset_ms[] = {0, 0, 0, 0, 20, 0, 25, 0, 30};
555 size_t expected_num_packets =
556 sizeof(expected_size_ms) / sizeof(expected_size_ms[0]);
557 EXPECT_EQ(expected_num_packets, packet_list.size());
558
559 PacketList::iterator it = packet_list.begin();
560 int i = 0;
561 while (it != packet_list.end()) {
562 size_t length_bytes = expected_size_ms[i] * bytes_per_ms_;
563 uint32_t expected_timestamp = kBaseTimestamp +
564 expected_timestamp_offset_ms[i] * samples_per_ms_;
565 VerifyPacket((*it), length_bytes, kPayloadType, kSequenceNumber,
566 expected_timestamp, expected_payload_value[i]);
567 delete [] (*it)->payload;
568 delete (*it);
569 it = packet_list.erase(it);
570 ++i;
571 }
572
573 // The destructor is called when decoder_database goes out of scope.
574 EXPECT_CALL(decoder_database, Die());
575 }
576
577 INSTANTIATE_TEST_CASE_P(
578 PayloadSplitter,
579 SplitBySamplesTest,
580 ::testing::Values(NetEqDecoder::kDecoderPCMu,
581 NetEqDecoder::kDecoderPCMa,
582 NetEqDecoder::kDecoderPCMu_2ch,
583 NetEqDecoder::kDecoderPCMa_2ch,
584 NetEqDecoder::kDecoderG722,
585 NetEqDecoder::kDecoderPCM16B,
586 NetEqDecoder::kDecoderPCM16Bwb,
587 NetEqDecoder::kDecoderPCM16Bswb32kHz,
588 NetEqDecoder::kDecoderPCM16Bswb48kHz,
589 NetEqDecoder::kDecoderPCM16B_2ch,
590 NetEqDecoder::kDecoderPCM16Bwb_2ch,
591 NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch,
592 NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch,
593 NetEqDecoder::kDecoderPCM16B_5ch));
594
595 class SplitIlbcTest : public ::testing::TestWithParam<std::pair<int, int> > {
596 protected:
SetUp()597 virtual void SetUp() {
598 const std::pair<int, int> parameters = GetParam();
599 num_frames_ = parameters.first;
600 frame_length_ms_ = parameters.second;
601 frame_length_bytes_ = (frame_length_ms_ == 20) ? 38 : 50;
602 }
603 size_t num_frames_;
604 int frame_length_ms_;
605 size_t frame_length_bytes_;
606 };
607
608 // Test splitting sample-based payloads.
TEST_P(SplitIlbcTest,NumFrames)609 TEST_P(SplitIlbcTest, NumFrames) {
610 PacketList packet_list;
611 static const uint8_t kPayloadType = 17; // Just a random number.
612 const int frame_length_samples = frame_length_ms_ * 8;
613 size_t payload_length_bytes = frame_length_bytes_ * num_frames_;
614 Packet* packet = CreatePacket(kPayloadType, payload_length_bytes, 0);
615 // Fill payload with increasing integers {0, 1, 2, ...}.
616 for (size_t i = 0; i < packet->payload_length; ++i) {
617 packet->payload[i] = static_cast<uint8_t>(i);
618 }
619 packet_list.push_back(packet);
620
621 MockDecoderDatabase decoder_database;
622 // Tell the mock decoder database to return DecoderInfo structs with different
623 // codec types.
624 // Use scoped pointers to avoid having to delete them later.
625 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info(
626 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, 8000, NULL,
627 false));
628 EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
629 .WillRepeatedly(Return(info.get()));
630
631 PayloadSplitter splitter;
632 EXPECT_EQ(0, splitter.SplitAudio(&packet_list, decoder_database));
633 EXPECT_EQ(num_frames_, packet_list.size());
634
635 PacketList::iterator it = packet_list.begin();
636 int frame_num = 0;
637 uint8_t payload_value = 0;
638 while (it != packet_list.end()) {
639 Packet* packet = (*it);
640 EXPECT_EQ(kBaseTimestamp + frame_length_samples * frame_num,
641 packet->header.timestamp);
642 EXPECT_EQ(frame_length_bytes_, packet->payload_length);
643 EXPECT_EQ(kPayloadType, packet->header.payloadType);
644 EXPECT_EQ(kSequenceNumber, packet->header.sequenceNumber);
645 EXPECT_EQ(true, packet->primary);
646 ASSERT_FALSE(packet->payload == NULL);
647 for (size_t i = 0; i < packet->payload_length; ++i) {
648 EXPECT_EQ(payload_value, packet->payload[i]);
649 ++payload_value;
650 }
651 delete [] (*it)->payload;
652 delete (*it);
653 it = packet_list.erase(it);
654 ++frame_num;
655 }
656
657 // The destructor is called when decoder_database goes out of scope.
658 EXPECT_CALL(decoder_database, Die());
659 }
660
661 // Test 1 through 5 frames of 20 and 30 ms size.
662 // Also test the maximum number of frames in one packet for 20 and 30 ms.
663 // The maximum is defined by the largest payload length that can be uniquely
664 // resolved to a frame size of either 38 bytes (20 ms) or 50 bytes (30 ms).
665 INSTANTIATE_TEST_CASE_P(
666 PayloadSplitter, SplitIlbcTest,
667 ::testing::Values(std::pair<int, int>(1, 20), // 1 frame, 20 ms.
668 std::pair<int, int>(2, 20), // 2 frames, 20 ms.
669 std::pair<int, int>(3, 20), // And so on.
670 std::pair<int, int>(4, 20),
671 std::pair<int, int>(5, 20),
672 std::pair<int, int>(24, 20),
673 std::pair<int, int>(1, 30),
674 std::pair<int, int>(2, 30),
675 std::pair<int, int>(3, 30),
676 std::pair<int, int>(4, 30),
677 std::pair<int, int>(5, 30),
678 std::pair<int, int>(18, 30)));
679
680 // Test too large payload size.
TEST(IlbcPayloadSplitter,TooLargePayload)681 TEST(IlbcPayloadSplitter, TooLargePayload) {
682 PacketList packet_list;
683 static const uint8_t kPayloadType = 17; // Just a random number.
684 size_t kPayloadLengthBytes = 950;
685 Packet* packet = CreatePacket(kPayloadType, kPayloadLengthBytes, 0);
686 packet_list.push_back(packet);
687
688 MockDecoderDatabase decoder_database;
689 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info(
690 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, 8000, NULL,
691 false));
692 EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
693 .WillRepeatedly(Return(info.get()));
694
695 PayloadSplitter splitter;
696 EXPECT_EQ(PayloadSplitter::kTooLargePayload,
697 splitter.SplitAudio(&packet_list, decoder_database));
698 EXPECT_EQ(1u, packet_list.size());
699
700 // Delete the packets and payloads to avoid having the test leak memory.
701 PacketList::iterator it = packet_list.begin();
702 while (it != packet_list.end()) {
703 delete [] (*it)->payload;
704 delete (*it);
705 it = packet_list.erase(it);
706 }
707
708 // The destructor is called when decoder_database goes out of scope.
709 EXPECT_CALL(decoder_database, Die());
710 }
711
712 // Payload not an integer number of frames.
TEST(IlbcPayloadSplitter,UnevenPayload)713 TEST(IlbcPayloadSplitter, UnevenPayload) {
714 PacketList packet_list;
715 static const uint8_t kPayloadType = 17; // Just a random number.
716 size_t kPayloadLengthBytes = 39; // Not an even number of frames.
717 Packet* packet = CreatePacket(kPayloadType, kPayloadLengthBytes, 0);
718 packet_list.push_back(packet);
719
720 MockDecoderDatabase decoder_database;
721 rtc::scoped_ptr<DecoderDatabase::DecoderInfo> info(
722 new DecoderDatabase::DecoderInfo(NetEqDecoder::kDecoderILBC, 8000, NULL,
723 false));
724 EXPECT_CALL(decoder_database, GetDecoderInfo(kPayloadType))
725 .WillRepeatedly(Return(info.get()));
726
727 PayloadSplitter splitter;
728 EXPECT_EQ(PayloadSplitter::kFrameSplitError,
729 splitter.SplitAudio(&packet_list, decoder_database));
730 EXPECT_EQ(1u, packet_list.size());
731
732 // Delete the packets and payloads to avoid having the test leak memory.
733 PacketList::iterator it = packet_list.begin();
734 while (it != packet_list.end()) {
735 delete [] (*it)->payload;
736 delete (*it);
737 it = packet_list.erase(it);
738 }
739
740 // The destructor is called when decoder_database goes out of scope.
741 EXPECT_CALL(decoder_database, Die());
742 }
743
TEST(FecPayloadSplitter,MixedPayload)744 TEST(FecPayloadSplitter, MixedPayload) {
745 PacketList packet_list;
746 DecoderDatabase decoder_database;
747
748 decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus, "opus");
749 decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu");
750
751 Packet* packet = CreatePacket(0, 10, 0xFF, true);
752 packet_list.push_back(packet);
753
754 packet = CreatePacket(0, 10, 0); // Non-FEC Opus payload.
755 packet_list.push_back(packet);
756
757 packet = CreatePacket(1, 10, 0); // Non-Opus payload.
758 packet_list.push_back(packet);
759
760 PayloadSplitter splitter;
761 EXPECT_EQ(PayloadSplitter::kOK,
762 splitter.SplitFec(&packet_list, &decoder_database));
763 EXPECT_EQ(4u, packet_list.size());
764
765 // Check first packet.
766 packet = packet_list.front();
767 EXPECT_EQ(0, packet->header.payloadType);
768 EXPECT_EQ(kBaseTimestamp - 20 * 48, packet->header.timestamp);
769 EXPECT_EQ(10U, packet->payload_length);
770 EXPECT_FALSE(packet->primary);
771 delete [] packet->payload;
772 delete packet;
773 packet_list.pop_front();
774
775 // Check second packet.
776 packet = packet_list.front();
777 EXPECT_EQ(0, packet->header.payloadType);
778 EXPECT_EQ(kBaseTimestamp, packet->header.timestamp);
779 EXPECT_EQ(10U, packet->payload_length);
780 EXPECT_TRUE(packet->primary);
781 delete [] packet->payload;
782 delete packet;
783 packet_list.pop_front();
784
785 // Check third packet.
786 packet = packet_list.front();
787 VerifyPacket(packet, 10, 0, kSequenceNumber, kBaseTimestamp, 0, true);
788 delete [] packet->payload;
789 delete packet;
790 packet_list.pop_front();
791
792 // Check fourth packet.
793 packet = packet_list.front();
794 VerifyPacket(packet, 10, 1, kSequenceNumber, kBaseTimestamp, 0, true);
795 delete [] packet->payload;
796 delete packet;
797 }
798
TEST(FecPayloadSplitter,EmbedFecInRed)799 TEST(FecPayloadSplitter, EmbedFecInRed) {
800 PacketList packet_list;
801 DecoderDatabase decoder_database;
802
803 const int kTimestampOffset = 20 * 48; // 20 ms * 48 kHz.
804 uint8_t payload_types[] = {0, 0};
805 decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus, "opus");
806 Packet* packet = CreateRedPayload(2, payload_types, kTimestampOffset, true);
807 packet_list.push_back(packet);
808
809 PayloadSplitter splitter;
810 EXPECT_EQ(PayloadSplitter::kOK,
811 splitter.SplitRed(&packet_list));
812 EXPECT_EQ(PayloadSplitter::kOK,
813 splitter.SplitFec(&packet_list, &decoder_database));
814
815 EXPECT_EQ(4u, packet_list.size());
816
817 // Check first packet. FEC packet copied from primary payload in RED.
818 packet = packet_list.front();
819 EXPECT_EQ(0, packet->header.payloadType);
820 EXPECT_EQ(kBaseTimestamp - kTimestampOffset, packet->header.timestamp);
821 EXPECT_EQ(kPayloadLength, packet->payload_length);
822 EXPECT_FALSE(packet->primary);
823 EXPECT_EQ(packet->payload[3], 1);
824 delete [] packet->payload;
825 delete packet;
826 packet_list.pop_front();
827
828 // Check second packet. Normal packet copied from primary payload in RED.
829 packet = packet_list.front();
830 EXPECT_EQ(0, packet->header.payloadType);
831 EXPECT_EQ(kBaseTimestamp, packet->header.timestamp);
832 EXPECT_EQ(kPayloadLength, packet->payload_length);
833 EXPECT_TRUE(packet->primary);
834 EXPECT_EQ(packet->payload[3], 1);
835 delete [] packet->payload;
836 delete packet;
837 packet_list.pop_front();
838
839 // Check third packet. FEC packet copied from secondary payload in RED.
840 packet = packet_list.front();
841 EXPECT_EQ(0, packet->header.payloadType);
842 EXPECT_EQ(kBaseTimestamp - 2 * kTimestampOffset, packet->header.timestamp);
843 EXPECT_EQ(kPayloadLength, packet->payload_length);
844 EXPECT_FALSE(packet->primary);
845 EXPECT_EQ(packet->payload[3], 0);
846 delete [] packet->payload;
847 delete packet;
848 packet_list.pop_front();
849
850 // Check fourth packet. Normal packet copied from primary payload in RED.
851 packet = packet_list.front();
852 EXPECT_EQ(0, packet->header.payloadType);
853 EXPECT_EQ(kBaseTimestamp - kTimestampOffset, packet->header.timestamp);
854 EXPECT_EQ(kPayloadLength, packet->payload_length);
855 EXPECT_TRUE(packet->primary);
856 EXPECT_EQ(packet->payload[3], 0);
857 delete [] packet->payload;
858 delete packet;
859 packet_list.pop_front();
860 }
861
862 } // namespace webrtc
863