Add new AcmGenericCodecTest and verify output from Encode function

The test specifically verifies that the output is as expected when
DTX/CNG is used.

COAUTHOR=kwiberg@webrtc.org
R=minyue@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8497}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8497 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc
new file mode 100644
index 0000000..1b8113c
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 2015 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 "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/safe_conversions.h"
+#include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
+
+namespace webrtc {
+namespace acm2 {
+
+namespace {
+const int kDataLengthSamples = 80;
+const int16_t kZeroData[kDataLengthSamples] = {0};
+const CodecInst kDefaultCodecInst =
+    {0, "pcmu", 8000, 2 * kDataLengthSamples, 1, 64000};
+const int kCngPt = 13;
+const int kNoCngPt = 255;
+const int kRedPt = 255;  // Not using RED in this test.
+}  // namespace
+
+class AcmGenericCodecTest : public ::testing::Test {
+ protected:
+  AcmGenericCodecTest() : timestamp_(0) {
+    acm_codec_params_ = {kDefaultCodecInst, true, true, VADNormal};
+  }
+
+  void CreateCodec() {
+    codec_.reset(new ACMGenericCodec(acm_codec_params_.codec_inst, kCngPt,
+                                     kNoCngPt, kNoCngPt, kNoCngPt,
+                                     false /* enable RED */, kRedPt));
+    ASSERT_TRUE(codec_);
+    ASSERT_EQ(0, codec_->InitEncoder(&acm_codec_params_, true));
+  }
+
+  void AddData() {
+    EXPECT_EQ(
+        0, codec_->Add10MsData(timestamp_, kZeroData, kDataLengthSamples, 1));
+    timestamp_ += kDataLengthSamples;
+  }
+
+  void EncodeAndVerify(int expected_return_val,
+                       size_t expected_out_length,
+                       uint32_t expected_timestamp,
+                       WebRtcACMEncodingType expected_encoding_type,
+                       int expected_payload_type,
+                       int expected_send_even_if_empty) {
+    uint8_t out[kDataLengthSamples];
+    int16_t out_length;
+    uint32_t out_timestamp;
+    WebRtcACMEncodingType encoding_type;
+    AudioEncoder::EncodedInfo encoded_info;
+    EXPECT_EQ(expected_return_val,
+              codec_->Encode(out, &out_length, &out_timestamp, &encoding_type,
+                             &encoded_info));
+    EXPECT_EQ(expected_timestamp, out_timestamp);
+    EXPECT_EQ(expected_encoding_type, encoding_type);
+    EXPECT_TRUE(encoded_info.redundant.empty());
+    EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
+    EXPECT_EQ(expected_out_length, rtc::checked_cast<size_t>(out_length));
+    EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
+    if (expected_payload_type >= 0)
+      EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
+    if (expected_send_even_if_empty >= 0)
+      EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty),
+                encoded_info.send_even_if_empty);
+  }
+
+  WebRtcACMCodecParams acm_codec_params_;
+  scoped_ptr<ACMGenericCodec> codec_;
+  uint32_t timestamp_;
+};
+
+// This test verifies that CNG frames are delivered as expected. Since the frame
+// size is set to 20 ms, we expect the first encode call to produce no output
+// (which is signaled as 0 bytes output of type kNoEncoding). The next encode
+// call should produce one SID frame of 9 bytes. The third call should not
+// result in any output (just like the first one). The fourth and final encode
+// call should produce an "empty frame", which is like no output, but with the
+// return value from the encode function being 1. (The reason to produce an
+// empty frame is to drive sending of DTMF packets in the RTP/RTCP module.)
+TEST_F(AcmGenericCodecTest, VerifyCngFrames) {
+  CreateCodec();
+  uint32_t expected_timestamp = timestamp_;
+  // Verify no frame.
+  AddData();
+  {
+    SCOPED_TRACE("First encoding");
+    EncodeAndVerify(0, 0, expected_timestamp, kNoEncoding, -1, -1);
+  }
+
+  // Verify SID frame delivered.
+  AddData();
+  {
+    SCOPED_TRACE("Second encoding");
+    EncodeAndVerify(9, 9, expected_timestamp, kPassiveDTXNB, kCngPt, 1);
+  }
+
+  // Verify no frame.
+  AddData();
+  {
+    SCOPED_TRACE("Third encoding");
+    EncodeAndVerify(0, 0, expected_timestamp, kNoEncoding, -1, -1);
+  }
+
+  // Verify NoEncoding.
+  AddData();
+  expected_timestamp += 2 * kDataLengthSamples;
+  {
+    SCOPED_TRACE("Fourth encoding");
+    EncodeAndVerify(1, 0, expected_timestamp, kNoEncoding, kCngPt, 1);
+  }
+}
+
+}  // namespace acm2
+}  // namespace webrtc
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 5b78e7a..8bb3745 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -91,6 +91,7 @@
           ],
           'sources': [
             'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc',
+            'audio_coding/main/acm2/acm_generic_codec_test.cc',
             'audio_coding/main/acm2/acm_generic_codec_opus_test.cc',
             'audio_coding/main/acm2/acm_receiver_unittest.cc',
             'audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc',