Update NetEq Quality Test.

1. move channel number of input file to the base class

2. limit channel number to be 1, since the resampler support only mono at the moment

3. adding a logging function

4. adding more switch to neteq_opus_quality_test

BUG=2692
R=henrik.lundin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/47239004

Cr-Commit-Position: refs/heads/master@{#9260}
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 fcfe862..134539f 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 @@
       : 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 9c6067d..85dd54d 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 @@
     : 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 d8aa2ca..29cf84e 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 @@
 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 @@
 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 @@
   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 @@
   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 @@
   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 d2833d8..d94ceb6 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 @@
       : 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 cec9674..c60b993 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 @@
 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 @@
 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 @@
 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 @@
       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 @@
   out_data_.reset(new int16_t[out_size_samples_ * channels_]);
 }
 
+NetEqQualityTest::~NetEqQualityTest() {
+  log_file_.close();
+}
+
 bool NoLoss::Lost() {
   return false;
 }
@@ -328,6 +344,10 @@
   srand(kInitSeed);
 }
 
+std::ofstream& NetEqQualityTest::Log() {
+  return log_file_;
+}
+
 bool NetEqQualityTest::PacketLost() {
   int cycles = block_duration_ms_ / kPacketLossTimeUnitMs;
 
@@ -349,19 +369,24 @@
   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 @@
       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 1cdafe6..4a0d808 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 <fstream>
 #include <gflags/gflags.h>
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/base/scoped_ptr.h"
@@ -65,8 +66,9 @@
   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 @@
   // 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 @@
   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 @@
 
   rtc::scoped_ptr<InputAudioFile> in_file_;
   rtc::scoped_ptr<AudioSink> output_;
-  FILE* log_file_;
+  std::ofstream log_file_;
 
   rtc::scoped_ptr<RtpGenerator> rtp_generator_;
   rtc::scoped_ptr<NetEq> neteq_;