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