| 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples); | 63 ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples); |
| 64 EXPECT_CALL(mock_encoder_, SampleRateHz()) | 64 EXPECT_CALL(mock_encoder_, SampleRateHz()) |
| 65 .WillRepeatedly(Return(sample_rate_hz_)); | 65 .WillRepeatedly(Return(sample_rate_hz_)); |
| 66 // Max10MsFramesInAPacket() is just used to verify that the SID frame period | 66 // Max10MsFramesInAPacket() is just used to verify that the SID frame period |
| 67 // is not too small. The return value does not matter that much, as long as | 67 // is not too small. The return value does not matter that much, as long as |
| 68 // it is smaller than 10. | 68 // it is smaller than 10. |
| 69 EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1u)); | 69 EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1u)); |
| 70 EXPECT_CALL(mock_encoder_, MaxEncodedBytes()) | 70 EXPECT_CALL(mock_encoder_, MaxEncodedBytes()) |
| 71 .WillRepeatedly(Return(kMockMaxEncodedBytes)); | 71 .WillRepeatedly(Return(kMockMaxEncodedBytes)); |
| 72 cng_.reset(new AudioEncoderCng(config_)); | 72 cng_.reset(new AudioEncoderCng(config_)); |
| 73 encoded_.resize(cng_->MaxEncodedBytes(), 0); | |
| 74 } | 73 } |
| 75 | 74 |
| 76 void Encode() { | 75 void Encode() { |
| 77 ASSERT_TRUE(cng_) << "Must call CreateCng() first."; | 76 ASSERT_TRUE(cng_) << "Must call CreateCng() first."; |
| 78 encoded_info_ = cng_->Encode( | 77 encoded_info_ = cng_->Encode( |
| 79 timestamp_, | 78 timestamp_, |
| 80 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_), | 79 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_), |
| 81 encoded_.size(), &encoded_[0]); | 80 &encoded_); |
| 82 timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_); | 81 timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_); |
| 83 } | 82 } |
| 84 | 83 |
| 85 // Expect |num_calls| calls to the encoder, all successful. The last call | 84 // Expect |num_calls| calls to the encoder, all successful. The last call |
| 86 // claims to have encoded |kMockMaxEncodedBytes| bytes, and all the preceding | 85 // claims to have encoded |kMockMaxEncodedBytes| bytes, and all the preceding |
| 87 // ones 0 bytes. | 86 // ones 0 bytes. |
| 88 void ExpectEncodeCalls(size_t num_calls) { | 87 void ExpectEncodeCalls(size_t num_calls) { |
| 89 InSequence s; | 88 InSequence s; |
| 90 AudioEncoder::EncodedInfo info; | 89 AudioEncoder::EncodedInfo info; |
| 91 for (size_t j = 0; j < num_calls - 1; ++j) { | 90 for (size_t j = 0; j < num_calls - 1; ++j) { |
| 92 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 91 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
| 93 .WillOnce(Return(info)); | 92 .WillOnce(Return(info)); |
| 94 } | 93 } |
| 95 info.encoded_bytes = kMockReturnEncodedBytes; | 94 info.encoded_bytes = kMockReturnEncodedBytes; |
| 96 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 95 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
| 97 .WillOnce(Return(info)); | 96 .WillOnce(Invoke( |
| 97 MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); |
| 98 } | 98 } |
| 99 | 99 |
| 100 // Verifies that the cng_ object waits until it has collected | 100 // Verifies that the cng_ object waits until it has collected |
| 101 // |blocks_per_frame| blocks of audio, and then dispatches all of them to | 101 // |blocks_per_frame| blocks of audio, and then dispatches all of them to |
| 102 // the underlying codec (speech or cng). | 102 // the underlying codec (speech or cng). |
| 103 void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) { | 103 void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) { |
| 104 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 104 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) |
| 105 .WillRepeatedly(Return(blocks_per_frame)); | 105 .WillRepeatedly(Return(blocks_per_frame)); |
| 106 CreateCng(); | 106 CreateCng(); |
| 107 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 107 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
| 108 .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive)); | 108 .WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive)); |
| 109 | 109 |
| 110 // Don't expect any calls to the encoder yet. | 110 // Don't expect any calls to the encoder yet. |
| 111 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0); | 111 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)).Times(0); |
| 112 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { | 112 for (size_t i = 0; i < blocks_per_frame - 1; ++i) { |
| 113 Encode(); | 113 Encode(); |
| 114 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 114 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
| 115 } | 115 } |
| 116 if (active_speech) | 116 if (active_speech) |
| 117 ExpectEncodeCalls(blocks_per_frame); | 117 ExpectEncodeCalls(blocks_per_frame); |
| 118 Encode(); | 118 Encode(); |
| 119 if (active_speech) { | 119 if (active_speech) { |
| 120 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); | 120 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); |
| 121 } else { | 121 } else { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 return encoded_info_.payload_type != kCngPayloadType; | 184 return encoded_info_.payload_type != kCngPayloadType; |
| 185 } | 185 } |
| 186 | 186 |
| 187 AudioEncoderCng::Config config_; | 187 AudioEncoderCng::Config config_; |
| 188 std::unique_ptr<AudioEncoderCng> cng_; | 188 std::unique_ptr<AudioEncoderCng> cng_; |
| 189 MockAudioEncoder mock_encoder_; | 189 MockAudioEncoder mock_encoder_; |
| 190 MockVad* mock_vad_; // Ownership is transferred to |cng_|. | 190 MockVad* mock_vad_; // Ownership is transferred to |cng_|. |
| 191 uint32_t timestamp_; | 191 uint32_t timestamp_; |
| 192 int16_t audio_[kMaxNumSamples]; | 192 int16_t audio_[kMaxNumSamples]; |
| 193 size_t num_audio_samples_10ms_; | 193 size_t num_audio_samples_10ms_; |
| 194 std::vector<uint8_t> encoded_; | 194 rtc::Buffer encoded_; |
| 195 AudioEncoder::EncodedInfo encoded_info_; | 195 AudioEncoder::EncodedInfo encoded_info_; |
| 196 int sample_rate_hz_; | 196 int sample_rate_hz_; |
| 197 }; | 197 }; |
| 198 | 198 |
| 199 TEST_F(AudioEncoderCngTest, CreateAndDestroy) { | 199 TEST_F(AudioEncoderCngTest, CreateAndDestroy) { |
| 200 CreateCng(); | 200 CreateCng(); |
| 201 } | 201 } |
| 202 | 202 |
| 203 TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) { | 203 TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) { |
| 204 CreateCng(); | 204 CreateCng(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 } | 252 } |
| 253 | 253 |
| 254 TEST_F(AudioEncoderCngTest, EncodePassive) { | 254 TEST_F(AudioEncoderCngTest, EncodePassive) { |
| 255 const size_t kBlocksPerFrame = 3; | 255 const size_t kBlocksPerFrame = 3; |
| 256 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) | 256 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()) |
| 257 .WillRepeatedly(Return(kBlocksPerFrame)); | 257 .WillRepeatedly(Return(kBlocksPerFrame)); |
| 258 CreateCng(); | 258 CreateCng(); |
| 259 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 259 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
| 260 .WillRepeatedly(Return(Vad::kPassive)); | 260 .WillRepeatedly(Return(Vad::kPassive)); |
| 261 // Expect no calls at all to the speech encoder mock. | 261 // Expect no calls at all to the speech encoder mock. |
| 262 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0); | 262 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)).Times(0); |
| 263 uint32_t expected_timestamp = timestamp_; | 263 uint32_t expected_timestamp = timestamp_; |
| 264 for (size_t i = 0; i < 100; ++i) { | 264 for (size_t i = 0; i < 100; ++i) { |
| 265 Encode(); | 265 Encode(); |
| 266 // Check if it was time to call the cng encoder. This is done once every | 266 // Check if it was time to call the cng encoder. This is done once every |
| 267 // |kBlocksPerFrame| calls. | 267 // |kBlocksPerFrame| calls. |
| 268 if ((i + 1) % kBlocksPerFrame == 0) { | 268 if ((i + 1) % kBlocksPerFrame == 0) { |
| 269 // Now check if a SID interval has elapsed. | 269 // Now check if a SID interval has elapsed. |
| 270 if ((i % (config_.sid_frame_interval_ms / 10)) < kBlocksPerFrame) { | 270 if ((i % (config_.sid_frame_interval_ms / 10)) < kBlocksPerFrame) { |
| 271 // If so, verify that we got a CNG encoding. | 271 // If so, verify that we got a CNG encoding. |
| 272 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 272 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 CheckVadInputSize(50, 30, 20); | 334 CheckVadInputSize(50, 30, 20); |
| 335 } | 335 } |
| 336 TEST_F(AudioEncoderCngTest, VadInputSize60Ms) { | 336 TEST_F(AudioEncoderCngTest, VadInputSize60Ms) { |
| 337 CreateCng(); | 337 CreateCng(); |
| 338 CheckVadInputSize(60, 30, 30); | 338 CheckVadInputSize(60, 30, 30); |
| 339 } | 339 } |
| 340 | 340 |
| 341 // Verifies that the correct payload type is set when CNG is encoded. | 341 // Verifies that the correct payload type is set when CNG is encoded. |
| 342 TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) { | 342 TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) { |
| 343 CreateCng(); | 343 CreateCng(); |
| 344 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).Times(0); | 344 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)).Times(0); |
| 345 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U)); | 345 EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U)); |
| 346 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 346 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
| 347 .WillOnce(Return(Vad::kPassive)); | 347 .WillOnce(Return(Vad::kPassive)); |
| 348 encoded_info_.payload_type = 0; | 348 encoded_info_.payload_type = 0; |
| 349 Encode(); | 349 Encode(); |
| 350 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 350 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
| 351 } | 351 } |
| 352 | 352 |
| 353 // Verifies that a SID frame is encoded immediately as the signal changes from | 353 // Verifies that a SID frame is encoded immediately as the signal changes from |
| 354 // active speech to passive. | 354 // active speech to passive. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 366 encoded_info_.encoded_bytes); | 366 encoded_info_.encoded_bytes); |
| 367 // Encode again, and make sure we got no frame at all (since the SID frame | 367 // Encode again, and make sure we got no frame at all (since the SID frame |
| 368 // period is 100 ms by default). | 368 // period is 100 ms by default). |
| 369 Encode(); | 369 Encode(); |
| 370 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 370 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
| 371 | 371 |
| 372 // Now encode active speech. | 372 // Now encode active speech. |
| 373 encoded_info_.payload_type = 0; | 373 encoded_info_.payload_type = 0; |
| 374 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 374 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
| 375 .WillOnce(Return(Vad::kActive)); | 375 .WillOnce(Return(Vad::kActive)); |
| 376 AudioEncoder::EncodedInfo info; | 376 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)).WillOnce( |
| 377 info.encoded_bytes = kMockReturnEncodedBytes; | 377 Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes))); |
| 378 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)).WillOnce(Return(info)); | |
| 379 Encode(); | 378 Encode(); |
| 380 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); | 379 EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes); |
| 381 | 380 |
| 382 // Go back to noise again, and verify that a SID frame is emitted. | 381 // Go back to noise again, and verify that a SID frame is emitted. |
| 383 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) | 382 EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)) |
| 384 .WillOnce(Return(Vad::kPassive)); | 383 .WillOnce(Return(Vad::kPassive)); |
| 385 Encode(); | 384 Encode(); |
| 386 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); | 385 EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type); |
| 387 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1, | 386 EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1, |
| 388 encoded_info_.encoded_bytes); | 387 encoded_info_.encoded_bytes); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 .WillRepeatedly(Return(7U)); | 456 .WillRepeatedly(Return(7U)); |
| 458 for (int i = 0; i < 6; ++i) | 457 for (int i = 0; i < 6; ++i) |
| 459 Encode(); | 458 Encode(); |
| 460 EXPECT_DEATH(Encode(), | 459 EXPECT_DEATH(Encode(), |
| 461 "Frame size cannot be larger than 60 ms when using VAD/CNG."); | 460 "Frame size cannot be larger than 60 ms when using VAD/CNG."); |
| 462 } | 461 } |
| 463 | 462 |
| 464 #endif // GTEST_HAS_DEATH_TEST | 463 #endif // GTEST_HAS_DEATH_TEST |
| 465 | 464 |
| 466 } // namespace webrtc | 465 } // namespace webrtc |
| OLD | NEW |