OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
27 namespace { | 27 namespace { |
28 static const size_t kMockMaxEncodedBytes = 1000; | 28 static const size_t kMockMaxEncodedBytes = 1000; |
29 static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo. | 29 static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo. |
30 static const size_t kMockReturnEncodedBytes = 17; | 30 static const size_t kMockReturnEncodedBytes = 17; |
31 static const int kCngPayloadType = 18; | 31 static const int kCngPayloadType = 18; |
32 } | 32 } |
33 | 33 |
34 class AudioEncoderCngTest : public ::testing::Test { | 34 class AudioEncoderCngTest : public ::testing::Test { |
35 protected: | 35 protected: |
36 AudioEncoderCngTest() | 36 AudioEncoderCngTest() |
37 : mock_vad_(new MockVad), | 37 : mock_encoder_owner_(new MockAudioEncoder), |
| 38 mock_encoder_(mock_encoder_owner_.get()), |
| 39 mock_vad_(new MockVad), |
38 timestamp_(4711), | 40 timestamp_(4711), |
39 num_audio_samples_10ms_(0), | 41 num_audio_samples_10ms_(0), |
40 sample_rate_hz_(8000) { | 42 sample_rate_hz_(8000) { |
41 memset(audio_, 0, kMaxNumSamples * 2); | 43 memset(audio_, 0, kMaxNumSamples * 2); |
42 config_.speech_encoder = &mock_encoder_; | 44 EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(1)); |
43 EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1)); | 45 EXPECT_CALL(*mock_encoder_, Die()).Times(1); |
44 // Let the AudioEncoderCng object use a MockVad instead of its internally | |
45 // created Vad object. | |
46 config_.vad = mock_vad_; | |
47 config_.payload_type = kCngPayloadType; | |
48 } | 46 } |
49 | 47 |
50 void TearDown() override { | 48 void TearDown() override { |
51 EXPECT_CALL(*mock_vad_, Die()).Times(1); | 49 EXPECT_CALL(*mock_vad_, Die()).Times(1); |
52 cng_.reset(); | 50 cng_.reset(); |
53 // Don't expect the cng_ object to delete the AudioEncoder object. But it | |
54 // will be deleted with the test fixture. This is why we explicitly delete | |
55 // the cng_ object above, and set expectations on mock_encoder_ afterwards. | |
56 EXPECT_CALL(mock_encoder_, Die()).Times(1); | |
57 } | 51 } |
58 | 52 |
59 void CreateCng() { | 53 AudioEncoderCng::Config MakeCngConfig() { |
60 // The config_ parameters may be changed by the TEST_Fs up until CreateCng() | 54 AudioEncoderCng::Config config; |
61 // is called, thus we cannot use the values until now. | 55 config.speech_encoder = std::move(mock_encoder_owner_); |
| 56 EXPECT_TRUE(config.speech_encoder); |
| 57 |
| 58 // Let the AudioEncoderCng object use a MockVad instead of its internally |
| 59 // created Vad object. |
| 60 config.vad = mock_vad_; |
| 61 config.payload_type = kCngPayloadType; |
| 62 |
| 63 return config; |
| 64 } |
| 65 |
| 66 void CreateCng(AudioEncoderCng::Config&& config) { |
62 num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000); | 67 num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000); |
63 ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples); | 68 ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples); |
64 EXPECT_CALL(mock_encoder_, SampleRateHz()) | 69 if (config.speech_encoder) { |
65 .WillRepeatedly(Return(sample_rate_hz_)); | 70 EXPECT_CALL(*mock_encoder_, SampleRateHz()) |
66 // Max10MsFramesInAPacket() is just used to verify that the SID frame period | 71 .WillRepeatedly(Return(sample_rate_hz_)); |
67 // is not too small. The return value does not matter that much, as long as | 72 // Max10MsFramesInAPacket() is just used to verify that the SID frame |
68 // it is smaller than 10. | 73 // period is not too small. The return value does not matter that much, |
69 EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1u)); | 74 // as long as it is smaller than 10. |
70 EXPECT_CALL(mock_encoder_, MaxEncodedBytes()) | 75 EXPECT_CALL(*mock_encoder_, Max10MsFramesInAPacket()) |
71 .WillRepeatedly(Return(kMockMaxEncodedBytes)); | 76 .WillOnce(Return(1u)); |
72 cng_.reset(new AudioEncoderCng(config_)); | 77 EXPECT_CALL(*mock_encoder_, MaxEncodedBytes()) |
| 78 .WillRepeatedly(Return(kMockMaxEncodedBytes)); |
| 79 } |
| 80 cng_.reset(new AudioEncoderCng(std::move(config))); |
73 } | 81 } |
74 | 82 |
75 void Encode() { | 83 void Encode() { |
76 ASSERT_TRUE(cng_) << "Must call CreateCng() first."; | 84 ASSERT_TRUE(cng_) << "Must call CreateCng() first."; |
77 encoded_info_ = cng_->Encode( | 85 encoded_info_ = cng_->Encode( |
78 timestamp_, | 86 timestamp_, |
79 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_), | 87 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_), |
80 &encoded_); | 88 &encoded_); |
81 timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_); | 89 timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_); |
82 } | 90 } |
83 | 91 |
84 // Expect |num_calls| calls to the encoder, all successful. The last call | 92 // Expect |num_calls| calls to the encoder, all successful. The last call |
85 // claims to have encoded |kMockMaxEncodedBytes| bytes, and all the preceding | 93 // claims to have encoded |kMockMaxEncodedBytes| bytes, and all the preceding |
86 // ones 0 bytes. | 94 // ones 0 bytes. |
87 void ExpectEncodeCalls(size_t num_calls) { | 95 void ExpectEncodeCalls(size_t num_calls) { |
88 InSequence s; | 96 InSequence s; |
89 AudioEncoder::EncodedInfo info; | 97 AudioEncoder::EncodedInfo info; |
90 for (size_t j = 0; j < num_calls - 1; ++j) { | 98 for (size_t j = 0; j < num_calls - 1; ++j) { |
91 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)) | 99 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)) |
92 .WillOnce(Return(info)); | 100 .WillOnce(Return(info)); |
93 } | 101 } |
94 info.encoded_bytes = kMockReturnEncodedBytes; | 102 info.encoded_bytes = kMockReturnEncodedBytes; |
95 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)) | 103 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)) |
96 .WillOnce(Invoke( | 104 .WillOnce( |
97 MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); | 105 Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); |
98 } | 106 } |
99 | 107 |
100 // Verifies that the cng_ object waits until it has collected | 108 // Verifies that the cng_ object waits until it has collected |
101 // |blocks_per_frame| blocks of audio, and then dispatches all of them to | 109 // |blocks_per_frame| blocks of audio, and then dispatches all of them to |
102 // the underlying codec (speech or cng). | 110 // the underlying codec (speech or cng). |
103 void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) { | 111 void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) { |
104 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 112 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
105 .WillRepeatedly(Return(blocks_per_frame)); | 113 .WillRepeatedly(Return(blocks_per_frame)); |
106 CreateCng(); | 114 auto config = MakeCngConfig(); |
| 115 const int num_cng_coefficients = config.num_cng_coefficients; |
| 116 CreateCng(std::move(config)); |
107 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 117 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
108 .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive)); | 118 .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive)); |
109 | 119 |
110 // Don't expect any calls to the encoder yet. | 120 // Don't expect any calls to the encoder yet. |
111 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0); | 121 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0); |
112 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { | 122 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { |
113 Encode(); | 123 Encode(); |
114 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 124 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
115 } | 125 } |
116 if (active_speech) | 126 if (active_speech) |
117 ExpectEncodeCalls(blocks_per_frame); | 127 ExpectEncodeCalls(blocks_per_frame); |
118 Encode(); | 128 Encode(); |
119 if (active_speech) { | 129 if (active_speech) { |
120 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); | 130 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); |
121 } else { | 131 } else { |
122 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients + 1), | 132 EXPECT_EQ(static_cast<size_t>(num_cng_coefficients + 1), |
123 encoded_info_.encoded_bytes); | 133 encoded_info_.encoded_bytes); |
124 } | 134 } |
125 } | 135 } |
126 | 136 |
127 // Verifies that the audio is partitioned into larger blocks before calling | 137 // Verifies that the audio is partitioned into larger blocks before calling |
128 // the VAD. | 138 // the VAD. |
129 void CheckVadInputSize(int input_frame_size_ms, | 139 void CheckVadInputSize(int input_frame_size_ms, |
130 int expected_first_block_size_ms, | 140 int expected_first_block_size_ms, |
131 int expected_second_block_size_ms) { | 141 int expected_second_block_size_ms) { |
132 const size_t blocks_per_frame = | 142 const size_t blocks_per_frame = |
133 static_cast<size_t>(input_frame_size_ms / 10); | 143 static_cast<size_t>(input_frame_size_ms / 10); |
134 | 144 |
135 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 145 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
136 .WillRepeatedly(Return(blocks_per_frame)); | 146 .WillRepeatedly(Return(blocks_per_frame)); |
137 | 147 |
138 // Expect nothing to happen before the last block is sent to cng_. | 148 // Expect nothing to happen before the last block is sent to cng_. |
139 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)).Times(0); | 149 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)).Times(0); |
140 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { | 150 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { |
141 Encode(); | 151 Encode(); |
142 } | 152 } |
143 | 153 |
144 // Let the VAD decision be passive, since an active decision may lead to | 154 // Let the VAD decision be passive, since an active decision may lead to |
145 // early termination of the decision loop. | 155 // early termination of the decision loop. |
(...skipping 14 matching lines...) Expand all Loading... |
160 Encode(); | 170 Encode(); |
161 } | 171 } |
162 | 172 |
163 // Tests a frame with both active and passive speech. Returns true if the | 173 // Tests a frame with both active and passive speech. Returns true if the |
164 // decision was active speech, false if it was passive. | 174 // decision was active speech, false if it was passive. |
165 bool CheckMixedActivePassive(Vad::Activity first_type, | 175 bool CheckMixedActivePassive(Vad::Activity first_type, |
166 Vad::Activity second_type) { | 176 Vad::Activity second_type) { |
167 // Set the speech encoder frame size to 60 ms, to ensure that the VAD will | 177 // Set the speech encoder frame size to 60 ms, to ensure that the VAD will |
168 // be called twice. | 178 // be called twice. |
169 const size_t blocks_per_frame = 6; | 179 const size_t blocks_per_frame = 6; |
170 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 180 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
171 .WillRepeatedly(Return(blocks_per_frame)); | 181 .WillRepeatedly(Return(blocks_per_frame)); |
172 InSequence s; | 182 InSequence s; |
173 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 183 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
174 .WillOnce(Return(first_type)); | 184 .WillOnce(Return(first_type)); |
175 if (first_type == Vad::kPassive) { | 185 if (first_type == Vad::kPassive) { |
176 // Expect a second call to the VAD only if the first frame was passive. | 186 // Expect a second call to the VAD only if the first frame was passive. |
177 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 187 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
178 .WillOnce(Return(second_type)); | 188 .WillOnce(Return(second_type)); |
179 } | 189 } |
180 encoded_info_.payload_type = 0; | 190 encoded_info_.payload_type = 0; |
181 for (size_t i = 0; i < blocks_per_frame; ++i) { | 191 for (size_t i = 0; i < blocks_per_frame; ++i) { |
182 Encode(); | 192 Encode(); |
183 } | 193 } |
184 return encoded_info_.payload_type != kCngPayloadType; | 194 return encoded_info_.payload_type != kCngPayloadType; |
185 } | 195 } |
186 | 196 |
187 AudioEncoderCng::Config config_; | |
188 std::unique_ptr<AudioEncoderCng> cng_; | 197 std::unique_ptr<AudioEncoderCng> cng_; |
189 MockAudioEncoder mock_encoder_; | 198 std::unique_ptr<MockAudioEncoder> mock_encoder_owner_; |
| 199 MockAudioEncoder* mock_encoder_; |
190 MockVad* mock_vad_; // Ownership is transferred to |cng_|. | 200 MockVad* mock_vad_; // Ownership is transferred to |cng_|. |
191 uint32_t timestamp_; | 201 uint32_t timestamp_; |
192 int16_t audio_[kMaxNumSamples]; | 202 int16_t audio_[kMaxNumSamples]; |
193 size_t num_audio_samples_10ms_; | 203 size_t num_audio_samples_10ms_; |
194 rtc::Buffer encoded_; | 204 rtc::Buffer encoded_; |
195 AudioEncoder::EncodedInfo encoded_info_; | 205 AudioEncoder::EncodedInfo encoded_info_; |
196 int sample_rate_hz_; | 206 int sample_rate_hz_; |
| 207 |
| 208 RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderCngTest); |
197 }; | 209 }; |
198 | 210 |
199 TEST_F(AudioEncoderCngTest, CreateAndDestroy) { | 211 TEST_F(AudioEncoderCngTest, CreateAndDestroy) { |
200 CreateCng(); | 212 CreateCng(MakeCngConfig()); |
201 } | 213 } |
202 | 214 |
203 TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) { | 215 TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) { |
204 CreateCng(); | 216 CreateCng(MakeCngConfig()); |
205 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(17U)); | 217 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
| 218 .WillOnce(Return(17U)); |
206 EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket()); | 219 EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket()); |
207 } | 220 } |
208 | 221 |
209 TEST_F(AudioEncoderCngTest, CheckChangeBitratePropagation) { | 222 TEST_F(AudioEncoderCngTest, CheckChangeBitratePropagation) { |
210 CreateCng(); | 223 CreateCng(MakeCngConfig()); |
211 EXPECT_CALL(mock_encoder_, SetTargetBitrate(4711)); | 224 EXPECT_CALL(*mock_encoder_, SetTargetBitrate(4711)); |
212 cng_->SetTargetBitrate(4711); | 225 cng_->SetTargetBitrate(4711); |
213 } | 226 } |
214 | 227 |
215 TEST_F(AudioEncoderCngTest, CheckProjectedPacketLossRatePropagation) { | 228 TEST_F(AudioEncoderCngTest, CheckProjectedPacketLossRatePropagation) { |
216 CreateCng(); | 229 CreateCng(MakeCngConfig()); |
217 EXPECT_CALL(mock_encoder_, SetProjectedPacketLossRate(0.5)); | 230 EXPECT_CALL(*mock_encoder_, SetProjectedPacketLossRate(0.5)); |
218 cng_->SetProjectedPacketLossRate(0.5); | 231 cng_->SetProjectedPacketLossRate(0.5); |
219 } | 232 } |
220 | 233 |
221 TEST_F(AudioEncoderCngTest, EncodeCallsVad) { | 234 TEST_F(AudioEncoderCngTest, EncodeCallsVad) { |
222 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 235 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
223 .WillRepeatedly(Return(1U)); | 236 .WillRepeatedly(Return(1U)); |
224 CreateCng(); | 237 CreateCng(MakeCngConfig()); |
225 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 238 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
226 .WillOnce(Return(Vad::kPassive)); | 239 .WillOnce(Return(Vad::kPassive)); |
227 Encode(); | 240 Encode(); |
228 } | 241 } |
229 | 242 |
230 TEST_F(AudioEncoderCngTest, EncodeCollects1BlockPassiveSpeech) { | 243 TEST_F(AudioEncoderCngTest, EncodeCollects1BlockPassiveSpeech) { |
231 CheckBlockGrouping(1, false); | 244 CheckBlockGrouping(1, false); |
232 } | 245 } |
233 | 246 |
234 TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksPassiveSpeech) { | 247 TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksPassiveSpeech) { |
(...skipping 11 matching lines...) Expand all Loading... |
246 TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksActiveSpeech) { | 259 TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksActiveSpeech) { |
247 CheckBlockGrouping(2, true); | 260 CheckBlockGrouping(2, true); |
248 } | 261 } |
249 | 262 |
250 TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) { | 263 TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) { |
251 CheckBlockGrouping(3, true); | 264 CheckBlockGrouping(3, true); |
252 } | 265 } |
253 | 266 |
254 TEST_F(AudioEncoderCngTest, EncodePassive) { | 267 TEST_F(AudioEncoderCngTest, EncodePassive) { |
255 const size_t kBlocksPerFrame = 3; | 268 const size_t kBlocksPerFrame = 3; |
256 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 269 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
257 .WillRepeatedly(Return(kBlocksPerFrame)); | 270 .WillRepeatedly(Return(kBlocksPerFrame)); |
258 CreateCng(); | 271 auto config = MakeCngConfig(); |
| 272 const auto sid_frame_interval_ms = config.sid_frame_interval_ms; |
| 273 const auto num_cng_coefficients = config.num_cng_coefficients; |
| 274 CreateCng(std::move(config)); |
259 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 275 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
260 .WillRepeatedly(Return(Vad::kPassive)); | 276 .WillRepeatedly(Return(Vad::kPassive)); |
261 // Expect no calls at all to the speech encoder mock. | 277 // Expect no calls at all to the speech encoder mock. |
262 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0); | 278 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0); |
263 uint32_t expected_timestamp = timestamp_; | 279 uint32_t expected_timestamp = timestamp_; |
264 for (size_t i = 0; i < 100; ++i) { | 280 for (size_t i = 0; i < 100; ++i) { |
265 Encode(); | 281 Encode(); |
266 // Check if it was time to call the cng encoder. This is done once every | 282 // Check if it was time to call the cng encoder. This is done once every |
267 // |kBlocksPerFrame| calls. | 283 // |kBlocksPerFrame| calls. |
268 if ((i + 1) % kBlocksPerFrame == 0) { | 284 if ((i + 1) % kBlocksPerFrame == 0) { |
269 // Now check if a SID interval has elapsed. | 285 // Now check if a SID interval has elapsed. |
270 if ((i % (config_.sid_frame_interval_ms / 10)) < kBlocksPerFrame) { | 286 if ((i % (sid_frame_interval_ms / 10)) < kBlocksPerFrame) { |
271 // If so, verify that we got a CNG encoding. | 287 // If so, verify that we got a CNG encoding. |
272 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 288 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
273 EXPECT_FALSE(encoded_info_.speech); | 289 EXPECT_FALSE(encoded_info_.speech); |
274 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1, | 290 EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1, |
275 encoded_info_.encoded_bytes); | 291 encoded_info_.encoded_bytes); |
276 EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp); | 292 EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp); |
277 } | 293 } |
278 expected_timestamp += kBlocksPerFrame * num_audio_samples_10ms_; | 294 expected_timestamp += kBlocksPerFrame * num_audio_samples_10ms_; |
279 } else { | 295 } else { |
280 // Otherwise, expect no output. | 296 // Otherwise, expect no output. |
281 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 297 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
282 } | 298 } |
283 } | 299 } |
284 } | 300 } |
285 | 301 |
286 // Verifies that the correct action is taken for frames with both active and | 302 // Verifies that the correct action is taken for frames with both active and |
287 // passive speech. | 303 // passive speech. |
288 TEST_F(AudioEncoderCngTest, MixedActivePassive) { | 304 TEST_F(AudioEncoderCngTest, MixedActivePassive) { |
289 CreateCng(); | 305 CreateCng(MakeCngConfig()); |
290 | 306 |
291 // All of the frame is active speech. | 307 // All of the frame is active speech. |
292 ExpectEncodeCalls(6); | 308 ExpectEncodeCalls(6); |
293 EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kActive)); | 309 EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kActive)); |
294 EXPECT_TRUE(encoded_info_.speech); | 310 EXPECT_TRUE(encoded_info_.speech); |
295 | 311 |
296 // First half of the frame is active speech. | 312 // First half of the frame is active speech. |
297 ExpectEncodeCalls(6); | 313 ExpectEncodeCalls(6); |
298 EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kPassive)); | 314 EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kPassive)); |
299 EXPECT_TRUE(encoded_info_.speech); | 315 EXPECT_TRUE(encoded_info_.speech); |
300 | 316 |
301 // Second half of the frame is active speech. | 317 // Second half of the frame is active speech. |
302 ExpectEncodeCalls(6); | 318 ExpectEncodeCalls(6); |
303 EXPECT_TRUE(CheckMixedActivePassive(Vad::kPassive, Vad::kActive)); | 319 EXPECT_TRUE(CheckMixedActivePassive(Vad::kPassive, Vad::kActive)); |
304 EXPECT_TRUE(encoded_info_.speech); | 320 EXPECT_TRUE(encoded_info_.speech); |
305 | 321 |
306 // All of the frame is passive speech. Expect no calls to |mock_encoder_|. | 322 // All of the frame is passive speech. Expect no calls to |mock_encoder_|. |
307 EXPECT_FALSE(CheckMixedActivePassive(Vad::kPassive, Vad::kPassive)); | 323 EXPECT_FALSE(CheckMixedActivePassive(Vad::kPassive, Vad::kPassive)); |
308 EXPECT_FALSE(encoded_info_.speech); | 324 EXPECT_FALSE(encoded_info_.speech); |
309 } | 325 } |
310 | 326 |
311 // These tests verify that the audio is partitioned into larger blocks before | 327 // These tests verify that the audio is partitioned into larger blocks before |
312 // calling the VAD. | 328 // calling the VAD. |
313 // The parameters for CheckVadInputSize are: | 329 // The parameters for CheckVadInputSize are: |
314 // CheckVadInputSize(frame_size, expected_first_block_size, | 330 // CheckVadInputSize(frame_size, expected_first_block_size, |
315 // expected_second_block_size); | 331 // expected_second_block_size); |
316 TEST_F(AudioEncoderCngTest, VadInputSize10Ms) { | 332 TEST_F(AudioEncoderCngTest, VadInputSize10Ms) { |
317 CreateCng(); | 333 CreateCng(MakeCngConfig()); |
318 CheckVadInputSize(10, 10, 0); | 334 CheckVadInputSize(10, 10, 0); |
319 } | 335 } |
320 TEST_F(AudioEncoderCngTest, VadInputSize20Ms) { | 336 TEST_F(AudioEncoderCngTest, VadInputSize20Ms) { |
321 CreateCng(); | 337 CreateCng(MakeCngConfig()); |
322 CheckVadInputSize(20, 20, 0); | 338 CheckVadInputSize(20, 20, 0); |
323 } | 339 } |
324 TEST_F(AudioEncoderCngTest, VadInputSize30Ms) { | 340 TEST_F(AudioEncoderCngTest, VadInputSize30Ms) { |
325 CreateCng(); | 341 CreateCng(MakeCngConfig()); |
326 CheckVadInputSize(30, 30, 0); | 342 CheckVadInputSize(30, 30, 0); |
327 } | 343 } |
328 TEST_F(AudioEncoderCngTest, VadInputSize40Ms) { | 344 TEST_F(AudioEncoderCngTest, VadInputSize40Ms) { |
329 CreateCng(); | 345 CreateCng(MakeCngConfig()); |
330 CheckVadInputSize(40, 20, 20); | 346 CheckVadInputSize(40, 20, 20); |
331 } | 347 } |
332 TEST_F(AudioEncoderCngTest, VadInputSize50Ms) { | 348 TEST_F(AudioEncoderCngTest, VadInputSize50Ms) { |
333 CreateCng(); | 349 CreateCng(MakeCngConfig()); |
334 CheckVadInputSize(50, 30, 20); | 350 CheckVadInputSize(50, 30, 20); |
335 } | 351 } |
336 TEST_F(AudioEncoderCngTest, VadInputSize60Ms) { | 352 TEST_F(AudioEncoderCngTest, VadInputSize60Ms) { |
337 CreateCng(); | 353 CreateCng(MakeCngConfig()); |
338 CheckVadInputSize(60, 30, 30); | 354 CheckVadInputSize(60, 30, 30); |
339 } | 355 } |
340 | 356 |
341 // Verifies that the correct payload type is set when CNG is encoded. | 357 // Verifies that the correct payload type is set when CNG is encoded. |
342 TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) { | 358 TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) { |
343 CreateCng(); | 359 CreateCng(MakeCngConfig()); |
344 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0); | 360 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0); |
345 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U)); | 361 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U)); |
346 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 362 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
347 .WillOnce(Return(Vad::kPassive)); | 363 .WillOnce(Return(Vad::kPassive)); |
348 encoded_info_.payload_type = 0; | 364 encoded_info_.payload_type = 0; |
349 Encode(); | 365 Encode(); |
350 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 366 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
351 } | 367 } |
352 | 368 |
353 // Verifies that a SID frame is encoded immediately as the signal changes from | 369 // Verifies that a SID frame is encoded immediately as the signal changes from |
354 // active speech to passive. | 370 // active speech to passive. |
355 TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) { | 371 TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) { |
356 CreateCng(); | 372 auto config = MakeCngConfig(); |
357 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 373 const auto num_cng_coefficients = config.num_cng_coefficients; |
| 374 CreateCng(std::move(config)); |
| 375 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
358 .WillRepeatedly(Return(1U)); | 376 .WillRepeatedly(Return(1U)); |
359 // Start with encoding noise. | 377 // Start with encoding noise. |
360 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 378 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
361 .Times(2) | 379 .Times(2) |
362 .WillRepeatedly(Return(Vad::kPassive)); | 380 .WillRepeatedly(Return(Vad::kPassive)); |
363 Encode(); | 381 Encode(); |
364 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 382 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
365 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1, | 383 EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1, |
366 encoded_info_.encoded_bytes); | 384 encoded_info_.encoded_bytes); |
367 // Encode again, and make sure we got no frame at all (since the SID frame | 385 // Encode again, and make sure we got no frame at all (since the SID frame |
368 // period is 100 ms by default). | 386 // period is 100 ms by default). |
369 Encode(); | 387 Encode(); |
370 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 388 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
371 | 389 |
372 // Now encode active speech. | 390 // Now encode active speech. |
373 encoded_info_.payload_type = 0; | 391 encoded_info_.payload_type = 0; |
374 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 392 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
375 .WillOnce(Return(Vad::kActive)); | 393 .WillOnce(Return(Vad::kActive)); |
376 EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).WillOnce( | 394 EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)) |
377 Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); | 395 .WillOnce( |
| 396 Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); |
378 Encode(); | 397 Encode(); |
379 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); | 398 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); |
380 | 399 |
381 // Go back to noise again, and verify that a SID frame is emitted. | 400 // Go back to noise again, and verify that a SID frame is emitted. |
382 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 401 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
383 .WillOnce(Return(Vad::kPassive)); | 402 .WillOnce(Return(Vad::kPassive)); |
384 Encode(); | 403 Encode(); |
385 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 404 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
386 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1, | 405 EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1, |
387 encoded_info_.encoded_bytes); | 406 encoded_info_.encoded_bytes); |
388 } | 407 } |
389 | 408 |
390 // Resetting the CNG should reset both the VAD and the encoder. | 409 // Resetting the CNG should reset both the VAD and the encoder. |
391 TEST_F(AudioEncoderCngTest, Reset) { | 410 TEST_F(AudioEncoderCngTest, Reset) { |
392 CreateCng(); | 411 CreateCng(MakeCngConfig()); |
393 EXPECT_CALL(mock_encoder_, Reset()).Times(1); | 412 EXPECT_CALL(*mock_encoder_, Reset()).Times(1); |
394 EXPECT_CALL(*mock_vad_, Reset()).Times(1); | 413 EXPECT_CALL(*mock_vad_, Reset()).Times(1); |
395 cng_->Reset(); | 414 cng_->Reset(); |
396 } | 415 } |
397 | 416 |
398 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 417 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
399 | 418 |
400 // This test fixture tests various error conditions that makes the | 419 // This test fixture tests various error conditions that makes the |
401 // AudioEncoderCng die via CHECKs. | 420 // AudioEncoderCng die via CHECKs. |
402 class AudioEncoderCngDeathTest : public AudioEncoderCngTest { | 421 class AudioEncoderCngDeathTest : public AudioEncoderCngTest { |
403 protected: | 422 protected: |
404 AudioEncoderCngDeathTest() : AudioEncoderCngTest() { | 423 AudioEncoderCngDeathTest() : AudioEncoderCngTest() { |
405 // Don't provide a Vad mock object, since it will leak when the test dies. | |
406 config_.vad = NULL; | |
407 EXPECT_CALL(*mock_vad_, Die()).Times(1); | 424 EXPECT_CALL(*mock_vad_, Die()).Times(1); |
408 delete mock_vad_; | 425 delete mock_vad_; |
409 mock_vad_ = NULL; | 426 mock_vad_ = nullptr; |
410 } | 427 } |
411 | 428 |
412 // Override AudioEncoderCngTest::TearDown, since that one expects a call to | 429 // Override AudioEncoderCngTest::TearDown, since that one expects a call to |
413 // the destructor of |mock_vad_|. In this case, that object is already | 430 // the destructor of |mock_vad_|. In this case, that object is already |
414 // deleted. | 431 // deleted. |
415 void TearDown() override { | 432 void TearDown() override { |
416 cng_.reset(); | 433 cng_.reset(); |
417 // Don't expect the cng_ object to delete the AudioEncoder object. But it | 434 } |
418 // will be deleted with the test fixture. This is why we explicitly delete | 435 |
419 // the cng_ object above, and set expectations on mock_encoder_ afterwards. | 436 AudioEncoderCng::Config MakeCngConfig() { |
420 EXPECT_CALL(mock_encoder_, Die()).Times(1); | 437 // Don't provide a Vad mock object, since it would leak when the test dies. |
| 438 auto config = AudioEncoderCngTest::MakeCngConfig(); |
| 439 config.vad = nullptr; |
| 440 return config; |
| 441 } |
| 442 |
| 443 void TryWrongNumCoefficients(int num) { |
| 444 EXPECT_DEATH( |
| 445 [&] { |
| 446 auto config = MakeCngConfig(); |
| 447 config.num_cng_coefficients = num; |
| 448 CreateCng(std::move(config)); |
| 449 }(), |
| 450 "Invalid configuration"); |
421 } | 451 } |
422 }; | 452 }; |
423 | 453 |
424 TEST_F(AudioEncoderCngDeathTest, WrongFrameSize) { | 454 TEST_F(AudioEncoderCngDeathTest, WrongFrameSize) { |
425 CreateCng(); | 455 CreateCng(MakeCngConfig()); |
426 num_audio_samples_10ms_ *= 2; // 20 ms frame. | 456 num_audio_samples_10ms_ *= 2; // 20 ms frame. |
427 EXPECT_DEATH(Encode(), ""); | 457 EXPECT_DEATH(Encode(), ""); |
428 num_audio_samples_10ms_ = 0; // Zero samples. | 458 num_audio_samples_10ms_ = 0; // Zero samples. |
429 EXPECT_DEATH(Encode(), ""); | 459 EXPECT_DEATH(Encode(), ""); |
430 } | 460 } |
431 | 461 |
432 TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficients) { | 462 TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsA) { |
433 config_.num_cng_coefficients = -1; | 463 TryWrongNumCoefficients(-1); |
434 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 464 } |
435 config_.num_cng_coefficients = 0; | 465 |
436 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 466 TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsB) { |
437 config_.num_cng_coefficients = 13; | 467 TryWrongNumCoefficients(0); |
438 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 468 } |
| 469 |
| 470 TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsC) { |
| 471 TryWrongNumCoefficients(13); |
439 } | 472 } |
440 | 473 |
441 TEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) { | 474 TEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) { |
442 config_.speech_encoder = NULL; | 475 auto config = MakeCngConfig(); |
443 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 476 config.speech_encoder = nullptr; |
| 477 EXPECT_DEATH(CreateCng(std::move(config)), ""); |
444 } | 478 } |
445 | 479 |
446 TEST_F(AudioEncoderCngDeathTest, Stereo) { | 480 TEST_F(AudioEncoderCngDeathTest, StereoEncoder) { |
447 EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(2)); | 481 EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(2)); |
448 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 482 EXPECT_DEATH(CreateCng(MakeCngConfig()), "Invalid configuration"); |
449 config_.num_channels = 2; | 483 } |
450 EXPECT_DEATH(CreateCng(), "Invalid configuration"); | 484 |
| 485 TEST_F(AudioEncoderCngDeathTest, StereoConfig) { |
| 486 EXPECT_DEATH( |
| 487 [&] { |
| 488 auto config = MakeCngConfig(); |
| 489 config.num_channels = 2; |
| 490 CreateCng(std::move(config)); |
| 491 }(), |
| 492 "Invalid configuration"); |
451 } | 493 } |
452 | 494 |
453 TEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) { | 495 TEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) { |
454 CreateCng(); | 496 CreateCng(MakeCngConfig()); |
455 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 497 EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()) |
456 .WillRepeatedly(Return(7U)); | 498 .WillRepeatedly(Return(7U)); |
457 for (int i = 0; i < 6; ++i) | 499 for (int i = 0; i < 6; ++i) |
458 Encode(); | 500 Encode(); |
459 EXPECT_DEATH(Encode(), | 501 EXPECT_DEATH(Encode(), |
460 "Frame size cannot be larger than 60 ms when using VAD/CNG."); | 502 "Frame size cannot be larger than 60 ms when using VAD/CNG."); |
461 } | 503 } |
462 | 504 |
463 #endif // GTEST_HAS_DEATH_TEST | 505 #endif // GTEST_HAS_DEATH_TEST |
464 | 506 |
465 } // namespace webrtc | 507 } // namespace webrtc |
OLD | NEW |