1ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org/*
2ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *
4ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
5ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org */
10ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
1151ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org#include <vector>
1251ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org
13ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
1400b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h"
15ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org#include "webrtc/common_audio/vad/mock/mock_vad.h"
163c652b67468d182bd36aee4c31557621be50cc92kjellander@webrtc.org#include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h"
17ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h"
18ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
19ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgusing ::testing::Return;
20ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgusing ::testing::_;
21ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgusing ::testing::SetArgPointee;
22ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgusing ::testing::InSequence;
233b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.orgusing ::testing::Invoke;
24ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
25ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgnamespace webrtc {
26ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
27ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgnamespace {
2851ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.orgstatic const size_t kMockMaxEncodedBytes = 1000;
29ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgstatic const size_t kMaxNumSamples = 48 * 10 * 2;  // 10 ms @ 48 kHz stereo.
30ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgstatic const size_t kMockReturnEncodedBytes = 17;
31ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgstatic const int kCngPayloadType = 18;
32ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
33ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
34ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgclass AudioEncoderCngTest : public ::testing::Test {
35ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org protected:
36ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  AudioEncoderCngTest()
37e9e7896293747b2084e7f018675276f5096cdafckwiberg      : mock_vad_(new MockVad),
38ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        timestamp_(4711),
398bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org        num_audio_samples_10ms_(0),
408bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org        sample_rate_hz_(8000) {
41ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    memset(audio_, 0, kMaxNumSamples * 2);
42ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    config_.speech_encoder = &mock_encoder_;
4305211277798ca4791fbdc508e24d7fd06d5ee6ffkwiberg@webrtc.org    EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
44ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Let the AudioEncoderCng object use a MockVad instead of its internally
45ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // created Vad object.
46ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    config_.vad = mock_vad_;
47ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    config_.payload_type = kCngPayloadType;
48ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
49ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
5014665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void TearDown() override {
51ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(*mock_vad_, Die()).Times(1);
52ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    cng_.reset();
53ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Don't expect the cng_ object to delete the AudioEncoder object. But it
54ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // will be deleted with the test fixture. This is why we explicitly delete
55ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // the cng_ object above, and set expectations on mock_encoder_ afterwards.
56ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(mock_encoder_, Die()).Times(1);
57ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
58ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
59ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  void CreateCng() {
60ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // The config_ parameters may be changed by the TEST_Fs up until CreateCng()
61ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // is called, thus we cannot use the values until now.
62dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000);
63ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples);
6405211277798ca4791fbdc508e24d7fd06d5ee6ffkwiberg@webrtc.org    EXPECT_CALL(mock_encoder_, SampleRateHz())
658bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org        .WillRepeatedly(Return(sample_rate_hz_));
66ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Max10MsFramesInAPacket() is just used to verify that the SID frame period
67ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // is not too small. The return value does not matter that much, as long as
68ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // it is smaller than 10.
69dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1u));
7051ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org    EXPECT_CALL(mock_encoder_, MaxEncodedBytes())
7151ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org        .WillRepeatedly(Return(kMockMaxEncodedBytes));
72ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    cng_.reset(new AudioEncoderCng(config_));
7351ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org    encoded_.resize(cng_->MaxEncodedBytes(), 0);
74ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
75ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
76ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  void Encode() {
77ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    ASSERT_TRUE(cng_) << "Must call CreateCng() first.";
78288886b2ec9a2dac730f115e9c3079d8439efe60kwiberg    encoded_info_ = cng_->Encode(
79288886b2ec9a2dac730f115e9c3079d8439efe60kwiberg        timestamp_,
80288886b2ec9a2dac730f115e9c3079d8439efe60kwiberg        rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_),
81288886b2ec9a2dac730f115e9c3079d8439efe60kwiberg        encoded_.size(), &encoded_[0]);
82b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting    timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_);
83ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
84ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
85367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  // Expect |num_calls| calls to the encoder, all successful. The last call
86367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  // claims to have encoded |kMockMaxEncodedBytes| bytes, and all the preceding
87367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  // ones 0 bytes.
88dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void ExpectEncodeCalls(size_t num_calls) {
89367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    InSequence s;
90367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    AudioEncoder::EncodedInfo info;
91dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t j = 0; j < num_calls - 1; ++j) {
92367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin      EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
93367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin          .WillOnce(Return(info));
94367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    }
95367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    info.encoded_bytes = kMockReturnEncodedBytes;
96367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
97367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin        .WillOnce(Return(info));
98367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  }
99367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin
100ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Verifies that the cng_ object waits until it has collected
101ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // |blocks_per_frame| blocks of audio, and then dispatches all of them to
102ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // the underlying codec (speech or cng).
103dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) {
104ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
105ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        .WillRepeatedly(Return(blocks_per_frame));
106ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    CreateCng();
107ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
108ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive));
109ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
110ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Don't expect any calls to the encoder yet.
1119afaee74ab1ef36c8b4ea4c22f4c5aebf2359da2jmarusic@webrtc.org    EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0);
112dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
113ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      Encode();
1143b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org      EXPECT_EQ(0u, encoded_info_.encoded_bytes);
115ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
116367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin    if (active_speech)
117367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin      ExpectEncodeCalls(blocks_per_frame);
118ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    Encode();
119ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    if (active_speech) {
1203b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org      EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
121ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    } else {
122ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients + 1),
1233b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org                encoded_info_.encoded_bytes);
124ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
125ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
126ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
127ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Verifies that the audio is partitioned into larger blocks before calling
128ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // the VAD.
129ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  void CheckVadInputSize(int input_frame_size_ms,
130ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org                         int expected_first_block_size_ms,
131ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org                         int expected_second_block_size_ms) {
132dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t blocks_per_frame =
133dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting        static_cast<size_t>(input_frame_size_ms / 10);
134ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
135ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
136ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        .WillRepeatedly(Return(blocks_per_frame));
137ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
138ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Expect nothing to happen before the last block is sent to cng_.
139ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)).Times(0);
140dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
141ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      Encode();
142ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
143ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
144ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Let the VAD decision be passive, since an active decision may lead to
145ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // early termination of the decision loop.
146ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    InSequence s;
147ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(
148ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        *mock_vad_,
1498bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org        VoiceActivity(_, expected_first_block_size_ms * sample_rate_hz_ / 1000,
1508bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org                      sample_rate_hz_)).WillOnce(Return(Vad::kPassive));
151ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    if (expected_second_block_size_ms > 0) {
152ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      EXPECT_CALL(*mock_vad_,
153ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org                  VoiceActivity(
1548bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org                      _, expected_second_block_size_ms * sample_rate_hz_ / 1000,
1558bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org                      sample_rate_hz_)).WillOnce(Return(Vad::kPassive));
156ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
157ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
158ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // With this call to Encode(), |mock_vad_| should be called according to the
159ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // above expectations.
160ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    Encode();
161ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
162ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
163ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Tests a frame with both active and passive speech. Returns true if the
164ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // decision was active speech, false if it was passive.
165ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  bool CheckMixedActivePassive(Vad::Activity first_type,
166ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org                               Vad::Activity second_type) {
167ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Set the speech encoder frame size to 60 ms, to ensure that the VAD will
168ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // be called twice.
169dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    const size_t blocks_per_frame = 6;
170ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
171ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        .WillRepeatedly(Return(blocks_per_frame));
172ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    InSequence s;
173ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
174ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        .WillOnce(Return(first_type));
175ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    if (first_type == Vad::kPassive) {
176ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      // Expect a second call to the VAD only if the first frame was passive.
177ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
178ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org          .WillOnce(Return(second_type));
179ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
180ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    encoded_info_.payload_type = 0;
181dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    for (size_t i = 0; i < blocks_per_frame; ++i) {
182ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      Encode();
183ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
184ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    return encoded_info_.payload_type != kCngPayloadType;
185ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
186ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
187ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  AudioEncoderCng::Config config_;
18800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<AudioEncoderCng> cng_;
189ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  MockAudioEncoder mock_encoder_;
190ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  MockVad* mock_vad_;  // Ownership is transferred to |cng_|.
191ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  uint32_t timestamp_;
192ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  int16_t audio_[kMaxNumSamples];
193ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  size_t num_audio_samples_10ms_;
19451ccf376387266225cd8c78e63238b725860f0afjmarusic@webrtc.org  std::vector<uint8_t> encoded_;
195ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  AudioEncoder::EncodedInfo encoded_info_;
1968bb32d600b85b2d3b85598f43f009f82faad6006henrik.lundin@webrtc.org  int sample_rate_hz_;
197ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org};
198ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
199ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, CreateAndDestroy) {
200ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
201ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
202ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
203ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) {
204ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
205dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(17U));
206dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket());
207ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
208ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
209478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, CheckChangeBitratePropagation) {
210478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  CreateCng();
211478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, SetTargetBitrate(4711));
212478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  cng_->SetTargetBitrate(4711);
213478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org}
214478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org
215478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, CheckProjectedPacketLossRatePropagation) {
216478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  CreateCng();
217478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, SetProjectedPacketLossRate(0.5));
218478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org  cng_->SetProjectedPacketLossRate(0.5);
219478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org}
220478cedc055f95bd160b53a4d7b69d8b3dd023ec7henrik.lundin@webrtc.org
221ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCallsVad) {
222ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
223dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      .WillRepeatedly(Return(1U));
224ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
225ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
226ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillOnce(Return(Vad::kPassive));
227ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
228ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
229ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
230ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects1BlockPassiveSpeech) {
231ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(1, false);
232ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
233ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
234ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects2BlocksPassiveSpeech) {
235ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(2, false);
236ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
237ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
238ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects3BlocksPassiveSpeech) {
239ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(3, false);
240ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
241ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
242ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects1BlockActiveSpeech) {
243ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(1, true);
244ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
245ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
246ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects2BlocksActiveSpeech) {
247ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(2, true);
248ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
249ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
250ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) {
251ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckBlockGrouping(3, true);
252ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
253ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
254ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, EncodePassive) {
255dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  const size_t kBlocksPerFrame = 3;
256ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
257ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillRepeatedly(Return(kBlocksPerFrame));
258ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
259ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
260ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillRepeatedly(Return(Vad::kPassive));
261ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Expect no calls at all to the speech encoder mock.
2629afaee74ab1ef36c8b4ea4c22f4c5aebf2359da2jmarusic@webrtc.org  EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0);
263ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  uint32_t expected_timestamp = timestamp_;
264dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  for (size_t i = 0; i < 100; ++i) {
265ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    Encode();
266ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Check if it was time to call the cng encoder. This is done once every
267ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // |kBlocksPerFrame| calls.
268ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    if ((i + 1) % kBlocksPerFrame == 0) {
269ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      // Now check if a SID interval has elapsed.
270ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      if ((i % (config_.sid_frame_interval_ms / 10)) < kBlocksPerFrame) {
271ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        // If so, verify that we got a CNG encoding.
272ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
273c86bbbaa9348b868e94c021426abcc2f5e0144b0henrik.lundin@webrtc.org        EXPECT_FALSE(encoded_info_.speech);
274ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
2753b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org                  encoded_info_.encoded_bytes);
276ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org        EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp);
277ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      }
278ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      expected_timestamp += kBlocksPerFrame * num_audio_samples_10ms_;
279ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    } else {
280ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      // Otherwise, expect no output.
2813b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org      EXPECT_EQ(0u, encoded_info_.encoded_bytes);
282ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    }
283ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
284ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
285ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
286ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// Verifies that the correct action is taken for frames with both active and
287ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// passive speech.
288ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, MixedActivePassive) {
289ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
290ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
291ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // All of the frame is active speech.
292367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  ExpectEncodeCalls(6);
293ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kActive));
294c86bbbaa9348b868e94c021426abcc2f5e0144b0henrik.lundin@webrtc.org  EXPECT_TRUE(encoded_info_.speech);
295ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
296ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // First half of the frame is active speech.
297367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  ExpectEncodeCalls(6);
298ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kPassive));
299c86bbbaa9348b868e94c021426abcc2f5e0144b0henrik.lundin@webrtc.org  EXPECT_TRUE(encoded_info_.speech);
300ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
301ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Second half of the frame is active speech.
302367c868c998e96bc1aac41b607548d6125fa6b1eHenrik Lundin  ExpectEncodeCalls(6);
303ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_TRUE(CheckMixedActivePassive(Vad::kPassive, Vad::kActive));
304c86bbbaa9348b868e94c021426abcc2f5e0144b0henrik.lundin@webrtc.org  EXPECT_TRUE(encoded_info_.speech);
305ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
306ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // All of the frame is passive speech. Expect no calls to |mock_encoder_|.
307ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_FALSE(CheckMixedActivePassive(Vad::kPassive, Vad::kPassive));
308c86bbbaa9348b868e94c021426abcc2f5e0144b0henrik.lundin@webrtc.org  EXPECT_FALSE(encoded_info_.speech);
309ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
310ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
311ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// These tests verify that the audio is partitioned into larger blocks before
312ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// calling the VAD.
313ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// The parameters for CheckVadInputSize are:
314ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// CheckVadInputSize(frame_size, expected_first_block_size,
315ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org//                   expected_second_block_size);
316ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize10Ms) {
317ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
318ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(10, 10, 0);
319ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
320ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize20Ms) {
321ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
322ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(20, 20, 0);
323ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
324ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize30Ms) {
325ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
326ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(30, 30, 0);
327ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
328ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize40Ms) {
329ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
330ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(40, 20, 20);
331ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
332ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize50Ms) {
333ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
334ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(50, 30, 20);
335ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
336ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VadInputSize60Ms) {
337ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
338ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CheckVadInputSize(60, 30, 30);
339ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
340ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
341ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// Verifies that the correct payload type is set when CNG is encoded.
342ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VerifyCngPayloadType) {
343ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
3449afaee74ab1ef36c8b4ea4c22f4c5aebf2359da2jmarusic@webrtc.org  EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0);
345dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U));
346ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
347ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillOnce(Return(Vad::kPassive));
348ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  encoded_info_.payload_type = 0;
349ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
350ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
351ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
352ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
353ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// Verifies that a SID frame is encoded immediately as the signal changes from
354ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// active speech to passive.
355ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
356ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
357ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
358dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      .WillRepeatedly(Return(1U));
359ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Start with encoding noise.
360ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
361ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .Times(2)
362ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillRepeatedly(Return(Vad::kPassive));
363ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
364ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
365ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
3663b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org            encoded_info_.encoded_bytes);
367ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Encode again, and make sure we got no frame at all (since the SID frame
368ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // period is 100 ms by default).
369ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
3703b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org  EXPECT_EQ(0u, encoded_info_.encoded_bytes);
371ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
372ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Now encode active speech.
373ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  encoded_info_.payload_type = 0;
374ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
375ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillOnce(Return(Vad::kActive));
3763b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org  AudioEncoder::EncodedInfo info;
3773b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org  info.encoded_bytes = kMockReturnEncodedBytes;
3789afaee74ab1ef36c8b4ea4c22f4c5aebf2359da2jmarusic@webrtc.org  EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).WillOnce(Return(info));
379ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
3803b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org  EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
381ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
382ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Go back to noise again, and verify that a SID frame is emitted.
383ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
384ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org      .WillOnce(Return(Vad::kPassive));
385ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  Encode();
386ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
387ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
3883b79daff14127f3adb19b16d94336d44ff49e841henrik.lundin@webrtc.org            encoded_info_.encoded_bytes);
389ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
390ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
39112cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg// Resetting the CNG should reset both the VAD and the encoder.
39212cfc9b4dacd6942377df1f29a64bdbec591920ekwibergTEST_F(AudioEncoderCngTest, Reset) {
39312cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg  CreateCng();
39412cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg  EXPECT_CALL(mock_encoder_, Reset()).Times(1);
39512cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg  EXPECT_CALL(*mock_vad_, Reset()).Times(1);
39612cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg  cng_->Reset();
39712cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg}
39812cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg
399ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
400ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
401ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// This test fixture tests various error conditions that makes the
402ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org// AudioEncoderCng die via CHECKs.
403ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgclass AudioEncoderCngDeathTest : public AudioEncoderCngTest {
404ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org protected:
405ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  AudioEncoderCngDeathTest() : AudioEncoderCngTest() {
406ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Don't provide a Vad mock object, since it will leak when the test dies.
407ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    config_.vad = NULL;
408ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(*mock_vad_, Die()).Times(1);
409ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    delete mock_vad_;
410ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    mock_vad_ = NULL;
411ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
412ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
413ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // Override AudioEncoderCngTest::TearDown, since that one expects a call to
414ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // the destructor of |mock_vad_|. In this case, that object is already
415ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  // deleted.
41614665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void TearDown() override {
417ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    cng_.reset();
418ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // Don't expect the cng_ object to delete the AudioEncoder object. But it
419ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // will be deleted with the test fixture. This is why we explicitly delete
420ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    // the cng_ object above, and set expectations on mock_encoder_ afterwards.
421ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    EXPECT_CALL(mock_encoder_, Die()).Times(1);
422ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  }
423ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org};
424ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
425ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngDeathTest, WrongFrameSize) {
426ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
427ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  num_audio_samples_10ms_ *= 2;  // 20 ms frame.
428ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(Encode(), "");
429ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  num_audio_samples_10ms_ = 0;  // Zero samples.
430ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(Encode(), "");
431ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
432ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
433ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngDeathTest, WrongNumCoefficients) {
434ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  config_.num_cng_coefficients = -1;
435ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
436ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  config_.num_cng_coefficients = 0;
437ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
438ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  config_.num_cng_coefficients = 13;
439ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
440ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
441ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
442ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) {
443ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  config_.speech_encoder = NULL;
444ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
445ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
446ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
447ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngDeathTest, Stereo) {
44805211277798ca4791fbdc508e24d7fd06d5ee6ffkwiberg@webrtc.org  EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(2));
449ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
450ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  config_.num_channels = 2;
451ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(CreateCng(), "Invalid configuration");
452ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
453ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
454ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.orgTEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) {
455ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  CreateCng();
456ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
457dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      .WillRepeatedly(Return(7U));
458ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  for (int i = 0; i < 6; ++i)
459ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org    Encode();
460ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org  EXPECT_DEATH(Encode(),
461ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org               "Frame size cannot be larger than 60 ms when using VAD/CNG.");
462ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}
463ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
464ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org#endif  // GTEST_HAS_DEATH_TEST
465ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org
466ff1a3e36bdd023fc2d3bef9af6b161ce144ffd6bhenrik.lundin@webrtc.org}  // namespace webrtc
467