diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc index fcfe86222f..134539f054 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc @@ -47,11 +47,15 @@ class NetEqIlbcQualityTest : public NetEqQualityTest { : NetEqQualityTest(FLAGS_frame_size_ms, kInputSampleRateKhz, kOutputSampleRateKhz, - kDecoderILBC, - 1) { + kDecoderILBC) { + } + + void SetUp() override { + ASSERT_EQ(1, channels_) << "iLBC supports only mono audio."; AudioEncoderIlbc::Config config; config.frame_size_ms = FLAGS_frame_size_ms; encoder_.reset(new AudioEncoderIlbc(config)); + NetEqQualityTest::SetUp(); } int EncodeBlock(int16_t* in_data, diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc index 9c6067dc6f..85dd54d9bd 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc @@ -54,13 +54,13 @@ NetEqIsacQualityTest::NetEqIsacQualityTest() : NetEqQualityTest(kIsacBlockDurationMs, kIsacInputSamplingKhz, kIsacOutputSamplingKhz, - kDecoderISAC, - 1), + kDecoderISAC), isac_encoder_(NULL), bit_rate_kbps_(FLAGS_bit_rate_kbps) { } void NetEqIsacQualityTest::SetUp() { + ASSERT_EQ(1, channels_) << "iSAC supports only mono audio."; // Create encoder memory. WebRtcIsacfix_Create(&isac_encoder_); ASSERT_TRUE(isac_encoder_ != NULL); diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc index d8aa2cac2a..29cf84e48c 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc @@ -24,34 +24,6 @@ namespace { static const int kOpusBlockDurationMs = 20; static const int kOpusSamplingKhz = 48; -// Define switch for sample rate. -static bool ValidateSampleRate(const char* flagname, int32_t value) { - if (value == 8000 || value == 16000 || value == 32000 || value == 48000) - return true; - printf("Invalid sample rate should be 8000, 16000, 32000 or 48000 Hz."); - return false; -} - -DEFINE_int32(input_sample_rate, - kOpusSamplingKhz * 1000, - "Sample rate of input file."); - -static const bool sample_rate_dummy = - RegisterFlagValidator(&FLAGS_input_sample_rate, &ValidateSampleRate); - -// Define switch for channels. -static bool ValidateChannels(const char* flagname, int32_t value) { - if (value == 1 || value == 2) - return true; - printf("Invalid number of channels, should be either 1 or 2."); - return false; -} - -DEFINE_int32(channels, 1, "Number of channels in input audio."); - -static const bool channels_dummy = - RegisterFlagValidator(&FLAGS_channels, &ValidateChannels); - // Define switch for bit rate. static bool ValidateBitRate(const char* flagname, int32_t value) { if (value >= 6 && value <= 510) @@ -65,6 +37,37 @@ DEFINE_int32(bit_rate_kbps, 32, "Target bit rate (kbps)."); static const bool bit_rate_dummy = RegisterFlagValidator(&FLAGS_bit_rate_kbps, &ValidateBitRate); +// Define switch for complexity. +static bool ValidateComplexity(const char* flagname, int32_t value) { + if (value >= -1 && value <= 10) + return true; + printf("Invalid complexity setting, should be between 0 and 10."); + return false; +} + +DEFINE_int32(complexity, 10, "Complexity: 0 ~ 10 -- defined as in Opus" + "specification."); + +static const bool complexity_dummy = + RegisterFlagValidator(&FLAGS_complexity, &ValidateComplexity); + +// Define switch for maxplaybackrate +DEFINE_int32(maxplaybackrate, 48000, "Maximum playback rate (Hz)."); + +// Define switch for application mode. +static bool ValidateApplication(const char* flagname, int32_t value) { + if (value != 0 && value != 1) { + printf("Invalid application mode, should be 0 or 1."); + return false; + } + return true; +} + +DEFINE_int32(application, 0, "Application mode: 0 -- VOIP, 1 -- Audio."); + +static const bool application_dummy = + RegisterFlagValidator(&FLAGS_application, &ValidateApplication); + // Define switch for reported packet loss rate. static bool ValidatePacketLossRate(const char* flagname, int32_t value) { if (value >= 0 && value <= 100) @@ -106,36 +109,41 @@ class NetEqOpusQualityTest : public NetEqQualityTest { WebRtcOpusEncInst* opus_encoder_; OpusRepacketizer* repacketizer_; int sub_block_size_samples_; - int channels_; int bit_rate_kbps_; bool fec_; bool dtx_; + int complexity_; + int maxplaybackrate_; int target_loss_rate_; int sub_packets_; + int application_; }; NetEqOpusQualityTest::NetEqOpusQualityTest() : NetEqQualityTest(kOpusBlockDurationMs * FLAGS_sub_packets, kOpusSamplingKhz, kOpusSamplingKhz, - (FLAGS_channels == 1) ? kDecoderOpus : kDecoderOpus_2ch, - FLAGS_channels), + kDecoderOpus), opus_encoder_(NULL), repacketizer_(NULL), sub_block_size_samples_(kOpusBlockDurationMs * kOpusSamplingKhz), - channels_(FLAGS_channels), bit_rate_kbps_(FLAGS_bit_rate_kbps), fec_(FLAGS_fec), dtx_(FLAGS_dtx), + complexity_(FLAGS_complexity), + maxplaybackrate_(FLAGS_maxplaybackrate), target_loss_rate_(FLAGS_reported_loss_rate), sub_packets_(FLAGS_sub_packets) { + // Redefine decoder type if input is stereo. + if (channels_ > 1) { + decoder_type_ = kDecoderOpus_2ch; + } + application_ = FLAGS_application; } void NetEqOpusQualityTest::SetUp() { - // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode. - int app = channels_ == 1 ? 0 : 1; // Create encoder memory. - WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app); + WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_); ASSERT_TRUE(opus_encoder_); // Create repacketizer. @@ -150,6 +158,8 @@ void NetEqOpusQualityTest::SetUp() { if (dtx_) { EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_)); } + EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, complexity_)); + EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, maxplaybackrate_)); EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, target_loss_rate_)); NetEqQualityTest::SetUp(); @@ -172,6 +182,9 @@ int NetEqOpusQualityTest::EncodeBlock(int16_t* in_data, for (int idx = 0; idx < sub_packets_; idx++) { value = WebRtcOpus_Encode(opus_encoder_, pointer, sub_block_size_samples_, max_bytes, payload); + Log() << "Encoded a frame with Opus mode " + << (value == 0 ? 0 : payload[0] >> 3) + << std::endl; if (OPUS_OK != opus_repacketizer_cat(repacketizer_, payload, value)) { opus_repacketizer_init(repacketizer_); // If the repacketization fails, we discard this frame. diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc index d2833d8926..d94ceb60f8 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc @@ -47,11 +47,15 @@ class NetEqPcmuQualityTest : public NetEqQualityTest { : NetEqQualityTest(FLAGS_frame_size_ms, kInputSampleRateKhz, kOutputSampleRateKhz, - kDecoderPCMu, - 1) { + kDecoderPCMu) { + } + + void SetUp() override { + ASSERT_EQ(1, channels_) << "PCMu supports only mono audio."; AudioEncoderPcmU::Config config; config.frame_size_ms = FLAGS_frame_size_ms; encoder_.reset(new AudioEncoderPcmU(config)); + NetEqQualityTest::SetUp(); } int EncodeBlock(int16_t* in_data, diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc index cec96747bf..c60b993ad8 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc @@ -48,7 +48,8 @@ static bool ValidateInFilename(const char* flagname, const string& value) { DEFINE_string( in_filename, ResourcePath("audio_coding/speech_mono_16kHz", "pcm"), - "Filename for input audio (specify sample rate with --input_sample_rate)."); + "Filename for input audio (specify sample rate with --input_sample_rate ," + "and channels with --channels)."); static const bool in_filename_dummy = RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename); @@ -66,6 +67,19 @@ DEFINE_int32(input_sample_rate, 16000, "Sample rate of input file in Hz."); static const bool sample_rate_dummy = RegisterFlagValidator(&FLAGS_input_sample_rate, &ValidateSampleRate); +// Define switch for channels. +static bool ValidateChannels(const char* flagname, int32_t value) { + if (value == 1) + return true; + printf("Invalid number of channels, current support only 1."); + return false; +} + +DEFINE_int32(channels, 1, "Number of channels in input audio."); + +static const bool channels_dummy = + RegisterFlagValidator(&FLAGS_channels, &ValidateChannels); + // Define switch for output file name. static bool ValidateOutFilename(const char* flagname, const string& value) { if (!ValidateFilename(value, true)) { @@ -194,17 +208,16 @@ static double ProbTrans00Solver(int units, double loss_rate, NetEqQualityTest::NetEqQualityTest(int block_duration_ms, int in_sampling_khz, int out_sampling_khz, - enum NetEqDecoder decoder_type, - int channels) - : decoded_time_ms_(0), + enum NetEqDecoder decoder_type) + : decoder_type_(decoder_type), + channels_(FLAGS_channels), + decoded_time_ms_(0), decodable_time_ms_(0), drift_factor_(FLAGS_drift_factor), packet_loss_rate_(FLAGS_packet_loss_rate), block_duration_ms_(block_duration_ms), in_sampling_khz_(in_sampling_khz), out_sampling_khz_(out_sampling_khz), - decoder_type_(decoder_type), - channels_(channels), in_size_samples_(in_sampling_khz_ * block_duration_ms_), out_size_samples_(out_sampling_khz_ * kOutputSizeMs), payload_size_bytes_(0), @@ -212,14 +225,13 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms, in_file_(new ResampleInputAudioFile(FLAGS_in_filename, FLAGS_input_sample_rate, in_sampling_khz * 1000)), - log_file_(NULL), rtp_generator_( new RtpGenerator(in_sampling_khz_, 0, 0, decodable_time_ms_)), total_payload_size_bytes_(0) { const std::string out_filename = FLAGS_out_filename; const std::string log_filename = out_filename + ".log"; - log_file_ = fopen(log_filename.c_str(), "wt"); - CHECK(log_file_); + log_file_.open(log_filename.c_str(), std::ofstream::out); + CHECK(log_file_.is_open()); if (out_filename.size() >= 4 && out_filename.substr(out_filename.size() - 4) == ".wav") { @@ -240,6 +252,10 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms, out_data_.reset(new int16_t[out_size_samples_ * channels_]); } +NetEqQualityTest::~NetEqQualityTest() { + log_file_.close(); +} + bool NoLoss::Lost() { return false; } @@ -328,6 +344,10 @@ void NetEqQualityTest::SetUp() { srand(kInitSeed); } +std::ofstream& NetEqQualityTest::Log() { + return log_file_; +} + bool NetEqQualityTest::PacketLost() { int cycles = block_duration_ms_ / kPacketLossTimeUnitMs; @@ -349,19 +369,24 @@ int NetEqQualityTest::Transmit() { int packet_input_time_ms = rtp_generator_->GetRtpHeader(kPayloadType, in_size_samples_, &rtp_header_); + Log() << "Packet of size " + << payload_size_bytes_ + << " bytes, for frame at " + << packet_input_time_ms + << " ms "; if (payload_size_bytes_ > 0) { - fprintf(log_file_, "Packet at %d ms", packet_input_time_ms); if (!PacketLost()) { int ret = neteq_->InsertPacket(rtp_header_, &payload_[0], payload_size_bytes_, packet_input_time_ms * in_sampling_khz_); if (ret != NetEq::kOK) return -1; - fprintf(log_file_, " OK.\n"); + Log() << "was sent."; } else { - fprintf(log_file_, " Lost.\n"); + Log() << "was lost."; } } + Log() << std::endl; return packet_input_time_ms; } @@ -399,7 +424,10 @@ void NetEqQualityTest::Simulate() { decoded_time_ms_ += audio_size_samples / out_sampling_khz_; } } - fprintf(log_file_, "%f", 8.0f * total_payload_size_bytes_ / FLAGS_runtime_ms); + Log() << "Average bit rate was " + << 8.0f * total_payload_size_bytes_ / FLAGS_runtime_ms + << " kbps" + << std::endl; } } // namespace test diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h index 1cdafe6f83..4a0d808aec 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_QUALITY_TEST_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_QUALITY_TEST_H_ +#include #include #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" @@ -65,8 +66,9 @@ class NetEqQualityTest : public ::testing::Test { NetEqQualityTest(int block_duration_ms, int in_sampling_khz, int out_sampling_khz, - enum NetEqDecoder decoder_type, - int channels); + enum NetEqDecoder decoder_type); + virtual ~NetEqQualityTest(); + void SetUp() override; // EncodeBlock(...) does the following: @@ -93,6 +95,12 @@ class NetEqQualityTest : public ::testing::Test { // Runs encoding / transmitting / decoding. void Simulate(); + // Write to log file. Usage Log() << ... + std::ofstream& Log(); + + enum NetEqDecoder decoder_type_; + const int channels_; + private: int decoded_time_ms_; int decodable_time_ms_; @@ -101,8 +109,6 @@ class NetEqQualityTest : public ::testing::Test { const int block_duration_ms_; const int in_sampling_khz_; const int out_sampling_khz_; - const enum NetEqDecoder decoder_type_; - const int channels_; // Number of samples per channel in a frame. const int in_size_samples_; @@ -115,7 +121,7 @@ class NetEqQualityTest : public ::testing::Test { rtc::scoped_ptr in_file_; rtc::scoped_ptr output_; - FILE* log_file_; + std::ofstream log_file_; rtc::scoped_ptr rtp_generator_; rtc::scoped_ptr neteq_;