diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 34df39f492..fc5a80354d 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -1343,6 +1343,8 @@ if (rtc_include_tests) { "test/opus_test.cc", "test/opus_test.h", "test/target_delay_unittest.cc", + "test/utility.cc", + "test/utility.h", ] deps = [ ":audio_coding", diff --git a/modules/audio_coding/test/Channel.cc b/modules/audio_coding/test/Channel.cc index 8cb5baa7d1..bb970c1d65 100644 --- a/modules/audio_coding/test/Channel.cc +++ b/modules/audio_coding/test/Channel.cc @@ -287,6 +287,113 @@ void Channel::ResetStats() { _channelCritSect.Leave(); } +int16_t Channel::Stats(CodecInst& codecInst, + ACMTestPayloadStats& payloadStats) { + _channelCritSect.Enter(); + int n; + payloadStats.payloadType = -1; + for (n = 0; n < MAX_NUM_PAYLOADS; n++) { + if (_payloadStats[n].payloadType == codecInst.pltype) { + memcpy(&payloadStats, &_payloadStats[n], sizeof(ACMTestPayloadStats)); + break; + } + } + if (payloadStats.payloadType == -1) { + _channelCritSect.Leave(); + return -1; + } + for (n = 0; n < MAX_NUM_FRAMESIZES; n++) { + if (payloadStats.frameSizeStats[n].frameSizeSample == 0) { + _channelCritSect.Leave(); + return 0; + } + payloadStats.frameSizeStats[n].usageLenSec = + (double)payloadStats.frameSizeStats[n].totalEncodedSamples / + (double)codecInst.plfreq; + + payloadStats.frameSizeStats[n].rateBitPerSec = + payloadStats.frameSizeStats[n].totalPayloadLenByte * 8 / + payloadStats.frameSizeStats[n].usageLenSec; + } + _channelCritSect.Leave(); + return 0; +} + +void Channel::Stats(uint32_t* numPackets) { + _channelCritSect.Enter(); + int k; + int n; + memset(numPackets, 0, MAX_NUM_PAYLOADS * sizeof(uint32_t)); + for (k = 0; k < MAX_NUM_PAYLOADS; k++) { + if (_payloadStats[k].payloadType == -1) { + break; + } + numPackets[k] = 0; + for (n = 0; n < MAX_NUM_FRAMESIZES; n++) { + if (_payloadStats[k].frameSizeStats[n].frameSizeSample == 0) { + break; + } + numPackets[k] += _payloadStats[k].frameSizeStats[n].numPackets; + } + } + _channelCritSect.Leave(); +} + +void Channel::Stats(uint8_t* payloadType, uint32_t* payloadLenByte) { + _channelCritSect.Enter(); + + int k; + int n; + memset(payloadLenByte, 0, MAX_NUM_PAYLOADS * sizeof(uint32_t)); + for (k = 0; k < MAX_NUM_PAYLOADS; k++) { + if (_payloadStats[k].payloadType == -1) { + break; + } + payloadType[k] = (uint8_t)_payloadStats[k].payloadType; + payloadLenByte[k] = 0; + for (n = 0; n < MAX_NUM_FRAMESIZES; n++) { + if (_payloadStats[k].frameSizeStats[n].frameSizeSample == 0) { + break; + } + payloadLenByte[k] += + (uint16_t)_payloadStats[k].frameSizeStats[n].totalPayloadLenByte; + } + } + + _channelCritSect.Leave(); +} + +void Channel::PrintStats(CodecInst& codecInst) { + ACMTestPayloadStats payloadStats; + Stats(codecInst, payloadStats); + printf("%s %d kHz\n", codecInst.plname, codecInst.plfreq / 1000); + printf("=====================================================\n"); + if (payloadStats.payloadType == -1) { + printf("No Packets are sent with payload-type %d (%s)\n\n", + codecInst.pltype, codecInst.plname); + return; + } + for (int k = 0; k < MAX_NUM_FRAMESIZES; k++) { + if (payloadStats.frameSizeStats[k].frameSizeSample == 0) { + break; + } + printf("Frame-size.................... %d samples\n", + payloadStats.frameSizeStats[k].frameSizeSample); + printf("Average Rate.................. %.0f bits/sec\n", + payloadStats.frameSizeStats[k].rateBitPerSec); + printf("Maximum Payload-Size.......... %" PRIuS " Bytes\n", + payloadStats.frameSizeStats[k].maxPayloadLen); + printf("Maximum Instantaneous Rate.... %.0f bits/sec\n", + ((double)payloadStats.frameSizeStats[k].maxPayloadLen * 8.0 * + (double)codecInst.plfreq) / + (double)payloadStats.frameSizeStats[k].frameSizeSample); + printf("Number of Packets............. %u\n", + (unsigned int)payloadStats.frameSizeStats[k].numPackets); + printf("Duration...................... %0.3f sec\n\n", + payloadStats.frameSizeStats[k].usageLenSec); + } +} + uint32_t Channel::LastInTimestamp() { uint32_t timestamp; _channelCritSect.Enter(); diff --git a/modules/audio_coding/test/Channel.h b/modules/audio_coding/test/Channel.h index eb197c6d1d..fd161fb139 100644 --- a/modules/audio_coding/test/Channel.h +++ b/modules/audio_coding/test/Channel.h @@ -58,6 +58,14 @@ class Channel : public AudioPacketizationCallback { void ResetStats(); + int16_t Stats(CodecInst& codecInst, ACMTestPayloadStats& payloadStats); + + void Stats(uint32_t* numPackets); + + void Stats(uint8_t* payloadType, uint32_t* payloadLenByte); + + void PrintStats(CodecInst& codecInst); + void SetIsStereo(bool isStereo) { _isStereo = isStereo; } uint32_t LastInTimestamp(); diff --git a/modules/audio_coding/test/EncodeDecodeTest.cc b/modules/audio_coding/test/EncodeDecodeTest.cc index 70319c03df..240836688c 100644 --- a/modules/audio_coding/test/EncodeDecodeTest.cc +++ b/modules/audio_coding/test/EncodeDecodeTest.cc @@ -14,9 +14,12 @@ #include #include +#include "absl/strings/match.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "modules/audio_coding/codecs/audio_format_conversion.h" #include "modules/audio_coding/include/audio_coding_module.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/strings/string_builder.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -50,12 +53,14 @@ Sender::Sender() } void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream, - std::string in_file_name, int in_sample_rate, - int payload_type, SdpAudioFormat format) { + std::string in_file_name, int sample_rate, size_t channels) { + struct CodecInst sendCodec; + int codecNo; + // Open input file const std::string file_name = webrtc::test::ResourcePath(in_file_name, "pcm"); - _pcmFile.Open(file_name, in_sample_rate, "rb"); - if (format.num_channels == 2) { + _pcmFile.Open(file_name, sample_rate, "rb"); + if (channels == 2) { _pcmFile.ReadStereo(true); } // Set test length to 500 ms (50 blocks of 10 ms each). @@ -63,9 +68,16 @@ void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream, // Fast-forward 1 second (100 blocks) since the file starts with silence. _pcmFile.FastForward(100); + // Set the codec for the current test. + codecNo = codeId; + + EXPECT_EQ(0, acm->Codec(codecNo, &sendCodec)); + + sendCodec.channels = channels; + acm->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder( - payload_type, format, absl::nullopt)); - _packetization = new TestPacketization(rtpStream, format.clockrate_hz); + sendCodec.pltype, CodecInstToSdp(sendCodec), absl::nullopt)); + _packetization = new TestPacketization(rtpStream, sendCodec.plfreq); EXPECT_EQ(0, acm->RegisterTransportCallback(_packetization)); _acm = acm; @@ -100,39 +112,30 @@ Receiver::Receiver() } void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream, - std::string out_file_name, size_t channels, int file_num) { + std::string out_file_name, size_t channels) { + struct CodecInst recvCodec = CodecInst(); + int noOfCodecs; EXPECT_EQ(0, acm->InitializeReceiver()); - if (channels == 1) { - acm->SetReceiveCodecs({{103, {"ISAC", 16000, 1}}, - {104, {"ISAC", 32000, 1}}, - {107, {"L16", 8000, 1}}, - {108, {"L16", 16000, 1}}, - {109, {"L16", 32000, 1}}, - {0, {"PCMU", 8000, 1}}, - {8, {"PCMA", 8000, 1}}, - {102, {"ILBC", 8000, 1}}, - {9, {"G722", 8000, 1}}, - {120, {"OPUS", 48000, 2}}, - {13, {"CN", 8000, 1}}, - {98, {"CN", 16000, 1}}, - {99, {"CN", 32000, 1}}}); - } else { - ASSERT_EQ(channels, 2u); - acm->SetReceiveCodecs({{111, {"L16", 8000, 2}}, - {112, {"L16", 16000, 2}}, - {113, {"L16", 32000, 2}}, - {110, {"PCMU", 8000, 2}}, - {118, {"PCMA", 8000, 2}}, - {119, {"G722", 8000, 2}}, - {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}}); + noOfCodecs = acm->NumberOfCodecs(); + for (int i = 0; i < noOfCodecs; i++) { + EXPECT_EQ(0, acm->Codec(i, &recvCodec)); + if (recvCodec.channels == channels) + EXPECT_EQ(true, acm->RegisterReceiveCodec(recvCodec.pltype, + CodecInstToSdp(recvCodec))); + // Forces mono/stereo for Opus. + if (!strcmp(recvCodec.plname, "opus")) { + recvCodec.channels = channels; + EXPECT_EQ(true, acm->RegisterReceiveCodec(recvCodec.pltype, + CodecInstToSdp(recvCodec))); + } } int playSampFreq; std::string file_name; rtc::StringBuilder file_stream; - file_stream << webrtc::test::OutputPath() << out_file_name << file_num - << ".pcm"; + file_stream << webrtc::test::OutputPath() << out_file_name + << static_cast(codeId) << ".pcm"; file_name = file_stream.str(); _rtpStream = rtpStream; @@ -222,45 +225,85 @@ void Receiver::Run() { } } -EncodeDecodeTest::EncodeDecodeTest() = default; +EncodeDecodeTest::EncodeDecodeTest(int test_mode) { + // There used to be different test modes. The only one still supported is the + // "autotest" mode. + RTC_CHECK_EQ(0, test_mode); +} void EncodeDecodeTest::Perform() { - const std::map send_codecs = {{103, {"ISAC", 16000, 1}}, - {104, {"ISAC", 32000, 1}}, - {107, {"L16", 8000, 1}}, - {108, {"L16", 16000, 1}}, - {109, {"L16", 32000, 1}}, - {0, {"PCMU", 8000, 1}}, - {8, {"PCMA", 8000, 1}}, - {102, {"ILBC", 8000, 1}}, - {9, {"G722", 8000, 1}}}; - int file_num = 0; - for (const auto& send_codec : send_codecs) { - RTPFile rtpFile; - std::unique_ptr acm(AudioCodingModule::Create( - AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))); + int numCodecs = 1; + int codePars[3]; // Frequency, packet size, rate. + int numPars[52]; // Number of codec parameters sets (freq, pacsize, rate) + // to test, for a given codec. - std::string fileName = webrtc::test::TempFilename( - webrtc::test::OutputPath(), "encode_decode_rtp"); - rtpFile.Open(fileName.c_str(), "wb+"); - rtpFile.WriteHeader(); - Sender sender; - sender.Setup(acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000, - send_codec.first, send_codec.second); - sender.Run(); - sender.Teardown(); - rtpFile.Close(); + codePars[0] = 0; + codePars[1] = 0; + codePars[2] = 0; - rtpFile.Open(fileName.c_str(), "rb"); - rtpFile.ReadHeader(); - Receiver receiver; - receiver.Setup(acm.get(), &rtpFile, "encodeDecode_out", 1, file_num); - receiver.Run(); - receiver.Teardown(); - rtpFile.Close(); + std::unique_ptr acm(AudioCodingModule::Create( + AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))); + struct CodecInst sendCodecTmp; + numCodecs = acm->NumberOfCodecs(); - file_num++; + for (int n = 0; n < numCodecs; n++) { + EXPECT_EQ(0, acm->Codec(n, &sendCodecTmp)); + if (absl::EqualsIgnoreCase(sendCodecTmp.plname, "telephone-event")) { + numPars[n] = 0; + } else if (absl::EqualsIgnoreCase(sendCodecTmp.plname, "cn")) { + numPars[n] = 0; + } else if (absl::EqualsIgnoreCase(sendCodecTmp.plname, "red")) { + numPars[n] = 0; + } else if (sendCodecTmp.channels == 2) { + numPars[n] = 0; + } else { + numPars[n] = 1; + } + } + + // Loop over all mono codecs: + for (int codeId = 0; codeId < numCodecs; codeId++) { + // Only encode using real mono encoders, not telephone-event and cng. + for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) { + // Encode all data to file. + std::string fileName = EncodeToFile(1, codeId, codePars); + + RTPFile rtpFile; + rtpFile.Open(fileName.c_str(), "rb"); + + _receiver.codeId = codeId; + + rtpFile.ReadHeader(); + _receiver.Setup(acm.get(), &rtpFile, "encodeDecode_out", 1); + _receiver.Run(); + _receiver.Teardown(); + rtpFile.Close(); + } } } +std::string EncodeDecodeTest::EncodeToFile(int fileType, + int codeId, + int* codePars) { + std::unique_ptr acm(AudioCodingModule::Create( + AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))); + RTPFile rtpFile; + std::string fileName = webrtc::test::TempFilename(webrtc::test::OutputPath(), + "encode_decode_rtp"); + rtpFile.Open(fileName.c_str(), "wb+"); + rtpFile.WriteHeader(); + + // Store for auto_test and logging. + _sender.codeId = codeId; + + _sender.Setup(acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000, 1); + if (acm->SendCodec()) { + _sender.Run(); + } + _sender.Teardown(); + rtpFile.Close(); + + return fileName; +} + } // namespace webrtc diff --git a/modules/audio_coding/test/EncodeDecodeTest.h b/modules/audio_coding/test/EncodeDecodeTest.h index df6ee5ffe1..9132d717e2 100644 --- a/modules/audio_coding/test/EncodeDecodeTest.h +++ b/modules/audio_coding/test/EncodeDecodeTest.h @@ -47,12 +47,13 @@ class Sender { public: Sender(); void Setup(AudioCodingModule *acm, RTPStream *rtpStream, - std::string in_file_name, int in_sample_rate, - int payload_type, SdpAudioFormat format); + std::string in_file_name, int sample_rate, size_t channels); void Teardown(); void Run(); bool Add10MsData(); + uint8_t codeId; + protected: AudioCodingModule* _acm; @@ -67,12 +68,15 @@ class Receiver { Receiver(); virtual ~Receiver() {}; void Setup(AudioCodingModule *acm, RTPStream *rtpStream, - std::string out_file_name, size_t channels, int file_num); + std::string out_file_name, size_t channels); void Teardown(); void Run(); virtual bool IncomingPacket(); bool PlayoutData(); + //for auto_test and logging + uint8_t codeId; + private: PCMFile _pcmFile; int16_t* _playoutBuffer; @@ -92,8 +96,17 @@ class Receiver { class EncodeDecodeTest { public: - EncodeDecodeTest(); + explicit EncodeDecodeTest(int test_mode); void Perform(); + + uint16_t _playoutFreq; + + private: + std::string EncodeToFile(int fileType, int codeId, int* codePars); + + protected: + Sender _sender; + Receiver _receiver; }; } // namespace webrtc diff --git a/modules/audio_coding/test/PacketLossTest.cc b/modules/audio_coding/test/PacketLossTest.cc index 6f876590d6..a1629fd006 100644 --- a/modules/audio_coding/test/PacketLossTest.cc +++ b/modules/audio_coding/test/PacketLossTest.cc @@ -30,7 +30,6 @@ void ReceiverWithPacketLoss::Setup(AudioCodingModule* acm, RTPStream* rtpStream, std::string out_file_name, int channels, - int file_num, int loss_rate, int burst_length) { loss_rate_ = loss_rate; @@ -38,7 +37,7 @@ void ReceiverWithPacketLoss::Setup(AudioCodingModule* acm, burst_lost_counter_ = burst_length_; // To prevent first packet gets lost. rtc::StringBuilder ss; ss << out_file_name << "_" << loss_rate_ << "_" << burst_length_ << "_"; - Receiver::Setup(acm, rtpStream, ss.str(), channels, file_num); + Receiver::Setup(acm, rtpStream, ss.str(), channels); } bool ReceiverWithPacketLoss::IncomingPacket() { @@ -90,11 +89,10 @@ SenderWithFEC::SenderWithFEC() : expected_loss_rate_(0) {} void SenderWithFEC::Setup(AudioCodingModule* acm, RTPStream* rtpStream, std::string in_file_name, - int payload_type, - SdpAudioFormat format, + int sample_rate, + int channels, int expected_loss_rate) { - Sender::Setup(acm, rtpStream, in_file_name, format.clockrate_hz, payload_type, - format); + Sender::Setup(acm, rtpStream, in_file_name, sample_rate, channels); EXPECT_TRUE(SetFEC(true)); EXPECT_TRUE(SetPacketLossRate(expected_loss_rate)); } @@ -125,6 +123,8 @@ PacketLossTest::PacketLossTest(int channels, in_file_name_(channels_ == 1 ? "audio_coding/testfile32kHz" : "audio_coding/teststereo32kHz"), sample_rate_hz_(32000), + sender_(new SenderWithFEC), + receiver_(new ReceiverWithPacketLoss), expected_loss_rate_(expected_loss_rate), actual_loss_rate_(actual_loss_rate), burst_length_(burst_length) {} @@ -133,32 +133,40 @@ void PacketLossTest::Perform() { #ifndef WEBRTC_CODEC_OPUS return; #else - RTPFile rtpFile; - std::unique_ptr acm(AudioCodingModule::Create( - AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))); - SdpAudioFormat send_format = SdpAudioFormat("opus", 48000, 2); - if (channels_ == 2) { - send_format.parameters = {{"stereo", "1"}}; - } + AudioCodingModule::Config config; + config.decoder_factory = CreateBuiltinAudioDecoderFactory(); + std::unique_ptr acm(AudioCodingModule::Create(config)); + int codec_id = acm->Codec("opus", 48000, channels_); + + RTPFile rtpFile; std::string fileName = webrtc::test::TempFilename(webrtc::test::OutputPath(), "packet_loss_test"); + + // Encode to file rtpFile.Open(fileName.c_str(), "wb+"); rtpFile.WriteHeader(); - SenderWithFEC sender; - sender.Setup(acm.get(), &rtpFile, in_file_name_, 120, send_format, + + sender_->codeId = codec_id; + + sender_->Setup(acm.get(), &rtpFile, in_file_name_, sample_rate_hz_, channels_, expected_loss_rate_); - sender.Run(); - sender.Teardown(); + if (acm->SendCodec()) { + sender_->Run(); + } + sender_->Teardown(); rtpFile.Close(); + // Decode to file rtpFile.Open(fileName.c_str(), "rb"); rtpFile.ReadHeader(); - ReceiverWithPacketLoss receiver; - receiver.Setup(acm.get(), &rtpFile, "packetLoss_out", channels_, 15, + + receiver_->codeId = codec_id; + + receiver_->Setup(acm.get(), &rtpFile, "packetLoss_out", channels_, actual_loss_rate_, burst_length_); - receiver.Run(); - receiver.Teardown(); + receiver_->Run(); + receiver_->Teardown(); rtpFile.Close(); #endif } diff --git a/modules/audio_coding/test/PacketLossTest.h b/modules/audio_coding/test/PacketLossTest.h index b26f6ec4ba..6018301dff 100644 --- a/modules/audio_coding/test/PacketLossTest.h +++ b/modules/audio_coding/test/PacketLossTest.h @@ -11,6 +11,7 @@ #ifndef MODULES_AUDIO_CODING_TEST_PACKETLOSSTEST_H_ #define MODULES_AUDIO_CODING_TEST_PACKETLOSSTEST_H_ +#include #include #include "modules/audio_coding/test/EncodeDecodeTest.h" @@ -23,7 +24,6 @@ class ReceiverWithPacketLoss : public Receiver { RTPStream* rtpStream, std::string out_file_name, int channels, - int file_num, int loss_rate, int burst_length); bool IncomingPacket() override; @@ -43,8 +43,8 @@ class SenderWithFEC : public Sender { void Setup(AudioCodingModule* acm, RTPStream* rtpStream, std::string in_file_name, - int payload_type, - SdpAudioFormat format, + int sample_rate, + int channels, int expected_loss_rate); bool SetPacketLossRate(int expected_loss_rate); bool SetFEC(bool enable_fec); @@ -65,6 +65,8 @@ class PacketLossTest { int channels_; std::string in_file_name_; int sample_rate_hz_; + std::unique_ptr sender_; + std::unique_ptr receiver_; int expected_loss_rate_; int actual_loss_rate_; int burst_length_; diff --git a/modules/audio_coding/test/TestAllCodecs.cc b/modules/audio_coding/test/TestAllCodecs.cc index aad80e8ca6..0099b2a9de 100644 --- a/modules/audio_coding/test/TestAllCodecs.cc +++ b/modules/audio_coding/test/TestAllCodecs.cc @@ -14,11 +14,13 @@ #include #include -#include "absl/strings/match.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "common_types.h" // NOLINT(build/include) +#include "modules/audio_coding/codecs/audio_format_conversion.h" +#include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_coding/include/audio_coding_module_typedefs.h" -#include "modules/include/module_common_types.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/logging.h" #include "rtc_base/stringencode.h" #include "rtc_base/strings/string_builder.h" @@ -33,11 +35,6 @@ // The test loops through all available mono codecs, encode at "a" sends over // the channel, and decodes at "b". -#define CHECK_ERROR(f) \ - do { \ - EXPECT_GE(f, 0) << "Error Calling API"; \ - } while (0) - namespace { const size_t kVariableSize = std::numeric_limits::max(); } @@ -104,7 +101,7 @@ void TestPack::reset_payload_size() { payload_size_ = 0; } -TestAllCodecs::TestAllCodecs() +TestAllCodecs::TestAllCodecs(int test_mode) : acm_a_(AudioCodingModule::Create( AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))), acm_b_(AudioCodingModule::Create( @@ -113,6 +110,8 @@ TestAllCodecs::TestAllCodecs() test_count_(0), packet_size_samples_(0), packet_size_bytes_(0) { + // test_mode = 0 for silent test (auto test) + test_mode_ = test_mode; } TestAllCodecs::~TestAllCodecs() { @@ -127,28 +126,23 @@ void TestAllCodecs::Perform() { webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); infile_a_.Open(file_name, 32000, "rb"); + if (test_mode_ == 0) { + RTC_LOG(LS_INFO) << "---------- TestAllCodecs ----------"; + } + acm_a_->InitializeReceiver(); acm_b_->InitializeReceiver(); - acm_b_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}}, - {104, {"ISAC", 32000, 1}}, - {107, {"L16", 8000, 1}}, - {108, {"L16", 16000, 1}}, - {109, {"L16", 32000, 1}}, - {111, {"L16", 8000, 2}}, - {112, {"L16", 16000, 2}}, - {113, {"L16", 32000, 2}}, - {0, {"PCMU", 8000, 1}}, - {110, {"PCMU", 8000, 2}}, - {8, {"PCMA", 8000, 1}}, - {118, {"PCMA", 8000, 2}}, - {102, {"ILBC", 8000, 1}}, - {9, {"G722", 8000, 1}}, - {119, {"G722", 8000, 2}}, - {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}, - {13, {"CN", 8000, 1}}, - {98, {"CN", 16000, 1}}, - {99, {"CN", 32000, 1}}}); + uint8_t num_encoders = acm_a_->NumberOfCodecs(); + CodecInst my_codec_param; + for (uint8_t n = 0; n < num_encoders; n++) { + acm_b_->Codec(n, &my_codec_param); + if (!strcmp(my_codec_param.plname, "opus")) { + my_codec_param.channels = 1; + } + acm_b_->RegisterReceiveCodec(my_codec_param.pltype, + CodecInstToSdp(my_codec_param)); + } // Create and connect the channel channel_a_to_b_ = new TestPack; @@ -157,6 +151,9 @@ void TestAllCodecs::Perform() { // All codecs are tested for all allowed sampling frequencies, rates and // packet sizes. + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_g722[] = "G722"; @@ -174,6 +171,9 @@ void TestAllCodecs::Perform() { Run(channel_a_to_b_); outfile_b_.Close(); #ifdef WEBRTC_CODEC_ILBC + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_ilbc[] = "ILBC"; @@ -188,6 +188,9 @@ void TestAllCodecs::Perform() { outfile_b_.Close(); #endif #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_isac[] = "ISAC"; @@ -202,6 +205,9 @@ void TestAllCodecs::Perform() { outfile_b_.Close(); #endif #ifdef WEBRTC_CODEC_ISAC + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); RegisterSendCodec('A', codec_isac, 32000, -1, 960, kVariableSize); @@ -214,6 +220,9 @@ void TestAllCodecs::Perform() { Run(channel_a_to_b_); outfile_b_.Close(); #endif + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_l16[] = "L16"; @@ -226,7 +235,9 @@ void TestAllCodecs::Perform() { RegisterSendCodec('A', codec_l16, 8000, 128000, 320, 0); Run(channel_a_to_b_); outfile_b_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); RegisterSendCodec('A', codec_l16, 16000, 256000, 160, 0); @@ -238,7 +249,9 @@ void TestAllCodecs::Perform() { RegisterSendCodec('A', codec_l16, 16000, 256000, 640, 0); Run(channel_a_to_b_); outfile_b_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); RegisterSendCodec('A', codec_l16, 32000, 512000, 320, 0); @@ -246,7 +259,9 @@ void TestAllCodecs::Perform() { RegisterSendCodec('A', codec_l16, 32000, 512000, 640, 0); Run(channel_a_to_b_); outfile_b_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_pcma[] = "PCMA"; @@ -262,7 +277,9 @@ void TestAllCodecs::Perform() { Run(channel_a_to_b_); RegisterSendCodec('A', codec_pcma, 8000, 64000, 480, 0); Run(channel_a_to_b_); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + } char codec_pcmu[] = "PCMU"; RegisterSendCodec('A', codec_pcmu, 8000, 64000, 80, 0); Run(channel_a_to_b_); @@ -278,6 +295,9 @@ void TestAllCodecs::Perform() { Run(channel_a_to_b_); outfile_b_.Close(); #ifdef WEBRTC_CODEC_OPUS + if (test_mode_ != 0) { + printf("===============================================================\n"); + } test_count_++; OpenOutFile(test_count_); char codec_opus[] = "OPUS"; @@ -297,6 +317,24 @@ void TestAllCodecs::Perform() { Run(channel_a_to_b_); outfile_b_.Close(); #endif + if (test_mode_ != 0) { + printf("===============================================================\n"); + + /* Print out all codecs that were not tested in the run */ + printf("The following codecs was not included in the test:\n"); +#ifndef WEBRTC_CODEC_ILBC + printf(" iLBC\n"); +#endif +#ifndef WEBRTC_CODEC_ISAC + printf(" ISAC float\n"); +#endif +#ifndef WEBRTC_CODEC_ISACFX + printf(" ISAC fix\n"); +#endif + + printf("\nTo complete the test, listen to the %d number of output files.\n", + test_count_); + } } // Register Codec to use in the test @@ -316,21 +354,21 @@ void TestAllCodecs::RegisterSendCodec(char side, int rate, int packet_size, size_t extra_byte) { + if (test_mode_ != 0) { + // Print out codec and settings. + printf("codec: %s Freq: %d Rate: %d PackSize: %d\n", codec_name, + sampling_freq_hz, rate, packet_size); + } + // Store packet-size in samples, used to validate the received packet. // If G.722, store half the size to compensate for the timestamp bug in the // RFC for G.722. // If iSAC runs in adaptive mode, packet size in samples can change on the // fly, so we exclude this test by setting |packet_size_samples_| to -1. - int clockrate_hz = sampling_freq_hz; - size_t num_channels = 1; - if (absl::EqualsIgnoreCase(codec_name, "G722")) { + if (!strcmp(codec_name, "G722")) { packet_size_samples_ = packet_size / 2; - clockrate_hz = sampling_freq_hz / 2; - } else if (absl::EqualsIgnoreCase(codec_name, "ISAC") && (rate == -1)) { + } else if (!strcmp(codec_name, "ISAC") && (rate == -1)) { packet_size_samples_ = -1; - } else if (absl::EqualsIgnoreCase(codec_name, "OPUS")) { - packet_size_samples_ = packet_size; - num_channels = 2; } else { packet_size_samples_ = packet_size; } @@ -364,9 +402,16 @@ void TestAllCodecs::RegisterSendCodec(char side, } ASSERT_TRUE(my_acm != NULL); + // Get all codec parameters before registering + CodecInst my_codec_param; + CHECK_ERROR(AudioCodingModule::Codec(codec_name, &my_codec_param, + sampling_freq_hz, 1)); + my_codec_param.rate = rate; + my_codec_param.pacsize = packet_size; + auto factory = CreateBuiltinAudioEncoderFactory(); constexpr int payload_type = 17; - SdpAudioFormat format = { codec_name, clockrate_hz, num_channels }; + SdpAudioFormat format = CodecInstToSdp(my_codec_param); format.parameters["ptime"] = rtc::ToString(rtc::CheckedDivExact( packet_size, rtc::CheckedDivExact(sampling_freq_hz, 1000))); my_acm->SetEncoder( @@ -440,4 +485,11 @@ void TestAllCodecs::OpenOutFile(int test_number) { outfile_b_.Open(filename, 32000, "wb"); } +void TestAllCodecs::DisplaySendReceiveCodec() { + CodecInst my_codec_param; + printf("%s -> ", acm_a_->SendCodec()->plname); + acm_b_->ReceiveCodec(&my_codec_param); + printf("%s\n", my_codec_param.plname); +} + } // namespace webrtc diff --git a/modules/audio_coding/test/TestAllCodecs.h b/modules/audio_coding/test/TestAllCodecs.h index 3125efeb0b..669a118f47 100644 --- a/modules/audio_coding/test/TestAllCodecs.h +++ b/modules/audio_coding/test/TestAllCodecs.h @@ -13,7 +13,7 @@ #include -#include "modules/audio_coding/include/audio_coding_module.h" +#include "modules/audio_coding/test/Channel.h" #include "modules/audio_coding/test/PCMFile.h" namespace webrtc { @@ -48,7 +48,7 @@ class TestPack : public AudioPacketizationCallback { class TestAllCodecs { public: - TestAllCodecs(); + explicit TestAllCodecs(int test_mode); ~TestAllCodecs(); void Perform(); @@ -67,7 +67,9 @@ class TestAllCodecs { void Run(TestPack* channel); void OpenOutFile(int test_number); + void DisplaySendReceiveCodec(); + int test_mode_; std::unique_ptr acm_a_; std::unique_ptr acm_b_; TestPack* channel_a_to_b_; diff --git a/modules/audio_coding/test/TestRedFec.cc b/modules/audio_coding/test/TestRedFec.cc index ac516663b0..8bb3971373 100644 --- a/modules/audio_coding/test/TestRedFec.cc +++ b/modules/audio_coding/test/TestRedFec.cc @@ -10,9 +10,8 @@ #include "modules/audio_coding/test/TestRedFec.h" -#include +#include -#include "absl/strings/match.h" #include "api/audio_codecs/L16/audio_decoder_L16.h" #include "api/audio_codecs/L16/audio_encoder_L16.h" #include "api/audio_codecs/audio_decoder_factory_template.h" @@ -25,11 +24,12 @@ #include "api/audio_codecs/isac/audio_encoder_isac_float.h" #include "api/audio_codecs/opus/audio_decoder_opus.h" #include "api/audio_codecs/opus/audio_encoder_opus.h" +#include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h" #include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h" #include "modules/audio_coding/include/audio_coding_module_typedefs.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/strings/string_builder.h" -#include "test/gtest.h" #include "test/testsupport/fileutils.h" namespace webrtc { @@ -173,7 +173,6 @@ void TestRedFec::RegisterSendCodec( auto encoder = encoder_factory_->MakeAudioEncoder(payload_type, codec_format, absl::nullopt); EXPECT_NE(encoder, nullptr); - std::map receive_codecs = {{payload_type, codec_format}}; if (!absl::EqualsIgnoreCase(codec_format.name, "opus")) { if (vad_mode.has_value()) { AudioEncoderCngConfig config; @@ -182,22 +181,22 @@ void TestRedFec::RegisterSendCodec( config.payload_type = cn_payload_type; config.vad_mode = vad_mode.value(); encoder = CreateComfortNoiseEncoder(std::move(config)); - receive_codecs.emplace( - std::make_pair(cn_payload_type, - SdpAudioFormat("CN", codec_format.clockrate_hz, 1))); + EXPECT_EQ(true, + other_acm->RegisterReceiveCodec( + cn_payload_type, {"CN", codec_format.clockrate_hz, 1})); } if (use_red) { AudioEncoderCopyRed::Config config; config.payload_type = red_payload_type; config.speech_encoder = std::move(encoder); encoder = absl::make_unique(std::move(config)); - receive_codecs.emplace( - std::make_pair(red_payload_type, - SdpAudioFormat("red", codec_format.clockrate_hz, 1))); + EXPECT_EQ(true, + other_acm->RegisterReceiveCodec( + red_payload_type, {"red", codec_format.clockrate_hz, 1})); } } acm->SetEncoder(std::move(encoder)); - other_acm->SetReceiveCodecs(receive_codecs); + EXPECT_EQ(true, other_acm->RegisterReceiveCodec(payload_type, codec_format)); } void TestRedFec::Run() { diff --git a/modules/audio_coding/test/TestStereo.cc b/modules/audio_coding/test/TestStereo.cc index dd4be6a524..bf8e1894d0 100644 --- a/modules/audio_coding/test/TestStereo.cc +++ b/modules/audio_coding/test/TestStereo.cc @@ -15,8 +15,9 @@ #include "absl/strings/match.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "modules/audio_coding/codecs/audio_format_conversion.h" #include "modules/audio_coding/include/audio_coding_module_typedefs.h" -#include "modules/include/module_common_types.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/strings/string_builder.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -31,6 +32,7 @@ TestPackStereo::TestPackStereo() last_in_timestamp_(0), total_bytes_(0), payload_size_(0), + codec_mode_(kNotSet), lost_packet_(false) {} TestPackStereo::~TestPackStereo() {} @@ -96,7 +98,7 @@ void TestPackStereo::set_lost_packet(bool lost) { lost_packet_ = lost; } -TestStereo::TestStereo() +TestStereo::TestStereo(int test_mode) : acm_a_(AudioCodingModule::Create( AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))), acm_b_(AudioCodingModule::Create( @@ -106,6 +108,8 @@ TestStereo::TestStereo() pack_size_samp_(0), pack_size_bytes_(0), counter_(0) { + // test_mode = 0 for silent test (auto test) + test_mode_ = test_mode; } TestStereo::~TestStereo() { @@ -138,25 +142,27 @@ void TestStereo::Perform() { EXPECT_EQ(0, acm_a_->InitializeReceiver()); EXPECT_EQ(0, acm_b_->InitializeReceiver()); - acm_b_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}}, - {104, {"ISAC", 32000, 1}}, - {107, {"L16", 8000, 1}}, - {108, {"L16", 16000, 1}}, - {109, {"L16", 32000, 1}}, - {111, {"L16", 8000, 2}}, - {112, {"L16", 16000, 2}}, - {113, {"L16", 32000, 2}}, - {0, {"PCMU", 8000, 1}}, - {110, {"PCMU", 8000, 2}}, - {8, {"PCMA", 8000, 1}}, - {118, {"PCMA", 8000, 2}}, - {102, {"ILBC", 8000, 1}}, - {9, {"G722", 8000, 1}}, - {119, {"G722", 8000, 2}}, - {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}, - {13, {"CN", 8000, 1}}, - {98, {"CN", 16000, 1}}, - {99, {"CN", 32000, 1}}}); + // Register all available codes as receiving codecs. + uint8_t num_encoders = acm_a_->NumberOfCodecs(); + CodecInst my_codec_param; + for (uint8_t n = 0; n < num_encoders; n++) { + EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param)); + EXPECT_EQ(true, acm_b_->RegisterReceiveCodec( + my_codec_param.pltype, CodecInstToSdp(my_codec_param))); + } + + // Test that unregister all receive codecs works. + for (uint8_t n = 0; n < num_encoders; n++) { + EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param)); + EXPECT_EQ(0, acm_b_->UnregisterReceiveCodec(my_codec_param.pltype)); + } + + // Register all available codes as receiving codecs once more. + for (uint8_t n = 0; n < num_encoders; n++) { + EXPECT_EQ(0, acm_b_->Codec(n, &my_codec_param)); + EXPECT_EQ(true, acm_b_->RegisterReceiveCodec( + my_codec_param.pltype, CodecInstToSdp(my_codec_param))); + } // Create and connect the channel. channel_a2b_ = new TestPackStereo; @@ -165,6 +171,9 @@ void TestStereo::Perform() { char codec_pcma_temp[] = "PCMA"; RegisterSendCodec('A', codec_pcma_temp, 8000, 64000, 80, 2); + if (test_mode_ != 0) { + printf("\n"); + } // // Test Stereo-To-Stereo for all codecs. @@ -174,6 +183,11 @@ void TestStereo::Perform() { // All codecs are tested for all allowed sampling frequencies, rates and // packet sizes. + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } channel_a2b_->set_codec_mode(kStereo); test_cntr_++; OpenOutFile(test_cntr_); @@ -192,6 +206,11 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } channel_a2b_->set_codec_mode(kStereo); test_cntr_++; OpenOutFile(test_cntr_); @@ -206,6 +225,11 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels); @@ -218,6 +242,11 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels); @@ -226,6 +255,11 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); #ifdef PCMA_AND_PCMU + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } channel_a2b_->set_codec_mode(kStereo); audio_channels = 2; codec_channels = 2; @@ -244,8 +278,13 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); RegisterSendCodec('A', codec_pcma, 8000, 64000, 480, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); - out_file_.Close(); + out_file_.Close(); + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } test_cntr_++; OpenOutFile(test_cntr_); char codec_pcmu[] = "PCMU"; @@ -264,6 +303,11 @@ void TestStereo::Perform() { out_file_.Close(); #endif #ifdef WEBRTC_CODEC_OPUS + if (test_mode_ != 0) { + printf("===========================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-stereo\n"); + } channel_a2b_->set_codec_mode(kStereo); audio_channels = 2; codec_channels = 2; @@ -296,6 +340,11 @@ void TestStereo::Perform() { audio_channels = 1; codec_channels = 2; + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } test_cntr_++; channel_a2b_->set_codec_mode(kStereo); OpenOutFile(test_cntr_); @@ -303,25 +352,43 @@ void TestStereo::Perform() { Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } test_cntr_++; channel_a2b_->set_codec_mode(kStereo); OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 8000, 128000, 80, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); #ifdef PCMA_AND_PCMU + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } test_cntr_++; channel_a2b_->set_codec_mode(kStereo); OpenOutFile(test_cntr_); @@ -332,6 +399,12 @@ void TestStereo::Perform() { out_file_.Close(); #endif #ifdef WEBRTC_CODEC_OPUS + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Mono-to-stereo\n"); + } + // Keep encode and decode in stereo. test_cntr_++; channel_a2b_->set_codec_mode(kStereo); @@ -353,30 +426,54 @@ void TestStereo::Perform() { channel_a2b_->set_codec_mode(kMono); // Run stereo audio and mono codec. + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_g722, 16000, 64000, 160, codec_channels); + Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 8000, 128000, 80, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); - + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 16000, 256000, 160, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); - + if (test_mode_ != 0) { + printf("==============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_l16, 32000, 512000, 320, codec_channels); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); #ifdef PCMA_AND_PCMU + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); RegisterSendCodec('A', codec_pcmu, 8000, 64000, 80, codec_channels); @@ -386,11 +483,26 @@ void TestStereo::Perform() { out_file_.Close(); #endif #ifdef WEBRTC_CODEC_OPUS + if (test_mode_ != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n", test_cntr_ + 1); + printf("Test type: Stereo-to-mono\n"); + } test_cntr_++; OpenOutFile(test_cntr_); // Encode and decode in mono. RegisterSendCodec('A', codec_opus, 48000, 32000, 960, codec_channels); - acm_b_->SetReceiveCodecs({{120, {"OPUS", 48000, 2}}}); + CodecInst opus_codec_param; + for (uint8_t n = 0; n < num_encoders; n++) { + EXPECT_EQ(0, acm_b_->Codec(n, &opus_codec_param)); + if (!strcmp(opus_codec_param.plname, "opus")) { + opus_codec_param.channels = 1; + EXPECT_EQ(true, + acm_b_->RegisterReceiveCodec(opus_codec_param.pltype, + CodecInstToSdp(opus_codec_param))); + break; + } + } Run(channel_a2b_, audio_channels, codec_channels); // Encode in stereo, decode in mono. @@ -404,22 +516,65 @@ void TestStereo::Perform() { // Decode in mono. test_cntr_++; OpenOutFile(test_cntr_); + if (test_mode_ != 0) { + // Print out codec and settings + printf( + "Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960" + " Decode: mono\n", + test_cntr_); + } Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); // Decode in stereo. test_cntr_++; OpenOutFile(test_cntr_); - acm_b_->SetReceiveCodecs({{120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}}); + if (test_mode_ != 0) { + // Print out codec and settings + printf( + "Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960" + " Decode: stereo\n", + test_cntr_); + } + opus_codec_param.channels = 2; + EXPECT_EQ(true, + acm_b_->RegisterReceiveCodec(opus_codec_param.pltype, + CodecInstToSdp(opus_codec_param))); Run(channel_a2b_, audio_channels, 2); out_file_.Close(); // Decode in mono. test_cntr_++; OpenOutFile(test_cntr_); - acm_b_->SetReceiveCodecs({{120, {"OPUS", 48000, 2}}}); + if (test_mode_ != 0) { + // Print out codec and settings + printf( + "Test number: %d\nCodec: Opus Freq: 48000 Rate :32000 PackSize: 960" + " Decode: mono\n", + test_cntr_); + } + opus_codec_param.channels = 1; + EXPECT_EQ(true, + acm_b_->RegisterReceiveCodec(opus_codec_param.pltype, + CodecInstToSdp(opus_codec_param))); Run(channel_a2b_, audio_channels, codec_channels); out_file_.Close(); + #endif + // Print out which codecs were tested, and which were not, in the run. + if (test_mode_ != 0) { + printf("\nThe following codecs was INCLUDED in the test:\n"); + printf(" G.722\n"); + printf(" PCM16\n"); + printf(" G.711\n"); +#ifdef WEBRTC_CODEC_OPUS + printf(" Opus\n"); +#endif + printf( + "\nTo complete the test, listen to the %d number of output " + "files.\n", + test_cntr_); + } + // Delete the file pointers. delete in_file_stereo_; delete in_file_mono_; @@ -439,6 +594,12 @@ void TestStereo::RegisterSendCodec(char side, int rate, int pack_size, int channels) { + if (test_mode_ != 0) { + // Print out codec and settings + printf("Codec: %s Freq: %d Rate: %d PackSize: %d\n", codec_name, + sampling_freq_hz, rate, pack_size); + } + // Store packet size in samples, used to validate the received packet pack_size_samp_ = pack_size; @@ -558,7 +719,7 @@ void TestStereo::Run(TestPackStereo* channel, } } - // Run receive side of ACM + // Run received side of ACM bool muted; EXPECT_EQ(0, acm_b_->PlayoutData10Ms(out_freq_hz_b, &audio_frame, &muted)); ASSERT_FALSE(muted); @@ -597,4 +758,17 @@ void TestStereo::OpenOutFile(int16_t test_number) { out_file_.Open(file_name, 32000, "wb"); } +void TestStereo::DisplaySendReceiveCodec() { + auto send_codec = acm_a_->SendCodec(); + if (test_mode_ != 0) { + ASSERT_TRUE(send_codec); + printf("%s -> ", send_codec->plname); + } + CodecInst receive_codec; + acm_b_->ReceiveCodec(&receive_codec); + if (test_mode_ != 0) { + printf("%s\n", receive_codec.plname); + } +} + } // namespace webrtc diff --git a/modules/audio_coding/test/TestStereo.h b/modules/audio_coding/test/TestStereo.h index da10bf15dd..0d80631b37 100644 --- a/modules/audio_coding/test/TestStereo.h +++ b/modules/audio_coding/test/TestStereo.h @@ -15,7 +15,7 @@ #include -#include "modules/audio_coding/include/audio_coding_module.h" +#include "modules/audio_coding/test/Channel.h" #include "modules/audio_coding/test/PCMFile.h" #define PCMA_AND_PCMU @@ -58,7 +58,7 @@ class TestPackStereo : public AudioPacketizationCallback { class TestStereo { public: - TestStereo(); + explicit TestStereo(int test_mode); ~TestStereo(); void Perform(); @@ -79,6 +79,9 @@ class TestStereo { int out_channels, int percent_loss = 0); void OpenOutFile(int16_t test_number); + void DisplaySendReceiveCodec(); + + int test_mode_; std::unique_ptr acm_a_; std::unique_ptr acm_b_; diff --git a/modules/audio_coding/test/TestVADDTX.cc b/modules/audio_coding/test/TestVADDTX.cc index 8e16280080..09c69f9c6b 100644 --- a/modules/audio_coding/test/TestVADDTX.cc +++ b/modules/audio_coding/test/TestVADDTX.cc @@ -23,8 +23,8 @@ #include "api/audio_codecs/opus/audio_encoder_opus.h" #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h" #include "modules/audio_coding/test/PCMFile.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/strings/string_builder.h" -#include "test/gtest.h" #include "test/testsupport/fileutils.h" namespace webrtc { @@ -94,9 +94,8 @@ bool TestVadDtx::RegisterCodec(const SdpAudioFormat& codec_format, channel_->SetIsStereo(encoder->NumChannels() > 1); acm_send_->SetEncoder(std::move(encoder)); - std::map receive_codecs = {{payload_type, codec_format}}; - acm_receive_->SetReceiveCodecs(receive_codecs); - + EXPECT_EQ(true, + acm_receive_->RegisterReceiveCodec(payload_type, codec_format)); return added_comfort_noise; } diff --git a/modules/audio_coding/test/TestVADDTX.h b/modules/audio_coding/test/TestVADDTX.h index f2358e7799..68b2c1e232 100644 --- a/modules/audio_coding/test/TestVADDTX.h +++ b/modules/audio_coding/test/TestVADDTX.h @@ -16,6 +16,7 @@ #include "api/audio_codecs/audio_decoder_factory.h" #include "api/audio_codecs/audio_encoder_factory.h" #include "common_audio/vad/include/vad.h" +#include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_coding/include/audio_coding_module_typedefs.h" #include "modules/audio_coding/test/Channel.h" diff --git a/modules/audio_coding/test/Tester.cc b/modules/audio_coding/test/Tester.cc index 750656f85f..85926f1261 100644 --- a/modules/audio_coding/test/Tester.cc +++ b/modules/audio_coding/test/Tester.cc @@ -25,8 +25,12 @@ #include "test/gtest.h" #include "test/testsupport/fileutils.h" +// This parameter is used to describe how to run the tests. It is normally +// set to 0, and all tests are run in quite mode. +#define ACM_TEST_MODE 0 + TEST(AudioCodingModuleTest, TestAllCodecs) { - webrtc::TestAllCodecs().Perform(); + webrtc::TestAllCodecs(ACM_TEST_MODE).Perform(); } #if defined(WEBRTC_ANDROID) @@ -34,7 +38,7 @@ TEST(AudioCodingModuleTest, DISABLED_TestEncodeDecode) { #else TEST(AudioCodingModuleTest, TestEncodeDecode) { #endif - webrtc::EncodeDecodeTest().Perform(); + webrtc::EncodeDecodeTest(ACM_TEST_MODE).Perform(); } TEST(AudioCodingModuleTest, TestRedFec) { @@ -46,7 +50,7 @@ TEST(AudioCodingModuleTest, DISABLED_TestIsac) { #else TEST(AudioCodingModuleTest, TestIsac) { #endif - webrtc::ISACTest().Perform(); + webrtc::ISACTest(ACM_TEST_MODE).Perform(); } #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \ @@ -66,7 +70,7 @@ TEST(AudioCodingModuleTest, DISABLED_TestStereo) { #else TEST(AudioCodingModuleTest, TestStereo) { #endif - webrtc::TestStereo().Perform(); + webrtc::TestStereo(ACM_TEST_MODE).Perform(); } TEST(AudioCodingModuleTest, TestWebRtcVadDtx) { diff --git a/modules/audio_coding/test/TwoWayCommunication.cc b/modules/audio_coding/test/TwoWayCommunication.cc index 3af114e0ba..2079a94d9c 100644 --- a/modules/audio_coding/test/TwoWayCommunication.cc +++ b/modules/audio_coding/test/TwoWayCommunication.cc @@ -16,9 +16,15 @@ #include +#ifdef WIN32 +#include +#endif + #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/test/PCMFile.h" +#include "modules/audio_coding/test/utility.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -59,26 +65,25 @@ void TwoWayCommunication::SetUpAutotest( const int payload_type1, const SdpAudioFormat& format2, const int payload_type2) { - //--- Set A codecs _acmA->SetEncoder( encoder_factory->MakeAudioEncoder(payload_type1, format1, absl::nullopt)); - _acmA->SetReceiveCodecs({{payload_type2, format2}}); + EXPECT_EQ(true, _acmA->RegisterReceiveCodec(payload_type2, format2)); //--- Set ref-A codecs _acmRefA->SetEncoder( encoder_factory->MakeAudioEncoder(payload_type1, format1, absl::nullopt)); - _acmRefA->SetReceiveCodecs({{payload_type2, format2}}); + EXPECT_EQ(true, _acmRefA->RegisterReceiveCodec(payload_type2, format2)); //--- Set B codecs _acmB->SetEncoder( encoder_factory->MakeAudioEncoder(payload_type2, format2, absl::nullopt)); - _acmB->SetReceiveCodecs({{payload_type1, format1}}); + EXPECT_EQ(true, _acmB->RegisterReceiveCodec(payload_type1, format1)); //--- Set ref-B codecs _acmRefB->SetEncoder( encoder_factory->MakeAudioEncoder(payload_type2, format2, absl::nullopt)); - _acmRefB->SetReceiveCodecs({{payload_type1, format1}}); + EXPECT_EQ(true, _acmRefB->RegisterReceiveCodec(payload_type1, format1)); uint16_t frequencyHz; @@ -179,13 +184,14 @@ void TwoWayCommunication::Perform() { if (((secPassed % 5) == 4) && (msecPassed >= 990)) { _acmB->SetEncoder(encoder_factory->MakeAudioEncoder( payload_type2, format2, absl::nullopt)); + EXPECT_TRUE(_acmB->SendCodec()); } // Initialize receiver on side A. if (((secPassed % 7) == 6) && (msecPassed == 0)) EXPECT_EQ(0, _acmA->InitializeReceiver()); // Re-register codec on side A. if (((secPassed % 7) == 6) && (msecPassed >= 990)) { - _acmA->SetReceiveCodecs({{payload_type2, format2}}); + EXPECT_EQ(true, _acmA->RegisterReceiveCodec(payload_type2, format2)); } } } diff --git a/modules/audio_coding/test/TwoWayCommunication.h b/modules/audio_coding/test/TwoWayCommunication.h index 7d0cdb9566..a679732bff 100644 --- a/modules/audio_coding/test/TwoWayCommunication.h +++ b/modules/audio_coding/test/TwoWayCommunication.h @@ -18,6 +18,7 @@ #include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_coding/test/Channel.h" #include "modules/audio_coding/test/PCMFile.h" +#include "modules/audio_coding/test/utility.h" namespace webrtc { diff --git a/modules/audio_coding/test/iSACTest.cc b/modules/audio_coding/test/iSACTest.cc index 339d419955..c332fe08f1 100644 --- a/modules/audio_coding/test/iSACTest.cc +++ b/modules/audio_coding/test/iSACTest.cc @@ -14,9 +14,20 @@ #include #include +#ifdef _WIN32 +#include +#elif defined(WEBRTC_LINUX) +#include +#else +#include +#include +#endif + #include "absl/strings/match.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/isac/audio_encoder_isac_float.h" +#include "modules/audio_coding/codecs/audio_format_conversion.h" +#include "modules/audio_coding/test/utility.h" #include "rtc_base/strings/string_builder.h" #include "rtc_base/timeutils.h" #include "system_wrappers/include/sleep.h" @@ -32,10 +43,15 @@ using ::testing::StrCaseEq; namespace { -constexpr int kISAC16kPayloadType = 103; -constexpr int kISAC32kPayloadType = 104; -const SdpAudioFormat kISAC16kFormat = { "ISAC", 16000, 1 }; -const SdpAudioFormat kISAC32kFormat = { "ISAC", 32000, 1 }; +AudioEncoderIsacFloat::Config MakeConfig(const CodecInst& ci) { + EXPECT_THAT(ci.plname, StrCaseEq("ISAC")); + EXPECT_THAT(ci.plfreq, AnyOf(Eq(16000), Eq(32000))); + EXPECT_THAT(ci.channels, Eq(1u)); + AudioEncoderIsacFloat::Config config; + config.sample_rate_hz = ci.plfreq; + EXPECT_THAT(config.IsOk(), Eq(true)); + return config; +} AudioEncoderIsacFloat::Config TweakConfig( AudioEncoderIsacFloat::Config config, @@ -61,96 +77,43 @@ void SetISACConfigDefault(ACMTestISACConfig& isacConfig) { } // namespace -ISACTest::ACMTestTimer::ACMTestTimer() : _msec(0), _sec(0), _min(0), _hour(0) { - return; -} - -ISACTest::ACMTestTimer::~ACMTestTimer() { - return; -} - -void ISACTest::ACMTestTimer::Reset() { - _msec = 0; - _sec = 0; - _min = 0; - _hour = 0; - return; -} -void ISACTest::ACMTestTimer::Tick10ms() { - _msec += 10; - Adjust(); - return; -} - -void ISACTest::ACMTestTimer::Tick1ms() { - _msec++; - Adjust(); - return; -} - -void ISACTest::ACMTestTimer::Tick100ms() { - _msec += 100; - Adjust(); - return; -} - -void ISACTest::ACMTestTimer::Tick1sec() { - _sec++; - Adjust(); - return; -} - -void ISACTest::ACMTestTimer::CurrentTimeHMS(char* currTime) { - sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min, - (double)_sec + (double)_msec / 1000.); - return; -} - -void ISACTest::ACMTestTimer::CurrentTime(unsigned long& h, - unsigned char& m, - unsigned char& s, - unsigned short& ms) { - h = _hour; - m = _min; - s = _sec; - ms = _msec; - return; -} - -void ISACTest::ACMTestTimer::Adjust() { - unsigned int n; - if (_msec >= 1000) { - n = _msec / 1000; - _msec -= (1000 * n); - _sec += n; - } - if (_sec >= 60) { - n = _sec / 60; - _sec -= (n * 60); - _min += n; - } - if (_min >= 60) { - n = _min / 60; - _min -= (n * 60); - _hour += n; - } -} - -ISACTest::ISACTest() +ISACTest::ISACTest(int testMode) : _acmA(AudioCodingModule::Create( AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))), _acmB(AudioCodingModule::Create( - AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))) {} + AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))), + _testMode(testMode) {} ISACTest::~ISACTest() {} void ISACTest::Setup() { + int codecCntr; + CodecInst codecParam; + + for (codecCntr = 0; codecCntr < AudioCodingModule::NumberOfCodecs(); + codecCntr++) { + EXPECT_EQ(0, AudioCodingModule::Codec(codecCntr, &codecParam)); + if (absl::EqualsIgnoreCase(codecParam.plname, "ISAC") && + codecParam.plfreq == 16000) { + memcpy(&_paramISAC16kHz, &codecParam, sizeof(CodecInst)); + _idISAC16kHz = codecCntr; + } + if (absl::EqualsIgnoreCase(codecParam.plname, "ISAC") && + codecParam.plfreq == 32000) { + memcpy(&_paramISAC32kHz, &codecParam, sizeof(CodecInst)); + _idISAC32kHz = codecCntr; + } + } + // Register both iSAC-wb & iSAC-swb in both sides as receiver codecs. - std::map receive_codecs = - {{kISAC16kPayloadType, kISAC16kFormat}, - {kISAC32kPayloadType, kISAC32kFormat}}; - _acmA->SetReceiveCodecs(receive_codecs); - _acmB->SetReceiveCodecs(receive_codecs); + EXPECT_EQ(true, _acmA->RegisterReceiveCodec(_paramISAC16kHz.pltype, + CodecInstToSdp(_paramISAC16kHz))); + EXPECT_EQ(true, _acmA->RegisterReceiveCodec(_paramISAC32kHz.pltype, + CodecInstToSdp(_paramISAC32kHz))); + EXPECT_EQ(true, _acmB->RegisterReceiveCodec(_paramISAC16kHz.pltype, + CodecInstToSdp(_paramISAC16kHz))); + EXPECT_EQ(true, _acmB->RegisterReceiveCodec(_paramISAC32kHz.pltype, + CodecInstToSdp(_paramISAC32kHz))); //--- Set A-to-B channel _channel_A2B.reset(new Channel); @@ -165,14 +128,10 @@ void ISACTest::Setup() { file_name_swb_ = webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); - _acmB->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat), - kISAC16kPayloadType)); - _acmA->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat), - kISAC32kPayloadType)); + _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC16kHz), _paramISAC16kHz.pltype)); + _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC32kHz), _paramISAC32kHz.pltype)); _inFileA.Open(file_name_swb_, 32000, "rb"); // Set test length to 500 ms (50 blocks of 10 ms each). @@ -187,9 +146,9 @@ void ISACTest::Setup() { while (!_inFileA.EndOfFile()) { Run10ms(); } - - EXPECT_TRUE(_acmA->ReceiveFormat()); - EXPECT_TRUE(_acmB->ReceiveFormat()); + CodecInst receiveCodec; + EXPECT_EQ(0, _acmA->ReceiveCodec(&receiveCodec)); + EXPECT_EQ(0, _acmB->ReceiveCodec(&receiveCodec)); _inFileA.Close(); _outFileA.Close(); @@ -211,13 +170,45 @@ void ISACTest::Perform() { testNr++; EncodeDecode(testNr, wbISACConfig, swbISACConfig); + if (_testMode != 0) { + SetISACConfigDefault(wbISACConfig); + SetISACConfigDefault(swbISACConfig); + + wbISACConfig.currentRateBitPerSec = -1; + swbISACConfig.currentRateBitPerSec = -1; + wbISACConfig.initRateBitPerSec = 13000; + wbISACConfig.initFrameSizeInMsec = 60; + swbISACConfig.initRateBitPerSec = 20000; + swbISACConfig.initFrameSizeInMsec = 30; + testNr++; + EncodeDecode(testNr, wbISACConfig, swbISACConfig); + + SetISACConfigDefault(wbISACConfig); + SetISACConfigDefault(swbISACConfig); + + wbISACConfig.currentRateBitPerSec = 20000; + swbISACConfig.currentRateBitPerSec = 48000; + testNr++; + EncodeDecode(testNr, wbISACConfig, swbISACConfig); + + wbISACConfig.currentRateBitPerSec = 16000; + swbISACConfig.currentRateBitPerSec = 30000; + wbISACConfig.currentFrameSizeMsec = 60; + testNr++; + EncodeDecode(testNr, wbISACConfig, swbISACConfig); + } + SetISACConfigDefault(wbISACConfig); SetISACConfigDefault(swbISACConfig); testNr++; EncodeDecode(testNr, wbISACConfig, swbISACConfig); testNr++; - SwitchingSamplingRate(testNr, 4); + if (_testMode == 0) { + SwitchingSamplingRate(testNr, 4); + } else { + SwitchingSamplingRate(testNr, 80); + } } void ISACTest::Run10ms() { @@ -254,16 +245,12 @@ void ISACTest::EncodeDecode(int testNr, _outFileB.Open(file_name_out, 32000, "wb"); // Side A is sending super-wideband, and side B is sending wideband. - _acmA->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat), - swbISACConfig), - kISAC32kPayloadType)); - _acmB->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat), - wbISACConfig), - kISAC16kPayloadType)); + _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + TweakConfig(MakeConfig(_paramISAC32kHz), swbISACConfig), + _paramISAC32kHz.pltype)); + _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + TweakConfig(MakeConfig(_paramISAC16kHz), wbISACConfig), + _paramISAC16kHz.pltype)); bool adaptiveMode = false; if ((swbISACConfig.currentRateBitPerSec == -1) || @@ -275,10 +262,30 @@ void ISACTest::EncodeDecode(int testNr, _channel_B2A->ResetStats(); char currentTime[500]; + int64_t time_ms = rtc::TimeMillis(); while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) { Run10ms(); _myTimer.Tick10ms(); _myTimer.CurrentTimeHMS(currentTime); + + if ((adaptiveMode) && (_testMode != 0)) { + time_ms += 10; + int64_t time_left_ms = time_ms - rtc::TimeMillis(); + if (time_left_ms > 0) { + SleepMs(time_left_ms); + } + + EXPECT_TRUE(_acmA->SendCodec()); + EXPECT_TRUE(_acmB->SendCodec()); + } + } + + if (_testMode != 0) { + printf("\n\nSide A statistics\n\n"); + _channel_A2B->PrintStats(_paramISAC32kHz); + + printf("\n\nSide B statistics\n\n"); + _channel_B2A->PrintStats(_paramISAC16kHz); } _channel_A2B->ResetStats(); @@ -309,14 +316,10 @@ void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) { // Start with side A sending super-wideband and side B seding wideband. // Toggle sending wideband/super-wideband in this test. - _acmA->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat), - kISAC32kPayloadType)); - _acmB->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat), - kISAC16kPayloadType)); + _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC32kHz), _paramISAC32kHz.pltype)); + _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC16kHz), _paramISAC16kHz.pltype)); int numSendCodecChanged = 0; _myTimer.Reset(); @@ -325,23 +328,21 @@ void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) { Run10ms(); _myTimer.Tick10ms(); _myTimer.CurrentTimeHMS(currentTime); + if (_testMode == 2) + printf("\r%s", currentTime); if (_inFileA.EndOfFile()) { if (_inFileA.SamplingFrequency() == 16000) { // Switch side A to send super-wideband. _inFileA.Close(); _inFileA.Open(file_name_swb_, 32000, "rb"); - _acmA->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat), - kISAC32kPayloadType)); + _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC32kHz), _paramISAC32kHz.pltype)); } else { // Switch side A to send wideband. _inFileA.Close(); _inFileA.Open(file_name_swb_, 32000, "rb"); - _acmA->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat), - kISAC16kPayloadType)); + _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC16kHz), _paramISAC16kHz.pltype)); } numSendCodecChanged++; } @@ -351,18 +352,14 @@ void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) { // Switch side B to send super-wideband. _inFileB.Close(); _inFileB.Open(file_name_swb_, 32000, "rb"); - _acmB->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat), - kISAC32kPayloadType)); + _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC32kHz), _paramISAC32kHz.pltype)); } else { // Switch side B to send wideband. _inFileB.Close(); _inFileB.Open(file_name_swb_, 32000, "rb"); - _acmB->SetEncoder( - AudioEncoderIsacFloat::MakeAudioEncoder( - *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat), - kISAC16kPayloadType)); + _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder( + MakeConfig(_paramISAC16kHz), _paramISAC16kHz.pltype)); } numSendCodecChanged++; } diff --git a/modules/audio_coding/test/iSACTest.h b/modules/audio_coding/test/iSACTest.h index e0004763d9..0b140b6032 100644 --- a/modules/audio_coding/test/iSACTest.h +++ b/modules/audio_coding/test/iSACTest.h @@ -15,9 +15,14 @@ #include +#include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_coding/test/Channel.h" #include "modules/audio_coding/test/PCMFile.h" +#include "modules/audio_coding/test/utility.h" + +#define MAX_FILE_NAME_LENGTH_BYTE 500 +#define NO_OF_CLIENTS 15 namespace webrtc { @@ -32,37 +37,12 @@ struct ACMTestISACConfig { class ISACTest { public: - ISACTest(); + explicit ISACTest(int testMode); ~ISACTest(); void Perform(); private: - class ACMTestTimer { - public: - ACMTestTimer(); - ~ACMTestTimer(); - - void Reset(); - void Tick10ms(); - void Tick1ms(); - void Tick100ms(); - void Tick1sec(); - void CurrentTimeHMS(char* currTime); - void CurrentTime(unsigned long& h, - unsigned char& m, - unsigned char& s, - unsigned short& ms); - - private: - void Adjust(); - - unsigned short _msec; - unsigned char _sec; - unsigned char _min; - unsigned long _hour; - }; - void Setup(); void Run10ms(); @@ -85,9 +65,15 @@ class ISACTest { PCMFile _outFileA; PCMFile _outFileB; + uint8_t _idISAC16kHz; + uint8_t _idISAC32kHz; + CodecInst _paramISAC16kHz; + CodecInst _paramISAC32kHz; + std::string file_name_swb_; ACMTestTimer _myTimer; + int _testMode; }; } // namespace webrtc diff --git a/modules/audio_coding/test/opus_test.cc b/modules/audio_coding/test/opus_test.cc index 1e24e5dae7..954b1832c1 100644 --- a/modules/audio_coding/test/opus_test.cc +++ b/modules/audio_coding/test/opus_test.cc @@ -13,9 +13,12 @@ #include #include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "common_types.h" // NOLINT(build/include) +#include "modules/audio_coding/codecs/audio_format_conversion.h" #include "modules/audio_coding/codecs/opus/opus_interface.h" #include "modules/audio_coding/include/audio_coding_module_typedefs.h" #include "modules/audio_coding/test/TestStereo.h" +#include "modules/audio_coding/test/utility.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -86,10 +89,13 @@ void OpusTest::Perform() { EXPECT_EQ(0, acm_receiver_->InitializeReceiver()); // Register Opus stereo as receiving codec. - constexpr int kOpusPayloadType = 120; - const SdpAudioFormat kOpusFormatStereo("opus", 48000, 2, {{"stereo", "1"}}); - payload_type_ = kOpusPayloadType; - acm_receiver_->SetReceiveCodecs({{kOpusPayloadType, kOpusFormatStereo}}); + CodecInst opus_codec_param; + int codec_id = acm_receiver_->Codec("opus", 48000, 2); + EXPECT_EQ(0, acm_receiver_->Codec(codec_id, &opus_codec_param)); + payload_type_ = opus_codec_param.pltype; + EXPECT_EQ(true, + acm_receiver_->RegisterReceiveCodec( + opus_codec_param.pltype, CodecInstToSdp(opus_codec_param))); // Create and connect the channel. channel_a2b_ = new TestPackStereo; @@ -153,8 +159,10 @@ void OpusTest::Perform() { OpenOutFile(test_cntr); // Register Opus mono as receiving codec. - const SdpAudioFormat kOpusFormatMono("opus", 48000, 2); - acm_receiver_->SetReceiveCodecs({{kOpusPayloadType, kOpusFormatMono}}); + opus_codec_param.channels = 1; + EXPECT_EQ(true, + acm_receiver_->RegisterReceiveCodec( + opus_codec_param.pltype, CodecInstToSdp(opus_codec_param))); // Run Opus with 2.5 ms frame size. Run(channel_a2b_, audio_channels, 32000, 120); diff --git a/modules/audio_coding/test/opus_test.h b/modules/audio_coding/test/opus_test.h index c69f922adb..019e96b9b2 100644 --- a/modules/audio_coding/test/opus_test.h +++ b/modules/audio_coding/test/opus_test.h @@ -17,6 +17,7 @@ #include "modules/audio_coding/acm2/acm_resampler.h" #include "modules/audio_coding/codecs/opus/opus_interface.h" +#include "modules/audio_coding/test/Channel.h" #include "modules/audio_coding/test/PCMFile.h" #include "modules/audio_coding/test/TestStereo.h" diff --git a/modules/audio_coding/test/target_delay_unittest.cc b/modules/audio_coding/test/target_delay_unittest.cc index 8d82b6eb87..071a6d898d 100644 --- a/modules/audio_coding/test/target_delay_unittest.cc +++ b/modules/audio_coding/test/target_delay_unittest.cc @@ -12,8 +12,10 @@ #include "api/audio/audio_frame.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "modules/audio_coding/include/audio_coding_module.h" +#include "modules/audio_coding/test/utility.h" #include "modules/include/module_common_types.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" @@ -33,9 +35,8 @@ class TargetDelayTest : public ::testing::Test { ASSERT_EQ(0, acm_->InitializeReceiver()); constexpr int pltype = 108; - std::map receive_codecs = - {{pltype, {"L16", kSampleRateHz, 1}}}; - acm_->SetReceiveCodecs(receive_codecs); + ASSERT_EQ(true, + acm_->RegisterReceiveCodec(pltype, {"L16", kSampleRateHz, 1})); rtp_info_.header.payloadType = pltype; rtp_info_.header.timestamp = 0; diff --git a/modules/audio_coding/test/utility.cc b/modules/audio_coding/test/utility.cc new file mode 100644 index 0000000000..53f807790e --- /dev/null +++ b/modules/audio_coding/test/utility.cc @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2011 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 "utility.h" + +#include +#include +#include +#include + +#include "absl/strings/match.h" +#include "modules/audio_coding/include/audio_coding_module.h" +#include "test/gtest.h" + +#define NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE 13 + +namespace webrtc { + +ACMTestTimer::ACMTestTimer() : _msec(0), _sec(0), _min(0), _hour(0) { + return; +} + +ACMTestTimer::~ACMTestTimer() { + return; +} + +void ACMTestTimer::Reset() { + _msec = 0; + _sec = 0; + _min = 0; + _hour = 0; + return; +} +void ACMTestTimer::Tick10ms() { + _msec += 10; + Adjust(); + return; +} + +void ACMTestTimer::Tick1ms() { + _msec++; + Adjust(); + return; +} + +void ACMTestTimer::Tick100ms() { + _msec += 100; + Adjust(); + return; +} + +void ACMTestTimer::Tick1sec() { + _sec++; + Adjust(); + return; +} + +void ACMTestTimer::CurrentTimeHMS(char* currTime) { + sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min, + (double)_sec + (double)_msec / 1000.); + return; +} + +void ACMTestTimer::CurrentTime(unsigned long& h, + unsigned char& m, + unsigned char& s, + unsigned short& ms) { + h = _hour; + m = _min; + s = _sec; + ms = _msec; + return; +} + +void ACMTestTimer::Adjust() { + unsigned int n; + if (_msec >= 1000) { + n = _msec / 1000; + _msec -= (1000 * n); + _sec += n; + } + if (_sec >= 60) { + n = _sec / 60; + _sec -= (n * 60); + _min += n; + } + if (_min >= 60) { + n = _min / 60; + _min -= (n * 60); + _hour += n; + } +} + +int16_t ChooseCodec(CodecInst& codecInst) { + PrintCodecs(); + // AudioCodingModule* tmpACM = AudioCodingModule::Create(0); + uint8_t noCodec = AudioCodingModule::NumberOfCodecs(); + int8_t codecID; + bool outOfRange = false; + char myStr[15] = ""; + do { + printf("\nChoose a codec [0]: "); + EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL); + codecID = atoi(myStr); + if ((codecID < 0) || (codecID >= noCodec)) { + printf("\nOut of range.\n"); + outOfRange = true; + } + } while (outOfRange); + + CHECK_ERROR(AudioCodingModule::Codec((uint8_t)codecID, &codecInst)); + return 0; +} + +void PrintCodecs() { + uint8_t noCodec = AudioCodingModule::NumberOfCodecs(); + + CodecInst codecInst; + printf("No Name [Hz] [bps]\n"); + for (uint8_t codecCntr = 0; codecCntr < noCodec; codecCntr++) { + AudioCodingModule::Codec(codecCntr, &codecInst); + printf("%2d- %-18s %5d %6d\n", codecCntr, codecInst.plname, + codecInst.plfreq, codecInst.rate); + } +} + +namespace test { + +CircularBuffer::CircularBuffer(uint32_t len) + : _buff(NULL), + _idx(0), + _buffIsFull(false), + _calcAvg(false), + _calcVar(false), + _sum(0), + _sumSqr(0) { + _buff = new double[len]; + if (_buff == NULL) { + _buffLen = 0; + } else { + for (uint32_t n = 0; n < len; n++) { + _buff[n] = 0; + } + _buffLen = len; + } +} + +CircularBuffer::~CircularBuffer() { + if (_buff != NULL) { + delete[] _buff; + _buff = NULL; + } +} + +void CircularBuffer::Update(const double newVal) { + assert(_buffLen > 0); + + // store the value that is going to be overwritten + double oldVal = _buff[_idx]; + // record the new value + _buff[_idx] = newVal; + // increment the index, to point to where we would + // write next + _idx++; + // it is a circular buffer, if we are at the end + // we have to cycle to the beginning + if (_idx >= _buffLen) { + // flag that the buffer is filled up. + _buffIsFull = true; + _idx = 0; + } + + // Update + + if (_calcAvg) { + // for the average we have to update + // the sum + _sum += (newVal - oldVal); + } + + if (_calcVar) { + // to calculate variance we have to update + // the sum of squares + _sumSqr += (double)(newVal - oldVal) * (double)(newVal + oldVal); + } +} + +void CircularBuffer::SetArithMean(bool enable) { + assert(_buffLen > 0); + + if (enable && !_calcAvg) { + uint32_t lim; + if (_buffIsFull) { + lim = _buffLen; + } else { + lim = _idx; + } + _sum = 0; + for (uint32_t n = 0; n < lim; n++) { + _sum += _buff[n]; + } + } + _calcAvg = enable; +} + +void CircularBuffer::SetVariance(bool enable) { + assert(_buffLen > 0); + + if (enable && !_calcVar) { + uint32_t lim; + if (_buffIsFull) { + lim = _buffLen; + } else { + lim = _idx; + } + _sumSqr = 0; + for (uint32_t n = 0; n < lim; n++) { + _sumSqr += _buff[n] * _buff[n]; + } + } + _calcAvg = enable; +} + +int16_t CircularBuffer::ArithMean(double& mean) { + assert(_buffLen > 0); + + if (_buffIsFull) { + mean = _sum / (double)_buffLen; + return 0; + } else { + if (_idx > 0) { + mean = _sum / (double)_idx; + return 0; + } else { + return -1; + } + } +} + +int16_t CircularBuffer::Variance(double& var) { + assert(_buffLen > 0); + + if (_buffIsFull) { + var = _sumSqr / (double)_buffLen; + return 0; + } else { + if (_idx > 0) { + var = _sumSqr / (double)_idx; + return 0; + } else { + return -1; + } + } +} + +} // namespace test + +bool FixedPayloadTypeCodec(const char* payloadName) { + char fixPayloadTypeCodecs[NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE][32] = { + "PCMU", "PCMA", "GSM", "G723", "DVI4", "LPC", "PCMA", + "G722", "QCELP", "CN", "MPA", "G728", "G729"}; + + for (int n = 0; n < NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE; n++) { + if (absl::EqualsIgnoreCase(payloadName, fixPayloadTypeCodecs[n])) { + return true; + } + } + return false; +} + +void VADCallback::Reset() { + memset(_numFrameTypes, 0, sizeof(_numFrameTypes)); +} + +VADCallback::VADCallback() { + memset(_numFrameTypes, 0, sizeof(_numFrameTypes)); +} + +void VADCallback::PrintFrameTypes() { + printf("kEmptyFrame......... %d\n", _numFrameTypes[kEmptyFrame]); + printf("kAudioFrameSpeech... %d\n", _numFrameTypes[kAudioFrameSpeech]); + printf("kAudioFrameCN....... %d\n", _numFrameTypes[kAudioFrameCN]); + printf("kVideoFrameKey...... %d\n", _numFrameTypes[kVideoFrameKey]); + printf("kVideoFrameDelta.... %d\n", _numFrameTypes[kVideoFrameDelta]); +} + +int32_t VADCallback::InFrameType(FrameType frame_type) { + _numFrameTypes[frame_type]++; + return 0; +} + +} // namespace webrtc diff --git a/modules/audio_coding/test/utility.h b/modules/audio_coding/test/utility.h new file mode 100644 index 0000000000..6f17df5bdf --- /dev/null +++ b/modules/audio_coding/test/utility.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 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 MODULES_AUDIO_CODING_TEST_UTILITY_H_ +#define MODULES_AUDIO_CODING_TEST_UTILITY_H_ + +#include "modules/audio_coding/include/audio_coding_module.h" +#include "test/gtest.h" + +namespace webrtc { + +//----------------------------- +#define CHECK_ERROR(f) \ + do { \ + EXPECT_GE(f, 0) << "Error Calling API"; \ + } while (0) + +//----------------------------- +#define CHECK_PROTECTED(f) \ + do { \ + if (f >= 0) { \ + ADD_FAILURE() << "Error Calling API"; \ + } else { \ + printf("An expected error is caught.\n"); \ + } \ + } while (0) + +//---------------------------- +#define CHECK_ERROR_MT(f) \ + do { \ + if (f < 0) { \ + fprintf(stderr, "Error Calling API in file %s at line %d \n", __FILE__, \ + __LINE__); \ + } \ + } while (0) + +//---------------------------- +#define CHECK_PROTECTED_MT(f) \ + do { \ + if (f >= 0) { \ + fprintf(stderr, "Error Calling API in file %s at line %d \n", __FILE__, \ + __LINE__); \ + } else { \ + printf("An expected error is caught.\n"); \ + } \ + } while (0) + +#define DELETE_POINTER(p) \ + do { \ + if (p != NULL) { \ + delete p; \ + p = NULL; \ + } \ + } while (0) + +class ACMTestTimer { + public: + ACMTestTimer(); + ~ACMTestTimer(); + + void Reset(); + void Tick10ms(); + void Tick1ms(); + void Tick100ms(); + void Tick1sec(); + void CurrentTimeHMS(char* currTime); + void CurrentTime(unsigned long& h, + unsigned char& m, + unsigned char& s, + unsigned short& ms); + + private: + void Adjust(); + + unsigned short _msec; + unsigned char _sec; + unsigned char _min; + unsigned long _hour; +}; + +// To avoid clashes with CircularBuffer in APM. +namespace test { + +class CircularBuffer { + public: + CircularBuffer(uint32_t len); + ~CircularBuffer(); + + void SetArithMean(bool enable); + void SetVariance(bool enable); + + void Update(const double newVal); + void IsBufferFull(); + + int16_t Variance(double& var); + int16_t ArithMean(double& mean); + + protected: + double* _buff; + uint32_t _idx; + uint32_t _buffLen; + + bool _buffIsFull; + bool _calcAvg; + bool _calcVar; + double _sum; + double _sumSqr; +}; + +} // namespace test + +int16_t ChooseCodec(CodecInst& codecInst); + +void PrintCodecs(); + +bool FixedPayloadTypeCodec(const char* payloadName); + +class VADCallback : public ACMVADCallback { + public: + VADCallback(); + + int32_t InFrameType(FrameType frame_type) override; + + void PrintFrameTypes(); + void Reset(); + + private: + uint32_t _numFrameTypes[5]; +}; + +} // namespace webrtc + +#endif // MODULES_AUDIO_CODING_TEST_UTILITY_H_