blob: bc2a9de17be18d6c3dd58a2c4cb58f7dc6f1721e [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2011 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/*
12 * This file includes unit tests for NetEQ.
13 */
14
15#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
16
17#include <stdlib.h>
18#include <string.h> // memset
19
turaj@webrtc.orgff43c852013-09-25 00:07:27 +000020#include <cmath>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000021#include <string>
22#include <vector>
23
turaj@webrtc.orga6101d72013-10-01 22:01:09 +000024#include "gflags/gflags.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000025#include "gtest/gtest.h"
26#include "webrtc/modules/audio_coding/neteq4/test/NETEQTEST_RTPpacket.h"
turaj@webrtc.orgff43c852013-09-25 00:07:27 +000027#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000028#include "webrtc/test/testsupport/fileutils.h"
henrike@webrtc.orga950300b2013-07-08 18:53:54 +000029#include "webrtc/test/testsupport/gtest_disable.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000030#include "webrtc/typedefs.h"
31
turaj@webrtc.orga6101d72013-10-01 22:01:09 +000032DEFINE_bool(gen_ref, false, "Generate reference files.");
33
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000034namespace webrtc {
35
turaj@webrtc.org7b75ac62013-09-26 00:27:56 +000036static bool IsAllZero(const int16_t* buf, int buf_length) {
37 bool all_zero = true;
38 for (int n = 0; n < buf_length && all_zero; ++n)
39 all_zero = buf[n] == 0;
40 return all_zero;
41}
42
43static bool IsAllNonZero(const int16_t* buf, int buf_length) {
44 bool all_non_zero = true;
45 for (int n = 0; n < buf_length && all_non_zero; ++n)
46 all_non_zero = buf[n] != 0;
47 return all_non_zero;
48}
49
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050class RefFiles {
51 public:
52 RefFiles(const std::string& input_file, const std::string& output_file);
53 ~RefFiles();
54 template<class T> void ProcessReference(const T& test_results);
55 template<typename T, size_t n> void ProcessReference(
56 const T (&test_results)[n],
57 size_t length);
58 template<typename T, size_t n> void WriteToFile(
59 const T (&test_results)[n],
60 size_t length);
61 template<typename T, size_t n> void ReadFromFileAndCompare(
62 const T (&test_results)[n],
63 size_t length);
64 void WriteToFile(const NetEqNetworkStatistics& stats);
65 void ReadFromFileAndCompare(const NetEqNetworkStatistics& stats);
66 void WriteToFile(const RtcpStatistics& stats);
67 void ReadFromFileAndCompare(const RtcpStatistics& stats);
68
69 FILE* input_fp_;
70 FILE* output_fp_;
71};
72
73RefFiles::RefFiles(const std::string &input_file,
74 const std::string &output_file)
75 : input_fp_(NULL),
76 output_fp_(NULL) {
77 if (!input_file.empty()) {
78 input_fp_ = fopen(input_file.c_str(), "rb");
79 EXPECT_TRUE(input_fp_ != NULL);
80 }
81 if (!output_file.empty()) {
82 output_fp_ = fopen(output_file.c_str(), "wb");
83 EXPECT_TRUE(output_fp_ != NULL);
84 }
85}
86
87RefFiles::~RefFiles() {
88 if (input_fp_) {
89 EXPECT_EQ(EOF, fgetc(input_fp_)); // Make sure that we reached the end.
90 fclose(input_fp_);
91 }
92 if (output_fp_) fclose(output_fp_);
93}
94
95template<class T>
96void RefFiles::ProcessReference(const T& test_results) {
97 WriteToFile(test_results);
98 ReadFromFileAndCompare(test_results);
99}
100
101template<typename T, size_t n>
102void RefFiles::ProcessReference(const T (&test_results)[n], size_t length) {
103 WriteToFile(test_results, length);
104 ReadFromFileAndCompare(test_results, length);
105}
106
107template<typename T, size_t n>
108void RefFiles::WriteToFile(const T (&test_results)[n], size_t length) {
109 if (output_fp_) {
110 ASSERT_EQ(length, fwrite(&test_results, sizeof(T), length, output_fp_));
111 }
112}
113
114template<typename T, size_t n>
115void RefFiles::ReadFromFileAndCompare(const T (&test_results)[n],
116 size_t length) {
117 if (input_fp_) {
118 // Read from ref file.
119 T* ref = new T[length];
120 ASSERT_EQ(length, fread(ref, sizeof(T), length, input_fp_));
121 // Compare
122 ASSERT_EQ(0, memcmp(&test_results, ref, sizeof(T) * length));
123 delete [] ref;
124 }
125}
126
127void RefFiles::WriteToFile(const NetEqNetworkStatistics& stats) {
128 if (output_fp_) {
129 ASSERT_EQ(1u, fwrite(&stats, sizeof(NetEqNetworkStatistics), 1,
130 output_fp_));
131 }
132}
133
134void RefFiles::ReadFromFileAndCompare(
135 const NetEqNetworkStatistics& stats) {
136 if (input_fp_) {
137 // Read from ref file.
138 size_t stat_size = sizeof(NetEqNetworkStatistics);
139 NetEqNetworkStatistics ref_stats;
140 ASSERT_EQ(1u, fread(&ref_stats, stat_size, 1, input_fp_));
141 // Compare
142 EXPECT_EQ(0, memcmp(&stats, &ref_stats, stat_size));
143 }
144}
145
146void RefFiles::WriteToFile(const RtcpStatistics& stats) {
147 if (output_fp_) {
148 ASSERT_EQ(1u, fwrite(&(stats.fraction_lost), sizeof(stats.fraction_lost), 1,
149 output_fp_));
150 ASSERT_EQ(1u, fwrite(&(stats.cumulative_lost),
151 sizeof(stats.cumulative_lost), 1, output_fp_));
152 ASSERT_EQ(1u, fwrite(&(stats.extended_max), sizeof(stats.extended_max), 1,
153 output_fp_));
154 ASSERT_EQ(1u, fwrite(&(stats.jitter), sizeof(stats.jitter), 1,
155 output_fp_));
156 }
157}
158
159void RefFiles::ReadFromFileAndCompare(
160 const RtcpStatistics& stats) {
161 if (input_fp_) {
162 // Read from ref file.
163 RtcpStatistics ref_stats;
164 ASSERT_EQ(1u, fread(&(ref_stats.fraction_lost),
165 sizeof(ref_stats.fraction_lost), 1, input_fp_));
166 ASSERT_EQ(1u, fread(&(ref_stats.cumulative_lost),
167 sizeof(ref_stats.cumulative_lost), 1, input_fp_));
168 ASSERT_EQ(1u, fread(&(ref_stats.extended_max),
169 sizeof(ref_stats.extended_max), 1, input_fp_));
170 ASSERT_EQ(1u, fread(&(ref_stats.jitter), sizeof(ref_stats.jitter), 1,
171 input_fp_));
172 // Compare
173 EXPECT_EQ(ref_stats.fraction_lost, stats.fraction_lost);
174 EXPECT_EQ(ref_stats.cumulative_lost, stats.cumulative_lost);
175 EXPECT_EQ(ref_stats.extended_max, stats.extended_max);
176 EXPECT_EQ(ref_stats.jitter, stats.jitter);
177 }
178}
179
180class NetEqDecodingTest : public ::testing::Test {
181 protected:
182 // NetEQ must be polled for data once every 10 ms. Thus, neither of the
183 // constants below can be changed.
184 static const int kTimeStepMs = 10;
185 static const int kBlockSize8kHz = kTimeStepMs * 8;
186 static const int kBlockSize16kHz = kTimeStepMs * 16;
187 static const int kBlockSize32kHz = kTimeStepMs * 32;
188 static const int kMaxBlockSize = kBlockSize32kHz;
189 static const int kInitSampleRateHz = 8000;
190
191 NetEqDecodingTest();
192 virtual void SetUp();
193 virtual void TearDown();
194 void SelectDecoders(NetEqDecoder* used_codec);
195 void LoadDecoders();
196 void OpenInputFile(const std::string &rtp_file);
197 void Process(NETEQTEST_RTPpacket* rtp_ptr, int* out_len);
198 void DecodeAndCompare(const std::string &rtp_file,
199 const std::string &ref_file);
200 void DecodeAndCheckStats(const std::string &rtp_file,
201 const std::string &stat_ref_file,
202 const std::string &rtcp_ref_file);
203 static void PopulateRtpInfo(int frame_index,
204 int timestamp,
205 WebRtcRTPHeader* rtp_info);
206 static void PopulateCng(int frame_index,
207 int timestamp,
208 WebRtcRTPHeader* rtp_info,
209 uint8_t* payload,
210 int* payload_len);
211
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000212 void CheckBgnOff(int sampling_rate, NetEqBackgroundNoiseMode bgn_mode);
213
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000214 NetEq* neteq_;
215 FILE* rtp_fp_;
216 unsigned int sim_clock_;
217 int16_t out_data_[kMaxBlockSize];
218 int output_sample_rate_;
219};
220
221// Allocating the static const so that it can be passed by reference.
222const int NetEqDecodingTest::kTimeStepMs;
223const int NetEqDecodingTest::kBlockSize8kHz;
224const int NetEqDecodingTest::kBlockSize16kHz;
225const int NetEqDecodingTest::kBlockSize32kHz;
226const int NetEqDecodingTest::kMaxBlockSize;
227const int NetEqDecodingTest::kInitSampleRateHz;
228
229NetEqDecodingTest::NetEqDecodingTest()
230 : neteq_(NULL),
231 rtp_fp_(NULL),
232 sim_clock_(0),
233 output_sample_rate_(kInitSampleRateHz) {
234 memset(out_data_, 0, sizeof(out_data_));
235}
236
237void NetEqDecodingTest::SetUp() {
238 neteq_ = NetEq::Create(kInitSampleRateHz);
239 ASSERT_TRUE(neteq_);
240 LoadDecoders();
241}
242
243void NetEqDecodingTest::TearDown() {
244 delete neteq_;
245 if (rtp_fp_)
246 fclose(rtp_fp_);
247}
248
249void NetEqDecodingTest::LoadDecoders() {
250 // Load PCMu.
251 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCMu, 0));
252 // Load PCMa.
253 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCMa, 8));
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000254#ifndef WEBRTC_ANDROID
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 // Load iLBC.
256 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderILBC, 102));
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000257#endif // WEBRTC_ANDROID
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000258 // Load iSAC.
259 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderISAC, 103));
260 // Load iSAC SWB.
261 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderISACswb, 104));
henrik.lundin@webrtc.orgac59dba2013-01-31 09:55:24 +0000262 // Load iSAC FB.
263 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderISACfb, 105));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000264 // Load PCM16B nb.
265 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCM16B, 93));
266 // Load PCM16B wb.
267 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCM16Bwb, 94));
268 // Load PCM16B swb32.
269 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCM16Bswb32kHz, 95));
270 // Load CNG 8 kHz.
271 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGnb, 13));
272 // Load CNG 16 kHz.
273 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGwb, 98));
274}
275
276void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) {
277 rtp_fp_ = fopen(rtp_file.c_str(), "rb");
278 ASSERT_TRUE(rtp_fp_ != NULL);
279 ASSERT_EQ(0, NETEQTEST_RTPpacket::skipFileHeader(rtp_fp_));
280}
281
282void NetEqDecodingTest::Process(NETEQTEST_RTPpacket* rtp, int* out_len) {
283 // Check if time to receive.
284 while ((sim_clock_ >= rtp->time()) &&
285 (rtp->dataLen() >= 0)) {
286 if (rtp->dataLen() > 0) {
287 WebRtcRTPHeader rtpInfo;
288 rtp->parseHeader(&rtpInfo);
289 ASSERT_EQ(0, neteq_->InsertPacket(
290 rtpInfo,
291 rtp->payload(),
292 rtp->payloadLen(),
293 rtp->time() * (output_sample_rate_ / 1000)));
294 }
295 // Get next packet.
296 ASSERT_NE(-1, rtp->readFromFile(rtp_fp_));
297 }
298
henrik.lundin@webrtc.orge1d468c2013-01-30 07:37:20 +0000299 // Get audio from NetEq.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000300 NetEqOutputType type;
301 int num_channels;
302 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, out_len,
303 &num_channels, &type));
304 ASSERT_TRUE((*out_len == kBlockSize8kHz) ||
305 (*out_len == kBlockSize16kHz) ||
306 (*out_len == kBlockSize32kHz));
307 output_sample_rate_ = *out_len / 10 * 1000;
308
309 // Increase time.
310 sim_clock_ += kTimeStepMs;
311}
312
313void NetEqDecodingTest::DecodeAndCompare(const std::string &rtp_file,
314 const std::string &ref_file) {
315 OpenInputFile(rtp_file);
316
317 std::string ref_out_file = "";
318 if (ref_file.empty()) {
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000319 ref_out_file = webrtc::test::OutputPath() + "neteq_universal_ref.pcm";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000320 }
321 RefFiles ref_files(ref_file, ref_out_file);
322
323 NETEQTEST_RTPpacket rtp;
324 ASSERT_GT(rtp.readFromFile(rtp_fp_), 0);
325 int i = 0;
326 while (rtp.dataLen() >= 0) {
327 std::ostringstream ss;
328 ss << "Lap number " << i++ << " in DecodeAndCompare while loop";
329 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
330 int out_len;
331 ASSERT_NO_FATAL_FAILURE(Process(&rtp, &out_len));
332 ASSERT_NO_FATAL_FAILURE(ref_files.ProcessReference(out_data_, out_len));
333 }
334}
335
336void NetEqDecodingTest::DecodeAndCheckStats(const std::string &rtp_file,
337 const std::string &stat_ref_file,
338 const std::string &rtcp_ref_file) {
339 OpenInputFile(rtp_file);
340 std::string stat_out_file = "";
341 if (stat_ref_file.empty()) {
342 stat_out_file = webrtc::test::OutputPath() +
343 "neteq_network_stats.dat";
344 }
345 RefFiles network_stat_files(stat_ref_file, stat_out_file);
346
347 std::string rtcp_out_file = "";
348 if (rtcp_ref_file.empty()) {
349 rtcp_out_file = webrtc::test::OutputPath() +
350 "neteq_rtcp_stats.dat";
351 }
352 RefFiles rtcp_stat_files(rtcp_ref_file, rtcp_out_file);
353
354 NETEQTEST_RTPpacket rtp;
355 ASSERT_GT(rtp.readFromFile(rtp_fp_), 0);
356 while (rtp.dataLen() >= 0) {
357 int out_len;
358 Process(&rtp, &out_len);
359
360 // Query the network statistics API once per second
361 if (sim_clock_ % 1000 == 0) {
362 // Process NetworkStatistics.
363 NetEqNetworkStatistics network_stats;
364 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
365 network_stat_files.ProcessReference(network_stats);
366
367 // Process RTCPstat.
368 RtcpStatistics rtcp_stats;
369 neteq_->GetRtcpStatistics(&rtcp_stats);
370 rtcp_stat_files.ProcessReference(rtcp_stats);
371 }
372 }
373}
374
375void NetEqDecodingTest::PopulateRtpInfo(int frame_index,
376 int timestamp,
377 WebRtcRTPHeader* rtp_info) {
378 rtp_info->header.sequenceNumber = frame_index;
379 rtp_info->header.timestamp = timestamp;
380 rtp_info->header.ssrc = 0x1234; // Just an arbitrary SSRC.
381 rtp_info->header.payloadType = 94; // PCM16b WB codec.
382 rtp_info->header.markerBit = 0;
383}
384
385void NetEqDecodingTest::PopulateCng(int frame_index,
386 int timestamp,
387 WebRtcRTPHeader* rtp_info,
388 uint8_t* payload,
389 int* payload_len) {
390 rtp_info->header.sequenceNumber = frame_index;
391 rtp_info->header.timestamp = timestamp;
392 rtp_info->header.ssrc = 0x1234; // Just an arbitrary SSRC.
393 rtp_info->header.payloadType = 98; // WB CNG.
394 rtp_info->header.markerBit = 0;
395 payload[0] = 64; // Noise level -64 dBov, quite arbitrarily chosen.
396 *payload_len = 1; // Only noise level, no spectral parameters.
397}
398
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000399void NetEqDecodingTest::CheckBgnOff(int sampling_rate_hz,
400 NetEqBackgroundNoiseMode bgn_mode) {
401 int expected_samples_per_channel = 0;
402 uint8_t payload_type = 0xFF; // Invalid.
403 if (sampling_rate_hz == 8000) {
404 expected_samples_per_channel = kBlockSize8kHz;
405 payload_type = 93; // PCM 16, 8 kHz.
406 } else if (sampling_rate_hz == 16000) {
407 expected_samples_per_channel = kBlockSize16kHz;
408 payload_type = 94; // PCM 16, 16 kHZ.
409 } else if (sampling_rate_hz == 32000) {
410 expected_samples_per_channel = kBlockSize32kHz;
411 payload_type = 95; // PCM 16, 32 kHz.
412 } else {
413 ASSERT_TRUE(false); // Unsupported test case.
414 }
415
416 NetEqOutputType type;
417 int16_t output[kBlockSize32kHz]; // Maximum size is chosen.
418 int16_t input[kBlockSize32kHz]; // Maximum size is chosen.
419
420 // Payload of 10 ms of PCM16 32 kHz.
421 uint8_t payload[kBlockSize32kHz * sizeof(int16_t)];
422
423 // Random payload.
424 for (int n = 0; n < expected_samples_per_channel; ++n) {
425 input[n] = (rand() & ((1 << 10) - 1)) - ((1 << 5) - 1);
426 }
427 int enc_len_bytes = WebRtcPcm16b_EncodeW16(
428 input, expected_samples_per_channel, reinterpret_cast<int16_t*>(payload));
429 ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2);
430
431 WebRtcRTPHeader rtp_info;
432 PopulateRtpInfo(0, 0, &rtp_info);
433 rtp_info.header.payloadType = payload_type;
434
435 int number_channels = 0;
436 int samples_per_channel = 0;
437
438 uint32_t receive_timestamp = 0;
439 for (int n = 0; n < 10; ++n) { // Insert few packets and get audio.
440 number_channels = 0;
441 samples_per_channel = 0;
442 ASSERT_EQ(0, neteq_->InsertPacket(
443 rtp_info, payload, enc_len_bytes, receive_timestamp));
444 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel,
445 &number_channels, &type));
446 ASSERT_EQ(1, number_channels);
447 ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
448 ASSERT_EQ(kOutputNormal, type);
449
450 // Next packet.
451 rtp_info.header.timestamp += expected_samples_per_channel;
452 rtp_info.header.sequenceNumber++;
453 receive_timestamp += expected_samples_per_channel;
454 }
455
456 number_channels = 0;
457 samples_per_channel = 0;
458
459 // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull one
460 // frame without checking speech-type. This is the first frame pulled without
461 // inserting any packet, and might not be labeled as PCL.
462 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel,
463 &number_channels, &type));
464 ASSERT_EQ(1, number_channels);
465 ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
466
467 // To be able to test the fading of background noise we need at lease to pull
468 // 610 frames.
469 const int kFadingThreshold = 610;
470
471 // Test several CNG-to-PLC packet for the expected behavior. The number 20 is
472 // arbitrary, but sufficiently large to test enough number of frames.
473 const int kNumPlcToCngTestFrames = 20;
474 bool plc_to_cng = false;
475 for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) {
476 number_channels = 0;
477 samples_per_channel = 0;
478 memset(output, 1, sizeof(output)); // Set to non-zero.
479 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel,
480 &number_channels, &type));
481 ASSERT_EQ(1, number_channels);
482 ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
483 if (type == kOutputPLCtoCNG) {
484 plc_to_cng = true;
485 double sum_squared = 0;
486 for (int k = 0; k < number_channels * samples_per_channel; ++k)
487 sum_squared += output[k] * output[k];
488 if (bgn_mode == kBgnOn) {
489 EXPECT_NE(0, sum_squared);
490 } else if (bgn_mode == kBgnOff || n > kFadingThreshold) {
491 EXPECT_EQ(0, sum_squared);
492 }
493 } else {
494 EXPECT_EQ(kOutputPLC, type);
495 }
496 }
497 EXPECT_TRUE(plc_to_cng); // Just to be sure that PLC-to-CNG has occurred.
498}
499
kjellander@webrtc.org6eba2772013-06-04 05:46:37 +0000500#if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS)
501// Disabled for Windows 64-bit until webrtc:1458 is fixed.
502#define MAYBE_TestBitExactness DISABLED_TestBitExactness
503#else
504#define MAYBE_TestBitExactness TestBitExactness
505#endif
506
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000507TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(MAYBE_TestBitExactness)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000508 const std::string kInputRtpFile = webrtc::test::ProjectRootPath() +
henrik.lundin@webrtc.org73deaad2013-01-31 13:32:51 +0000509 "resources/audio_coding/neteq_universal_new.rtp";
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000510#if defined(_MSC_VER) && (_MSC_VER >= 1700)
511 // For Visual Studio 2012 and later, we will have to use the generic reference
512 // file, rather than the windows-specific one.
513 const std::string kInputRefFile = webrtc::test::ProjectRootPath() +
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000514 "resources/audio_coding/neteq4_universal_ref.pcm";
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000515#else
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000516 const std::string kInputRefFile =
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000517 webrtc::test::ResourcePath("audio_coding/neteq4_universal_ref", "pcm");
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000518#endif
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000519
520 if (FLAGS_gen_ref) {
521 DecodeAndCompare(kInputRtpFile, "");
522 } else {
523 DecodeAndCompare(kInputRtpFile, kInputRefFile);
524 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000525}
526
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000527TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(TestNetworkStatistics)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000528 const std::string kInputRtpFile = webrtc::test::ProjectRootPath() +
henrik.lundin@webrtc.org73deaad2013-01-31 13:32:51 +0000529 "resources/audio_coding/neteq_universal_new.rtp";
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000530#if defined(_MSC_VER) && (_MSC_VER >= 1700)
531 // For Visual Studio 2012 and later, we will have to use the generic reference
532 // file, rather than the windows-specific one.
533 const std::string kNetworkStatRefFile = webrtc::test::ProjectRootPath() +
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000534 "resources/audio_coding/neteq4_network_stats.dat";
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000535#else
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000536 const std::string kNetworkStatRefFile =
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000537 webrtc::test::ResourcePath("audio_coding/neteq4_network_stats", "dat");
henrik.lundin@webrtc.org6e3968f2013-01-31 15:07:30 +0000538#endif
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000539 const std::string kRtcpStatRefFile =
turaj@webrtc.orga6101d72013-10-01 22:01:09 +0000540 webrtc::test::ResourcePath("audio_coding/neteq4_rtcp_stats", "dat");
541 if (FLAGS_gen_ref) {
542 DecodeAndCheckStats(kInputRtpFile, "", "");
543 } else {
544 DecodeAndCheckStats(kInputRtpFile, kNetworkStatRefFile, kRtcpStatRefFile);
545 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000546}
547
548// TODO(hlundin): Re-enable test once the statistics interface is up and again.
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000549TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(TestFrameWaitingTimeStatistics)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000550 // Use fax mode to avoid time-scaling. This is to simplify the testing of
551 // packet waiting times in the packet buffer.
552 neteq_->SetPlayoutMode(kPlayoutFax);
553 ASSERT_EQ(kPlayoutFax, neteq_->PlayoutMode());
554 // Insert 30 dummy packets at once. Each packet contains 10 ms 16 kHz audio.
555 size_t num_frames = 30;
556 const int kSamples = 10 * 16;
557 const int kPayloadBytes = kSamples * 2;
558 for (size_t i = 0; i < num_frames; ++i) {
559 uint16_t payload[kSamples] = {0};
560 WebRtcRTPHeader rtp_info;
561 rtp_info.header.sequenceNumber = i;
562 rtp_info.header.timestamp = i * kSamples;
563 rtp_info.header.ssrc = 0x1234; // Just an arbitrary SSRC.
564 rtp_info.header.payloadType = 94; // PCM16b WB codec.
565 rtp_info.header.markerBit = 0;
566 ASSERT_EQ(0, neteq_->InsertPacket(
567 rtp_info,
568 reinterpret_cast<uint8_t*>(payload),
569 kPayloadBytes, 0));
570 }
571 // Pull out all data.
572 for (size_t i = 0; i < num_frames; ++i) {
573 int out_len;
574 int num_channels;
575 NetEqOutputType type;
576 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
577 &num_channels, &type));
578 ASSERT_EQ(kBlockSize16kHz, out_len);
579 }
580
581 std::vector<int> waiting_times;
582 neteq_->WaitingTimes(&waiting_times);
583 int len = waiting_times.size();
584 EXPECT_EQ(num_frames, waiting_times.size());
585 // Since all frames are dumped into NetEQ at once, but pulled out with 10 ms
586 // spacing (per definition), we expect the delay to increase with 10 ms for
587 // each packet.
588 for (size_t i = 0; i < waiting_times.size(); ++i) {
589 EXPECT_EQ(static_cast<int>(i + 1) * 10, waiting_times[i]);
590 }
591
592 // Check statistics again and make sure it's been reset.
593 neteq_->WaitingTimes(&waiting_times);
594 len = waiting_times.size();
595 EXPECT_EQ(0, len);
596
597 // Process > 100 frames, and make sure that that we get statistics
598 // only for 100 frames. Note the new SSRC, causing NetEQ to reset.
599 num_frames = 110;
600 for (size_t i = 0; i < num_frames; ++i) {
601 uint16_t payload[kSamples] = {0};
602 WebRtcRTPHeader rtp_info;
603 rtp_info.header.sequenceNumber = i;
604 rtp_info.header.timestamp = i * kSamples;
605 rtp_info.header.ssrc = 0x1235; // Just an arbitrary SSRC.
606 rtp_info.header.payloadType = 94; // PCM16b WB codec.
607 rtp_info.header.markerBit = 0;
608 ASSERT_EQ(0, neteq_->InsertPacket(
609 rtp_info,
610 reinterpret_cast<uint8_t*>(payload),
611 kPayloadBytes, 0));
612 int out_len;
613 int num_channels;
614 NetEqOutputType type;
615 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
616 &num_channels, &type));
617 ASSERT_EQ(kBlockSize16kHz, out_len);
618 }
619
620 neteq_->WaitingTimes(&waiting_times);
621 EXPECT_EQ(100u, waiting_times.size());
622}
623
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000624TEST_F(NetEqDecodingTest,
625 DISABLED_ON_ANDROID(TestAverageInterArrivalTimeNegative)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000626 const int kNumFrames = 3000; // Needed for convergence.
627 int frame_index = 0;
628 const int kSamples = 10 * 16;
629 const int kPayloadBytes = kSamples * 2;
630 while (frame_index < kNumFrames) {
631 // Insert one packet each time, except every 10th time where we insert two
632 // packets at once. This will create a negative clock-drift of approx. 10%.
633 int num_packets = (frame_index % 10 == 0 ? 2 : 1);
634 for (int n = 0; n < num_packets; ++n) {
635 uint8_t payload[kPayloadBytes] = {0};
636 WebRtcRTPHeader rtp_info;
637 PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info);
638 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
639 ++frame_index;
640 }
641
642 // Pull out data once.
643 int out_len;
644 int num_channels;
645 NetEqOutputType type;
646 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
647 &num_channels, &type));
648 ASSERT_EQ(kBlockSize16kHz, out_len);
649 }
650
651 NetEqNetworkStatistics network_stats;
652 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
653 EXPECT_EQ(-103196, network_stats.clockdrift_ppm);
654}
655
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000656TEST_F(NetEqDecodingTest,
657 DISABLED_ON_ANDROID(TestAverageInterArrivalTimePositive)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000658 const int kNumFrames = 5000; // Needed for convergence.
659 int frame_index = 0;
660 const int kSamples = 10 * 16;
661 const int kPayloadBytes = kSamples * 2;
662 for (int i = 0; i < kNumFrames; ++i) {
663 // Insert one packet each time, except every 10th time where we don't insert
664 // any packet. This will create a positive clock-drift of approx. 11%.
665 int num_packets = (i % 10 == 9 ? 0 : 1);
666 for (int n = 0; n < num_packets; ++n) {
667 uint8_t payload[kPayloadBytes] = {0};
668 WebRtcRTPHeader rtp_info;
669 PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info);
670 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
671 ++frame_index;
672 }
673
674 // Pull out data once.
675 int out_len;
676 int num_channels;
677 NetEqOutputType type;
678 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
679 &num_channels, &type));
680 ASSERT_EQ(kBlockSize16kHz, out_len);
681 }
682
683 NetEqNetworkStatistics network_stats;
684 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
685 EXPECT_EQ(110946, network_stats.clockdrift_ppm);
686}
687
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000688TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(LongCngWithClockDrift)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000689 uint16_t seq_no = 0;
690 uint32_t timestamp = 0;
691 const int kFrameSizeMs = 30;
692 const int kSamples = kFrameSizeMs * 16;
693 const int kPayloadBytes = kSamples * 2;
694 // Apply a clock drift of -25 ms / s (sender faster than receiver).
695 const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
696 double next_input_time_ms = 0.0;
697 double t_ms;
698 NetEqOutputType type;
699
700 // Insert speech for 5 seconds.
701 const int kSpeechDurationMs = 5000;
702 for (t_ms = 0; t_ms < kSpeechDurationMs; t_ms += 10) {
703 // Each turn in this for loop is 10 ms.
704 while (next_input_time_ms <= t_ms) {
705 // Insert one 30 ms speech frame.
706 uint8_t payload[kPayloadBytes] = {0};
707 WebRtcRTPHeader rtp_info;
708 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
709 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
710 ++seq_no;
711 timestamp += kSamples;
712 next_input_time_ms += static_cast<double>(kFrameSizeMs) * kDriftFactor;
713 }
714 // Pull out data once.
715 int out_len;
716 int num_channels;
717 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
718 &num_channels, &type));
719 ASSERT_EQ(kBlockSize16kHz, out_len);
720 }
721
722 EXPECT_EQ(kOutputNormal, type);
723 int32_t delay_before = timestamp - neteq_->PlayoutTimestamp();
724
725 // Insert CNG for 1 minute (= 60000 ms).
726 const int kCngPeriodMs = 100;
727 const int kCngPeriodSamples = kCngPeriodMs * 16; // Period in 16 kHz samples.
728 const int kCngDurationMs = 60000;
729 for (; t_ms < kSpeechDurationMs + kCngDurationMs; t_ms += 10) {
730 // Each turn in this for loop is 10 ms.
731 while (next_input_time_ms <= t_ms) {
732 // Insert one CNG frame each 100 ms.
733 uint8_t payload[kPayloadBytes];
734 int payload_len;
735 WebRtcRTPHeader rtp_info;
736 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
737 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0));
738 ++seq_no;
739 timestamp += kCngPeriodSamples;
740 next_input_time_ms += static_cast<double>(kCngPeriodMs) * kDriftFactor;
741 }
742 // Pull out data once.
743 int out_len;
744 int num_channels;
745 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
746 &num_channels, &type));
747 ASSERT_EQ(kBlockSize16kHz, out_len);
748 }
749
750 EXPECT_EQ(kOutputCNG, type);
751
752 // Insert speech again until output type is speech.
753 while (type != kOutputNormal) {
754 // Each turn in this for loop is 10 ms.
755 while (next_input_time_ms <= t_ms) {
756 // Insert one 30 ms speech frame.
757 uint8_t payload[kPayloadBytes] = {0};
758 WebRtcRTPHeader rtp_info;
759 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
760 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
761 ++seq_no;
762 timestamp += kSamples;
763 next_input_time_ms += static_cast<double>(kFrameSizeMs) * kDriftFactor;
764 }
765 // Pull out data once.
766 int out_len;
767 int num_channels;
768 ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
769 &num_channels, &type));
770 ASSERT_EQ(kBlockSize16kHz, out_len);
771 // Increase clock.
772 t_ms += 10;
773 }
774
775 int32_t delay_after = timestamp - neteq_->PlayoutTimestamp();
776 // Compare delay before and after, and make sure it differs less than 20 ms.
777 EXPECT_LE(delay_after, delay_before + 20 * 16);
778 EXPECT_GE(delay_after, delay_before - 20 * 16);
779}
780
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000781TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(UnknownPayloadType)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000782 const int kPayloadBytes = 100;
783 uint8_t payload[kPayloadBytes] = {0};
784 WebRtcRTPHeader rtp_info;
785 PopulateRtpInfo(0, 0, &rtp_info);
786 rtp_info.header.payloadType = 1; // Not registered as a decoder.
787 EXPECT_EQ(NetEq::kFail,
788 neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
789 EXPECT_EQ(NetEq::kUnknownRtpPayloadType, neteq_->LastError());
790}
791
minyue@webrtc.org7bb54362013-08-06 05:40:57 +0000792TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(OversizePacket)) {
793 // Payload size is greater than packet buffer size
794 const int kPayloadBytes = NetEq::kMaxBytesInBuffer + 1;
795 uint8_t payload[kPayloadBytes] = {0};
796 WebRtcRTPHeader rtp_info;
797 PopulateRtpInfo(0, 0, &rtp_info);
798 rtp_info.header.payloadType = 103; // iSAC, no packet splitting.
799 EXPECT_EQ(NetEq::kFail,
800 neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
801 EXPECT_EQ(NetEq::kOversizePacket, neteq_->LastError());
802}
803
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000804TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(DecoderError)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000805 const int kPayloadBytes = 100;
806 uint8_t payload[kPayloadBytes] = {0};
807 WebRtcRTPHeader rtp_info;
808 PopulateRtpInfo(0, 0, &rtp_info);
809 rtp_info.header.payloadType = 103; // iSAC, but the payload is invalid.
810 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0));
811 NetEqOutputType type;
812 // Set all of |out_data_| to 1, and verify that it was set to 0 by the call
813 // to GetAudio.
814 for (int i = 0; i < kMaxBlockSize; ++i) {
815 out_data_[i] = 1;
816 }
817 int num_channels;
818 int samples_per_channel;
819 EXPECT_EQ(NetEq::kFail,
820 neteq_->GetAudio(kMaxBlockSize, out_data_,
821 &samples_per_channel, &num_channels, &type));
822 // Verify that there is a decoder error to check.
823 EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError());
824 // Code 6730 is an iSAC error code.
825 EXPECT_EQ(6730, neteq_->LastDecoderError());
826 // Verify that the first 160 samples are set to 0, and that the remaining
827 // samples are left unmodified.
828 static const int kExpectedOutputLength = 160; // 10 ms at 16 kHz sample rate.
829 for (int i = 0; i < kExpectedOutputLength; ++i) {
830 std::ostringstream ss;
831 ss << "i = " << i;
832 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
833 EXPECT_EQ(0, out_data_[i]);
834 }
835 for (int i = kExpectedOutputLength; i < kMaxBlockSize; ++i) {
836 std::ostringstream ss;
837 ss << "i = " << i;
838 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
839 EXPECT_EQ(1, out_data_[i]);
840 }
841}
842
henrike@webrtc.orga950300b2013-07-08 18:53:54 +0000843TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(GetAudioBeforeInsertPacket)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000844 NetEqOutputType type;
845 // Set all of |out_data_| to 1, and verify that it was set to 0 by the call
846 // to GetAudio.
847 for (int i = 0; i < kMaxBlockSize; ++i) {
848 out_data_[i] = 1;
849 }
850 int num_channels;
851 int samples_per_channel;
852 EXPECT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_,
853 &samples_per_channel,
854 &num_channels, &type));
855 // Verify that the first block of samples is set to 0.
856 static const int kExpectedOutputLength =
857 kInitSampleRateHz / 100; // 10 ms at initial sample rate.
858 for (int i = 0; i < kExpectedOutputLength; ++i) {
859 std::ostringstream ss;
860 ss << "i = " << i;
861 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
862 EXPECT_EQ(0, out_data_[i]);
863 }
864}
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000865
turaj@webrtc.org3fdeddb2013-09-25 22:19:22 +0000866TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(BackgroundNoise)) {
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000867 neteq_->SetBackgroundNoiseMode(kBgnOn);
868 CheckBgnOff(8000, kBgnOn);
869 CheckBgnOff(16000, kBgnOn);
870 CheckBgnOff(32000, kBgnOn);
871 EXPECT_EQ(kBgnOn, neteq_->BackgroundNoiseMode());
872
873 neteq_->SetBackgroundNoiseMode(kBgnOff);
874 CheckBgnOff(8000, kBgnOff);
875 CheckBgnOff(16000, kBgnOff);
876 CheckBgnOff(32000, kBgnOff);
877 EXPECT_EQ(kBgnOff, neteq_->BackgroundNoiseMode());
878
879 neteq_->SetBackgroundNoiseMode(kBgnFade);
880 CheckBgnOff(8000, kBgnFade);
881 CheckBgnOff(16000, kBgnFade);
882 CheckBgnOff(32000, kBgnFade);
883 EXPECT_EQ(kBgnFade, neteq_->BackgroundNoiseMode());
884}
turaj@webrtc.org7b75ac62013-09-26 00:27:56 +0000885
886TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(SyncPacketInsert)) {
887 WebRtcRTPHeader rtp_info;
888 uint32_t receive_timestamp = 0;
889 // For the readability use the following payloads instead of the defaults of
890 // this test.
891 uint8_t kPcm16WbPayloadType = 1;
892 uint8_t kCngNbPayloadType = 2;
893 uint8_t kCngWbPayloadType = 3;
894 uint8_t kCngSwb32PayloadType = 4;
895 uint8_t kCngSwb48PayloadType = 5;
896 uint8_t kAvtPayloadType = 6;
897 uint8_t kRedPayloadType = 7;
898 uint8_t kIsacPayloadType = 9; // Payload type 8 is already registered.
899
900 // Register decoders.
901 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderPCM16Bwb,
902 kPcm16WbPayloadType));
903 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGnb, kCngNbPayloadType));
904 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGwb, kCngWbPayloadType));
905 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGswb32kHz,
906 kCngSwb32PayloadType));
907 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderCNGswb48kHz,
908 kCngSwb48PayloadType));
909 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderAVT, kAvtPayloadType));
910 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderRED, kRedPayloadType));
911 ASSERT_EQ(0, neteq_->RegisterPayloadType(kDecoderISAC, kIsacPayloadType));
912
913 PopulateRtpInfo(0, 0, &rtp_info);
914 rtp_info.header.payloadType = kPcm16WbPayloadType;
915
916 // The first packet injected cannot be sync-packet.
917 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
918
919 // Payload length of 10 ms PCM16 16 kHz.
920 const int kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
921 uint8_t payload[kPayloadBytes] = {0};
922 ASSERT_EQ(0, neteq_->InsertPacket(
923 rtp_info, payload, kPayloadBytes, receive_timestamp));
924
925 // Next packet. Last packet contained 10 ms audio.
926 rtp_info.header.sequenceNumber++;
927 rtp_info.header.timestamp += kBlockSize16kHz;
928 receive_timestamp += kBlockSize16kHz;
929
930 // Unacceptable payload types CNG, AVT (DTMF), RED.
931 rtp_info.header.payloadType = kCngNbPayloadType;
932 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
933
934 rtp_info.header.payloadType = kCngWbPayloadType;
935 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
936
937 rtp_info.header.payloadType = kCngSwb32PayloadType;
938 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
939
940 rtp_info.header.payloadType = kCngSwb48PayloadType;
941 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
942
943 rtp_info.header.payloadType = kAvtPayloadType;
944 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
945
946 rtp_info.header.payloadType = kRedPayloadType;
947 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
948
949 // Change of codec cannot be initiated with a sync packet.
950 rtp_info.header.payloadType = kIsacPayloadType;
951 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
952
953 // Change of SSRC is not allowed with a sync packet.
954 rtp_info.header.payloadType = kPcm16WbPayloadType;
955 ++rtp_info.header.ssrc;
956 EXPECT_EQ(-1, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
957
958 --rtp_info.header.ssrc;
959 EXPECT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
960}
961
962// First insert several noise like packets, then sync-packets. Decoding all
963// packets should not produce error, statistics should not show any packet loss
964// and sync-packets should decode to zero.
965TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(SyncPacketDecode)) {
966 WebRtcRTPHeader rtp_info;
967 PopulateRtpInfo(0, 0, &rtp_info);
968 const int kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
969 uint8_t payload[kPayloadBytes];
970 int16_t decoded[kBlockSize16kHz];
971 for (int n = 0; n < kPayloadBytes; ++n) {
972 payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence.
973 }
974 // Insert some packets which decode to noise. We are not interested in
975 // actual decoded values.
976 NetEqOutputType output_type;
977 int num_channels;
978 int samples_per_channel;
979 uint32_t receive_timestamp = 0;
980 int delay_samples = 0;
981 for (int n = 0; n < 100; ++n) {
982 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
983 receive_timestamp));
984 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
985 &samples_per_channel, &num_channels,
986 &output_type));
987 ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
988 ASSERT_EQ(1, num_channels);
989
990 // Even if there is RTP packet in NetEq's buffer, the first frame pulled
991 // from NetEq starts with few zero samples. Here we measure this delay.
992 if (n == 0) {
993 while(decoded[delay_samples] == 0) delay_samples++;
994 }
995 rtp_info.header.sequenceNumber++;
996 rtp_info.header.timestamp += kBlockSize16kHz;
997 receive_timestamp += kBlockSize16kHz;
998 }
999 const int kNumSyncPackets = 10;
1000 // Insert sync-packets, the decoded sequence should be all-zero.
1001 for (int n = 0; n < kNumSyncPackets; ++n) {
1002 ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
1003 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
1004 &samples_per_channel, &num_channels,
1005 &output_type));
1006 ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
1007 ASSERT_EQ(1, num_channels);
1008 EXPECT_TRUE(IsAllZero(&decoded[delay_samples],
1009 samples_per_channel * num_channels - delay_samples));
1010 delay_samples = 0; // Delay only matters in the first frame.
1011 rtp_info.header.sequenceNumber++;
1012 rtp_info.header.timestamp += kBlockSize16kHz;
1013 receive_timestamp += kBlockSize16kHz;
1014 }
1015 // We insert a regular packet, if sync packet are not correctly buffered then
1016 // network statistics would show some packet loss.
1017 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
1018 receive_timestamp));
1019 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
1020 &samples_per_channel, &num_channels,
1021 &output_type));
1022 // Make sure the last inserted packet is decoded and there are non-zero
1023 // samples.
1024 EXPECT_FALSE(IsAllZero(decoded, samples_per_channel * num_channels));
1025 NetEqNetworkStatistics network_stats;
1026 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
1027 // Expecting a "clean" network.
1028 EXPECT_EQ(0, network_stats.packet_loss_rate);
1029 EXPECT_EQ(0, network_stats.expand_rate);
1030 EXPECT_EQ(0, network_stats.accelerate_rate);
1031 EXPECT_EQ(0, network_stats.preemptive_rate);
1032}
1033
1034// Test if the size of the packet buffer reported correctly when containing
1035// sync packets. Also, test if network packets override sync packets. That is to
1036// prefer decoding a network packet to a sync packet, if both have same sequence
1037// number and timestamp.
1038TEST_F(NetEqDecodingTest,
1039 DISABLED_ON_ANDROID(SyncPacketBufferSizeAndOverridenByNetworkPackets)) {
1040 WebRtcRTPHeader rtp_info;
1041 PopulateRtpInfo(0, 0, &rtp_info);
1042 const int kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
1043 uint8_t payload[kPayloadBytes];
1044 int16_t decoded[kBlockSize16kHz];
1045 for (int n = 0; n < kPayloadBytes; ++n) {
1046 payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence.
1047 }
1048 // Insert some packets which decode to noise. We are not interested in
1049 // actual decoded values.
1050 NetEqOutputType output_type;
1051 int num_channels;
1052 int samples_per_channel;
1053 uint32_t receive_timestamp = 0;
1054 for (int n = 0; n < 1; ++n) {
1055 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
1056 receive_timestamp));
1057 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
1058 &samples_per_channel, &num_channels,
1059 &output_type));
1060 ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
1061 ASSERT_EQ(1, num_channels);
1062 rtp_info.header.sequenceNumber++;
1063 rtp_info.header.timestamp += kBlockSize16kHz;
1064 receive_timestamp += kBlockSize16kHz;
1065 }
1066 const int kNumSyncPackets = 10;
1067
1068 WebRtcRTPHeader first_sync_packet_rtp_info;
1069 memcpy(&first_sync_packet_rtp_info, &rtp_info, sizeof(rtp_info));
1070
1071 // Insert sync-packets, but no decoding.
1072 for (int n = 0; n < kNumSyncPackets; ++n) {
1073 ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
1074 rtp_info.header.sequenceNumber++;
1075 rtp_info.header.timestamp += kBlockSize16kHz;
1076 receive_timestamp += kBlockSize16kHz;
1077 }
1078 NetEqNetworkStatistics network_stats;
1079 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
1080 EXPECT_EQ(kNumSyncPackets * 10, network_stats.current_buffer_size_ms);
1081
1082 // Rewind |rtp_info| to that of the first sync packet.
1083 memcpy(&rtp_info, &first_sync_packet_rtp_info, sizeof(rtp_info));
1084
1085 // Insert.
1086 for (int n = 0; n < kNumSyncPackets; ++n) {
1087 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes,
1088 receive_timestamp));
1089 rtp_info.header.sequenceNumber++;
1090 rtp_info.header.timestamp += kBlockSize16kHz;
1091 receive_timestamp += kBlockSize16kHz;
1092 }
1093
1094 // Decode.
1095 for (int n = 0; n < kNumSyncPackets; ++n) {
1096 ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
1097 &samples_per_channel, &num_channels,
1098 &output_type));
1099 ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
1100 ASSERT_EQ(1, num_channels);
1101 EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels));
1102 }
1103}
1104
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001105} // namespace