blob: 4b6e5d7ac8ca257b6e45aa4823564b317c43772e [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
Henrik Kjellander74640892015-10-29 11:31:02 +010011#include "webrtc/modules/audio_coding/neteq/include/neteq.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
pbos@webrtc.org3ecc1622014-03-07 15:23:34 +000013#include <math.h>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000014#include <stdlib.h>
15#include <string.h> // memset
16
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +000017#include <algorithm>
kwiberg2d0c3322016-02-14 09:28:33 -080018#include <memory>
turaj@webrtc.org78b41a02013-11-22 20:27:07 +000019#include <set>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000020#include <string>
21#include <vector>
22
turaj@webrtc.orga6101d72013-10-01 22:01:09 +000023#include "gflags/gflags.h"
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000024#include "testing/gtest/include/gtest/gtest.h"
minyue4f906772016-04-29 11:05:14 -070025#include "webrtc/base/sha1digest.h"
26#include "webrtc/base/stringencode.h"
ossue3525782016-05-25 07:37:43 -070027#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +000028#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
henrik.lundin@webrtc.org966a7082014-11-17 09:08:38 +000029#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
kjellander@webrtc.org3c652b62015-11-18 23:07:57 +010030#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h"
henrik.lundin6d8e0112016-03-04 10:34:21 -080031#include "webrtc/modules/include/module_common_types.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000032#include "webrtc/test/testsupport/fileutils.h"
33#include "webrtc/typedefs.h"
34
minyue5f026d02015-12-16 07:36:04 -080035#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT
36#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
37#include "external/webrtc/webrtc/modules/audio_coding/neteq/neteq_unittest.pb.h"
38#else
39#include "webrtc/audio_coding/neteq/neteq_unittest.pb.h"
40#endif
41#endif
42
turaj@webrtc.orga6101d72013-10-01 22:01:09 +000043DEFINE_bool(gen_ref, false, "Generate reference files.");
44
minyue5f026d02015-12-16 07:36:04 -080045namespace {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000046
minyue4f906772016-04-29 11:05:14 -070047const std::string& PlatformChecksum(const std::string& checksum_general,
48 const std::string& checksum_android,
49 const std::string& checksum_win_32,
50 const std::string& checksum_win_64) {
51#ifdef WEBRTC_ANDROID
52 return checksum_android;
53#elif WEBRTC_WIN
54 #ifdef WEBRTC_ARCH_64_BITS
55 return checksum_win_64;
56 #else
57 return checksum_win_32;
58 #endif // WEBRTC_ARCH_64_BITS
59#else
60 return checksum_general;
61#endif // WEBRTC_WIN
62}
63
minyue5f026d02015-12-16 07:36:04 -080064#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT
65void Convert(const webrtc::NetEqNetworkStatistics& stats_raw,
66 webrtc::neteq_unittest::NetEqNetworkStatistics* stats) {
67 stats->set_current_buffer_size_ms(stats_raw.current_buffer_size_ms);
68 stats->set_preferred_buffer_size_ms(stats_raw.preferred_buffer_size_ms);
69 stats->set_jitter_peaks_found(stats_raw.jitter_peaks_found);
70 stats->set_packet_loss_rate(stats_raw.packet_loss_rate);
71 stats->set_packet_discard_rate(stats_raw.packet_discard_rate);
72 stats->set_expand_rate(stats_raw.expand_rate);
73 stats->set_speech_expand_rate(stats_raw.speech_expand_rate);
74 stats->set_preemptive_rate(stats_raw.preemptive_rate);
75 stats->set_accelerate_rate(stats_raw.accelerate_rate);
76 stats->set_secondary_decoded_rate(stats_raw.secondary_decoded_rate);
77 stats->set_clockdrift_ppm(stats_raw.clockdrift_ppm);
78 stats->set_added_zero_samples(stats_raw.added_zero_samples);
79 stats->set_mean_waiting_time_ms(stats_raw.mean_waiting_time_ms);
80 stats->set_median_waiting_time_ms(stats_raw.median_waiting_time_ms);
81 stats->set_min_waiting_time_ms(stats_raw.min_waiting_time_ms);
82 stats->set_max_waiting_time_ms(stats_raw.max_waiting_time_ms);
83}
84
85void Convert(const webrtc::RtcpStatistics& stats_raw,
86 webrtc::neteq_unittest::RtcpStatistics* stats) {
87 stats->set_fraction_lost(stats_raw.fraction_lost);
88 stats->set_cumulative_lost(stats_raw.cumulative_lost);
89 stats->set_extended_max_sequence_number(
90 stats_raw.extended_max_sequence_number);
91 stats->set_jitter(stats_raw.jitter);
92}
93
minyue4f906772016-04-29 11:05:14 -070094void AddMessage(FILE* file, rtc::MessageDigest* digest,
95 const std::string& message) {
minyue5f026d02015-12-16 07:36:04 -080096 int32_t size = message.length();
minyue4f906772016-04-29 11:05:14 -070097 if (file)
98 ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file));
99 digest->Update(&size, sizeof(size));
100
101 if (file)
102 ASSERT_EQ(static_cast<size_t>(size),
103 fwrite(message.data(), sizeof(char), size, file));
104 digest->Update(message.data(), sizeof(char) * size);
minyue5f026d02015-12-16 07:36:04 -0800105}
106
minyue5f026d02015-12-16 07:36:04 -0800107#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT
108
henrik.lundin7a926812016-05-12 13:51:28 -0700109void LoadDecoders(webrtc::NetEq* neteq) {
110 // Load PCMu.
111 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMu,
112 "pcmu", 0));
113 // Load PCMa.
114 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMa,
115 "pcma", 8));
116#ifdef WEBRTC_CODEC_ILBC
117 // Load iLBC.
118 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderILBC,
119 "ilbc", 102));
120#endif
121#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
122 // Load iSAC.
123 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderISAC,
124 "isac", 103));
125#endif
126#ifdef WEBRTC_CODEC_ISAC
127 // Load iSAC SWB.
128 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderISACswb,
129 "isac-swb", 104));
130#endif
131#ifdef WEBRTC_CODEC_OPUS
132 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderOpus,
133 "opus", 111));
134#endif
135 // Load PCM16B nb.
136 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCM16B,
137 "pcm16-nb", 93));
138 // Load PCM16B wb.
139 ASSERT_EQ(0, neteq->RegisterPayloadType(
140 webrtc::NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb", 94));
141 // Load PCM16B swb32.
142 ASSERT_EQ(
143 0, neteq->RegisterPayloadType(
144 webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32", 95));
145 // Load CNG 8 kHz.
146 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderCNGnb,
147 "cng-nb", 13));
148 // Load CNG 16 kHz.
149 ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderCNGwb,
150 "cng-wb", 98));
151}
minyue5f026d02015-12-16 07:36:04 -0800152} // namespace
153
154namespace webrtc {
155
minyue4f906772016-04-29 11:05:14 -0700156class ResultSink {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000157 public:
minyue4f906772016-04-29 11:05:14 -0700158 explicit ResultSink(const std::string& output_file);
159 ~ResultSink();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000160
minyue4f906772016-04-29 11:05:14 -0700161 template<typename T, size_t n> void AddResult(
162 const T (&test_results)[n],
163 size_t length);
164
165 void AddResult(const NetEqNetworkStatistics& stats);
166 void AddResult(const RtcpStatistics& stats);
167
168 void VerifyChecksum(const std::string& ref_check_sum);
169
170 private:
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171 FILE* output_fp_;
minyue4f906772016-04-29 11:05:14 -0700172 std::unique_ptr<rtc::MessageDigest> digest_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000173};
174
minyue4f906772016-04-29 11:05:14 -0700175ResultSink::ResultSink(const std::string &output_file)
176 : output_fp_(nullptr),
177 digest_(new rtc::Sha1Digest()) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000178 if (!output_file.empty()) {
179 output_fp_ = fopen(output_file.c_str(), "wb");
180 EXPECT_TRUE(output_fp_ != NULL);
181 }
182}
183
minyue4f906772016-04-29 11:05:14 -0700184ResultSink::~ResultSink() {
185 if (output_fp_)
186 fclose(output_fp_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000187}
188
189template<typename T, size_t n>
minyue4f906772016-04-29 11:05:14 -0700190void ResultSink::AddResult(const T (&test_results)[n], size_t length) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000191 if (output_fp_) {
192 ASSERT_EQ(length, fwrite(&test_results, sizeof(T), length, output_fp_));
193 }
minyue4f906772016-04-29 11:05:14 -0700194 digest_->Update(&test_results, sizeof(T) * length);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195}
196
minyue4f906772016-04-29 11:05:14 -0700197void ResultSink::AddResult(const NetEqNetworkStatistics& stats_raw) {
minyue5f026d02015-12-16 07:36:04 -0800198#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT
minyue5f026d02015-12-16 07:36:04 -0800199 neteq_unittest::NetEqNetworkStatistics stats;
200 Convert(stats_raw, &stats);
201
202 std::string stats_string;
203 ASSERT_TRUE(stats.SerializeToString(&stats_string));
minyue4f906772016-04-29 11:05:14 -0700204 AddMessage(output_fp_, digest_.get(), stats_string);
minyue5f026d02015-12-16 07:36:04 -0800205#else
206 FAIL() << "Writing to reference file requires Proto Buffer.";
207#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000208}
209
minyue4f906772016-04-29 11:05:14 -0700210void ResultSink::AddResult(const RtcpStatistics& stats_raw) {
minyue5f026d02015-12-16 07:36:04 -0800211#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT
minyue5f026d02015-12-16 07:36:04 -0800212 neteq_unittest::RtcpStatistics stats;
213 Convert(stats_raw, &stats);
214
215 std::string stats_string;
216 ASSERT_TRUE(stats.SerializeToString(&stats_string));
minyue4f906772016-04-29 11:05:14 -0700217 AddMessage(output_fp_, digest_.get(), stats_string);
minyue5f026d02015-12-16 07:36:04 -0800218#else
219 FAIL() << "Writing to reference file requires Proto Buffer.";
220#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000221}
222
minyue4f906772016-04-29 11:05:14 -0700223void ResultSink::VerifyChecksum(const std::string& checksum) {
224 std::vector<char> buffer;
225 buffer.resize(digest_->Size());
226 digest_->Finish(&buffer[0], buffer.size());
227 const std::string result = rtc::hex_encode(&buffer[0], digest_->Size());
228 EXPECT_EQ(checksum, result);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229}
230
231class NetEqDecodingTest : public ::testing::Test {
232 protected:
233 // NetEQ must be polled for data once every 10 ms. Thus, neither of the
234 // constants below can be changed.
235 static const int kTimeStepMs = 10;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700236 static const size_t kBlockSize8kHz = kTimeStepMs * 8;
237 static const size_t kBlockSize16kHz = kTimeStepMs * 16;
238 static const size_t kBlockSize32kHz = kTimeStepMs * 32;
minyue93c08b72015-12-22 09:57:41 -0800239 static const size_t kBlockSize48kHz = kTimeStepMs * 48;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000240 static const int kInitSampleRateHz = 8000;
241
242 NetEqDecodingTest();
243 virtual void SetUp();
244 virtual void TearDown();
245 void SelectDecoders(NetEqDecoder* used_codec);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000246 void OpenInputFile(const std::string &rtp_file);
henrik.lundin6d8e0112016-03-04 10:34:21 -0800247 void Process();
minyue5f026d02015-12-16 07:36:04 -0800248
henrik.lundin@webrtc.org4e4b0982014-08-11 14:48:49 +0000249 void DecodeAndCompare(const std::string& rtp_file,
minyue4f906772016-04-29 11:05:14 -0700250 const std::string& output_checksum,
251 const std::string& network_stats_checksum,
252 const std::string& rtcp_stats_checksum,
253 bool gen_ref);
minyue5f026d02015-12-16 07:36:04 -0800254
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000255 static void PopulateRtpInfo(int frame_index,
256 int timestamp,
257 WebRtcRTPHeader* rtp_info);
258 static void PopulateCng(int frame_index,
259 int timestamp,
260 WebRtcRTPHeader* rtp_info,
261 uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000262 size_t* payload_len);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000263
turaj@webrtc.org78b41a02013-11-22 20:27:07 +0000264 void WrapTest(uint16_t start_seq_no, uint32_t start_timestamp,
265 const std::set<uint16_t>& drop_seq_numbers,
266 bool expect_seq_no_wrap, bool expect_timestamp_wrap);
267
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000268 void LongCngWithClockDrift(double drift_factor,
269 double network_freeze_ms,
270 bool pull_audio_during_freeze,
271 int delay_tolerance_ms,
272 int max_time_to_speech_ms);
273
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +0000274 void DuplicateCng();
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000275
henrik.lundin0d96ab72016-04-06 12:28:26 -0700276 rtc::Optional<uint32_t> PlayoutTimestamp();
wu@webrtc.org94454b72014-06-05 20:34:08 +0000277
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000278 NetEq* neteq_;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000279 NetEq::Config config_;
kwiberg2d0c3322016-02-14 09:28:33 -0800280 std::unique_ptr<test::RtpFileSource> rtp_source_;
281 std::unique_ptr<test::Packet> packet_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000282 unsigned int sim_clock_;
henrik.lundin6d8e0112016-03-04 10:34:21 -0800283 AudioFrame out_frame_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000284 int output_sample_rate_;
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +0000285 int algorithmic_delay_ms_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000286};
287
288// Allocating the static const so that it can be passed by reference.
289const int NetEqDecodingTest::kTimeStepMs;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700290const size_t NetEqDecodingTest::kBlockSize8kHz;
291const size_t NetEqDecodingTest::kBlockSize16kHz;
292const size_t NetEqDecodingTest::kBlockSize32kHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000293const int NetEqDecodingTest::kInitSampleRateHz;
294
295NetEqDecodingTest::NetEqDecodingTest()
296 : neteq_(NULL),
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000297 config_(),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000298 sim_clock_(0),
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +0000299 output_sample_rate_(kInitSampleRateHz),
300 algorithmic_delay_ms_(0) {
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000301 config_.sample_rate_hz = kInitSampleRateHz;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000302}
303
304void NetEqDecodingTest::SetUp() {
ossue3525782016-05-25 07:37:43 -0700305 neteq_ = NetEq::Create(config_, CreateBuiltinAudioDecoderFactory());
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +0000306 NetEqNetworkStatistics stat;
307 ASSERT_EQ(0, neteq_->NetworkStatistics(&stat));
308 algorithmic_delay_ms_ = stat.current_buffer_size_ms;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000309 ASSERT_TRUE(neteq_);
henrik.lundin7a926812016-05-12 13:51:28 -0700310 LoadDecoders(neteq_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000311}
312
313void NetEqDecodingTest::TearDown() {
314 delete neteq_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000315}
316
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000317void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) {
henrik.lundin@webrtc.org966a7082014-11-17 09:08:38 +0000318 rtp_source_.reset(test::RtpFileSource::Create(rtp_file));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000319}
320
henrik.lundin6d8e0112016-03-04 10:34:21 -0800321void NetEqDecodingTest::Process() {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000322 // Check if time to receive.
henrik.lundin@webrtc.org966a7082014-11-17 09:08:38 +0000323 while (packet_ && sim_clock_ >= packet_->time_ms()) {
324 if (packet_->payload_length_bytes() > 0) {
325 WebRtcRTPHeader rtp_header;
326 packet_->ConvertHeader(&rtp_header);
ivoc72c08ed2016-01-20 07:26:24 -0800327#ifndef WEBRTC_CODEC_ISAC
328 // Ignore payload type 104 (iSAC-swb) if ISAC is not supported.
329 if (rtp_header.header.payloadType != 104)
330#endif
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000331 ASSERT_EQ(0, neteq_->InsertPacket(
kwibergee2bac22015-11-11 10:34:00 -0800332 rtp_header,
333 rtc::ArrayView<const uint8_t>(
334 packet_->payload(), packet_->payload_length_bytes()),
335 static_cast<uint32_t>(packet_->time_ms() *
336 (output_sample_rate_ / 1000))));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000337 }
338 // Get next packet.
henrik.lundin46ba49c2016-05-24 22:50:47 -0700339 packet_ = rtp_source_->NextPacket();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000340 }
341
henrik.lundin@webrtc.orge1d468c2013-01-30 07:37:20 +0000342 // Get audio from NetEq.
henrik.lundin7a926812016-05-12 13:51:28 -0700343 bool muted;
344 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
345 ASSERT_FALSE(muted);
henrik.lundin6d8e0112016-03-04 10:34:21 -0800346 ASSERT_TRUE((out_frame_.samples_per_channel_ == kBlockSize8kHz) ||
347 (out_frame_.samples_per_channel_ == kBlockSize16kHz) ||
348 (out_frame_.samples_per_channel_ == kBlockSize32kHz) ||
349 (out_frame_.samples_per_channel_ == kBlockSize48kHz));
350 output_sample_rate_ = out_frame_.sample_rate_hz_;
henrik.lundind89814b2015-11-23 06:49:25 -0800351 EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000352
353 // Increase time.
354 sim_clock_ += kTimeStepMs;
355}
356
minyue4f906772016-04-29 11:05:14 -0700357void NetEqDecodingTest::DecodeAndCompare(
358 const std::string& rtp_file,
359 const std::string& output_checksum,
360 const std::string& network_stats_checksum,
361 const std::string& rtcp_stats_checksum,
362 bool gen_ref) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000363 OpenInputFile(rtp_file);
364
minyue4f906772016-04-29 11:05:14 -0700365 std::string ref_out_file =
366 gen_ref ? webrtc::test::OutputPath() + "neteq_universal_ref.pcm" : "";
367 ResultSink output(ref_out_file);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000368
minyue4f906772016-04-29 11:05:14 -0700369 std::string stat_out_file =
370 gen_ref ? webrtc::test::OutputPath() + "neteq_network_stats.dat" : "";
371 ResultSink network_stats(stat_out_file);
henrik.lundin@webrtc.org4e4b0982014-08-11 14:48:49 +0000372
minyue4f906772016-04-29 11:05:14 -0700373 std::string rtcp_out_file =
374 gen_ref ? webrtc::test::OutputPath() + "neteq_rtcp_stats.dat" : "";
375 ResultSink rtcp_stats(rtcp_out_file);
henrik.lundin@webrtc.org4e4b0982014-08-11 14:48:49 +0000376
henrik.lundin46ba49c2016-05-24 22:50:47 -0700377 packet_ = rtp_source_->NextPacket();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000378 int i = 0;
henrik.lundin@webrtc.org966a7082014-11-17 09:08:38 +0000379 while (packet_) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000380 std::ostringstream ss;
381 ss << "Lap number " << i++ << " in DecodeAndCompare while loop";
382 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800383 ASSERT_NO_FATAL_FAILURE(Process());
minyue4f906772016-04-29 11:05:14 -0700384 ASSERT_NO_FATAL_FAILURE(output.AddResult(
henrik.lundin6d8e0112016-03-04 10:34:21 -0800385 out_frame_.data_, out_frame_.samples_per_channel_));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000386
387 // Query the network statistics API once per second
388 if (sim_clock_ % 1000 == 0) {
389 // Process NetworkStatistics.
minyue4f906772016-04-29 11:05:14 -0700390 NetEqNetworkStatistics current_network_stats;
391 ASSERT_EQ(0, neteq_->NetworkStatistics(&current_network_stats));
392 ASSERT_NO_FATAL_FAILURE(network_stats.AddResult(current_network_stats));
393
henrik.lundin9c3efd02015-08-27 13:12:22 -0700394 // Compare with CurrentDelay, which should be identical.
minyue4f906772016-04-29 11:05:14 -0700395 EXPECT_EQ(current_network_stats.current_buffer_size_ms,
396 neteq_->CurrentDelayMs());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000397
398 // Process RTCPstat.
minyue4f906772016-04-29 11:05:14 -0700399 RtcpStatistics current_rtcp_stats;
400 neteq_->GetRtcpStatistics(&current_rtcp_stats);
401 ASSERT_NO_FATAL_FAILURE(rtcp_stats.AddResult(current_rtcp_stats));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000402 }
403 }
minyue4f906772016-04-29 11:05:14 -0700404
405 SCOPED_TRACE("Check output audio.");
406 output.VerifyChecksum(output_checksum);
407 SCOPED_TRACE("Check network stats.");
408 network_stats.VerifyChecksum(network_stats_checksum);
409 SCOPED_TRACE("Check rtcp stats.");
410 rtcp_stats.VerifyChecksum(rtcp_stats_checksum);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000411}
412
413void NetEqDecodingTest::PopulateRtpInfo(int frame_index,
414 int timestamp,
415 WebRtcRTPHeader* rtp_info) {
416 rtp_info->header.sequenceNumber = frame_index;
417 rtp_info->header.timestamp = timestamp;
418 rtp_info->header.ssrc = 0x1234; // Just an arbitrary SSRC.
419 rtp_info->header.payloadType = 94; // PCM16b WB codec.
420 rtp_info->header.markerBit = 0;
421}
422
423void NetEqDecodingTest::PopulateCng(int frame_index,
424 int timestamp,
425 WebRtcRTPHeader* rtp_info,
426 uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000427 size_t* payload_len) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000428 rtp_info->header.sequenceNumber = frame_index;
429 rtp_info->header.timestamp = timestamp;
430 rtp_info->header.ssrc = 0x1234; // Just an arbitrary SSRC.
431 rtp_info->header.payloadType = 98; // WB CNG.
432 rtp_info->header.markerBit = 0;
433 payload[0] = 64; // Noise level -64 dBov, quite arbitrarily chosen.
434 *payload_len = 1; // Only noise level, no spectral parameters.
435}
436
ivoc72c08ed2016-01-20 07:26:24 -0800437#if !defined(WEBRTC_IOS) && defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \
438 (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
439 defined(WEBRTC_CODEC_ILBC) && defined(WEBRTC_CODEC_G722) && \
pbosc7a65692016-05-06 12:50:04 -0700440 !defined(WEBRTC_ARCH_ARM64)
minyue5f026d02015-12-16 07:36:04 -0800441#define MAYBE_TestBitExactness TestBitExactness
kwiberg98ab3a42015-09-30 21:54:21 -0700442#else
minyue5f026d02015-12-16 07:36:04 -0800443#define MAYBE_TestBitExactness DISABLED_TestBitExactness
kwiberg98ab3a42015-09-30 21:54:21 -0700444#endif
minyue5f026d02015-12-16 07:36:04 -0800445TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
minyue49c454e2016-01-08 11:30:14 -0800446 const std::string input_rtp_file =
447 webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
henrik.lundin@webrtc.org4e4b0982014-08-11 14:48:49 +0000448
minyue4f906772016-04-29 11:05:14 -0700449 const std::string output_checksum = PlatformChecksum(
henrik.lundinc7668042016-08-25 23:53:38 -0700450 "acd33f5c73625c1529c412ad59b5565132826f1b",
451 "1a2e82a0410421c1d1d3eb0615334db5e2c63784",
452 "acd33f5c73625c1529c412ad59b5565132826f1b",
453 "52797b781758a1d2303140b80b9c5030c9093d6b");
minyue4f906772016-04-29 11:05:14 -0700454
455 const std::string network_stats_checksum = PlatformChecksum(
henrik.lundinc7668042016-08-25 23:53:38 -0700456 "9c5bb9e74a583be89313b158a19ea10d41bf9de6",
457 "e948ec65cf18852ba2a197189a3186635db34c3b",
458 "9c5bb9e74a583be89313b158a19ea10d41bf9de6",
459 "9c5bb9e74a583be89313b158a19ea10d41bf9de6");
minyue4f906772016-04-29 11:05:14 -0700460
461 const std::string rtcp_stats_checksum = PlatformChecksum(
462 "b8880bf9fed2487efbddcb8d94b9937a29ae521d",
463 "f3f7b3d3e71d7e635240b5373b57df6a7e4ce9d4",
464 "b8880bf9fed2487efbddcb8d94b9937a29ae521d",
465 "b8880bf9fed2487efbddcb8d94b9937a29ae521d");
466
467 DecodeAndCompare(input_rtp_file,
468 output_checksum,
469 network_stats_checksum,
470 rtcp_stats_checksum,
471 FLAGS_gen_ref);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000472}
473
minyue93c08b72015-12-22 09:57:41 -0800474#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID) && \
475 defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \
pbosc7a65692016-05-06 12:50:04 -0700476 defined(WEBRTC_CODEC_OPUS)
minyue93c08b72015-12-22 09:57:41 -0800477#define MAYBE_TestOpusBitExactness TestOpusBitExactness
478#else
479#define MAYBE_TestOpusBitExactness DISABLED_TestOpusBitExactness
480#endif
flim64a7eab2016-08-12 04:36:05 -0700481TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
minyue93c08b72015-12-22 09:57:41 -0800482 const std::string input_rtp_file =
483 webrtc::test::ResourcePath("audio_coding/neteq_opus", "rtp");
minyue93c08b72015-12-22 09:57:41 -0800484
minyue4f906772016-04-29 11:05:14 -0700485 const std::string output_checksum = PlatformChecksum(
flim64a7eab2016-08-12 04:36:05 -0700486 "9d7d52bc94e941d106aa518f324f16a58d231586",
487 "9d7d52bc94e941d106aa518f324f16a58d231586",
488 "9d7d52bc94e941d106aa518f324f16a58d231586",
489 "9d7d52bc94e941d106aa518f324f16a58d231586");
minyue4f906772016-04-29 11:05:14 -0700490
491 const std::string network_stats_checksum = PlatformChecksum(
flim64a7eab2016-08-12 04:36:05 -0700492 "191af29ed3b8b6dd4c4cc94dc3f33bdf48f055ef",
493 "191af29ed3b8b6dd4c4cc94dc3f33bdf48f055ef",
494 "191af29ed3b8b6dd4c4cc94dc3f33bdf48f055ef",
495 "191af29ed3b8b6dd4c4cc94dc3f33bdf48f055ef");
minyue4f906772016-04-29 11:05:14 -0700496
497 const std::string rtcp_stats_checksum = PlatformChecksum(
498 "e37c797e3de6a64dda88c9ade7a013d022a2e1e0",
499 "e37c797e3de6a64dda88c9ade7a013d022a2e1e0",
500 "e37c797e3de6a64dda88c9ade7a013d022a2e1e0",
501 "e37c797e3de6a64dda88c9ade7a013d022a2e1e0");
502
503 DecodeAndCompare(input_rtp_file,
504 output_checksum,
505 network_stats_checksum,
506 rtcp_stats_checksum,
507 FLAGS_gen_ref);
minyue93c08b72015-12-22 09:57:41 -0800508}
509
henrik.lundin@webrtc.org7cbc4f92014-10-07 06:37:39 +0000510// Use fax mode to avoid time-scaling. This is to simplify the testing of
511// packet waiting times in the packet buffer.
512class NetEqDecodingTestFaxMode : public NetEqDecodingTest {
513 protected:
514 NetEqDecodingTestFaxMode() : NetEqDecodingTest() {
515 config_.playout_mode = kPlayoutFax;
516 }
517};
518
519TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000520 // Insert 30 dummy packets at once. Each packet contains 10 ms 16 kHz audio.
521 size_t num_frames = 30;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000522 const size_t kSamples = 10 * 16;
523 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000524 for (size_t i = 0; i < num_frames; ++i) {
kwibergee2bac22015-11-11 10:34:00 -0800525 const uint8_t payload[kPayloadBytes] = {0};
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000526 WebRtcRTPHeader rtp_info;
527 rtp_info.header.sequenceNumber = i;
528 rtp_info.header.timestamp = i * kSamples;
529 rtp_info.header.ssrc = 0x1234; // Just an arbitrary SSRC.
530 rtp_info.header.payloadType = 94; // PCM16b WB codec.
531 rtp_info.header.markerBit = 0;
kwibergee2bac22015-11-11 10:34:00 -0800532 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000533 }
534 // Pull out all data.
535 for (size_t i = 0; i < num_frames; ++i) {
henrik.lundin7a926812016-05-12 13:51:28 -0700536 bool muted;
537 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800538 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000539 }
540
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200541 NetEqNetworkStatistics stats;
542 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000543 // Since all frames are dumped into NetEQ at once, but pulled out with 10 ms
544 // spacing (per definition), we expect the delay to increase with 10 ms for
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200545 // each packet. Thus, we are calculating the statistics for a series from 10
546 // to 300, in steps of 10 ms.
547 EXPECT_EQ(155, stats.mean_waiting_time_ms);
548 EXPECT_EQ(155, stats.median_waiting_time_ms);
549 EXPECT_EQ(10, stats.min_waiting_time_ms);
550 EXPECT_EQ(300, stats.max_waiting_time_ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000551
552 // Check statistics again and make sure it's been reset.
Henrik Lundin1bb8cf82015-08-25 13:08:04 +0200553 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
554 EXPECT_EQ(-1, stats.mean_waiting_time_ms);
555 EXPECT_EQ(-1, stats.median_waiting_time_ms);
556 EXPECT_EQ(-1, stats.min_waiting_time_ms);
557 EXPECT_EQ(-1, stats.max_waiting_time_ms);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000558}
559
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000560TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000561 const int kNumFrames = 3000; // Needed for convergence.
562 int frame_index = 0;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000563 const size_t kSamples = 10 * 16;
564 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000565 while (frame_index < kNumFrames) {
566 // Insert one packet each time, except every 10th time where we insert two
567 // packets at once. This will create a negative clock-drift of approx. 10%.
568 int num_packets = (frame_index % 10 == 0 ? 2 : 1);
569 for (int n = 0; n < num_packets; ++n) {
570 uint8_t payload[kPayloadBytes] = {0};
571 WebRtcRTPHeader rtp_info;
572 PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -0800573 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000574 ++frame_index;
575 }
576
577 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700578 bool muted;
579 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800580 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000581 }
582
583 NetEqNetworkStatistics network_stats;
584 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
585 EXPECT_EQ(-103196, network_stats.clockdrift_ppm);
586}
587
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000588TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000589 const int kNumFrames = 5000; // Needed for convergence.
590 int frame_index = 0;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000591 const size_t kSamples = 10 * 16;
592 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000593 for (int i = 0; i < kNumFrames; ++i) {
594 // Insert one packet each time, except every 10th time where we don't insert
595 // any packet. This will create a positive clock-drift of approx. 11%.
596 int num_packets = (i % 10 == 9 ? 0 : 1);
597 for (int n = 0; n < num_packets; ++n) {
598 uint8_t payload[kPayloadBytes] = {0};
599 WebRtcRTPHeader rtp_info;
600 PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -0800601 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000602 ++frame_index;
603 }
604
605 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700606 bool muted;
607 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800608 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000609 }
610
611 NetEqNetworkStatistics network_stats;
612 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
613 EXPECT_EQ(110946, network_stats.clockdrift_ppm);
614}
615
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000616void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
617 double network_freeze_ms,
618 bool pull_audio_during_freeze,
619 int delay_tolerance_ms,
620 int max_time_to_speech_ms) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000621 uint16_t seq_no = 0;
622 uint32_t timestamp = 0;
623 const int kFrameSizeMs = 30;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000624 const size_t kSamples = kFrameSizeMs * 16;
625 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000626 double next_input_time_ms = 0.0;
627 double t_ms;
henrik.lundin7a926812016-05-12 13:51:28 -0700628 bool muted;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000629
630 // Insert speech for 5 seconds.
631 const int kSpeechDurationMs = 5000;
632 for (t_ms = 0; t_ms < kSpeechDurationMs; t_ms += 10) {
633 // Each turn in this for loop is 10 ms.
634 while (next_input_time_ms <= t_ms) {
635 // Insert one 30 ms speech frame.
636 uint8_t payload[kPayloadBytes] = {0};
637 WebRtcRTPHeader rtp_info;
638 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -0800639 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000640 ++seq_no;
641 timestamp += kSamples;
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000642 next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000643 }
644 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700645 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800646 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000647 }
648
henrik.lundin55480f52016-03-08 02:37:57 -0800649 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin0d96ab72016-04-06 12:28:26 -0700650 rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
651 ASSERT_TRUE(playout_timestamp);
652 int32_t delay_before = timestamp - *playout_timestamp;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000653
654 // Insert CNG for 1 minute (= 60000 ms).
655 const int kCngPeriodMs = 100;
656 const int kCngPeriodSamples = kCngPeriodMs * 16; // Period in 16 kHz samples.
657 const int kCngDurationMs = 60000;
658 for (; t_ms < kSpeechDurationMs + kCngDurationMs; t_ms += 10) {
659 // Each turn in this for loop is 10 ms.
660 while (next_input_time_ms <= t_ms) {
661 // Insert one CNG frame each 100 ms.
662 uint8_t payload[kPayloadBytes];
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000663 size_t payload_len;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000664 WebRtcRTPHeader rtp_info;
665 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
kwibergee2bac22015-11-11 10:34:00 -0800666 ASSERT_EQ(0, neteq_->InsertPacket(
667 rtp_info,
668 rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000669 ++seq_no;
670 timestamp += kCngPeriodSamples;
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000671 next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000672 }
673 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700674 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800675 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000676 }
677
henrik.lundin55480f52016-03-08 02:37:57 -0800678 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000679
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000680 if (network_freeze_ms > 0) {
681 // First keep pulling audio for |network_freeze_ms| without inserting
682 // any data, then insert CNG data corresponding to |network_freeze_ms|
683 // without pulling any output audio.
684 const double loop_end_time = t_ms + network_freeze_ms;
685 for (; t_ms < loop_end_time; t_ms += 10) {
686 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700687 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800688 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800689 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000690 }
691 bool pull_once = pull_audio_during_freeze;
692 // If |pull_once| is true, GetAudio will be called once half-way through
693 // the network recovery period.
694 double pull_time_ms = (t_ms + next_input_time_ms) / 2;
695 while (next_input_time_ms <= t_ms) {
696 if (pull_once && next_input_time_ms >= pull_time_ms) {
697 pull_once = false;
698 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700699 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800700 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800701 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000702 t_ms += 10;
703 }
704 // Insert one CNG frame each 100 ms.
705 uint8_t payload[kPayloadBytes];
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000706 size_t payload_len;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000707 WebRtcRTPHeader rtp_info;
708 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
kwibergee2bac22015-11-11 10:34:00 -0800709 ASSERT_EQ(0, neteq_->InsertPacket(
710 rtp_info,
711 rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000712 ++seq_no;
713 timestamp += kCngPeriodSamples;
714 next_input_time_ms += kCngPeriodMs * drift_factor;
715 }
716 }
717
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000718 // Insert speech again until output type is speech.
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000719 double speech_restart_time_ms = t_ms;
henrik.lundin55480f52016-03-08 02:37:57 -0800720 while (out_frame_.speech_type_ != AudioFrame::kNormalSpeech) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000721 // Each turn in this for loop is 10 ms.
722 while (next_input_time_ms <= t_ms) {
723 // Insert one 30 ms speech frame.
724 uint8_t payload[kPayloadBytes] = {0};
725 WebRtcRTPHeader rtp_info;
726 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -0800727 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000728 ++seq_no;
729 timestamp += kSamples;
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000730 next_input_time_ms += kFrameSizeMs * drift_factor;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000731 }
732 // Pull out data once.
henrik.lundin7a926812016-05-12 13:51:28 -0700733 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800734 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000735 // Increase clock.
736 t_ms += 10;
737 }
738
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000739 // Check that the speech starts again within reasonable time.
740 double time_until_speech_returns_ms = t_ms - speech_restart_time_ms;
741 EXPECT_LT(time_until_speech_returns_ms, max_time_to_speech_ms);
henrik.lundin0d96ab72016-04-06 12:28:26 -0700742 playout_timestamp = PlayoutTimestamp();
743 ASSERT_TRUE(playout_timestamp);
744 int32_t delay_after = timestamp - *playout_timestamp;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000745 // Compare delay before and after, and make sure it differs less than 20 ms.
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000746 EXPECT_LE(delay_after, delay_before + delay_tolerance_ms * 16);
747 EXPECT_GE(delay_after, delay_before - delay_tolerance_ms * 16);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000748}
749
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000750TEST_F(NetEqDecodingTest, LongCngWithNegativeClockDrift) {
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000751 // Apply a clock drift of -25 ms / s (sender faster than receiver).
752 const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000753 const double kNetworkFreezeTimeMs = 0.0;
754 const bool kGetAudioDuringFreezeRecovery = false;
755 const int kDelayToleranceMs = 20;
756 const int kMaxTimeToSpeechMs = 100;
757 LongCngWithClockDrift(kDriftFactor,
758 kNetworkFreezeTimeMs,
759 kGetAudioDuringFreezeRecovery,
760 kDelayToleranceMs,
761 kMaxTimeToSpeechMs);
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000762}
763
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000764TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDrift) {
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000765 // Apply a clock drift of +25 ms / s (sender slower than receiver).
766 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000767 const double kNetworkFreezeTimeMs = 0.0;
768 const bool kGetAudioDuringFreezeRecovery = false;
769 const int kDelayToleranceMs = 20;
770 const int kMaxTimeToSpeechMs = 100;
771 LongCngWithClockDrift(kDriftFactor,
772 kNetworkFreezeTimeMs,
773 kGetAudioDuringFreezeRecovery,
774 kDelayToleranceMs,
775 kMaxTimeToSpeechMs);
776}
777
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000778TEST_F(NetEqDecodingTest, LongCngWithNegativeClockDriftNetworkFreeze) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000779 // Apply a clock drift of -25 ms / s (sender faster than receiver).
780 const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
781 const double kNetworkFreezeTimeMs = 5000.0;
782 const bool kGetAudioDuringFreezeRecovery = false;
783 const int kDelayToleranceMs = 50;
784 const int kMaxTimeToSpeechMs = 200;
785 LongCngWithClockDrift(kDriftFactor,
786 kNetworkFreezeTimeMs,
787 kGetAudioDuringFreezeRecovery,
788 kDelayToleranceMs,
789 kMaxTimeToSpeechMs);
790}
791
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000792TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDriftNetworkFreeze) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000793 // Apply a clock drift of +25 ms / s (sender slower than receiver).
794 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
795 const double kNetworkFreezeTimeMs = 5000.0;
796 const bool kGetAudioDuringFreezeRecovery = false;
797 const int kDelayToleranceMs = 20;
798 const int kMaxTimeToSpeechMs = 100;
799 LongCngWithClockDrift(kDriftFactor,
800 kNetworkFreezeTimeMs,
801 kGetAudioDuringFreezeRecovery,
802 kDelayToleranceMs,
803 kMaxTimeToSpeechMs);
804}
805
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000806TEST_F(NetEqDecodingTest, LongCngWithPositiveClockDriftNetworkFreezeExtraPull) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000807 // Apply a clock drift of +25 ms / s (sender slower than receiver).
808 const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
809 const double kNetworkFreezeTimeMs = 5000.0;
810 const bool kGetAudioDuringFreezeRecovery = true;
811 const int kDelayToleranceMs = 20;
812 const int kMaxTimeToSpeechMs = 100;
813 LongCngWithClockDrift(kDriftFactor,
814 kNetworkFreezeTimeMs,
815 kGetAudioDuringFreezeRecovery,
816 kDelayToleranceMs,
817 kMaxTimeToSpeechMs);
818}
819
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000820TEST_F(NetEqDecodingTest, LongCngWithoutClockDrift) {
henrik.lundin@webrtc.org24779fe2014-03-14 12:40:05 +0000821 const double kDriftFactor = 1.0; // No drift.
822 const double kNetworkFreezeTimeMs = 0.0;
823 const bool kGetAudioDuringFreezeRecovery = false;
824 const int kDelayToleranceMs = 10;
825 const int kMaxTimeToSpeechMs = 50;
826 LongCngWithClockDrift(kDriftFactor,
827 kNetworkFreezeTimeMs,
828 kGetAudioDuringFreezeRecovery,
829 kDelayToleranceMs,
830 kMaxTimeToSpeechMs);
henrik.lundin@webrtc.orgfcfc6a92014-02-13 11:42:28 +0000831}
832
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000833TEST_F(NetEqDecodingTest, UnknownPayloadType) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000834 const size_t kPayloadBytes = 100;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000835 uint8_t payload[kPayloadBytes] = {0};
836 WebRtcRTPHeader rtp_info;
837 PopulateRtpInfo(0, 0, &rtp_info);
838 rtp_info.header.payloadType = 1; // Not registered as a decoder.
kwibergee2bac22015-11-11 10:34:00 -0800839 EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000840 EXPECT_EQ(NetEq::kUnknownRtpPayloadType, neteq_->LastError());
841}
842
Peter Boströme2976c82016-01-04 22:44:05 +0100843#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
ivoc72c08ed2016-01-20 07:26:24 -0800844#define MAYBE_DecoderError DecoderError
845#else
846#define MAYBE_DecoderError DISABLED_DecoderError
847#endif
848
Peter Boströme2976c82016-01-04 22:44:05 +0100849TEST_F(NetEqDecodingTest, MAYBE_DecoderError) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000850 const size_t kPayloadBytes = 100;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000851 uint8_t payload[kPayloadBytes] = {0};
852 WebRtcRTPHeader rtp_info;
853 PopulateRtpInfo(0, 0, &rtp_info);
854 rtp_info.header.payloadType = 103; // iSAC, but the payload is invalid.
kwibergee2bac22015-11-11 10:34:00 -0800855 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000856 // Set all of |out_data_| to 1, and verify that it was set to 0 by the call
857 // to GetAudio.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800858 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
859 out_frame_.data_[i] = 1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000860 }
henrik.lundin7a926812016-05-12 13:51:28 -0700861 bool muted;
862 EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_, &muted));
863 ASSERT_FALSE(muted);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000864 // Verify that there is a decoder error to check.
865 EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError());
ivoc72c08ed2016-01-20 07:26:24 -0800866
867 enum NetEqDecoderError {
868 ISAC_LENGTH_MISMATCH = 6730,
869 ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH = 6640
870 };
871#if defined(WEBRTC_CODEC_ISAC)
872 EXPECT_EQ(ISAC_LENGTH_MISMATCH, neteq_->LastDecoderError());
873#elif defined(WEBRTC_CODEC_ISACFX)
874 EXPECT_EQ(ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH, neteq_->LastDecoderError());
875#endif
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000876 // Verify that the first 160 samples are set to 0, and that the remaining
877 // samples are left unmodified.
878 static const int kExpectedOutputLength = 160; // 10 ms at 16 kHz sample rate.
879 for (int i = 0; i < kExpectedOutputLength; ++i) {
880 std::ostringstream ss;
881 ss << "i = " << i;
882 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800883 EXPECT_EQ(0, out_frame_.data_[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000884 }
henrik.lundin6d8e0112016-03-04 10:34:21 -0800885 for (size_t i = kExpectedOutputLength; i < AudioFrame::kMaxDataSizeSamples;
886 ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000887 std::ostringstream ss;
888 ss << "i = " << i;
889 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800890 EXPECT_EQ(1, out_frame_.data_[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000891 }
892}
893
henrik.lundin@webrtc.orgb4e80e02014-05-15 07:14:00 +0000894TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000895 // Set all of |out_data_| to 1, and verify that it was set to 0 by the call
896 // to GetAudio.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800897 for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
898 out_frame_.data_[i] = 1;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000899 }
henrik.lundin7a926812016-05-12 13:51:28 -0700900 bool muted;
901 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
902 ASSERT_FALSE(muted);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000903 // Verify that the first block of samples is set to 0.
904 static const int kExpectedOutputLength =
905 kInitSampleRateHz / 100; // 10 ms at initial sample rate.
906 for (int i = 0; i < kExpectedOutputLength; ++i) {
907 std::ostringstream ss;
908 ss << "i = " << i;
909 SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
henrik.lundin6d8e0112016-03-04 10:34:21 -0800910 EXPECT_EQ(0, out_frame_.data_[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000911 }
henrik.lundind89814b2015-11-23 06:49:25 -0800912 // Verify that the sample rate did not change from the initial configuration.
913 EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000914}
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000915
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000916class NetEqBgnTest : public NetEqDecodingTest {
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000917 protected:
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000918 virtual void TestCondition(double sum_squared_noise,
919 bool should_be_faded) = 0;
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000920
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000921 void CheckBgn(int sampling_rate_hz) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700922 size_t expected_samples_per_channel = 0;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000923 uint8_t payload_type = 0xFF; // Invalid.
924 if (sampling_rate_hz == 8000) {
925 expected_samples_per_channel = kBlockSize8kHz;
926 payload_type = 93; // PCM 16, 8 kHz.
927 } else if (sampling_rate_hz == 16000) {
928 expected_samples_per_channel = kBlockSize16kHz;
929 payload_type = 94; // PCM 16, 16 kHZ.
930 } else if (sampling_rate_hz == 32000) {
931 expected_samples_per_channel = kBlockSize32kHz;
932 payload_type = 95; // PCM 16, 32 kHz.
933 } else {
934 ASSERT_TRUE(false); // Unsupported test case.
935 }
turaj@webrtc.orgff43c852013-09-25 00:07:27 +0000936
henrik.lundin6d8e0112016-03-04 10:34:21 -0800937 AudioFrame output;
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000938 test::AudioLoop input;
939 // We are using the same 32 kHz input file for all tests, regardless of
940 // |sampling_rate_hz|. The output may sound weird, but the test is still
941 // valid.
942 ASSERT_TRUE(input.Init(
943 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"),
944 10 * sampling_rate_hz, // Max 10 seconds loop length.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700945 expected_samples_per_channel));
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000946
947 // Payload of 10 ms of PCM16 32 kHz.
948 uint8_t payload[kBlockSize32kHz * sizeof(int16_t)];
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000949 WebRtcRTPHeader rtp_info;
950 PopulateRtpInfo(0, 0, &rtp_info);
951 rtp_info.header.payloadType = payload_type;
952
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000953 uint32_t receive_timestamp = 0;
henrik.lundin7a926812016-05-12 13:51:28 -0700954 bool muted;
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000955 for (int n = 0; n < 10; ++n) { // Insert few packets and get audio.
kwiberg288886b2015-11-06 01:21:35 -0800956 auto block = input.GetNextBlock();
957 ASSERT_EQ(expected_samples_per_channel, block.size());
958 size_t enc_len_bytes =
959 WebRtcPcm16b_Encode(block.data(), block.size(), payload);
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +0000960 ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2);
961
kwibergee2bac22015-11-11 10:34:00 -0800962 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
963 payload, enc_len_bytes),
964 receive_timestamp));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800965 output.Reset();
henrik.lundin7a926812016-05-12 13:51:28 -0700966 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800967 ASSERT_EQ(1u, output.num_channels_);
968 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -0800969 ASSERT_EQ(AudioFrame::kNormalSpeech, output.speech_type_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000970
971 // Next packet.
972 rtp_info.header.timestamp += expected_samples_per_channel;
973 rtp_info.header.sequenceNumber++;
974 receive_timestamp += expected_samples_per_channel;
975 }
976
henrik.lundin6d8e0112016-03-04 10:34:21 -0800977 output.Reset();
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000978
979 // Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull
980 // one frame without checking speech-type. This is the first frame pulled
981 // without inserting any packet, and might not be labeled as PLC.
henrik.lundin7a926812016-05-12 13:51:28 -0700982 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800983 ASSERT_EQ(1u, output.num_channels_);
984 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +0000985
986 // To be able to test the fading of background noise we need at lease to
987 // pull 611 frames.
988 const int kFadingThreshold = 611;
989
990 // Test several CNG-to-PLC packet for the expected behavior. The number 20
991 // is arbitrary, but sufficiently large to test enough number of frames.
992 const int kNumPlcToCngTestFrames = 20;
993 bool plc_to_cng = false;
994 for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) {
henrik.lundin6d8e0112016-03-04 10:34:21 -0800995 output.Reset();
996 memset(output.data_, 1, sizeof(output.data_)); // Set to non-zero.
henrik.lundin7a926812016-05-12 13:51:28 -0700997 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
998 ASSERT_FALSE(muted);
henrik.lundin6d8e0112016-03-04 10:34:21 -0800999 ASSERT_EQ(1u, output.num_channels_);
1000 ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -08001001 if (output.speech_type_ == AudioFrame::kPLCCNG) {
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +00001002 plc_to_cng = true;
1003 double sum_squared = 0;
henrik.lundin6d8e0112016-03-04 10:34:21 -08001004 for (size_t k = 0;
1005 k < output.num_channels_ * output.samples_per_channel_; ++k)
1006 sum_squared += output.data_[k] * output.data_[k];
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +00001007 TestCondition(sum_squared, n > kFadingThreshold);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +00001008 } else {
henrik.lundin55480f52016-03-08 02:37:57 -08001009 EXPECT_EQ(AudioFrame::kPLC, output.speech_type_);
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +00001010 }
1011 }
1012 EXPECT_TRUE(plc_to_cng); // Just to be sure that PLC-to-CNG has occurred.
1013 }
1014};
1015
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +00001016class NetEqBgnTestOn : public NetEqBgnTest {
1017 protected:
1018 NetEqBgnTestOn() : NetEqBgnTest() {
1019 config_.background_noise_mode = NetEq::kBgnOn;
1020 }
1021
1022 void TestCondition(double sum_squared_noise, bool /*should_be_faded*/) {
1023 EXPECT_NE(0, sum_squared_noise);
1024 }
1025};
1026
1027class NetEqBgnTestOff : public NetEqBgnTest {
1028 protected:
1029 NetEqBgnTestOff() : NetEqBgnTest() {
1030 config_.background_noise_mode = NetEq::kBgnOff;
1031 }
1032
1033 void TestCondition(double sum_squared_noise, bool /*should_be_faded*/) {
1034 EXPECT_EQ(0, sum_squared_noise);
1035 }
1036};
1037
1038class NetEqBgnTestFade : public NetEqBgnTest {
1039 protected:
1040 NetEqBgnTestFade() : NetEqBgnTest() {
1041 config_.background_noise_mode = NetEq::kBgnFade;
1042 }
1043
1044 void TestCondition(double sum_squared_noise, bool should_be_faded) {
1045 if (should_be_faded)
1046 EXPECT_EQ(0, sum_squared_noise);
1047 }
1048};
1049
henrika1d34fe92015-06-16 10:04:20 +02001050TEST_F(NetEqBgnTestOn, RunTest) {
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +00001051 CheckBgn(8000);
1052 CheckBgn(16000);
1053 CheckBgn(32000);
turaj@webrtc.orgff43c852013-09-25 00:07:27 +00001054}
turaj@webrtc.org7b75ac62013-09-26 00:27:56 +00001055
henrika1d34fe92015-06-16 10:04:20 +02001056TEST_F(NetEqBgnTestOff, RunTest) {
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +00001057 CheckBgn(8000);
1058 CheckBgn(16000);
1059 CheckBgn(32000);
1060}
1061
henrika1d34fe92015-06-16 10:04:20 +02001062TEST_F(NetEqBgnTestFade, RunTest) {
henrik.lundin@webrtc.org9b8102c2014-08-21 08:27:44 +00001063 CheckBgn(8000);
1064 CheckBgn(16000);
1065 CheckBgn(32000);
1066}
henrik.lundin@webrtc.orgea257842014-08-07 12:27:37 +00001067
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001068void NetEqDecodingTest::WrapTest(uint16_t start_seq_no,
1069 uint32_t start_timestamp,
1070 const std::set<uint16_t>& drop_seq_numbers,
1071 bool expect_seq_no_wrap,
1072 bool expect_timestamp_wrap) {
1073 uint16_t seq_no = start_seq_no;
1074 uint32_t timestamp = start_timestamp;
1075 const int kBlocksPerFrame = 3; // Number of 10 ms blocks per frame.
1076 const int kFrameSizeMs = kBlocksPerFrame * kTimeStepMs;
1077 const int kSamples = kBlockSize16kHz * kBlocksPerFrame;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001078 const size_t kPayloadBytes = kSamples * sizeof(int16_t);
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001079 double next_input_time_ms = 0.0;
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001080 uint32_t receive_timestamp = 0;
1081
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001082 // Insert speech for 2 seconds.
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001083 const int kSpeechDurationMs = 2000;
1084 int packets_inserted = 0;
1085 uint16_t last_seq_no;
1086 uint32_t last_timestamp;
1087 bool timestamp_wrapped = false;
1088 bool seq_no_wrapped = false;
1089 for (double t_ms = 0; t_ms < kSpeechDurationMs; t_ms += 10) {
1090 // Each turn in this for loop is 10 ms.
1091 while (next_input_time_ms <= t_ms) {
1092 // Insert one 30 ms speech frame.
1093 uint8_t payload[kPayloadBytes] = {0};
1094 WebRtcRTPHeader rtp_info;
1095 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
1096 if (drop_seq_numbers.find(seq_no) == drop_seq_numbers.end()) {
1097 // This sequence number was not in the set to drop. Insert it.
1098 ASSERT_EQ(0,
kwibergee2bac22015-11-11 10:34:00 -08001099 neteq_->InsertPacket(rtp_info, payload, receive_timestamp));
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001100 ++packets_inserted;
1101 }
1102 NetEqNetworkStatistics network_stats;
1103 ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
1104
1105 // Due to internal NetEq logic, preferred buffer-size is about 4 times the
1106 // packet size for first few packets. Therefore we refrain from checking
1107 // the criteria.
1108 if (packets_inserted > 4) {
1109 // Expect preferred and actual buffer size to be no more than 2 frames.
1110 EXPECT_LE(network_stats.preferred_buffer_size_ms, kFrameSizeMs * 2);
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +00001111 EXPECT_LE(network_stats.current_buffer_size_ms, kFrameSizeMs * 2 +
1112 algorithmic_delay_ms_);
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001113 }
1114 last_seq_no = seq_no;
1115 last_timestamp = timestamp;
1116
1117 ++seq_no;
1118 timestamp += kSamples;
1119 receive_timestamp += kSamples;
1120 next_input_time_ms += static_cast<double>(kFrameSizeMs);
1121
1122 seq_no_wrapped |= seq_no < last_seq_no;
1123 timestamp_wrapped |= timestamp < last_timestamp;
1124 }
1125 // Pull out data once.
henrik.lundin6d8e0112016-03-04 10:34:21 -08001126 AudioFrame output;
henrik.lundin7a926812016-05-12 13:51:28 -07001127 bool muted;
1128 ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001129 ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
1130 ASSERT_EQ(1u, output.num_channels_);
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001131
1132 // Expect delay (in samples) to be less than 2 packets.
henrik.lundin0d96ab72016-04-06 12:28:26 -07001133 rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
1134 ASSERT_TRUE(playout_timestamp);
1135 EXPECT_LE(timestamp - *playout_timestamp,
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001136 static_cast<uint32_t>(kSamples * 2));
turaj@webrtc.org78b41a02013-11-22 20:27:07 +00001137 }
1138 // Make sure we have actually tested wrap-around.
1139 ASSERT_EQ(expect_seq_no_wrap, seq_no_wrapped);
1140 ASSERT_EQ(expect_timestamp_wrap, timestamp_wrapped);
1141}
1142
1143TEST_F(NetEqDecodingTest, SequenceNumberWrap) {
1144 // Start with a sequence number that will soon wrap.
1145 std::set<uint16_t> drop_seq_numbers; // Don't drop any packets.
1146 WrapTest(0xFFFF - 10, 0, drop_seq_numbers, true, false);
1147}
1148
1149TEST_F(NetEqDecodingTest, SequenceNumberWrapAndDrop) {
1150 // Start with a sequence number that will soon wrap.
1151 std::set<uint16_t> drop_seq_numbers;
1152 drop_seq_numbers.insert(0xFFFF);
1153 drop_seq_numbers.insert(0x0);
1154 WrapTest(0xFFFF - 10, 0, drop_seq_numbers, true, false);
1155}
1156
1157TEST_F(NetEqDecodingTest, TimestampWrap) {
1158 // Start with a timestamp that will soon wrap.
1159 std::set<uint16_t> drop_seq_numbers;
1160 WrapTest(0, 0xFFFFFFFF - 3000, drop_seq_numbers, false, true);
1161}
1162
1163TEST_F(NetEqDecodingTest, TimestampAndSequenceNumberWrap) {
1164 // Start with a timestamp and a sequence number that will wrap at the same
1165 // time.
1166 std::set<uint16_t> drop_seq_numbers;
1167 WrapTest(0xFFFF - 10, 0xFFFFFFFF - 5000, drop_seq_numbers, true, true);
1168}
1169
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001170void NetEqDecodingTest::DuplicateCng() {
1171 uint16_t seq_no = 0;
1172 uint32_t timestamp = 0;
1173 const int kFrameSizeMs = 10;
1174 const int kSampleRateKhz = 16;
1175 const int kSamples = kFrameSizeMs * kSampleRateKhz;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001176 const size_t kPayloadBytes = kSamples * 2;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001177
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +00001178 const int algorithmic_delay_samples = std::max(
1179 algorithmic_delay_ms_ * kSampleRateKhz, 5 * kSampleRateKhz / 8);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001180 // Insert three speech packets. Three are needed to get the frame length
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001181 // correct.
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001182 uint8_t payload[kPayloadBytes] = {0};
1183 WebRtcRTPHeader rtp_info;
henrik.lundin7a926812016-05-12 13:51:28 -07001184 bool muted;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001185 for (int i = 0; i < 3; ++i) {
1186 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -08001187 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001188 ++seq_no;
1189 timestamp += kSamples;
1190
1191 // Pull audio once.
henrik.lundin7a926812016-05-12 13:51:28 -07001192 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001193 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001194 }
1195 // Verify speech output.
henrik.lundin55480f52016-03-08 02:37:57 -08001196 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001197
1198 // Insert same CNG packet twice.
1199 const int kCngPeriodMs = 100;
1200 const int kCngPeriodSamples = kCngPeriodMs * kSampleRateKhz;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001201 size_t payload_len;
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001202 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
1203 // This is the first time this CNG packet is inserted.
kwibergee2bac22015-11-11 10:34:00 -08001204 ASSERT_EQ(
1205 0, neteq_->InsertPacket(
1206 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001207
1208 // Pull audio once and make sure CNG is played.
henrik.lundin7a926812016-05-12 13:51:28 -07001209 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001210 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -08001211 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin0d96ab72016-04-06 12:28:26 -07001212 EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG.
1213 EXPECT_EQ(timestamp - algorithmic_delay_samples,
1214 out_frame_.timestamp_ + out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001215
1216 // Insert the same CNG packet again. Note that at this point it is old, since
1217 // we have already decoded the first copy of it.
kwibergee2bac22015-11-11 10:34:00 -08001218 ASSERT_EQ(
1219 0, neteq_->InsertPacket(
1220 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001221
1222 // Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since
1223 // we have already pulled out CNG once.
1224 for (int cng_time_ms = 10; cng_time_ms < kCngPeriodMs; cng_time_ms += 10) {
henrik.lundin7a926812016-05-12 13:51:28 -07001225 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001226 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -08001227 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin0d96ab72016-04-06 12:28:26 -07001228 EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG.
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +00001229 EXPECT_EQ(timestamp - algorithmic_delay_samples,
henrik.lundin0d96ab72016-04-06 12:28:26 -07001230 out_frame_.timestamp_ + out_frame_.samples_per_channel_);
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001231 }
1232
1233 // Insert speech again.
1234 ++seq_no;
1235 timestamp += kCngPeriodSamples;
1236 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -08001237 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001238
1239 // Pull audio once and verify that the output is speech again.
henrik.lundin7a926812016-05-12 13:51:28 -07001240 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001241 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -08001242 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin0d96ab72016-04-06 12:28:26 -07001243 rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
1244 ASSERT_TRUE(playout_timestamp);
turaj@webrtc.org8d1cdaa2014-04-11 18:47:55 +00001245 EXPECT_EQ(timestamp + kSamples - algorithmic_delay_samples,
henrik.lundin0d96ab72016-04-06 12:28:26 -07001246 *playout_timestamp);
wu@webrtc.org94454b72014-06-05 20:34:08 +00001247}
1248
henrik.lundin0d96ab72016-04-06 12:28:26 -07001249rtc::Optional<uint32_t> NetEqDecodingTest::PlayoutTimestamp() {
1250 return neteq_->GetPlayoutTimestamp();
henrik.lundin@webrtc.orgca8cb952014-03-12 10:26:52 +00001251}
1252
1253TEST_F(NetEqDecodingTest, DiscardDuplicateCng) { DuplicateCng(); }
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001254
1255TEST_F(NetEqDecodingTest, CngFirst) {
1256 uint16_t seq_no = 0;
1257 uint32_t timestamp = 0;
1258 const int kFrameSizeMs = 10;
1259 const int kSampleRateKhz = 16;
1260 const int kSamples = kFrameSizeMs * kSampleRateKhz;
1261 const int kPayloadBytes = kSamples * 2;
1262 const int kCngPeriodMs = 100;
1263 const int kCngPeriodSamples = kCngPeriodMs * kSampleRateKhz;
1264 size_t payload_len;
1265
1266 uint8_t payload[kPayloadBytes] = {0};
1267 WebRtcRTPHeader rtp_info;
1268
1269 PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
kwibergee2bac22015-11-11 10:34:00 -08001270 ASSERT_EQ(
1271 NetEq::kOK,
1272 neteq_->InsertPacket(
1273 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001274 ++seq_no;
1275 timestamp += kCngPeriodSamples;
1276
1277 // Pull audio once and make sure CNG is played.
henrik.lundin7a926812016-05-12 13:51:28 -07001278 bool muted;
1279 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001280 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin55480f52016-03-08 02:37:57 -08001281 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001282
1283 // Insert some speech packets.
henrik.lundin549d80b2016-08-25 00:44:24 -07001284 const uint32_t first_speech_timestamp = timestamp;
1285 int timeout_counter = 0;
1286 do {
1287 ASSERT_LT(timeout_counter++, 20) << "Test timed out";
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001288 PopulateRtpInfo(seq_no, timestamp, &rtp_info);
kwibergee2bac22015-11-11 10:34:00 -08001289 ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001290 ++seq_no;
1291 timestamp += kSamples;
1292
1293 // Pull audio once.
henrik.lundin7a926812016-05-12 13:51:28 -07001294 ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -08001295 ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
henrik.lundin549d80b2016-08-25 00:44:24 -07001296 } while (!IsNewerTimestamp(out_frame_.timestamp_, first_speech_timestamp));
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001297 // Verify speech output.
henrik.lundin55480f52016-03-08 02:37:57 -08001298 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
henrik.lundin@webrtc.orgc93437e2014-12-01 11:42:42 +00001299}
henrik.lundin7a926812016-05-12 13:51:28 -07001300
1301class NetEqDecodingTestWithMutedState : public NetEqDecodingTest {
1302 public:
1303 NetEqDecodingTestWithMutedState() : NetEqDecodingTest() {
1304 config_.enable_muted_state = true;
1305 }
1306
1307 protected:
1308 static constexpr size_t kSamples = 10 * 16;
1309 static constexpr size_t kPayloadBytes = kSamples * 2;
1310
1311 void InsertPacket(uint32_t rtp_timestamp) {
1312 uint8_t payload[kPayloadBytes] = {0};
1313 WebRtcRTPHeader rtp_info;
1314 PopulateRtpInfo(0, rtp_timestamp, &rtp_info);
1315 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
1316 }
1317
henrik.lundin42feb512016-09-20 06:51:40 -07001318 void InsertCngPacket(uint32_t rtp_timestamp) {
1319 uint8_t payload[kPayloadBytes] = {0};
1320 WebRtcRTPHeader rtp_info;
1321 size_t payload_len;
1322 PopulateCng(0, rtp_timestamp, &rtp_info, payload, &payload_len);
1323 EXPECT_EQ(
1324 NetEq::kOK,
1325 neteq_->InsertPacket(
1326 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
1327 }
1328
henrik.lundin7a926812016-05-12 13:51:28 -07001329 bool GetAudioReturnMuted() {
1330 bool muted;
1331 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
1332 return muted;
1333 }
1334
1335 void GetAudioUntilMuted() {
1336 while (!GetAudioReturnMuted()) {
1337 ASSERT_LT(counter_++, 1000) << "Test timed out";
1338 }
1339 }
1340
1341 void GetAudioUntilNormal() {
1342 bool muted = false;
1343 while (out_frame_.speech_type_ != AudioFrame::kNormalSpeech) {
1344 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
1345 ASSERT_LT(counter_++, 1000) << "Test timed out";
1346 }
1347 EXPECT_FALSE(muted);
1348 }
1349
1350 int counter_ = 0;
1351};
1352
1353// Verifies that NetEq goes in and out of muted state as expected.
1354TEST_F(NetEqDecodingTestWithMutedState, MutedState) {
1355 // Insert one speech packet.
1356 InsertPacket(0);
1357 // Pull out audio once and expect it not to be muted.
1358 EXPECT_FALSE(GetAudioReturnMuted());
1359 // Pull data until faded out.
1360 GetAudioUntilMuted();
1361
1362 // Verify that output audio is not written during muted mode. Other parameters
1363 // should be correct, though.
1364 AudioFrame new_frame;
1365 for (auto& d : new_frame.data_) {
1366 d = 17;
1367 }
1368 bool muted;
1369 EXPECT_EQ(0, neteq_->GetAudio(&new_frame, &muted));
1370 EXPECT_TRUE(muted);
1371 for (auto d : new_frame.data_) {
1372 EXPECT_EQ(17, d);
1373 }
1374 EXPECT_EQ(out_frame_.timestamp_ + out_frame_.samples_per_channel_,
1375 new_frame.timestamp_);
1376 EXPECT_EQ(out_frame_.samples_per_channel_, new_frame.samples_per_channel_);
1377 EXPECT_EQ(out_frame_.sample_rate_hz_, new_frame.sample_rate_hz_);
1378 EXPECT_EQ(out_frame_.num_channels_, new_frame.num_channels_);
1379 EXPECT_EQ(out_frame_.speech_type_, new_frame.speech_type_);
1380 EXPECT_EQ(out_frame_.vad_activity_, new_frame.vad_activity_);
1381
1382 // Insert new data. Timestamp is corrected for the time elapsed since the last
1383 // packet. Verify that normal operation resumes.
1384 InsertPacket(kSamples * counter_);
1385 GetAudioUntilNormal();
henrik.lundin612c25e2016-05-25 08:21:04 -07001386
1387 NetEqNetworkStatistics stats;
1388 EXPECT_EQ(0, neteq_->NetworkStatistics(&stats));
1389 // NetEqNetworkStatistics::expand_rate tells the fraction of samples that were
1390 // concealment samples, in Q14 (16384 = 100%) .The vast majority should be
1391 // concealment samples in this test.
1392 EXPECT_GT(stats.expand_rate, 14000);
1393 // And, it should be greater than the speech_expand_rate.
1394 EXPECT_GT(stats.expand_rate, stats.speech_expand_rate);
henrik.lundin7a926812016-05-12 13:51:28 -07001395}
1396
1397// Verifies that NetEq goes out of muted state when given a delayed packet.
1398TEST_F(NetEqDecodingTestWithMutedState, MutedStateDelayedPacket) {
1399 // Insert one speech packet.
1400 InsertPacket(0);
1401 // Pull out audio once and expect it not to be muted.
1402 EXPECT_FALSE(GetAudioReturnMuted());
1403 // Pull data until faded out.
1404 GetAudioUntilMuted();
1405 // Insert new data. Timestamp is only corrected for the half of the time
1406 // elapsed since the last packet. That is, the new packet is delayed. Verify
1407 // that normal operation resumes.
1408 InsertPacket(kSamples * counter_ / 2);
1409 GetAudioUntilNormal();
1410}
1411
1412// Verifies that NetEq goes out of muted state when given a future packet.
1413TEST_F(NetEqDecodingTestWithMutedState, MutedStateFuturePacket) {
1414 // Insert one speech packet.
1415 InsertPacket(0);
1416 // Pull out audio once and expect it not to be muted.
1417 EXPECT_FALSE(GetAudioReturnMuted());
1418 // Pull data until faded out.
1419 GetAudioUntilMuted();
1420 // Insert new data. Timestamp is over-corrected for the time elapsed since the
1421 // last packet. That is, the new packet is too early. Verify that normal
1422 // operation resumes.
1423 InsertPacket(kSamples * counter_ * 2);
1424 GetAudioUntilNormal();
1425}
1426
1427// Verifies that NetEq goes out of muted state when given an old packet.
1428TEST_F(NetEqDecodingTestWithMutedState, MutedStateOldPacket) {
1429 // Insert one speech packet.
1430 InsertPacket(0);
1431 // Pull out audio once and expect it not to be muted.
1432 EXPECT_FALSE(GetAudioReturnMuted());
1433 // Pull data until faded out.
1434 GetAudioUntilMuted();
1435
1436 EXPECT_NE(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
1437 // Insert packet which is older than the first packet.
1438 InsertPacket(kSamples * (counter_ - 1000));
1439 EXPECT_FALSE(GetAudioReturnMuted());
1440 EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
1441}
1442
henrik.lundin42feb512016-09-20 06:51:40 -07001443// Verifies that NetEq doesn't enter muted state when CNG mode is active and the
1444// packet stream is suspended for a long time.
1445TEST_F(NetEqDecodingTestWithMutedState, DoNotMuteExtendedCngWithoutPackets) {
1446 // Insert one CNG packet.
1447 InsertCngPacket(0);
1448
1449 // Pull 10 seconds of audio (10 ms audio generated per lap).
1450 for (int i = 0; i < 1000; ++i) {
1451 bool muted;
1452 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
1453 ASSERT_FALSE(muted);
1454 }
1455 EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
1456}
1457
1458// Verifies that NetEq goes back to normal after a long CNG period with the
1459// packet stream suspended.
1460TEST_F(NetEqDecodingTestWithMutedState, RecoverAfterExtendedCngWithoutPackets) {
1461 // Insert one CNG packet.
1462 InsertCngPacket(0);
1463
1464 // Pull 10 seconds of audio (10 ms audio generated per lap).
1465 for (int i = 0; i < 1000; ++i) {
1466 bool muted;
1467 EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
1468 }
1469
1470 // Insert new data. Timestamp is corrected for the time elapsed since the last
1471 // packet. Verify that normal operation resumes.
1472 InsertPacket(kSamples * counter_);
1473 GetAudioUntilNormal();
1474}
1475
henrik.lundin7a926812016-05-12 13:51:28 -07001476class NetEqDecodingTestTwoInstances : public NetEqDecodingTest {
1477 public:
1478 NetEqDecodingTestTwoInstances() : NetEqDecodingTest() {}
1479
1480 void SetUp() override {
1481 NetEqDecodingTest::SetUp();
1482 config2_ = config_;
1483 }
1484
1485 void CreateSecondInstance() {
ossue3525782016-05-25 07:37:43 -07001486 neteq2_.reset(NetEq::Create(config2_, CreateBuiltinAudioDecoderFactory()));
henrik.lundin7a926812016-05-12 13:51:28 -07001487 ASSERT_TRUE(neteq2_);
1488 LoadDecoders(neteq2_.get());
1489 }
1490
1491 protected:
1492 std::unique_ptr<NetEq> neteq2_;
1493 NetEq::Config config2_;
1494};
1495
1496namespace {
1497::testing::AssertionResult AudioFramesEqualExceptData(const AudioFrame& a,
1498 const AudioFrame& b) {
1499 if (a.timestamp_ != b.timestamp_)
1500 return ::testing::AssertionFailure() << "timestamp_ diff (" << a.timestamp_
1501 << " != " << b.timestamp_ << ")";
1502 if (a.sample_rate_hz_ != b.sample_rate_hz_)
1503 return ::testing::AssertionFailure() << "sample_rate_hz_ diff ("
1504 << a.sample_rate_hz_
1505 << " != " << b.sample_rate_hz_ << ")";
1506 if (a.samples_per_channel_ != b.samples_per_channel_)
1507 return ::testing::AssertionFailure()
1508 << "samples_per_channel_ diff (" << a.samples_per_channel_
1509 << " != " << b.samples_per_channel_ << ")";
1510 if (a.num_channels_ != b.num_channels_)
1511 return ::testing::AssertionFailure() << "num_channels_ diff ("
1512 << a.num_channels_
1513 << " != " << b.num_channels_ << ")";
1514 if (a.speech_type_ != b.speech_type_)
1515 return ::testing::AssertionFailure() << "speech_type_ diff ("
1516 << a.speech_type_
1517 << " != " << b.speech_type_ << ")";
1518 if (a.vad_activity_ != b.vad_activity_)
1519 return ::testing::AssertionFailure() << "vad_activity_ diff ("
1520 << a.vad_activity_
1521 << " != " << b.vad_activity_ << ")";
1522 return ::testing::AssertionSuccess();
1523}
1524
1525::testing::AssertionResult AudioFramesEqual(const AudioFrame& a,
1526 const AudioFrame& b) {
1527 ::testing::AssertionResult res = AudioFramesEqualExceptData(a, b);
1528 if (!res)
1529 return res;
1530 if (memcmp(
1531 a.data_, b.data_,
1532 a.samples_per_channel_ * a.num_channels_ * sizeof(a.data_[0])) != 0) {
1533 return ::testing::AssertionFailure() << "data_ diff";
1534 }
1535 return ::testing::AssertionSuccess();
1536}
1537
1538} // namespace
1539
1540TEST_F(NetEqDecodingTestTwoInstances, CompareMutedStateOnOff) {
1541 ASSERT_FALSE(config_.enable_muted_state);
1542 config2_.enable_muted_state = true;
1543 CreateSecondInstance();
1544
1545 // Insert one speech packet into both NetEqs.
1546 const size_t kSamples = 10 * 16;
1547 const size_t kPayloadBytes = kSamples * 2;
1548 uint8_t payload[kPayloadBytes] = {0};
1549 WebRtcRTPHeader rtp_info;
1550 PopulateRtpInfo(0, 0, &rtp_info);
1551 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
1552 EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload, 0));
1553
1554 AudioFrame out_frame1, out_frame2;
1555 bool muted;
1556 for (int i = 0; i < 1000; ++i) {
1557 std::ostringstream ss;
1558 ss << "i = " << i;
1559 SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure.
1560 EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted));
1561 EXPECT_FALSE(muted);
1562 EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted));
1563 if (muted) {
1564 EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2));
1565 } else {
1566 EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2));
1567 }
1568 }
1569 EXPECT_TRUE(muted);
1570
1571 // Insert new data. Timestamp is corrected for the time elapsed since the last
1572 // packet.
1573 PopulateRtpInfo(0, kSamples * 1000, &rtp_info);
1574 EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
1575 EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload, 0));
1576
1577 int counter = 0;
1578 while (out_frame1.speech_type_ != AudioFrame::kNormalSpeech) {
1579 ASSERT_LT(counter++, 1000) << "Test timed out";
1580 std::ostringstream ss;
1581 ss << "counter = " << counter;
1582 SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure.
1583 EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted));
1584 EXPECT_FALSE(muted);
1585 EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted));
1586 if (muted) {
1587 EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2));
1588 } else {
1589 EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2));
1590 }
1591 }
1592 EXPECT_FALSE(muted);
1593}
1594
henrik.lundin@webrtc.orge7ce4372014-01-09 14:01:55 +00001595} // namespace webrtc