diff options
Diffstat (limited to 'webrtc/modules/audio_coding/neteq/neteq_unittest.cc')
-rw-r--r-- | webrtc/modules/audio_coding/neteq/neteq_unittest.cc | 470 |
1 files changed, 289 insertions, 181 deletions
diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc index 4340f54975..8d52c615da 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc @@ -28,29 +28,91 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/test/testsupport/fileutils.h" -#include "webrtc/test/testsupport/gtest_disable.h" #include "webrtc/typedefs.h" +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/modules/audio_coding/neteq/neteq_unittest.pb.h" +#else +#include "webrtc/audio_coding/neteq/neteq_unittest.pb.h" +#endif +#endif + DEFINE_bool(gen_ref, false, "Generate reference files."); -namespace webrtc { +namespace { -static bool IsAllZero(const int16_t* buf, size_t buf_length) { +bool IsAllZero(const int16_t* buf, size_t buf_length) { bool all_zero = true; for (size_t n = 0; n < buf_length && all_zero; ++n) all_zero = buf[n] == 0; return all_zero; } -static bool IsAllNonZero(const int16_t* buf, size_t buf_length) { +bool IsAllNonZero(const int16_t* buf, size_t buf_length) { bool all_non_zero = true; for (size_t n = 0; n < buf_length && all_non_zero; ++n) all_non_zero = buf[n] != 0; return all_non_zero; } +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT +void Convert(const webrtc::NetEqNetworkStatistics& stats_raw, + webrtc::neteq_unittest::NetEqNetworkStatistics* stats) { + stats->set_current_buffer_size_ms(stats_raw.current_buffer_size_ms); + stats->set_preferred_buffer_size_ms(stats_raw.preferred_buffer_size_ms); + stats->set_jitter_peaks_found(stats_raw.jitter_peaks_found); + stats->set_packet_loss_rate(stats_raw.packet_loss_rate); + stats->set_packet_discard_rate(stats_raw.packet_discard_rate); + stats->set_expand_rate(stats_raw.expand_rate); + stats->set_speech_expand_rate(stats_raw.speech_expand_rate); + stats->set_preemptive_rate(stats_raw.preemptive_rate); + stats->set_accelerate_rate(stats_raw.accelerate_rate); + stats->set_secondary_decoded_rate(stats_raw.secondary_decoded_rate); + stats->set_clockdrift_ppm(stats_raw.clockdrift_ppm); + stats->set_added_zero_samples(stats_raw.added_zero_samples); + stats->set_mean_waiting_time_ms(stats_raw.mean_waiting_time_ms); + stats->set_median_waiting_time_ms(stats_raw.median_waiting_time_ms); + stats->set_min_waiting_time_ms(stats_raw.min_waiting_time_ms); + stats->set_max_waiting_time_ms(stats_raw.max_waiting_time_ms); +} + +void Convert(const webrtc::RtcpStatistics& stats_raw, + webrtc::neteq_unittest::RtcpStatistics* stats) { + stats->set_fraction_lost(stats_raw.fraction_lost); + stats->set_cumulative_lost(stats_raw.cumulative_lost); + stats->set_extended_max_sequence_number( + stats_raw.extended_max_sequence_number); + stats->set_jitter(stats_raw.jitter); +} + +void WriteMessage(FILE* file, const std::string& message) { + int32_t size = message.length(); + ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file)); + if (size <= 0) + return; + ASSERT_EQ(static_cast<size_t>(size), + fwrite(message.data(), sizeof(char), size, file)); +} + +void ReadMessage(FILE* file, std::string* message) { + int32_t size; + ASSERT_EQ(1u, fread(&size, sizeof(size), 1, file)); + if (size <= 0) + return; + rtc::scoped_ptr<char[]> buffer(new char[size]); + ASSERT_EQ(static_cast<size_t>(size), + fread(buffer.get(), sizeof(char), size, file)); + message->assign(buffer.get(), size); +} +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT + +} // namespace + +namespace webrtc { + class RefFiles { public: RefFiles(const std::string& input_file, const std::string& output_file); @@ -128,92 +190,84 @@ void RefFiles::ReadFromFileAndCompare(const T (&test_results)[n], } } -void RefFiles::WriteToFile(const NetEqNetworkStatistics& stats) { - if (output_fp_) { - ASSERT_EQ(1u, fwrite(&stats, sizeof(NetEqNetworkStatistics), 1, - output_fp_)); - } +void RefFiles::WriteToFile(const NetEqNetworkStatistics& stats_raw) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!output_fp_) + return; + neteq_unittest::NetEqNetworkStatistics stats; + Convert(stats_raw, &stats); + + std::string stats_string; + ASSERT_TRUE(stats.SerializeToString(&stats_string)); + WriteMessage(output_fp_, stats_string); +#else + FAIL() << "Writing to reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } void RefFiles::ReadFromFileAndCompare( const NetEqNetworkStatistics& stats) { - // TODO(minyue): Update resource/audio_coding/neteq_network_stats.dat and - // resource/audio_coding/neteq_network_stats_win32.dat. - struct NetEqNetworkStatisticsOld { - uint16_t current_buffer_size_ms; // Current jitter buffer size in ms. - uint16_t preferred_buffer_size_ms; // Target buffer size in ms. - uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky - // jitter; 0 otherwise. - uint16_t packet_loss_rate; // Loss rate (network + late) in Q14. - uint16_t packet_discard_rate; // Late loss rate in Q14. - uint16_t expand_rate; // Fraction (of original stream) of synthesized - // audio inserted through expansion (in Q14). - uint16_t preemptive_rate; // Fraction of data inserted through pre-emptive - // expansion (in Q14). - uint16_t accelerate_rate; // Fraction of data removed through acceleration - // (in Q14). - int32_t clockdrift_ppm; // Average clock-drift in parts-per-million - // (positive or negative). - int added_zero_samples; // Number of zero samples added in "off" mode. - }; - if (input_fp_) { - // Read from ref file. - size_t stat_size = sizeof(NetEqNetworkStatisticsOld); - NetEqNetworkStatisticsOld ref_stats; - ASSERT_EQ(1u, fread(&ref_stats, stat_size, 1, input_fp_)); - // Compare - ASSERT_EQ(stats.current_buffer_size_ms, ref_stats.current_buffer_size_ms); - ASSERT_EQ(stats.preferred_buffer_size_ms, - ref_stats.preferred_buffer_size_ms); - ASSERT_EQ(stats.jitter_peaks_found, ref_stats.jitter_peaks_found); - ASSERT_EQ(stats.packet_loss_rate, ref_stats.packet_loss_rate); - ASSERT_EQ(stats.packet_discard_rate, ref_stats.packet_discard_rate); - ASSERT_EQ(stats.expand_rate, ref_stats.expand_rate); - ASSERT_EQ(stats.preemptive_rate, ref_stats.preemptive_rate); - ASSERT_EQ(stats.accelerate_rate, ref_stats.accelerate_rate); - ASSERT_EQ(stats.clockdrift_ppm, ref_stats.clockdrift_ppm); - ASSERT_EQ(stats.added_zero_samples, - static_cast<size_t>(ref_stats.added_zero_samples)); - ASSERT_EQ(stats.secondary_decoded_rate, 0); - ASSERT_LE(stats.speech_expand_rate, ref_stats.expand_rate); - } +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!input_fp_) + return; + + std::string stats_string; + ReadMessage(input_fp_, &stats_string); + neteq_unittest::NetEqNetworkStatistics ref_stats; + ASSERT_TRUE(ref_stats.ParseFromString(stats_string)); + + // Compare + ASSERT_EQ(stats.current_buffer_size_ms, ref_stats.current_buffer_size_ms()); + ASSERT_EQ(stats.preferred_buffer_size_ms, + ref_stats.preferred_buffer_size_ms()); + ASSERT_EQ(stats.jitter_peaks_found, ref_stats.jitter_peaks_found()); + ASSERT_EQ(stats.packet_loss_rate, ref_stats.packet_loss_rate()); + ASSERT_EQ(stats.packet_discard_rate, ref_stats.packet_discard_rate()); + ASSERT_EQ(stats.expand_rate, ref_stats.expand_rate()); + ASSERT_EQ(stats.preemptive_rate, ref_stats.preemptive_rate()); + ASSERT_EQ(stats.accelerate_rate, ref_stats.accelerate_rate()); + ASSERT_EQ(stats.clockdrift_ppm, ref_stats.clockdrift_ppm()); + ASSERT_EQ(stats.added_zero_samples, ref_stats.added_zero_samples()); + ASSERT_EQ(stats.secondary_decoded_rate, ref_stats.secondary_decoded_rate()); + ASSERT_LE(stats.speech_expand_rate, ref_stats.expand_rate()); +#else + FAIL() << "Reading from reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } -void RefFiles::WriteToFile(const RtcpStatistics& stats) { - if (output_fp_) { - ASSERT_EQ(1u, fwrite(&(stats.fraction_lost), sizeof(stats.fraction_lost), 1, - output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.cumulative_lost), - sizeof(stats.cumulative_lost), 1, output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.extended_max_sequence_number), - sizeof(stats.extended_max_sequence_number), 1, - output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.jitter), sizeof(stats.jitter), 1, - output_fp_)); - } +void RefFiles::WriteToFile(const RtcpStatistics& stats_raw) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!output_fp_) + return; + neteq_unittest::RtcpStatistics stats; + Convert(stats_raw, &stats); + + std::string stats_string; + ASSERT_TRUE(stats.SerializeToString(&stats_string)); + WriteMessage(output_fp_, stats_string); +#else + FAIL() << "Writing to reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } -void RefFiles::ReadFromFileAndCompare( - const RtcpStatistics& stats) { - if (input_fp_) { - // Read from ref file. - RtcpStatistics ref_stats; - ASSERT_EQ(1u, fread(&(ref_stats.fraction_lost), - sizeof(ref_stats.fraction_lost), 1, input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.cumulative_lost), - sizeof(ref_stats.cumulative_lost), 1, input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.extended_max_sequence_number), - sizeof(ref_stats.extended_max_sequence_number), 1, - input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.jitter), sizeof(ref_stats.jitter), 1, - input_fp_)); - // Compare - ASSERT_EQ(ref_stats.fraction_lost, stats.fraction_lost); - ASSERT_EQ(ref_stats.cumulative_lost, stats.cumulative_lost); - ASSERT_EQ(ref_stats.extended_max_sequence_number, - stats.extended_max_sequence_number); - ASSERT_EQ(ref_stats.jitter, stats.jitter); - } +void RefFiles::ReadFromFileAndCompare(const RtcpStatistics& stats) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!input_fp_) + return; + std::string stats_string; + ReadMessage(input_fp_, &stats_string); + neteq_unittest::RtcpStatistics ref_stats; + ASSERT_TRUE(ref_stats.ParseFromString(stats_string)); + + // Compare + ASSERT_EQ(stats.fraction_lost, ref_stats.fraction_lost()); + ASSERT_EQ(stats.cumulative_lost, ref_stats.cumulative_lost()); + ASSERT_EQ(stats.extended_max_sequence_number, + ref_stats.extended_max_sequence_number()); + ASSERT_EQ(stats.jitter, ref_stats.jitter()); +#else + FAIL() << "Reading from reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } class NetEqDecodingTest : public ::testing::Test { @@ -224,7 +278,8 @@ class NetEqDecodingTest : public ::testing::Test { static const size_t kBlockSize8kHz = kTimeStepMs * 8; static const size_t kBlockSize16kHz = kTimeStepMs * 16; static const size_t kBlockSize32kHz = kTimeStepMs * 32; - static const size_t kMaxBlockSize = kBlockSize32kHz; + static const size_t kBlockSize48kHz = kTimeStepMs * 48; + static const size_t kMaxBlockSize = kBlockSize48kHz; static const int kInitSampleRateHz = 8000; NetEqDecodingTest(); @@ -234,10 +289,12 @@ class NetEqDecodingTest : public ::testing::Test { void LoadDecoders(); void OpenInputFile(const std::string &rtp_file); void Process(size_t* out_len); + void DecodeAndCompare(const std::string& rtp_file, const std::string& ref_file, const std::string& stat_ref_file, const std::string& rtcp_ref_file); + static void PopulateRtpInfo(int frame_index, int timestamp, WebRtcRTPHeader* rtp_info); @@ -304,32 +361,45 @@ void NetEqDecodingTest::TearDown() { void NetEqDecodingTest::LoadDecoders() { // Load PCMu. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMu, 0)); + ASSERT_EQ(0, + neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMu, "pcmu", 0)); // Load PCMa. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMa, 8)); + ASSERT_EQ(0, + neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMa, "pcma", 8)); #ifdef WEBRTC_CODEC_ILBC // Load iLBC. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderILBC, 102)); + ASSERT_EQ( + 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderILBC, "ilbc", 102)); #endif #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) // Load iSAC. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, 103)); + ASSERT_EQ( + 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, "isac", 103)); #endif #ifdef WEBRTC_CODEC_ISAC // Load iSAC SWB. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISACswb, 104)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISACswb, + "isac-swb", 104)); +#endif +#ifdef WEBRTC_CODEC_OPUS + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderOpus, + "opus", 111)); #endif // Load PCM16B nb. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16B, 93)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16B, + "pcm16-nb", 93)); // Load PCM16B wb. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, 94)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, + "pcm16-wb", 94)); // Load PCM16B swb32. - ASSERT_EQ( - 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bswb32kHz, 95)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bswb32kHz, + "pcm16-swb32", 95)); // Load CNG 8 kHz. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, 13)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, + "cng-nb", 13)); // Load CNG 16 kHz. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, 98)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, + "cng-wb", 98)); } void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) { @@ -343,10 +413,11 @@ void NetEqDecodingTest::Process(size_t* out_len) { WebRtcRTPHeader rtp_header; packet_->ConvertHeader(&rtp_header); ASSERT_EQ(0, neteq_->InsertPacket( - rtp_header, packet_->payload(), - packet_->payload_length_bytes(), - static_cast<uint32_t>( - packet_->time_ms() * (output_sample_rate_ / 1000)))); + rtp_header, + rtc::ArrayView<const uint8_t>( + packet_->payload(), packet_->payload_length_bytes()), + static_cast<uint32_t>(packet_->time_ms() * + (output_sample_rate_ / 1000)))); } // Get next packet. packet_.reset(rtp_source_->NextPacket()); @@ -354,13 +425,15 @@ void NetEqDecodingTest::Process(size_t* out_len) { // Get audio from NetEq. NetEqOutputType type; - int num_channels; + size_t num_channels; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, out_len, &num_channels, &type)); ASSERT_TRUE((*out_len == kBlockSize8kHz) || (*out_len == kBlockSize16kHz) || - (*out_len == kBlockSize32kHz)); + (*out_len == kBlockSize32kHz) || + (*out_len == kBlockSize48kHz)); output_sample_rate_ = static_cast<int>(*out_len / 10 * 1000); + EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz()); // Increase time. sim_clock_ += kTimeStepMs; @@ -442,17 +515,17 @@ void NetEqDecodingTest::PopulateCng(int frame_index, *payload_len = 1; // Only noise level, no spectral parameters. } -#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISAC)) && \ +#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID) && \ + defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \ + (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \ defined(WEBRTC_CODEC_ILBC) && defined(WEBRTC_CODEC_G722) -#define IF_ALL_CODECS(x) x +#define MAYBE_TestBitExactness TestBitExactness #else -#define IF_ALL_CODECS(x) DISABLED_##x +#define MAYBE_TestBitExactness DISABLED_TestBitExactness #endif - -TEST_F(NetEqDecodingTest, - DISABLED_ON_IOS(DISABLED_ON_ANDROID(IF_ALL_CODECS(TestBitExactness)))) { - const std::string input_rtp_file = webrtc::test::ProjectRootPath() + - "resources/audio_coding/neteq_universal_new.rtp"; +TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) { + const std::string input_rtp_file = + webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); // Note that neteq4_universal_ref.pcm and neteq4_universal_ref_win_32.pcm // are identical. The latter could have been removed, but if clients still // have a copy of the file, the test will fail. @@ -480,6 +553,34 @@ TEST_F(NetEqDecodingTest, } } +#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID) && \ + defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \ + defined(WEBRTC_CODEC_OPUS) +#define MAYBE_TestOpusBitExactness TestOpusBitExactness +#else +#define MAYBE_TestOpusBitExactness DISABLED_TestOpusBitExactness +#endif +TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) { + const std::string input_rtp_file = + webrtc::test::ResourcePath("audio_coding/neteq_opus", "rtp"); + const std::string input_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_ref", "pcm"); + const std::string network_stat_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_network_stats", + "dat"); + const std::string rtcp_stat_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_rtcp_stats", "dat"); + + if (FLAGS_gen_ref) { + DecodeAndCompare(input_rtp_file, "", "", ""); + } else { + DecodeAndCompare(input_rtp_file, + input_ref_file, + network_stat_ref_file, + rtcp_stat_ref_file); + } +} + // Use fax mode to avoid time-scaling. This is to simplify the testing of // packet waiting times in the packet buffer. class NetEqDecodingTestFaxMode : public NetEqDecodingTest { @@ -495,22 +596,19 @@ TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) { const size_t kSamples = 10 * 16; const size_t kPayloadBytes = kSamples * 2; for (size_t i = 0; i < num_frames; ++i) { - uint16_t payload[kSamples] = {0}; + const uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; rtp_info.header.sequenceNumber = i; rtp_info.header.timestamp = i * kSamples; rtp_info.header.ssrc = 0x1234; // Just an arbitrary SSRC. rtp_info.header.payloadType = 94; // PCM16b WB codec. rtp_info.header.markerBit = 0; - ASSERT_EQ(0, neteq_->InsertPacket( - rtp_info, - reinterpret_cast<uint8_t*>(payload), - kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); } // Pull out all data. for (size_t i = 0; i < num_frames; ++i) { size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -549,13 +647,13 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) { uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++frame_index; } // Pull out data once. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -580,13 +678,13 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) { uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++frame_index; } // Pull out data once. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -611,7 +709,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, double next_input_time_ms = 0.0; double t_ms; size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; // Insert speech for 5 seconds. @@ -623,7 +721,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor; @@ -649,7 +747,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, size_t payload_len; WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ(0, neteq_->InsertPacket( + rtp_info, + rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor; @@ -696,7 +796,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, size_t payload_len; WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ(0, neteq_->InsertPacket( + rtp_info, + rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; next_input_time_ms += kCngPeriodMs * drift_factor; @@ -712,7 +814,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; next_input_time_ms += kFrameSizeMs * drift_factor; @@ -823,31 +925,30 @@ TEST_F(NetEqDecodingTest, UnknownPayloadType) { WebRtcRTPHeader rtp_info; PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = 1; // Not registered as a decoder. - EXPECT_EQ(NetEq::kFail, - neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_info, payload, 0)); EXPECT_EQ(NetEq::kUnknownRtpPayloadType, neteq_->LastError()); } -#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) -#define IF_ISAC(x) x +#if defined(WEBRTC_ANDROID) +#define MAYBE_DecoderError DISABLED_DecoderError #else -#define IF_ISAC(x) DISABLED_##x +#define MAYBE_DecoderError DecoderError #endif - -TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(IF_ISAC(DecoderError))) { +#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) +TEST_F(NetEqDecodingTest, MAYBE_DecoderError) { const size_t kPayloadBytes = 100; uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = 103; // iSAC, but the payload is invalid. - EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); NetEqOutputType type; // Set all of |out_data_| to 1, and verify that it was set to 0 by the call // to GetAudio. for (size_t i = 0; i < kMaxBlockSize; ++i) { out_data_[i] = 1; } - int num_channels; + size_t num_channels; size_t samples_per_channel; EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(kMaxBlockSize, out_data_, @@ -872,6 +973,7 @@ TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(IF_ISAC(DecoderError))) { EXPECT_EQ(1, out_data_[i]); } } +#endif TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { NetEqOutputType type; @@ -880,7 +982,7 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { for (size_t i = 0; i < kMaxBlockSize; ++i) { out_data_[i] = 1; } - int num_channels; + size_t num_channels; size_t samples_per_channel; EXPECT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &samples_per_channel, @@ -894,6 +996,8 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. EXPECT_EQ(0, out_data_[i]); } + // Verify that the sample rate did not change from the initial configuration. + EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz()); } class NetEqBgnTest : public NetEqDecodingTest { @@ -934,27 +1038,29 @@ class NetEqBgnTest : public NetEqDecodingTest { PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = payload_type; - int number_channels = 0; + size_t number_channels = 0; size_t samples_per_channel = 0; uint32_t receive_timestamp = 0; for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. - size_t enc_len_bytes = WebRtcPcm16b_Encode( - input.GetNextBlock(), expected_samples_per_channel, payload); + auto block = input.GetNextBlock(); + ASSERT_EQ(expected_samples_per_channel, block.size()); + size_t enc_len_bytes = + WebRtcPcm16b_Encode(block.data(), block.size(), payload); ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2); number_channels = 0; samples_per_channel = 0; - ASSERT_EQ(0, - neteq_->InsertPacket(rtp_info, payload, enc_len_bytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>( + payload, enc_len_bytes), + receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); ASSERT_EQ(kOutputNormal, type); @@ -976,7 +1082,7 @@ class NetEqBgnTest : public NetEqDecodingTest { &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); // To be able to test the fading of background noise we need at lease to @@ -997,7 +1103,7 @@ class NetEqBgnTest : public NetEqDecodingTest { &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); if (type == kOutputPLCtoCNG) { plc_to_cng = true; @@ -1065,7 +1171,8 @@ TEST_F(NetEqBgnTestFade, RunTest) { CheckBgn(32000); } -TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { +#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) +TEST_F(NetEqDecodingTest, SyncPacketInsert) { WebRtcRTPHeader rtp_info; uint32_t receive_timestamp = 0; // For the readability use the following payloads instead of the defaults of @@ -1081,20 +1188,20 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { // Register decoders. ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, - kPcm16WbPayloadType)); + "pcm16-wb", kPcm16WbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, - kCngNbPayloadType)); + "cng-nb", kCngNbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, - kCngWbPayloadType)); + "cng-wb", kCngWbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGswb32kHz, - kCngSwb32PayloadType)); + "cng-swb32", kCngSwb32PayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGswb48kHz, - kCngSwb48PayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderAVT, + "cng-swb48", kCngSwb48PayloadType)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderAVT, "avt", kAvtPayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderRED, + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderRED, "red", kRedPayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, "isac", kIsacPayloadType)); PopulateRtpInfo(0, 0, &rtp_info); @@ -1106,8 +1213,7 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { // Payload length of 10 ms PCM16 16 kHz. const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t); uint8_t payload[kPayloadBytes] = {0}; - ASSERT_EQ(0, neteq_->InsertPacket( - rtp_info, payload, kPayloadBytes, receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); // Next packet. Last packet contained 10 ms audio. rtp_info.header.sequenceNumber++; @@ -1145,6 +1251,7 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { --rtp_info.header.ssrc; EXPECT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp)); } +#endif // First insert several noise like packets, then sync-packets. Decoding all // packets should not produce error, statistics should not show any packet loss @@ -1165,17 +1272,16 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - int num_channels; + size_t num_channels; size_t samples_per_channel; uint32_t receive_timestamp = 0; for (int n = 0; n < 100; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; @@ -1193,7 +1299,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); if (n > algorithmic_frame_delay) { EXPECT_TRUE(IsAllZero(decoded, samples_per_channel * num_channels)); } @@ -1205,8 +1311,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // We insert regular packets, if sync packet are not correctly buffered then // network statistics would show some packet loss. for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); @@ -1243,18 +1348,17 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - int num_channels; + size_t num_channels; size_t samples_per_channel; uint32_t receive_timestamp = 0; int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1; for (int n = 0; n < algorithmic_frame_delay; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; receive_timestamp += kBlockSize16kHz; @@ -1281,8 +1385,7 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { // Insert. for (int n = 0; n < kNumSyncPackets; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; receive_timestamp += kBlockSize16kHz; @@ -1294,7 +1397,7 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels)); } } @@ -1312,7 +1415,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, const size_t kPayloadBytes = kSamples * sizeof(int16_t); double next_input_time_ms = 0.0; int16_t decoded[kBlockSize16kHz]; - int num_channels; + size_t num_channels; size_t samples_per_channel; NetEqOutputType output_type; uint32_t receive_timestamp = 0; @@ -1334,8 +1437,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, if (drop_seq_numbers.find(seq_no) == drop_seq_numbers.end()) { // This sequence number was not in the set to drop. Insert it. ASSERT_EQ(0, - neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ++packets_inserted; } NetEqNetworkStatistics network_stats; @@ -1366,7 +1468,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); // Expect delay (in samples) to be less than 2 packets. EXPECT_LE(timestamp - PlayoutTimestamp(), @@ -1417,13 +1519,13 @@ void NetEqDecodingTest::DuplicateCng() { // Insert three speech packets. Three are needed to get the frame length // correct. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; for (int i = 0; i < 3; ++i) { PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; @@ -1442,7 +1544,9 @@ void NetEqDecodingTest::DuplicateCng() { size_t payload_len; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); // This is the first time this CNG packet is inserted. - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + 0, neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); // Pull audio once and make sure CNG is played. ASSERT_EQ(0, @@ -1454,7 +1558,9 @@ void NetEqDecodingTest::DuplicateCng() { // Insert the same CNG packet again. Note that at this point it is old, since // we have already decoded the first copy of it. - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + 0, neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); // Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since // we have already pulled out CNG once. @@ -1472,7 +1578,7 @@ void NetEqDecodingTest::DuplicateCng() { ++seq_no; timestamp += kCngPeriodSamples; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); // Pull audio once and verify that the output is speech again. ASSERT_EQ(0, @@ -1507,14 +1613,16 @@ TEST_F(NetEqDecodingTest, CngFirst) { WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + NetEq::kOK, + neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; // Pull audio once and make sure CNG is played. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -1524,7 +1632,7 @@ TEST_F(NetEqDecodingTest, CngFirst) { // Insert some speech packets. for (int i = 0; i < 3; ++i) { PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; |