Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Unified Diff: webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc

Issue 1702943002: Pass ownership of external encoders to the ACM (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
index a4416c955aaf779d34784c20d6c0ef6a649158ba..8f30d783ae4c8fa24170f6074163cae365343390 100644
--- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
@@ -34,42 +34,50 @@ static const int kCngPayloadType = 18;
class AudioEncoderCngTest : public ::testing::Test {
protected:
AudioEncoderCngTest()
- : mock_vad_(new MockVad),
+ : mock_encoder_owner_(new MockAudioEncoder),
+ mock_encoder_(mock_encoder_owner_.get()),
+ mock_vad_(new MockVad),
timestamp_(4711),
num_audio_samples_10ms_(0),
sample_rate_hz_(8000) {
memset(audio_, 0, kMaxNumSamples * 2);
- config_.speech_encoder = &mock_encoder_;
- EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
- // Let the AudioEncoderCng object use a MockVad instead of its internally
- // created Vad object.
- config_.vad = mock_vad_;
- config_.payload_type = kCngPayloadType;
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
+ EXPECT_CALL(*mock_encoder_, Die()).Times(1);
}
void TearDown() override {
EXPECT_CALL(*mock_vad_, Die()).Times(1);
cng_.reset();
- // Don't expect the cng_ object to delete the AudioEncoder object. But it
- // will be deleted with the test fixture. This is why we explicitly delete
- // the cng_ object above, and set expectations on mock_encoder_ afterwards.
- EXPECT_CALL(mock_encoder_, Die()).Times(1);
}
- void CreateCng() {
- // The config_ parameters may be changed by the TEST_Fs up until CreateCng()
- // is called, thus we cannot use the values until now.
+ AudioEncoderCng::Config MakeCngConfig() {
+ AudioEncoderCng::Config config;
+ config.speech_encoder = std::move(mock_encoder_owner_);
+ EXPECT_TRUE(config.speech_encoder);
+
+ // Let the AudioEncoderCng object use a MockVad instead of its internally
+ // created Vad object.
+ config.vad = mock_vad_;
+ config.payload_type = kCngPayloadType;
+
+ return config;
+ }
+
+ void CreateCng(AudioEncoderCng::Config&& config) {
num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000);
ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples);
- EXPECT_CALL(mock_encoder_, SampleRateHz())
- .WillRepeatedly(Return(sample_rate_hz_));
- // Max10MsFramesInAPacket() is just used to verify that the SID frame period
- // is not too small. The return value does not matter that much, as long as
- // it is smaller than 10.
- EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1u));
- EXPECT_CALL(mock_encoder_, MaxEncodedBytes())
- .WillRepeatedly(Return(kMockMaxEncodedBytes));
- cng_.reset(new AudioEncoderCng(config_));
+ if (config.speech_encoder) {
+ EXPECT_CALL(*mock_encoder_, SampleRateHz())
+ .WillRepeatedly(Return(sample_rate_hz_));
+ // Max10MsFramesInAPacket() is just used to verify that the SID frame
+ // period is not too small. The return value does not matter that much,
+ // as long as it is smaller than 10.
+ EXPECT_CALL(*mock_encoder_, Max10MsFramesInAPacket())
+ .WillOnce(Return(1u));
+ EXPECT_CALL(*mock_encoder_, MaxEncodedBytes())
+ .WillRepeatedly(Return(kMockMaxEncodedBytes));
+ }
+ cng_.reset(new AudioEncoderCng(std::move(config)));
}
void Encode() {
@@ -88,27 +96,29 @@ class AudioEncoderCngTest : public ::testing::Test {
InSequence s;
AudioEncoder::EncodedInfo info;
for (size_t j = 0; j < num_calls - 1; ++j) {
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _))
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
.WillOnce(Return(info));
}
info.encoded_bytes = kMockReturnEncodedBytes;
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _))
- .WillOnce(Invoke(
- MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(
+ Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
}
// Verifies that the cng_ object waits until it has collected
// |blocks_per_frame| blocks of audio, and then dispatches all of them to
// the underlying codec (speech or cng).
void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) {
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(blocks_per_frame));
- CreateCng();
+ auto config = MakeCngConfig();
+ const int num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
.WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive));
// Don't expect any calls to the encoder yet.
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
Encode();
EXPECT_EQ(0u, encoded_info_.encoded_bytes);
@@ -119,7 +129,7 @@ class AudioEncoderCngTest : public ::testing::Test {
if (active_speech) {
EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
} else {
- EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients + 1),
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients + 1),
encoded_info_.encoded_bytes);
}
}
@@ -132,7 +142,7 @@ class AudioEncoderCngTest : public ::testing::Test {
const size_t blocks_per_frame =
static_cast<size_t>(input_frame_size_ms / 10);
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(blocks_per_frame));
// Expect nothing to happen before the last block is sent to cng_.
@@ -167,7 +177,7 @@ class AudioEncoderCngTest : public ::testing::Test {
// Set the speech encoder frame size to 60 ms, to ensure that the VAD will
// be called twice.
const size_t blocks_per_frame = 6;
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(blocks_per_frame));
InSequence s;
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
@@ -184,9 +194,9 @@ class AudioEncoderCngTest : public ::testing::Test {
return encoded_info_.payload_type != kCngPayloadType;
}
- AudioEncoderCng::Config config_;
std::unique_ptr<AudioEncoderCng> cng_;
- MockAudioEncoder mock_encoder_;
+ std::unique_ptr<MockAudioEncoder> mock_encoder_owner_;
+ MockAudioEncoder* mock_encoder_;
MockVad* mock_vad_; // Ownership is transferred to |cng_|.
uint32_t timestamp_;
int16_t audio_[kMaxNumSamples];
@@ -194,34 +204,37 @@ class AudioEncoderCngTest : public ::testing::Test {
rtc::Buffer encoded_;
AudioEncoder::EncodedInfo encoded_info_;
int sample_rate_hz_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderCngTest);
};
TEST_F(AudioEncoderCngTest, CreateAndDestroy) {
- CreateCng();
+ CreateCng(MakeCngConfig());
}
TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(17U));
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
+ .WillOnce(Return(17U));
EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket());
}
TEST_F(AudioEncoderCngTest, CheckChangeBitratePropagation) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, SetTargetBitrate(4711));
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, SetTargetBitrate(4711));
cng_->SetTargetBitrate(4711);
}
TEST_F(AudioEncoderCngTest, CheckProjectedPacketLossRatePropagation) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, SetProjectedPacketLossRate(0.5));
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, SetProjectedPacketLossRate(0.5));
cng_->SetProjectedPacketLossRate(0.5);
}
TEST_F(AudioEncoderCngTest, EncodeCallsVad) {
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(1U));
- CreateCng();
+ CreateCng(MakeCngConfig());
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
.WillOnce(Return(Vad::kPassive));
Encode();
@@ -253,13 +266,16 @@ TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) {
TEST_F(AudioEncoderCngTest, EncodePassive) {
const size_t kBlocksPerFrame = 3;
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(kBlocksPerFrame));
- CreateCng();
+ auto config = MakeCngConfig();
+ const auto sid_frame_interval_ms = config.sid_frame_interval_ms;
+ const auto num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
.WillRepeatedly(Return(Vad::kPassive));
// Expect no calls at all to the speech encoder mock.
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
uint32_t expected_timestamp = timestamp_;
for (size_t i = 0; i < 100; ++i) {
Encode();
@@ -267,11 +283,11 @@ TEST_F(AudioEncoderCngTest, EncodePassive) {
// |kBlocksPerFrame| calls.
if ((i + 1) % kBlocksPerFrame == 0) {
// Now check if a SID interval has elapsed.
- if ((i % (config_.sid_frame_interval_ms / 10)) < kBlocksPerFrame) {
+ if ((i % (sid_frame_interval_ms / 10)) < kBlocksPerFrame) {
// If so, verify that we got a CNG encoding.
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
EXPECT_FALSE(encoded_info_.speech);
- EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
encoded_info_.encoded_bytes);
EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp);
}
@@ -286,7 +302,7 @@ TEST_F(AudioEncoderCngTest, EncodePassive) {
// Verifies that the correct action is taken for frames with both active and
// passive speech.
TEST_F(AudioEncoderCngTest, MixedActivePassive) {
- CreateCng();
+ CreateCng(MakeCngConfig());
// All of the frame is active speech.
ExpectEncodeCalls(6);
@@ -314,35 +330,35 @@ TEST_F(AudioEncoderCngTest, MixedActivePassive) {
// CheckVadInputSize(frame_size, expected_first_block_size,
// expected_second_block_size);
TEST_F(AudioEncoderCngTest, VadInputSize10Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(10, 10, 0);
}
TEST_F(AudioEncoderCngTest, VadInputSize20Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(20, 20, 0);
}
TEST_F(AudioEncoderCngTest, VadInputSize30Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(30, 30, 0);
}
TEST_F(AudioEncoderCngTest, VadInputSize40Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(40, 20, 20);
}
TEST_F(AudioEncoderCngTest, VadInputSize50Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(50, 30, 20);
}
TEST_F(AudioEncoderCngTest, VadInputSize60Ms) {
- CreateCng();
+ CreateCng(MakeCngConfig());
CheckVadInputSize(60, 30, 30);
}
// Verifies that the correct payload type is set when CNG is encoded.
TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).Times(0);
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U));
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U));
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
.WillOnce(Return(Vad::kPassive));
encoded_info_.payload_type = 0;
@@ -353,8 +369,10 @@ TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) {
// Verifies that a SID frame is encoded immediately as the signal changes from
// active speech to passive.
TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ auto config = MakeCngConfig();
+ const auto num_cng_coefficients = config.num_cng_coefficients;
+ CreateCng(std::move(config));
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(1U));
// Start with encoding noise.
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
@@ -362,7 +380,7 @@ TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
.WillRepeatedly(Return(Vad::kPassive));
Encode();
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
- EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
encoded_info_.encoded_bytes);
// Encode again, and make sure we got no frame at all (since the SID frame
// period is 100 ms by default).
@@ -373,8 +391,9 @@ TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
encoded_info_.payload_type = 0;
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
.WillOnce(Return(Vad::kActive));
- EXPECT_CALL(mock_encoder_, EncodeImpl(_, _, _)).WillOnce(
- Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
+ EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
+ .WillOnce(
+ Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
Encode();
EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
@@ -383,14 +402,14 @@ TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
.WillOnce(Return(Vad::kPassive));
Encode();
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
- EXPECT_EQ(static_cast<size_t>(config_.num_cng_coefficients) + 1,
+ EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
encoded_info_.encoded_bytes);
}
// Resetting the CNG should reset both the VAD and the encoder.
TEST_F(AudioEncoderCngTest, Reset) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, Reset()).Times(1);
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Reset()).Times(1);
EXPECT_CALL(*mock_vad_, Reset()).Times(1);
cng_->Reset();
}
@@ -402,11 +421,9 @@ TEST_F(AudioEncoderCngTest, Reset) {
class AudioEncoderCngDeathTest : public AudioEncoderCngTest {
protected:
AudioEncoderCngDeathTest() : AudioEncoderCngTest() {
- // Don't provide a Vad mock object, since it will leak when the test dies.
- config_.vad = NULL;
EXPECT_CALL(*mock_vad_, Die()).Times(1);
delete mock_vad_;
- mock_vad_ = NULL;
+ mock_vad_ = nullptr;
}
// Override AudioEncoderCngTest::TearDown, since that one expects a call to
@@ -414,45 +431,70 @@ class AudioEncoderCngDeathTest : public AudioEncoderCngTest {
// deleted.
void TearDown() override {
cng_.reset();
- // Don't expect the cng_ object to delete the AudioEncoder object. But it
- // will be deleted with the test fixture. This is why we explicitly delete
- // the cng_ object above, and set expectations on mock_encoder_ afterwards.
- EXPECT_CALL(mock_encoder_, Die()).Times(1);
+ }
+
+ AudioEncoderCng::Config MakeCngConfig() {
+ // Don't provide a Vad mock object, since it would leak when the test dies.
+ auto config = AudioEncoderCngTest::MakeCngConfig();
+ config.vad = nullptr;
+ return config;
+ }
+
+ void TryWrongNumCoefficients(int num) {
+ EXPECT_DEATH(
+ [&] {
+ auto config = MakeCngConfig();
+ config.num_cng_coefficients = num;
+ CreateCng(std::move(config));
+ }(),
+ "Invalid configuration");
}
};
TEST_F(AudioEncoderCngDeathTest, WrongFrameSize) {
- CreateCng();
+ CreateCng(MakeCngConfig());
num_audio_samples_10ms_ *= 2; // 20 ms frame.
EXPECT_DEATH(Encode(), "");
num_audio_samples_10ms_ = 0; // Zero samples.
EXPECT_DEATH(Encode(), "");
}
-TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficients) {
- config_.num_cng_coefficients = -1;
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
- config_.num_cng_coefficients = 0;
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
- config_.num_cng_coefficients = 13;
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsA) {
+ TryWrongNumCoefficients(-1);
+}
+
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsB) {
+ TryWrongNumCoefficients(0);
+}
+
+TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsC) {
+ TryWrongNumCoefficients(13);
}
TEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) {
- config_.speech_encoder = NULL;
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
+ auto config = MakeCngConfig();
+ config.speech_encoder = nullptr;
+ EXPECT_DEATH(CreateCng(std::move(config)), "");
+}
+
+TEST_F(AudioEncoderCngDeathTest, StereoEncoder) {
+ EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(2));
+ EXPECT_DEATH(CreateCng(MakeCngConfig()), "Invalid configuration");
}
-TEST_F(AudioEncoderCngDeathTest, Stereo) {
- EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(2));
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
- config_.num_channels = 2;
- EXPECT_DEATH(CreateCng(), "Invalid configuration");
+TEST_F(AudioEncoderCngDeathTest, StereoConfig) {
+ EXPECT_DEATH(
+ [&] {
+ auto config = MakeCngConfig();
+ config.num_channels = 2;
+ CreateCng(std::move(config));
+ }(),
+ "Invalid configuration");
}
TEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) {
- CreateCng();
- EXPECT_CALL(mock_encoder_, Num10MsFramesInNextPacket())
+ CreateCng(MakeCngConfig());
+ EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
.WillRepeatedly(Return(7U));
for (int i = 0; i < 6; ++i)
Encode();

Powered by Google App Engine
This is Rietveld 408576698