From 0e6e4d2ff2dc3458ad74aa994a106481df198cd2 Mon Sep 17 00:00:00 2001 From: "henrik.lundin@webrtc.org" Date: Tue, 23 Sep 2014 12:05:34 +0000 Subject: [PATCH] Reland "Converting five tests to use new AudioCoding interface" (r7258) This CL reverts r7264. The problem was that iSAC-SWB and iSAC-FB are not supported on android. These are now disabled. BUG=3520 R=kwiberg@webrtc.org Review URL: https://webrtc-codereview.appspot.com/23739004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7273 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../main/acm2/acm_receive_test.cc | 160 +-- .../audio_coding/main/acm2/acm_receive_test.h | 4 +- .../main/acm2/acm_receive_test_oldapi.cc | 187 ++++ .../main/acm2/acm_receive_test_oldapi.h | 63 ++ .../audio_coding/main/acm2/acm_send_test.cc | 20 +- .../audio_coding/main/acm2/acm_send_test.h | 6 +- .../main/acm2/acm_send_test_oldapi.cc | 145 +++ .../main/acm2/acm_send_test_oldapi.h | 86 ++ .../main/acm2/audio_coding_module.gypi | 12 + .../main/acm2/audio_coding_module_unittest.cc | 160 ++- .../audio_coding_module_unittest_oldapi.cc | 938 ++++++++++++++++++ webrtc/modules/modules.gyp | 1 + 12 files changed, 1575 insertions(+), 207 deletions(-) create mode 100644 webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc create mode 100644 webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h create mode 100644 webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.cc create mode 100644 webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h create mode 100644 webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receive_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_receive_test.cc index 79c9adf0b..7e41328e6 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receive_test.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_receive_test.cc @@ -22,124 +22,67 @@ namespace webrtc { namespace test { -namespace { -// Returns true if the codec should be registered, otherwise false. Changes -// the number of channels for the Opus codec to always be 1. -bool ModifyAndUseThisCodec(CodecInst* codec_param) { - if (STR_CASE_CMP(codec_param->plname, "CN") == 0 && - codec_param->plfreq == 48000) - return false; // Skip 48 kHz comfort noise. - - if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0) - return false; // Skip DTFM. - - return true; -} - -// Remaps payload types from ACM's default to those used in the resource file -// neteq_universal_new.rtp. Returns true if the codec should be registered, -// otherwise false. The payload types are set as follows (all are mono codecs): -// PCMu = 0; -// PCMa = 8; -// Comfort noise 8 kHz = 13 -// Comfort noise 16 kHz = 98 -// Comfort noise 32 kHz = 99 -// iLBC = 102 -// iSAC wideband = 103 -// iSAC super-wideband = 104 -// iSAC fullband = 124 -// AVT/DTMF = 106 -// RED = 117 -// PCM16b 8 kHz = 93 -// PCM16b 16 kHz = 94 -// PCM16b 32 kHz = 95 -// G.722 = 94 -bool RemapPltypeAndUseThisCodec(const char* plname, - int plfreq, - int channels, - int* pltype) { - if (channels != 1) - return false; // Don't use non-mono codecs. - - // Re-map pltypes to those used in the NetEq test files. - if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) { - *pltype = 0; - } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) { - *pltype = 8; - } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) { - *pltype = 13; - } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) { - *pltype = 98; - } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) { - *pltype = 99; - } else if (STR_CASE_CMP(plname, "ILBC") == 0) { - *pltype = 102; - } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) { - *pltype = 103; - } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) { - *pltype = 104; - } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 48000) { - *pltype = 124; - } else if (STR_CASE_CMP(plname, "telephone-event") == 0) { - *pltype = 106; - } else if (STR_CASE_CMP(plname, "red") == 0) { - *pltype = 117; - } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) { - *pltype = 93; - } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) { - *pltype = 94; - } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) { - *pltype = 95; - } else if (STR_CASE_CMP(plname, "G722") == 0) { - *pltype = 9; - } else { - // Don't use any other codecs. - return false; - } - return true; -} -} // namespace - AcmReceiveTest::AcmReceiveTest(PacketSource* packet_source, AudioSink* audio_sink, int output_freq_hz, NumOutputChannels exptected_output_channels) : clock_(0), - acm_(webrtc::AudioCodingModule::Create(0, &clock_)), packet_source_(packet_source), audio_sink_(audio_sink), output_freq_hz_(output_freq_hz), exptected_output_channels_(exptected_output_channels) { + webrtc::AudioCoding::Config config; + config.clock = &clock_; + config.playout_frequency_hz = output_freq_hz_; + acm_.reset(webrtc::AudioCoding::Create(config)); } void AcmReceiveTest::RegisterDefaultCodecs() { - CodecInst my_codec_param; - for (int n = 0; n < acm_->NumberOfCodecs(); n++) { - ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; - if (ModifyAndUseThisCodec(&my_codec_param)) { - ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) - << "Couldn't register receive codec.\n"; - } - } + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kOpus, 120)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISAC, 103)); +#ifndef WEBRTC_ANDROID + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISACSWB, 104)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISACFB, 105)); +#endif + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16B, 107)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bwb, 108)); + ASSERT_TRUE( + acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bswb32kHz, 109)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16B_2ch, 111)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bwb_2ch, 112)); + ASSERT_TRUE( + acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bswb32kHz_2ch, 113)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMU, 0)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMA, 8)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMU_2ch, 110)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMA_2ch, 118)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kILBC, 102)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kG722, 9)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kG722_2ch, 119)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNNB, 13)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNWB, 98)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNSWB, 99)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kRED, 127)); } void AcmReceiveTest::RegisterNetEqTestCodecs() { - CodecInst my_codec_param; - for (int n = 0; n < acm_->NumberOfCodecs(); n++) { - ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; - if (!ModifyAndUseThisCodec(&my_codec_param)) { - // Skip this codec. - continue; - } - - if (RemapPltypeAndUseThisCodec(my_codec_param.plname, - my_codec_param.plfreq, - my_codec_param.channels, - &my_codec_param.pltype)) { - ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) - << "Couldn't register receive codec.\n"; - } - } + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISAC, 103)); +#ifndef WEBRTC_ANDROID + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISACSWB, 104)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISACFB, 124)); +#endif + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16B, 93)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bwb, 94)); + ASSERT_TRUE( + acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCM16Bswb32kHz, 95)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMU, 0)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kPCMA, 8)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kILBC, 102)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kG722, 9)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNNB, 13)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNWB, 98)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kCNSWB, 99)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kRED, 117)); } void AcmReceiveTest::Run() { @@ -148,7 +91,7 @@ void AcmReceiveTest::Run() { // Pull audio until time to insert packet. while (clock_.TimeInMilliseconds() < packet->time_ms()) { AudioFrame output_frame; - EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame)); + EXPECT_TRUE(acm_->Get10MsAudio(&output_frame)); EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); const int samples_per_block = output_freq_hz_ * 10 / 1000; EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_); @@ -170,11 +113,10 @@ void AcmReceiveTest::Run() { header.header = packet->header(); header.frameType = kAudioFrameSpeech; memset(&header.type.Audio, 0, sizeof(RTPAudioHeader)); - EXPECT_EQ(0, - acm_->IncomingPacket( - packet->payload(), - static_cast(packet->payload_length_bytes()), - header)) + EXPECT_TRUE( + acm_->InsertPacket(packet->payload(), + static_cast(packet->payload_length_bytes()), + header)) << "Failure when inserting packet:" << std::endl << " PT = " << static_cast(header.header.payloadType) << std::endl << " TS = " << header.header.timestamp << std::endl diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receive_test.h b/webrtc/modules/audio_coding/main/acm2/acm_receive_test.h index c454020de..19fe4c534 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_receive_test.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_receive_test.h @@ -16,7 +16,7 @@ #include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { -class AudioCodingModule; +class AudioCoding; struct CodecInst; namespace test { @@ -50,7 +50,7 @@ class AcmReceiveTest { private: SimulatedClock clock_; - scoped_ptr acm_; + scoped_ptr acm_; PacketSource* packet_source_; AudioSink* audio_sink_; const int output_freq_hz_; diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc new file mode 100644 index 000000000..b0c9af138 --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" +#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" + +namespace webrtc { +namespace test { + +namespace { +// Returns true if the codec should be registered, otherwise false. Changes +// the number of channels for the Opus codec to always be 1. +bool ModifyAndUseThisCodec(CodecInst* codec_param) { + if (STR_CASE_CMP(codec_param->plname, "CN") == 0 && + codec_param->plfreq == 48000) + return false; // Skip 48 kHz comfort noise. + + if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0) + return false; // Skip DTFM. + + return true; +} + +// Remaps payload types from ACM's default to those used in the resource file +// neteq_universal_new.rtp. Returns true if the codec should be registered, +// otherwise false. The payload types are set as follows (all are mono codecs): +// PCMu = 0; +// PCMa = 8; +// Comfort noise 8 kHz = 13 +// Comfort noise 16 kHz = 98 +// Comfort noise 32 kHz = 99 +// iLBC = 102 +// iSAC wideband = 103 +// iSAC super-wideband = 104 +// iSAC fullband = 124 +// AVT/DTMF = 106 +// RED = 117 +// PCM16b 8 kHz = 93 +// PCM16b 16 kHz = 94 +// PCM16b 32 kHz = 95 +// G.722 = 94 +bool RemapPltypeAndUseThisCodec(const char* plname, + int plfreq, + int channels, + int* pltype) { + if (channels != 1) + return false; // Don't use non-mono codecs. + + // Re-map pltypes to those used in the NetEq test files. + if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) { + *pltype = 0; + } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) { + *pltype = 8; + } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) { + *pltype = 13; + } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) { + *pltype = 98; + } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) { + *pltype = 99; + } else if (STR_CASE_CMP(plname, "ILBC") == 0) { + *pltype = 102; + } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) { + *pltype = 103; + } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) { + *pltype = 104; + } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 48000) { + *pltype = 124; + } else if (STR_CASE_CMP(plname, "telephone-event") == 0) { + *pltype = 106; + } else if (STR_CASE_CMP(plname, "red") == 0) { + *pltype = 117; + } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) { + *pltype = 93; + } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) { + *pltype = 94; + } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) { + *pltype = 95; + } else if (STR_CASE_CMP(plname, "G722") == 0) { + *pltype = 9; + } else { + // Don't use any other codecs. + return false; + } + return true; +} +} // namespace + +AcmReceiveTestOldApi::AcmReceiveTestOldApi( + PacketSource* packet_source, + AudioSink* audio_sink, + int output_freq_hz, + NumOutputChannels exptected_output_channels) + : clock_(0), + acm_(webrtc::AudioCodingModule::Create(0, &clock_)), + packet_source_(packet_source), + audio_sink_(audio_sink), + output_freq_hz_(output_freq_hz), + exptected_output_channels_(exptected_output_channels) { +} + +void AcmReceiveTestOldApi::RegisterDefaultCodecs() { + CodecInst my_codec_param; + for (int n = 0; n < acm_->NumberOfCodecs(); n++) { + ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; + if (ModifyAndUseThisCodec(&my_codec_param)) { + ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) + << "Couldn't register receive codec.\n"; + } + } +} + +void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() { + CodecInst my_codec_param; + for (int n = 0; n < acm_->NumberOfCodecs(); n++) { + ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; + if (!ModifyAndUseThisCodec(&my_codec_param)) { + // Skip this codec. + continue; + } + + if (RemapPltypeAndUseThisCodec(my_codec_param.plname, + my_codec_param.plfreq, + my_codec_param.channels, + &my_codec_param.pltype)) { + ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) + << "Couldn't register receive codec.\n"; + } + } +} + +void AcmReceiveTestOldApi::Run() { + for (scoped_ptr packet(packet_source_->NextPacket()); packet; + packet.reset(packet_source_->NextPacket())) { + // Pull audio until time to insert packet. + while (clock_.TimeInMilliseconds() < packet->time_ms()) { + AudioFrame output_frame; + EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame)); + EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); + const int samples_per_block = output_freq_hz_ * 10 / 1000; + EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_); + if (exptected_output_channels_ != kArbitraryChannels) { + if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) { + // Don't check number of channels for PLC output, since each test run + // usually starts with a short period of mono PLC before decoding the + // first packet. + } else { + EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_); + } + } + ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame)); + clock_.AdvanceTimeMilliseconds(10); + } + + // Insert packet after converting from RTPHeader to WebRtcRTPHeader. + WebRtcRTPHeader header; + header.header = packet->header(); + header.frameType = kAudioFrameSpeech; + memset(&header.type.Audio, 0, sizeof(RTPAudioHeader)); + EXPECT_EQ(0, + acm_->IncomingPacket( + packet->payload(), + static_cast(packet->payload_length_bytes()), + header)) + << "Failure when inserting packet:" << std::endl + << " PT = " << static_cast(header.header.payloadType) << std::endl + << " TS = " << header.header.timestamp << std::endl + << " SN = " << header.header.sequenceNumber; + } +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h b/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h new file mode 100644 index 000000000..795893c2c --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVE_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVE_TEST_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" + +namespace webrtc { +class AudioCodingModule; +struct CodecInst; + +namespace test { +class AudioSink; +class PacketSource; + +class AcmReceiveTestOldApi { + public: + enum NumOutputChannels { + kArbitraryChannels = 0, + kMonoOutput = 1, + kStereoOutput = 2 + }; + + AcmReceiveTestOldApi(PacketSource* packet_source, + AudioSink* audio_sink, + int output_freq_hz, + NumOutputChannels exptected_output_channels); + virtual ~AcmReceiveTestOldApi() {} + + // Registers the codecs with default parameters from ACM. + void RegisterDefaultCodecs(); + + // Registers codecs with payload types matching the pre-encoded NetEq test + // files. + void RegisterNetEqTestCodecs(); + + // Runs the test and returns true if successful. + void Run(); + + private: + SimulatedClock clock_; + scoped_ptr acm_; + PacketSource* packet_source_; + AudioSink* audio_sink_; + const int output_freq_hz_; + NumOutputChannels exptected_output_channels_; + + DISALLOW_COPY_AND_ASSIGN(AcmReceiveTestOldApi); +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVE_TEST_H_ diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_send_test.cc index 30bf2fd36..ec3c25406 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_send_test.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test.cc @@ -27,7 +27,6 @@ AcmSendTest::AcmSendTest(InputAudioFile* audio_source, int source_rate_hz, int test_duration_ms) : clock_(0), - acm_(webrtc::AudioCodingModule::Create(0, &clock_)), audio_source_(audio_source), source_rate_hz_(source_rate_hz), input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000), @@ -37,24 +36,23 @@ AcmSendTest::AcmSendTest(InputAudioFile* audio_source, payload_type_(0), timestamp_(0), sequence_number_(0) { + webrtc::AudioCoding::Config config; + config.clock = &clock_; + config.transport = this; + acm_.reset(webrtc::AudioCoding::Create(config)); input_frame_.sample_rate_hz_ = source_rate_hz_; input_frame_.num_channels_ = 1; input_frame_.samples_per_channel_ = input_block_size_samples_; assert(input_block_size_samples_ * input_frame_.num_channels_ <= AudioFrame::kMaxDataSizeSamples); - acm_->RegisterTransportCallback(this); } -bool AcmSendTest::RegisterCodec(const char* payload_name, - int sampling_freq_hz, +bool AcmSendTest::RegisterCodec(int codec_type, int channels, int payload_type, int frame_size_samples) { - CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec_, sampling_freq_hz, - channels)); - codec_.pltype = payload_type; - codec_.pacsize = frame_size_samples; - codec_registered_ = (acm_->RegisterSendCodec(codec_) == 0); + codec_registered_ = + acm_->RegisterSendCodec(codec_type, payload_type, frame_size_samples); input_frame_.num_channels_ = channels; assert(input_block_size_samples_ * input_frame_.num_channels_ <= AudioFrame::kMaxDataSizeSamples); @@ -79,9 +77,9 @@ Packet* AcmSendTest::NextPacket() { input_frame_.num_channels_, input_frame_.data_); } - CHECK_EQ(0, acm_->Add10MsData(input_frame_)); + int32_t encoded_bytes = acm_->Add10MsAudio(input_frame_); + EXPECT_GE(encoded_bytes, 0); input_frame_.timestamp_ += input_block_size_samples_; - int32_t encoded_bytes = acm_->Process(); if (encoded_bytes > 0) { // Encoded packet received. return CreatePacket(); diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test.h b/webrtc/modules/audio_coding/main/acm2/acm_send_test.h index db5d9e551..8bc0cde07 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_send_test.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test.h @@ -33,8 +33,7 @@ class AcmSendTest : public AudioPacketizationCallback, public PacketSource { virtual ~AcmSendTest() {} // Registers the send codec. Returns true on success, false otherwise. - bool RegisterCodec(const char* payload_name, - int sampling_freq_hz, + bool RegisterCodec(int codec_type, int channels, int payload_type, int frame_size_samples); @@ -62,12 +61,11 @@ class AcmSendTest : public AudioPacketizationCallback, public PacketSource { Packet* CreatePacket(); SimulatedClock clock_; - scoped_ptr acm_; + scoped_ptr acm_; InputAudioFile* audio_source_; int source_rate_hz_; const int input_block_size_samples_; AudioFrame input_frame_; - CodecInst codec_; bool codec_registered_; int test_duration_ms_; // The following member variables are set whenever SendData() is called. diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.cc new file mode 100644 index 000000000..2f5178e05 --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h" + +#include +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" +#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet.h" + +namespace webrtc { +namespace test { + +AcmSendTestOldApi::AcmSendTestOldApi(InputAudioFile* audio_source, + int source_rate_hz, + int test_duration_ms) + : clock_(0), + acm_(webrtc::AudioCodingModule::Create(0, &clock_)), + audio_source_(audio_source), + source_rate_hz_(source_rate_hz), + input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000), + codec_registered_(false), + test_duration_ms_(test_duration_ms), + frame_type_(kAudioFrameSpeech), + payload_type_(0), + timestamp_(0), + sequence_number_(0) { + input_frame_.sample_rate_hz_ = source_rate_hz_; + input_frame_.num_channels_ = 1; + input_frame_.samples_per_channel_ = input_block_size_samples_; + assert(input_block_size_samples_ * input_frame_.num_channels_ <= + AudioFrame::kMaxDataSizeSamples); + acm_->RegisterTransportCallback(this); +} + +bool AcmSendTestOldApi::RegisterCodec(const char* payload_name, + int sampling_freq_hz, + int channels, + int payload_type, + int frame_size_samples) { + CHECK_EQ(0, + AudioCodingModule::Codec( + payload_name, &codec_, sampling_freq_hz, channels)); + codec_.pltype = payload_type; + codec_.pacsize = frame_size_samples; + codec_registered_ = (acm_->RegisterSendCodec(codec_) == 0); + input_frame_.num_channels_ = channels; + assert(input_block_size_samples_ * input_frame_.num_channels_ <= + AudioFrame::kMaxDataSizeSamples); + return codec_registered_; +} + +Packet* AcmSendTestOldApi::NextPacket() { + assert(codec_registered_); + if (filter_.test(payload_type_)) { + // This payload type should be filtered out. Since the payload type is the + // same throughout the whole test run, no packet at all will be delivered. + // We can just as well signal that the test is over by returning NULL. + return NULL; + } + // Insert audio and process until one packet is produced. + while (clock_.TimeInMilliseconds() < test_duration_ms_) { + clock_.AdvanceTimeMilliseconds(kBlockSizeMs); + CHECK(audio_source_->Read(input_block_size_samples_, input_frame_.data_)); + if (input_frame_.num_channels_ > 1) { + InputAudioFile::DuplicateInterleaved(input_frame_.data_, + input_block_size_samples_, + input_frame_.num_channels_, + input_frame_.data_); + } + CHECK_EQ(0, acm_->Add10MsData(input_frame_)); + input_frame_.timestamp_ += input_block_size_samples_; + int32_t encoded_bytes = acm_->Process(); + if (encoded_bytes > 0) { + // Encoded packet received. + return CreatePacket(); + } + } + // Test ended. + return NULL; +} + +// This method receives the callback from ACM when a new packet is produced. +int32_t AcmSendTestOldApi::SendData( + FrameType frame_type, + uint8_t payload_type, + uint32_t timestamp, + const uint8_t* payload_data, + uint16_t payload_len_bytes, + const RTPFragmentationHeader* fragmentation) { + // Store the packet locally. + frame_type_ = frame_type; + payload_type_ = payload_type; + timestamp_ = timestamp; + last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes); + assert(last_payload_vec_.size() == payload_len_bytes); + return 0; +} + +Packet* AcmSendTestOldApi::CreatePacket() { + const size_t kRtpHeaderSize = 12; + size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize; + uint8_t* packet_memory = new uint8_t[allocated_bytes]; + // Populate the header bytes. + packet_memory[0] = 0x80; + packet_memory[1] = payload_type_; + packet_memory[2] = (sequence_number_ >> 8) & 0xFF; + packet_memory[3] = (sequence_number_) & 0xFF; + packet_memory[4] = (timestamp_ >> 24) & 0xFF; + packet_memory[5] = (timestamp_ >> 16) & 0xFF; + packet_memory[6] = (timestamp_ >> 8) & 0xFF; + packet_memory[7] = timestamp_ & 0xFF; + // Set SSRC to 0x12345678. + packet_memory[8] = 0x12; + packet_memory[9] = 0x34; + packet_memory[10] = 0x56; + packet_memory[11] = 0x78; + + ++sequence_number_; + + // Copy the payload data. + memcpy(packet_memory + kRtpHeaderSize, + &last_payload_vec_[0], + last_payload_vec_.size()); + Packet* packet = + new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds()); + assert(packet); + assert(packet->valid_header()); + return packet; +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h new file mode 100644 index 000000000..ff229a0a5 --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_SEND_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_SEND_TEST_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" + +namespace webrtc { + +namespace test { +class InputAudioFile; +class Packet; + +class AcmSendTestOldApi : public AudioPacketizationCallback, + public PacketSource { + public: + AcmSendTestOldApi(InputAudioFile* audio_source, + int source_rate_hz, + int test_duration_ms); + virtual ~AcmSendTestOldApi() {} + + // Registers the send codec. Returns true on success, false otherwise. + bool RegisterCodec(const char* payload_name, + int sampling_freq_hz, + int channels, + int payload_type, + int frame_size_samples); + + // Returns the next encoded packet. Returns NULL if the test duration was + // exceeded. Ownership of the packet is handed over to the caller. + // Inherited from PacketSource. + Packet* NextPacket(); + + // Inherited from AudioPacketizationCallback. + virtual int32_t SendData( + FrameType frame_type, + uint8_t payload_type, + uint32_t timestamp, + const uint8_t* payload_data, + uint16_t payload_len_bytes, + const RTPFragmentationHeader* fragmentation) OVERRIDE; + + private: + static const int kBlockSizeMs = 10; + + // Creates a Packet object from the last packet produced by ACM (and received + // through the SendData method as a callback). Ownership of the new Packet + // object is transferred to the caller. + Packet* CreatePacket(); + + SimulatedClock clock_; + scoped_ptr acm_; + InputAudioFile* audio_source_; + int source_rate_hz_; + const int input_block_size_samples_; + AudioFrame input_frame_; + CodecInst codec_; + bool codec_registered_; + int test_duration_ms_; + // The following member variables are set whenever SendData() is called. + FrameType frame_type_; + int payload_type_; + uint32_t timestamp_; + uint16_t sequence_number_; + std::vector last_payload_vec_; + + DISALLOW_COPY_AND_ASSIGN(AcmSendTestOldApi); +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_SEND_TEST_H_ diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi index f88dbd371..d746a80b0 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi @@ -119,7 +119,11 @@ { 'target_name': 'acm_receive_test', 'type': 'static_library', + 'defines': [ + '<@(audio_coding_defines)', + ], 'dependencies': [ + '<@(audio_coding_dependencies)', 'audio_coding_module', 'neteq_unittest_tools', '<(DEPTH)/testing/gtest.gyp:gtest', @@ -127,12 +131,18 @@ 'sources': [ 'acm_receive_test.cc', 'acm_receive_test.h', + 'acm_receive_test_oldapi.cc', + 'acm_receive_test_oldapi.h', ], }, # acm_receive_test { 'target_name': 'acm_send_test', 'type': 'static_library', + 'defines': [ + '<@(audio_coding_defines)', + ], 'dependencies': [ + '<@(audio_coding_dependencies)', 'audio_coding_module', 'neteq_unittest_tools', '<(DEPTH)/testing/gtest.gyp:gtest', @@ -140,6 +150,8 @@ 'sources': [ 'acm_send_test.cc', 'acm_send_test.h', + 'acm_send_test_oldapi.cc', + 'acm_send_test_oldapi.h', ], }, # acm_send_test { diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc index 009218d19..2e9262d92 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc @@ -12,6 +12,7 @@ #include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" #include "webrtc/base/md5digest.h" #include "webrtc/modules/audio_coding/main/acm2/acm_receive_test.h" #include "webrtc/modules/audio_coding/main/acm2/acm_send_test.h" @@ -118,19 +119,15 @@ class PacketizationCallbackStub : public AudioPacketizationCallback { class AudioCodingModuleTest : public ::testing::Test { protected: AudioCodingModuleTest() - : id_(1), - rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)), - clock_(Clock::GetRealTimeClock()) {} + : rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)) { + config_.transport = &packet_cb_; + } ~AudioCodingModuleTest() {} void TearDown() OVERRIDE {} void SetUp() OVERRIDE { - acm_.reset(AudioCodingModule::Create(id_, clock_)); - - RegisterCodec(); - rtp_utility_->Populate(&rtp_header_); input_frame_.sample_rate_hz_ = kSampleRateHz; @@ -141,17 +138,32 @@ class AudioCodingModuleTest : public ::testing::Test { memset(input_frame_.data_, 0, input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0])); + } - ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_)); + void CreateAcm() { + acm_.reset(AudioCoding::Create(config_)); + ASSERT_TRUE(acm_.get() != NULL); + RegisterCodec(); } virtual void RegisterCodec() { - AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1); - codec_.pltype = kPayloadType; - // Register L16 codec in ACM. - ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_)); - ASSERT_EQ(0, acm_->RegisterSendCodec(codec_)); + int codec_type = acm2::ACMCodecDB::kNone; + switch (kSampleRateHz) { + case 8000: + codec_type = acm2::ACMCodecDB::kPCM16B; + break; + case 16000: + codec_type = acm2::ACMCodecDB::kPCM16Bwb; + break; + case 32000: + codec_type = acm2::ACMCodecDB::kPCM16Bswb32kHz; + break; + default: + FATAL() << "Sample rate not supported in this test."; + } + ASSERT_TRUE(acm_->RegisterSendCodec(codec_type, kPayloadType)); + ASSERT_TRUE(acm_->RegisterReceiveCodec(codec_type, kPayloadType)); } virtual void InsertPacketAndPullAudio() { @@ -161,41 +173,33 @@ class AudioCodingModuleTest : public ::testing::Test { virtual void InsertPacket() { const uint8_t kPayload[kPayloadSizeBytes] = {0}; - ASSERT_EQ(0, - acm_->IncomingPacket(kPayload, kPayloadSizeBytes, rtp_header_)); + ASSERT_TRUE(acm_->InsertPacket(kPayload, kPayloadSizeBytes, rtp_header_)); rtp_utility_->Forward(&rtp_header_); } virtual void PullAudio() { AudioFrame audio_frame; - ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame)); + ASSERT_TRUE(acm_->Get10MsAudio(&audio_frame)); } virtual void InsertAudio() { - ASSERT_EQ(0, acm_->Add10MsData(input_frame_)); + int encoded_bytes = acm_->Add10MsAudio(input_frame_); + ASSERT_GE(encoded_bytes, 0); input_frame_.timestamp_ += kNumSamples10ms; } - virtual void Encode() { - int32_t encoded_bytes = acm_->Process(); - // Expect to get one packet with two bytes per sample, or no packet at all, - // depending on how many 10 ms blocks go into |codec_.pacsize|. - EXPECT_TRUE(encoded_bytes == 2 * codec_.pacsize || encoded_bytes == 0); - } - - const int id_; + AudioCoding::Config config_; scoped_ptr rtp_utility_; - scoped_ptr acm_; + scoped_ptr acm_; PacketizationCallbackStub packet_cb_; WebRtcRTPHeader rtp_header_; AudioFrame input_frame_; - CodecInst codec_; - Clock* clock_; }; // Check if the statistics are initialized correctly. Before any call to ACM // all fields have to be zero. TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(InitializedToZero)) { + CreateAcm(); AudioDecodingCallStats stats; acm_->GetDecodingCallStatistics(&stats); EXPECT_EQ(0, stats.calls_to_neteq); @@ -209,10 +213,10 @@ TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(InitializedToZero)) { // Apply an initial playout delay. Calls to AudioCodingModule::PlayoutData10ms() // should result in generating silence, check the associated field. TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(SilenceGeneratorCalled)) { - AudioDecodingCallStats stats; const int kInitialDelay = 100; - - acm_->SetInitialPlayoutDelay(kInitialDelay); + config_.initial_playout_delay_ms = kInitialDelay; + CreateAcm(); + AudioDecodingCallStats stats; int num_calls = 0; for (int time_ms = 0; time_ms < kInitialDelay; @@ -232,6 +236,7 @@ TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(SilenceGeneratorCalled)) { // simulate packet loss and check if PLC and PLC-to-CNG statistics are // correctly updated. TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(NetEqCalls)) { + CreateAcm(); AudioDecodingCallStats stats; const int kNumNormalCalls = 10; @@ -263,21 +268,16 @@ TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(NetEqCalls)) { } TEST_F(AudioCodingModuleTest, VerifyOutputFrame) { + CreateAcm(); AudioFrame audio_frame; const int kSampleRateHz = 32000; - EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame)); - EXPECT_EQ(id_, audio_frame.id_); + EXPECT_TRUE(acm_->Get10MsAudio(&audio_frame)); EXPECT_EQ(0u, audio_frame.timestamp_); EXPECT_GT(audio_frame.num_channels_, 0); EXPECT_EQ(kSampleRateHz / 100, audio_frame.samples_per_channel_); EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_); } -TEST_F(AudioCodingModuleTest, FailOnZeroDesiredFrequency) { - AudioFrame audio_frame; - EXPECT_EQ(-1, acm_->PlayoutData10Ms(0, &audio_frame)); -} - // A multi-threaded test for ACM. This base class is using the PCM16b 16 kHz // codec, while the derive class AcmIsacMtTest is using iSAC. class AudioCodingModuleMtTest : public AudioCodingModuleTest { @@ -306,11 +306,12 @@ class AudioCodingModuleMtTest : public AudioCodingModuleTest { crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), next_insert_packet_time_ms_(0), fake_clock_(new SimulatedClock(0)) { - clock_ = fake_clock_.get(); + config_.clock = fake_clock_.get(); } virtual void SetUp() OVERRIDE { AudioCodingModuleTest::SetUp(); + CreateAcm(); StartThreads(); } @@ -357,7 +358,6 @@ class AudioCodingModuleMtTest : public AudioCodingModuleTest { } ++send_count_; InsertAudio(); - Encode(); if (TestDone()) { test_complete_->Set(); } @@ -373,7 +373,7 @@ class AudioCodingModuleMtTest : public AudioCodingModuleTest { SleepMs(1); { CriticalSectionScoped lock(crit_sect_.get()); - if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) { + if (fake_clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) { return true; } next_insert_packet_time_ms_ += 10; @@ -394,7 +394,7 @@ class AudioCodingModuleMtTest : public AudioCodingModuleTest { { CriticalSectionScoped lock(crit_sect_.get()); // Don't let the insert thread fall behind. - if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) { + if (next_insert_packet_time_ms_ < fake_clock_->TimeInMilliseconds()) { return true; } ++pull_audio_count_; @@ -439,6 +439,7 @@ class AcmIsacMtTest : public AudioCodingModuleMtTest { virtual void SetUp() OVERRIDE { AudioCodingModuleTest::SetUp(); + CreateAcm(); // Set up input audio source to read from specified file, loop after 5 // seconds, and deliver blocks of 10 ms. @@ -450,7 +451,6 @@ class AcmIsacMtTest : public AudioCodingModuleMtTest { int loop_counter = 0; while (packet_cb_.last_payload_len_bytes() == 0) { InsertAudio(); - Encode(); ASSERT_LT(loop_counter++, 10); } // Set |last_packet_number_| to one less that |num_calls| so that the packet @@ -462,13 +462,12 @@ class AcmIsacMtTest : public AudioCodingModuleMtTest { virtual void RegisterCodec() OVERRIDE { COMPILE_ASSERT(kSampleRateHz == 16000, test_designed_for_isac_16khz); - AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1); - codec_.pltype = kPayloadType; // Register iSAC codec in ACM, effectively unregistering the PCM16B codec // registered in AudioCodingModuleTest::SetUp(); - ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_)); - ASSERT_EQ(0, acm_->RegisterSendCodec(codec_)); + ASSERT_TRUE(acm_->RegisterSendCodec(acm2::ACMCodecDB::kISAC, kPayloadType)); + ASSERT_TRUE( + acm_->RegisterReceiveCodec(acm2::ACMCodecDB::kISAC, kPayloadType)); } virtual void InsertPacket() OVERRIDE { @@ -484,10 +483,8 @@ class AcmIsacMtTest : public AudioCodingModuleMtTest { last_packet_number_ = num_calls; } ASSERT_GT(last_payload_vec_.size(), 0u); - ASSERT_EQ( - 0, - acm_->IncomingPacket( - &last_payload_vec_[0], last_payload_vec_.size(), rtp_header_)); + ASSERT_TRUE(acm_->InsertPacket( + &last_payload_vec_[0], last_payload_vec_.size(), rtp_header_)); } virtual void InsertAudio() OVERRIDE { @@ -495,8 +492,6 @@ class AcmIsacMtTest : public AudioCodingModuleMtTest { AudioCodingModuleTest::InsertAudio(); } - virtual void Encode() OVERRIDE { ASSERT_GE(acm_->Process(), 0); } - // This method is the same as AudioCodingModuleMtTest::TestDone(), but here // it is using the constants defined in this class (i.e., shorter test run). virtual bool TestDone() OVERRIDE { @@ -634,19 +629,15 @@ class AcmSenderBitExactness : public ::testing::Test, // Registers a send codec in the test::AcmSendTest object. Returns true on // success, false on failure. - bool RegisterSendCodec(const char* payload_name, - int sampling_freq_hz, + bool RegisterSendCodec(int codec_type, int channels, int payload_type, int frame_size_samples, int frame_size_rtp_timestamps) { payload_type_ = payload_type; frame_size_rtp_timestamps_ = frame_size_rtp_timestamps; - return send_test_->RegisterCodec(payload_name, - sampling_freq_hz, - channels, - payload_type, - frame_size_samples); + return send_test_->RegisterCodec( + codec_type, channels, payload_type, frame_size_samples); } // Runs the test. SetUpSender() and RegisterSendCodec() must have been called @@ -728,15 +719,13 @@ class AcmSenderBitExactness : public ::testing::Test, payload_checksum_.Update(packet->payload(), packet->payload_length_bytes()); } - void SetUpTest(const char* codec_name, - int codec_sample_rate_hz, + void SetUpTest(int codec_type, int channels, int payload_type, int codec_frame_size_samples, int codec_frame_size_rtp_timestamps) { ASSERT_TRUE(SetUpSender()); - ASSERT_TRUE(RegisterSendCodec(codec_name, - codec_sample_rate_hz, + ASSERT_TRUE(RegisterSendCodec(codec_type, channels, payload_type, codec_frame_size_samples, @@ -754,7 +743,7 @@ class AcmSenderBitExactness : public ::testing::Test, }; TEST_F(AcmSenderBitExactness, IsacWb30ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kISAC, 1, 103, 480, 480)); Run(AcmReceiverBitExactness::PlatformChecksum( "c7e5bdadfa2871df95639fcc297cf23d", "0499ca260390769b3172136faad925b9", @@ -768,7 +757,7 @@ TEST_F(AcmSenderBitExactness, IsacWb30ms) { } TEST_F(AcmSenderBitExactness, IsacWb60ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kISAC, 1, 103, 960, 960)); Run(AcmReceiverBitExactness::PlatformChecksum( "14d63c5f08127d280e722e3191b73bdd", "8da003e16c5371af2dc2be79a50f9076", @@ -782,7 +771,8 @@ TEST_F(AcmSenderBitExactness, IsacWb60ms) { } TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(IsacSwb30ms)) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 32000, 1, 104, 960, 960)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kISACSWB, 1, 104, 960, 960)); Run(AcmReceiverBitExactness::PlatformChecksum( "98d960600eb4ddb3fcbe11f5057ddfd7", "", @@ -796,7 +786,7 @@ TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(IsacSwb30ms)) { } TEST_F(AcmSenderBitExactness, Pcm16_8000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kPCM16B, 1, 107, 80, 80)); Run("de4a98e1406f8b798d99cd0704e862e2", "c1edd36339ce0326cc4550041ad719a0", 100, @@ -804,7 +794,8 @@ TEST_F(AcmSenderBitExactness, Pcm16_8000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcm16_16000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCM16Bwb, 1, 108, 160, 160)); Run("ae646d7b68384a1269cc080dd4501916", "ad786526383178b08d80d6eee06e9bad", 100, @@ -812,7 +803,8 @@ TEST_F(AcmSenderBitExactness, Pcm16_16000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcm16_32000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCM16Bswb32kHz, 1, 109, 320, 320)); Run("7fe325e8fbaf755e3c5df0b11a4774fb", "5ef82ea885e922263606c6fdbc49f651", 100, @@ -820,7 +812,8 @@ TEST_F(AcmSenderBitExactness, Pcm16_32000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcm16_stereo_8000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCM16B_2ch, 2, 111, 80, 80)); Run("fb263b74e7ac3de915474d77e4744ceb", "62ce5adb0d4965d0a52ec98ae7f98974", 100, @@ -828,7 +821,8 @@ TEST_F(AcmSenderBitExactness, Pcm16_stereo_8000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcm16_stereo_16000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCM16Bwb_2ch, 2, 112, 160, 160)); Run("d09e9239553649d7ac93e19d304281fd", "41ca8edac4b8c71cd54fd9f25ec14870", 100, @@ -836,7 +830,8 @@ TEST_F(AcmSenderBitExactness, Pcm16_stereo_16000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcm16_stereo_32000khz_10ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCM16Bswb32kHz_2ch, 2, 113, 320, 320)); Run("5f025d4f390982cc26b3d92fe02e3044", "50e58502fb04421bf5b857dda4c96879", 100, @@ -844,7 +839,7 @@ TEST_F(AcmSenderBitExactness, Pcm16_stereo_32000khz_10ms) { } TEST_F(AcmSenderBitExactness, Pcmu_20ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 1, 0, 160, 160)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kPCMU, 1, 0, 160, 160)); Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9", 50, @@ -852,7 +847,7 @@ TEST_F(AcmSenderBitExactness, Pcmu_20ms) { } TEST_F(AcmSenderBitExactness, Pcma_20ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 1, 8, 160, 160)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kPCMA, 1, 8, 160, 160)); Run("39611f798969053925a49dc06d08de29", "6ad745e55aa48981bfc790d0eeef2dd1", 50, @@ -860,7 +855,8 @@ TEST_F(AcmSenderBitExactness, Pcma_20ms) { } TEST_F(AcmSenderBitExactness, Pcmu_stereo_20ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 2, 110, 160, 160)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCMU_2ch, 2, 110, 160, 160)); Run("437bec032fdc5cbaa0d5175430af7b18", "60b6f25e8d1e74cb679cfe756dd9bca5", 50, @@ -868,7 +864,8 @@ TEST_F(AcmSenderBitExactness, Pcmu_stereo_20ms) { } TEST_F(AcmSenderBitExactness, Pcma_stereo_20ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 2, 118, 160, 160)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kPCMA_2ch, 2, 118, 160, 160)); Run("a5c6d83c5b7cedbeff734238220a4b0c", "92b282c83efd20e7eeef52ba40842cf7", 50, @@ -876,7 +873,7 @@ TEST_F(AcmSenderBitExactness, Pcma_stereo_20ms) { } TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(Ilbc_30ms)) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("ILBC", 8000, 1, 102, 240, 240)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kILBC, 1, 102, 240, 240)); Run(AcmReceiverBitExactness::PlatformChecksum( "7b6ec10910debd9af08011d3ed5249f7", "android_audio", @@ -890,7 +887,7 @@ TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(Ilbc_30ms)) { } TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(G722_20ms)) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 1, 9, 320, 160)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kG722, 1, 9, 320, 160)); Run(AcmReceiverBitExactness::PlatformChecksum( "7d759436f2533582950d148b5161a36c", "android_audio", @@ -904,7 +901,8 @@ TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(G722_20ms)) { } TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(G722_stereo_20ms)) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 2, 119, 320, 160)); + ASSERT_NO_FATAL_FAILURE( + SetUpTest(acm2::ACMCodecDB::kG722_2ch, 2, 119, 320, 160)); Run(AcmReceiverBitExactness::PlatformChecksum( "7190ee718ab3d80eca181e5f7140c210", "android_audio", @@ -918,7 +916,7 @@ TEST_F(AcmSenderBitExactness, DISABLED_ON_ANDROID(G722_stereo_20ms)) { } TEST_F(AcmSenderBitExactness, Opus_stereo_20ms) { - ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960)); + ASSERT_NO_FATAL_FAILURE(SetUpTest(acm2::ACMCodecDB::kOpus, 2, 120, 960, 960)); Run(AcmReceiverBitExactness::PlatformChecksum( "855041f2490b887302bce9d544731849", "1e1a0fce893fef2d66886a7f09e2ebce", diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc new file mode 100644 index 000000000..104b5b88a --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc @@ -0,0 +1,938 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/md5digest.h" +#include "webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h" +#include "webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h" +#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" +#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h" +#include "webrtc/modules/audio_coding/neteq/tools/audio_checksum.h" +#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" +#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" +#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet.h" +#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/compile_assert.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/event_wrapper.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/sleep.h" +#include "webrtc/system_wrappers/interface/thread_annotations.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/test/testsupport/gtest_disable.h" + +namespace webrtc { + +const int kSampleRateHz = 16000; +const int kNumSamples10ms = kSampleRateHz / 100; +const int kFrameSizeMs = 10; // Multiple of 10. +const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms; +const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t); +const uint8_t kPayloadType = 111; + +class RtpUtility { + public: + RtpUtility(int samples_per_packet, uint8_t payload_type) + : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {} + + virtual ~RtpUtility() {} + + void Populate(WebRtcRTPHeader* rtp_header) { + rtp_header->header.sequenceNumber = 0xABCD; + rtp_header->header.timestamp = 0xABCDEF01; + rtp_header->header.payloadType = payload_type_; + rtp_header->header.markerBit = false; + rtp_header->header.ssrc = 0x1234; + rtp_header->header.numCSRCs = 0; + rtp_header->frameType = kAudioFrameSpeech; + + rtp_header->header.payload_type_frequency = kSampleRateHz; + rtp_header->type.Audio.channel = 1; + rtp_header->type.Audio.isCNG = false; + } + + void Forward(WebRtcRTPHeader* rtp_header) { + ++rtp_header->header.sequenceNumber; + rtp_header->header.timestamp += samples_per_packet_; + } + + private: + int samples_per_packet_; + uint8_t payload_type_; +}; + +class PacketizationCallbackStub : public AudioPacketizationCallback { + public: + PacketizationCallbackStub() + : num_calls_(0), + crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {} + + virtual int32_t SendData( + FrameType frame_type, + uint8_t payload_type, + uint32_t timestamp, + const uint8_t* payload_data, + uint16_t payload_len_bytes, + const RTPFragmentationHeader* fragmentation) OVERRIDE { + CriticalSectionScoped lock(crit_sect_.get()); + ++num_calls_; + last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes); + return 0; + } + + int num_calls() const { + CriticalSectionScoped lock(crit_sect_.get()); + return num_calls_; + } + + int last_payload_len_bytes() const { + CriticalSectionScoped lock(crit_sect_.get()); + return last_payload_vec_.size(); + } + + void SwapBuffers(std::vector* payload) { + CriticalSectionScoped lock(crit_sect_.get()); + last_payload_vec_.swap(*payload); + } + + private: + int num_calls_ GUARDED_BY(crit_sect_); + std::vector last_payload_vec_ GUARDED_BY(crit_sect_); + const scoped_ptr crit_sect_; +}; + +class AudioCodingModuleTestOldApi : public ::testing::Test { + protected: + AudioCodingModuleTestOldApi() + : id_(1), + rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)), + clock_(Clock::GetRealTimeClock()) {} + + ~AudioCodingModuleTestOldApi() {} + + void TearDown() {} + + void SetUp() { + acm_.reset(AudioCodingModule::Create(id_, clock_)); + + RegisterCodec(); + + rtp_utility_->Populate(&rtp_header_); + + input_frame_.sample_rate_hz_ = kSampleRateHz; + input_frame_.num_channels_ = 1; + input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000; // 10 ms. + COMPILE_ASSERT(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples, + audio_frame_too_small); + memset(input_frame_.data_, + 0, + input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0])); + + ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_)); + } + + virtual void RegisterCodec() { + AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1); + codec_.pltype = kPayloadType; + + // Register L16 codec in ACM. + ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_)); + ASSERT_EQ(0, acm_->RegisterSendCodec(codec_)); + } + + virtual void InsertPacketAndPullAudio() { + InsertPacket(); + PullAudio(); + } + + virtual void InsertPacket() { + const uint8_t kPayload[kPayloadSizeBytes] = {0}; + ASSERT_EQ(0, + acm_->IncomingPacket(kPayload, kPayloadSizeBytes, rtp_header_)); + rtp_utility_->Forward(&rtp_header_); + } + + virtual void PullAudio() { + AudioFrame audio_frame; + ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame)); + } + + virtual void InsertAudio() { + ASSERT_EQ(0, acm_->Add10MsData(input_frame_)); + input_frame_.timestamp_ += kNumSamples10ms; + } + + virtual void Encode() { + int32_t encoded_bytes = acm_->Process(); + // Expect to get one packet with two bytes per sample, or no packet at all, + // depending on how many 10 ms blocks go into |codec_.pacsize|. + EXPECT_TRUE(encoded_bytes == 2 * codec_.pacsize || encoded_bytes == 0); + } + + const int id_; + scoped_ptr rtp_utility_; + scoped_ptr acm_; + PacketizationCallbackStub packet_cb_; + WebRtcRTPHeader rtp_header_; + AudioFrame input_frame_; + CodecInst codec_; + Clock* clock_; +}; + +// Check if the statistics are initialized correctly. Before any call to ACM +// all fields have to be zero. +TEST_F(AudioCodingModuleTestOldApi, DISABLED_ON_ANDROID(InitializedToZero)) { + AudioDecodingCallStats stats; + acm_->GetDecodingCallStatistics(&stats); + EXPECT_EQ(0, stats.calls_to_neteq); + EXPECT_EQ(0, stats.calls_to_silence_generator); + EXPECT_EQ(0, stats.decoded_normal); + EXPECT_EQ(0, stats.decoded_cng); + EXPECT_EQ(0, stats.decoded_plc); + EXPECT_EQ(0, stats.decoded_plc_cng); +} + +// Apply an initial playout delay. Calls to AudioCodingModule::PlayoutData10ms() +// should result in generating silence, check the associated field. +TEST_F(AudioCodingModuleTestOldApi, + DISABLED_ON_ANDROID(SilenceGeneratorCalled)) { + AudioDecodingCallStats stats; + const int kInitialDelay = 100; + + acm_->SetInitialPlayoutDelay(kInitialDelay); + + int num_calls = 0; + for (int time_ms = 0; time_ms < kInitialDelay; + time_ms += kFrameSizeMs, ++num_calls) { + InsertPacketAndPullAudio(); + } + acm_->GetDecodingCallStatistics(&stats); + EXPECT_EQ(0, stats.calls_to_neteq); + EXPECT_EQ(num_calls, stats.calls_to_silence_generator); + EXPECT_EQ(0, stats.decoded_normal); + EXPECT_EQ(0, stats.decoded_cng); + EXPECT_EQ(0, stats.decoded_plc); + EXPECT_EQ(0, stats.decoded_plc_cng); +} + +// Insert some packets and pull audio. Check statistics are valid. Then, +// simulate packet loss and check if PLC and PLC-to-CNG statistics are +// correctly updated. +TEST_F(AudioCodingModuleTestOldApi, DISABLED_ON_ANDROID(NetEqCalls)) { + AudioDecodingCallStats stats; + const int kNumNormalCalls = 10; + + for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) { + InsertPacketAndPullAudio(); + } + acm_->GetDecodingCallStatistics(&stats); + EXPECT_EQ(kNumNormalCalls, stats.calls_to_neteq); + EXPECT_EQ(0, stats.calls_to_silence_generator); + EXPECT_EQ(kNumNormalCalls, stats.decoded_normal); + EXPECT_EQ(0, stats.decoded_cng); + EXPECT_EQ(0, stats.decoded_plc); + EXPECT_EQ(0, stats.decoded_plc_cng); + + const int kNumPlc = 3; + const int kNumPlcCng = 5; + + // Simulate packet-loss. NetEq first performs PLC then PLC fades to CNG. + for (int n = 0; n < kNumPlc + kNumPlcCng; ++n) { + PullAudio(); + } + acm_->GetDecodingCallStatistics(&stats); + EXPECT_EQ(kNumNormalCalls + kNumPlc + kNumPlcCng, stats.calls_to_neteq); + EXPECT_EQ(0, stats.calls_to_silence_generator); + EXPECT_EQ(kNumNormalCalls, stats.decoded_normal); + EXPECT_EQ(0, stats.decoded_cng); + EXPECT_EQ(kNumPlc, stats.decoded_plc); + EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng); +} + +TEST_F(AudioCodingModuleTestOldApi, VerifyOutputFrame) { + AudioFrame audio_frame; + const int kSampleRateHz = 32000; + EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame)); + EXPECT_EQ(id_, audio_frame.id_); + EXPECT_EQ(0u, audio_frame.timestamp_); + EXPECT_GT(audio_frame.num_channels_, 0); + EXPECT_EQ(kSampleRateHz / 100, audio_frame.samples_per_channel_); + EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_); +} + +TEST_F(AudioCodingModuleTestOldApi, FailOnZeroDesiredFrequency) { + AudioFrame audio_frame; + EXPECT_EQ(-1, acm_->PlayoutData10Ms(0, &audio_frame)); +} + +// A multi-threaded test for ACM. This base class is using the PCM16b 16 kHz +// codec, while the derive class AcmIsacMtTest is using iSAC. +class AudioCodingModuleMtTestOldApi : public AudioCodingModuleTestOldApi { + protected: + static const int kNumPackets = 500; + static const int kNumPullCalls = 500; + + AudioCodingModuleMtTestOldApi() + : AudioCodingModuleTestOldApi(), + send_thread_(ThreadWrapper::CreateThread(CbSendThread, + this, + kRealtimePriority, + "send")), + insert_packet_thread_(ThreadWrapper::CreateThread(CbInsertPacketThread, + this, + kRealtimePriority, + "insert_packet")), + pull_audio_thread_(ThreadWrapper::CreateThread(CbPullAudioThread, + this, + kRealtimePriority, + "pull_audio")), + test_complete_(EventWrapper::Create()), + send_count_(0), + insert_packet_count_(0), + pull_audio_count_(0), + crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), + next_insert_packet_time_ms_(0), + fake_clock_(new SimulatedClock(0)) { + clock_ = fake_clock_.get(); + } + + void SetUp() { + AudioCodingModuleTestOldApi::SetUp(); + StartThreads(); + } + + void StartThreads() { + unsigned int thread_id = 0; + ASSERT_TRUE(send_thread_->Start(thread_id)); + ASSERT_TRUE(insert_packet_thread_->Start(thread_id)); + ASSERT_TRUE(pull_audio_thread_->Start(thread_id)); + } + + void TearDown() { + AudioCodingModuleTestOldApi::TearDown(); + pull_audio_thread_->Stop(); + send_thread_->Stop(); + insert_packet_thread_->Stop(); + } + + EventTypeWrapper RunTest() { + return test_complete_->Wait(10 * 60 * 1000); // 10 minutes' timeout. + } + + virtual bool TestDone() { + if (packet_cb_.num_calls() > kNumPackets) { + CriticalSectionScoped lock(crit_sect_.get()); + if (pull_audio_count_ > kNumPullCalls) { + // Both conditions for completion are met. End the test. + return true; + } + } + return false; + } + + static bool CbSendThread(void* context) { + return reinterpret_cast(context) + ->CbSendImpl(); + } + + // The send thread doesn't have to care about the current simulated time, + // since only the AcmReceiver is using the clock. + bool CbSendImpl() { + SleepMs(1); + if (HasFatalFailure()) { + // End the test early if a fatal failure (ASSERT_*) has occurred. + test_complete_->Set(); + } + ++send_count_; + InsertAudio(); + Encode(); + if (TestDone()) { + test_complete_->Set(); + } + return true; + } + + static bool CbInsertPacketThread(void* context) { + return reinterpret_cast(context) + ->CbInsertPacketImpl(); + } + + bool CbInsertPacketImpl() { + SleepMs(1); + { + CriticalSectionScoped lock(crit_sect_.get()); + if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) { + return true; + } + next_insert_packet_time_ms_ += 10; + } + // Now we're not holding the crit sect when calling ACM. + ++insert_packet_count_; + InsertPacket(); + return true; + } + + static bool CbPullAudioThread(void* context) { + return reinterpret_cast(context) + ->CbPullAudioImpl(); + } + + bool CbPullAudioImpl() { + SleepMs(1); + { + CriticalSectionScoped lock(crit_sect_.get()); + // Don't let the insert thread fall behind. + if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) { + return true; + } + ++pull_audio_count_; + } + // Now we're not holding the crit sect when calling ACM. + PullAudio(); + fake_clock_->AdvanceTimeMilliseconds(10); + return true; + } + + scoped_ptr send_thread_; + scoped_ptr insert_packet_thread_; + scoped_ptr pull_audio_thread_; + const scoped_ptr test_complete_; + int send_count_; + int insert_packet_count_; + int pull_audio_count_ GUARDED_BY(crit_sect_); + const scoped_ptr crit_sect_; + int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_); + scoped_ptr fake_clock_; +}; + +TEST_F(AudioCodingModuleMtTestOldApi, DoTest) { + EXPECT_EQ(kEventSignaled, RunTest()); +} + +// This is a multi-threaded ACM test using iSAC. The test encodes audio +// from a PCM file. The most recent encoded frame is used as input to the +// receiving part. Depending on timing, it may happen that the same RTP packet +// is inserted into the receiver multiple times, but this is a valid use-case, +// and simplifies the test code a lot. +class AcmIsacMtTestOldApi : public AudioCodingModuleMtTestOldApi { + protected: + static const int kNumPackets = 500; + static const int kNumPullCalls = 500; + + AcmIsacMtTestOldApi() + : AudioCodingModuleMtTestOldApi(), last_packet_number_(0) {} + + ~AcmIsacMtTestOldApi() {} + + void SetUp() { + AudioCodingModuleTestOldApi::SetUp(); + + // Set up input audio source to read from specified file, loop after 5 + // seconds, and deliver blocks of 10 ms. + const std::string input_file_name = + webrtc::test::ResourcePath("audio_coding/speech_mono_16kHz", "pcm"); + audio_loop_.Init(input_file_name, 5 * kSampleRateHz, kNumSamples10ms); + + // Generate one packet to have something to insert. + int loop_counter = 0; + while (packet_cb_.last_payload_len_bytes() == 0) { + InsertAudio(); + Encode(); + ASSERT_LT(loop_counter++, 10); + } + // Set |last_packet_number_| to one less that |num_calls| so that the packet + // will be fetched in the next InsertPacket() call. + last_packet_number_ = packet_cb_.num_calls() - 1; + + StartThreads(); + } + + virtual void RegisterCodec() { + COMPILE_ASSERT(kSampleRateHz == 16000, test_designed_for_isac_16khz); + AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1); + codec_.pltype = kPayloadType; + + // Register iSAC codec in ACM, effectively unregistering the PCM16B codec + // registered in AudioCodingModuleTestOldApi::SetUp(); + ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_)); + ASSERT_EQ(0, acm_->RegisterSendCodec(codec_)); + } + + void InsertPacket() { + int num_calls = packet_cb_.num_calls(); // Store locally for thread safety. + if (num_calls > last_packet_number_) { + // Get the new payload out from the callback handler. + // Note that since we swap buffers here instead of directly inserting + // a pointer to the data in |packet_cb_|, we avoid locking the callback + // for the duration of the IncomingPacket() call. + packet_cb_.SwapBuffers(&last_payload_vec_); + ASSERT_GT(last_payload_vec_.size(), 0u); + rtp_utility_->Forward(&rtp_header_); + last_packet_number_ = num_calls; + } + ASSERT_GT(last_payload_vec_.size(), 0u); + ASSERT_EQ( + 0, + acm_->IncomingPacket( + &last_payload_vec_[0], last_payload_vec_.size(), rtp_header_)); + } + + void InsertAudio() { + memcpy(input_frame_.data_, audio_loop_.GetNextBlock(), kNumSamples10ms); + AudioCodingModuleTestOldApi::InsertAudio(); + } + + void Encode() { ASSERT_GE(acm_->Process(), 0); } + + // This method is the same as AudioCodingModuleMtTestOldApi::TestDone(), but + // here it is using the constants defined in this class (i.e., shorter test + // run). + virtual bool TestDone() { + if (packet_cb_.num_calls() > kNumPackets) { + CriticalSectionScoped lock(crit_sect_.get()); + if (pull_audio_count_ > kNumPullCalls) { + // Both conditions for completion are met. End the test. + return true; + } + } + return false; + } + + int last_packet_number_; + std::vector last_payload_vec_; + test::AudioLoop audio_loop_; +}; + +TEST_F(AcmIsacMtTestOldApi, DoTest) { + EXPECT_EQ(kEventSignaled, RunTest()); +} + +class AcmReceiverBitExactnessOldApi : public ::testing::Test { + public: + static std::string PlatformChecksum(std::string win64, + std::string android, + std::string others) { +#if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS) + return win64; +#elif defined(WEBRTC_ANDROID) + return android; +#else + return others; +#endif + } + + protected: + void Run(int output_freq_hz, const std::string& checksum_ref) { + const std::string input_file_name = + webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); + scoped_ptr packet_source( + test::RtpFileSource::Create(input_file_name)); +#ifdef WEBRTC_ANDROID + // Filter out iLBC and iSAC-swb since they are not supported on Android. + packet_source->FilterOutPayloadType(102); // iLBC. + packet_source->FilterOutPayloadType(104); // iSAC-swb. +#endif + + test::AudioChecksum checksum; + const std::string output_file_name = + webrtc::test::OutputPath() + + ::testing::UnitTest::GetInstance() + ->current_test_info() + ->test_case_name() + + "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() + + "_output.pcm"; + test::OutputAudioFile output_file(output_file_name); + test::AudioSinkFork output(&checksum, &output_file); + + test::AcmReceiveTestOldApi test( + packet_source.get(), + &output, + output_freq_hz, + test::AcmReceiveTestOldApi::kArbitraryChannels); + ASSERT_NO_FATAL_FAILURE(test.RegisterNetEqTestCodecs()); + test.Run(); + + std::string checksum_string = checksum.Finish(); + EXPECT_EQ(checksum_ref, checksum_string); + } +}; + +TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) { + Run(8000, + PlatformChecksum("bd6f8d9602cd82444ea2539e674df747", + "6ac89c7145072c26bfeba602cd661afb", + "8a8440f5511eb729221b9aac25cda3a0")); +} + +TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) { + Run(16000, + PlatformChecksum("a39bc6ee0c4eb15f3ad2f43cebcc571d", + "3e888eb04f57db2c6ef952fe64f17fe6", + "7be583092c5adbcb0f6cd66eca20ea63")); +} + +TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) { + Run(32000, + PlatformChecksum("80964572aaa2dc92f9e34896dd3802b3", + "aeca37e963310f5b6552b7edea23c2f1", + "3a84188abe9fca25fedd6034760f3e22")); +} + +TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) { + Run(48000, + PlatformChecksum("8aacde91f390e0d5a9c2ed571a25fd37", + "76b9e99e0a3998aa28355e7a2bd836f7", + "89b4b19bdb4de40f1d88302ef8cb9f9b")); +} + +// This test verifies bit exactness for the send-side of ACM. The test setup is +// a chain of three different test classes: +// +// test::AcmSendTest -> AcmSenderBitExactness -> test::AcmReceiveTest +// +// The receiver side is driving the test by requesting new packets from +// AcmSenderBitExactness::NextPacket(). This method, in turn, asks for the +// packet from test::AcmSendTest::NextPacket, which inserts audio from the +// input file until one packet is produced. (The input file loops indefinitely.) +// Before passing the packet to the receiver, this test class verifies the +// packet header and updates a payload checksum with the new payload. The +// decoded output from the receiver is also verified with a (separate) checksum. +class AcmSenderBitExactnessOldApi : public ::testing::Test, + public test::PacketSource { + protected: + static const int kTestDurationMs = 1000; + + AcmSenderBitExactnessOldApi() + : frame_size_rtp_timestamps_(0), + packet_count_(0), + payload_type_(0), + last_sequence_number_(0), + last_timestamp_(0) {} + + // Sets up the test::AcmSendTest object. Returns true on success, otherwise + // false. + bool SetUpSender() { + const std::string input_file_name = + webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); + // Note that |audio_source_| will loop forever. The test duration is set + // explicitly by |kTestDurationMs|. + audio_source_.reset(new test::InputAudioFile(input_file_name)); + static const int kSourceRateHz = 32000; + send_test_.reset(new test::AcmSendTestOldApi( + audio_source_.get(), kSourceRateHz, kTestDurationMs)); + return send_test_.get() != NULL; + } + + // Registers a send codec in the test::AcmSendTest object. Returns true on + // success, false on failure. + bool RegisterSendCodec(const char* payload_name, + int sampling_freq_hz, + int channels, + int payload_type, + int frame_size_samples, + int frame_size_rtp_timestamps) { + payload_type_ = payload_type; + frame_size_rtp_timestamps_ = frame_size_rtp_timestamps; + return send_test_->RegisterCodec(payload_name, + sampling_freq_hz, + channels, + payload_type, + frame_size_samples); + } + + // Runs the test. SetUpSender() and RegisterSendCodec() must have been called + // before calling this method. + void Run(const std::string& audio_checksum_ref, + const std::string& payload_checksum_ref, + int expected_packets, + test::AcmReceiveTestOldApi::NumOutputChannels expected_channels) { + // Set up the receiver used to decode the packets and verify the decoded + // output. + test::AudioChecksum audio_checksum; + const std::string output_file_name = + webrtc::test::OutputPath() + + ::testing::UnitTest::GetInstance() + ->current_test_info() + ->test_case_name() + + "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() + + "_output.pcm"; + test::OutputAudioFile output_file(output_file_name); + // Have the output audio sent both to file and to the checksum calculator. + test::AudioSinkFork output(&audio_checksum, &output_file); + const int kOutputFreqHz = 8000; + test::AcmReceiveTestOldApi receive_test( + this, &output, kOutputFreqHz, expected_channels); + ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs()); + + // This is where the actual test is executed. + receive_test.Run(); + + // Extract and verify the audio checksum. + std::string checksum_string = audio_checksum.Finish(); + EXPECT_EQ(audio_checksum_ref, checksum_string); + + // Extract and verify the payload checksum. + char checksum_result[rtc::Md5Digest::kSize]; + payload_checksum_.Finish(checksum_result, rtc::Md5Digest::kSize); + checksum_string = rtc::hex_encode(checksum_result, rtc::Md5Digest::kSize); + EXPECT_EQ(payload_checksum_ref, checksum_string); + + // Verify number of packets produced. + EXPECT_EQ(expected_packets, packet_count_); + } + + // Returns a pointer to the next packet. Returns NULL if the source is + // depleted (i.e., the test duration is exceeded), or if an error occurred. + // Inherited from test::PacketSource. + test::Packet* NextPacket() OVERRIDE { + // Get the next packet from AcmSendTest. Ownership of |packet| is + // transferred to this method. + test::Packet* packet = send_test_->NextPacket(); + if (!packet) + return NULL; + + VerifyPacket(packet); + // TODO(henrik.lundin) Save the packet to file as well. + + // Pass it on to the caller. The caller becomes the owner of |packet|. + return packet; + } + + // Verifies the packet. + void VerifyPacket(const test::Packet* packet) { + EXPECT_TRUE(packet->valid_header()); + // (We can check the header fields even if valid_header() is false.) + EXPECT_EQ(payload_type_, packet->header().payloadType); + if (packet_count_ > 0) { + // This is not the first packet. + uint16_t sequence_number_diff = + packet->header().sequenceNumber - last_sequence_number_; + EXPECT_EQ(1, sequence_number_diff); + uint32_t timestamp_diff = packet->header().timestamp - last_timestamp_; + EXPECT_EQ(frame_size_rtp_timestamps_, timestamp_diff); + } + ++packet_count_; + last_sequence_number_ = packet->header().sequenceNumber; + last_timestamp_ = packet->header().timestamp; + // Update the checksum. + payload_checksum_.Update(packet->payload(), packet->payload_length_bytes()); + } + + void SetUpTest(const char* codec_name, + int codec_sample_rate_hz, + int channels, + int payload_type, + int codec_frame_size_samples, + int codec_frame_size_rtp_timestamps) { + ASSERT_TRUE(SetUpSender()); + ASSERT_TRUE(RegisterSendCodec(codec_name, + codec_sample_rate_hz, + channels, + payload_type, + codec_frame_size_samples, + codec_frame_size_rtp_timestamps)); + } + + scoped_ptr send_test_; + scoped_ptr audio_source_; + uint32_t frame_size_rtp_timestamps_; + int packet_count_; + uint8_t payload_type_; + uint16_t last_sequence_number_; + uint32_t last_timestamp_; + rtc::Md5Digest payload_checksum_; +}; + +TEST_F(AcmSenderBitExactnessOldApi, IsacWb30ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "c7e5bdadfa2871df95639fcc297cf23d", + "0499ca260390769b3172136faad925b9", + "0b58f9eeee43d5891f5f6c75e77984a3"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "d42cb5195463da26c8129bbfe73a22e6", + "83de248aea9c3c2bd680b6952401b4ca", + "3c79f16f34218271f3dca4e2b1dfe1bb"), + 33, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "14d63c5f08127d280e722e3191b73bdd", + "8da003e16c5371af2dc2be79a50f9076", + "1ad29139a04782a33daad8c2b9b35875"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "ebe04a819d3a9d83a83a17f271e1139a", + "97aeef98553b5a4b5a68f8b716e8eaf0", + "9e0a0ab743ad987b55b8e14802769c56"), + 16, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, DISABLED_ON_ANDROID(IsacSwb30ms)) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 32000, 1, 104, 960, 960)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "98d960600eb4ddb3fcbe11f5057ddfd7", + "", + "2f6dfe142f735f1d96f6bd86d2526f42"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "cc9d2d86a71d6f99f97680a5c27e2762", + "", + "7b214fc3a5e33d68bf30e77969371f31"), + 33, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80)); + Run("de4a98e1406f8b798d99cd0704e862e2", + "c1edd36339ce0326cc4550041ad719a0", + 100, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160)); + Run("ae646d7b68384a1269cc080dd4501916", + "ad786526383178b08d80d6eee06e9bad", + 100, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320)); + Run("7fe325e8fbaf755e3c5df0b11a4774fb", + "5ef82ea885e922263606c6fdbc49f651", + 100, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80)); + Run("fb263b74e7ac3de915474d77e4744ceb", + "62ce5adb0d4965d0a52ec98ae7f98974", + 100, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160)); + Run("d09e9239553649d7ac93e19d304281fd", + "41ca8edac4b8c71cd54fd9f25ec14870", + 100, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320)); + Run("5f025d4f390982cc26b3d92fe02e3044", + "50e58502fb04421bf5b857dda4c96879", + 100, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcmu_20ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 1, 0, 160, 160)); + Run("81a9d4c0bb72e9becc43aef124c981e9", + "8f9b8750bd80fe26b6cbf6659b89f0f9", + 50, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcma_20ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 1, 8, 160, 160)); + Run("39611f798969053925a49dc06d08de29", + "6ad745e55aa48981bfc790d0eeef2dd1", + 50, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcmu_stereo_20ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 2, 110, 160, 160)); + Run("437bec032fdc5cbaa0d5175430af7b18", + "60b6f25e8d1e74cb679cfe756dd9bca5", + 50, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Pcma_stereo_20ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 2, 118, 160, 160)); + Run("a5c6d83c5b7cedbeff734238220a4b0c", + "92b282c83efd20e7eeef52ba40842cf7", + 50, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, DISABLED_ON_ANDROID(Ilbc_30ms)) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("ILBC", 8000, 1, 102, 240, 240)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "7b6ec10910debd9af08011d3ed5249f7", + "android_audio", + "7b6ec10910debd9af08011d3ed5249f7"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "cfae2e9f6aba96e145f2bcdd5050ce78", + "android_payload", + "cfae2e9f6aba96e145f2bcdd5050ce78"), + 33, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, DISABLED_ON_ANDROID(G722_20ms)) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 1, 9, 320, 160)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "7d759436f2533582950d148b5161a36c", + "android_audio", + "7d759436f2533582950d148b5161a36c"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "fc68a87e1380614e658087cb35d5ca10", + "android_payload", + "fc68a87e1380614e658087cb35d5ca10"), + 50, + test::AcmReceiveTestOldApi::kMonoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, DISABLED_ON_ANDROID(G722_stereo_20ms)) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 2, 119, 320, 160)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "7190ee718ab3d80eca181e5f7140c210", + "android_audio", + "7190ee718ab3d80eca181e5f7140c210"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "66516152eeaa1e650ad94ff85f668dac", + "android_payload", + "66516152eeaa1e650ad94ff85f668dac"), + 50, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) { + ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960)); + Run(AcmReceiverBitExactnessOldApi::PlatformChecksum( + "855041f2490b887302bce9d544731849", + "1e1a0fce893fef2d66886a7f09e2ebce", + "855041f2490b887302bce9d544731849"), + AcmReceiverBitExactnessOldApi::PlatformChecksum( + "d781cce1ab986b618d0da87226cdde30", + "1a1fe04dd12e755949987c8d729fb3e0", + "d781cce1ab986b618d0da87226cdde30"), + 50, + test::AcmReceiveTestOldApi::kStereoOutput); +} + +} // namespace webrtc diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index 1025d0182..777523aba 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -106,6 +106,7 @@ 'audio_coding/main/acm2/acm_receiver_unittest.cc', 'audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc', 'audio_coding/main/acm2/audio_coding_module_unittest.cc', + 'audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc', 'audio_coding/main/acm2/call_statistics_unittest.cc', 'audio_coding/main/acm2/initial_delay_manager_unittest.cc', 'audio_coding/main/acm2/nack_unittest.cc',