Chromium Code Reviews| Index: webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc |
| diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc |
| index 1b836f36645726cac37845eaf69204f9fb8a5a5e..d71324a0d80bde27b75dd9cace2ab906a2850b15 100644 |
| --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc |
| +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc |
| @@ -12,92 +12,153 @@ |
| #include "webrtc/base/checks.h" |
| #include "webrtc/common_types.h" |
| +#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h" |
| #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" |
| #include "webrtc/test/gtest.h" |
| namespace webrtc { |
| +using ::testing::NiceMock; |
| +using ::testing::Return; |
| namespace { |
| -const CodecInst kOpusSettings = {105, "opus", 48000, 960, 1, 32000}; |
| -} // namespace |
| -class AudioEncoderOpusTest : public ::testing::Test { |
| - protected: |
| - void CreateCodec(int num_channels) { |
| - codec_inst_.channels = num_channels; |
| - encoder_.reset(new AudioEncoderOpus(codec_inst_)); |
| - auto expected_app = |
| - num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio; |
| - EXPECT_EQ(expected_app, encoder_->application()); |
| - } |
| +const CodecInst kDefaultOpusSettings = {105, "opus", 48000, 960, 1, 32000}; |
| - CodecInst codec_inst_ = kOpusSettings; |
| - std::unique_ptr<AudioEncoderOpus> encoder_; |
| +AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { |
| + AudioEncoderOpus::Config config; |
| + config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); |
| + config.num_channels = codec_inst.channels; |
| + config.bitrate_bps = rtc::Optional<int>(codec_inst.rate); |
| + config.payload_type = codec_inst.pltype; |
| + config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip |
| + : AudioEncoderOpus::kAudio; |
| + return config; |
| +} |
| + |
| +struct AudioEncoderOpusStates { |
| + MockAudioNetworkAdaptor* mock_audio_network_adaptor; |
| + std::unique_ptr<AudioEncoderOpus> encoder; |
| }; |
| -TEST_F(AudioEncoderOpusTest, DefaultApplicationModeMono) { |
| - CreateCodec(1); |
| +AudioEncoderOpusStates CreateCodec(size_t num_channels, |
| + bool enable_audio_network_adaptor = false) { |
| + AudioEncoderOpusStates states; |
| + std::unique_ptr<MockAudioNetworkAdaptor> mock_audio_network_adaptor( |
| + new NiceMock<MockAudioNetworkAdaptor>()); |
| + EXPECT_CALL(*mock_audio_network_adaptor, Die()); |
| + states.mock_audio_network_adaptor = mock_audio_network_adaptor.get(); |
| + CodecInst codec_inst = kDefaultOpusSettings; |
| + codec_inst.channels = num_channels; |
| + auto config = CreateConfig(codec_inst); |
| + AudioEncoderOpus::AudioNetworkAdaptorCreator creator = [&](const std::string&, |
| + const Clock*) { |
| + return std::move(mock_audio_network_adaptor); |
| + }; |
|
kwiberg-webrtc
2016/10/04 16:04:06
This creator doesn't work, if I'm not mistaken. Th
minyue-webrtc
2016/10/04 17:07:13
Line 60 invokes |creator| and mock_audio_network_a
|
| + states.encoder.reset(new AudioEncoderOpus(config, &creator)); |
| + if (enable_audio_network_adaptor) { |
| + // This will invoke |creator|, which does not care about its arguments. |
| + // states.encoder->EnableAudioNetworkAdaptor("", nullptr); |
|
minyue-webrtc
2016/10/04 15:35:59
Oh, for testing, I added //, this should be remove
|
| + } |
| + return states; |
| +} |
| + |
| +AudioNetworkAdaptor::EncoderRuntimeConfig CreateEncoderRuntimeConfig() { |
| + constexpr int kBitrate = 40000; |
| + constexpr int kFrameLength = 60; |
| + constexpr bool kEnableFec = true; |
| + constexpr bool kEnableDtx = false; |
| + constexpr size_t kNumChannels = 1; |
| + constexpr float kPacketLossFraction = 0.1f; |
| + AudioNetworkAdaptor::EncoderRuntimeConfig config; |
| + config.bitrate_bps = rtc::Optional<int>(kBitrate); |
| + config.frame_length_ms = rtc::Optional<int>(kFrameLength); |
| + config.enable_fec = rtc::Optional<bool>(kEnableFec); |
| + config.enable_dtx = rtc::Optional<bool>(kEnableDtx); |
| + config.num_channels = rtc::Optional<size_t>(kNumChannels); |
| + config.uplink_packet_loss_fraction = |
| + rtc::Optional<float>(kPacketLossFraction); |
| + return config; |
| +} |
| + |
| +void CheckEncoderRuntimeConfig( |
| + const AudioEncoderOpus* encoder, |
| + const AudioNetworkAdaptor::EncoderRuntimeConfig& config) { |
| + EXPECT_EQ(*config.bitrate_bps, encoder->GetTargetBitrate()); |
| + EXPECT_EQ(*config.frame_length_ms, encoder->next_frame_length_ms()); |
| + EXPECT_EQ(*config.enable_fec, encoder->fec_enabled()); |
| + EXPECT_EQ(*config.enable_dtx, encoder->GetDtx()); |
| + EXPECT_EQ(*config.num_channels, encoder->num_channels_to_encode()); |
| +} |
| + |
| +} // namespace |
| + |
| +TEST(AudioEncoderOpusTest, DefaultApplicationModeMono) { |
| + auto states = CreateCodec(1); |
| + EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
| } |
| -TEST_F(AudioEncoderOpusTest, DefaultApplicationModeStereo) { |
| - CreateCodec(2); |
| +TEST(AudioEncoderOpusTest, DefaultApplicationModeStereo) { |
| + auto states = CreateCodec(2); |
| + EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); |
| } |
| -TEST_F(AudioEncoderOpusTest, ChangeApplicationMode) { |
| - CreateCodec(2); |
| - EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech)); |
| - EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); |
| +TEST(AudioEncoderOpusTest, ChangeApplicationMode) { |
| + auto states = CreateCodec(2); |
| + EXPECT_TRUE( |
| + states.encoder->SetApplication(AudioEncoder::Application::kSpeech)); |
| + EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
| } |
| -TEST_F(AudioEncoderOpusTest, ResetWontChangeApplicationMode) { |
| - CreateCodec(2); |
| +TEST(AudioEncoderOpusTest, ResetWontChangeApplicationMode) { |
| + auto states = CreateCodec(2); |
| // Trigger a reset. |
| - encoder_->Reset(); |
| + states.encoder->Reset(); |
| // Verify that the mode is still kAudio. |
| - EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application()); |
| + EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); |
| // Now change to kVoip. |
| - EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech)); |
| - EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); |
| + EXPECT_TRUE( |
| + states.encoder->SetApplication(AudioEncoder::Application::kSpeech)); |
| + EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
| // Trigger a reset again. |
| - encoder_->Reset(); |
| + states.encoder->Reset(); |
| // Verify that the mode is still kVoip. |
| - EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); |
| + EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
| } |
| -TEST_F(AudioEncoderOpusTest, ToggleDtx) { |
| - CreateCodec(2); |
| +TEST(AudioEncoderOpusTest, ToggleDtx) { |
| + auto states = CreateCodec(2); |
| // Enable DTX |
| - EXPECT_TRUE(encoder_->SetDtx(true)); |
| + EXPECT_TRUE(states.encoder->SetDtx(true)); |
| // Verify that the mode is still kAudio. |
| - EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application()); |
| + EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); |
| // Turn off DTX. |
| - EXPECT_TRUE(encoder_->SetDtx(false)); |
| + EXPECT_TRUE(states.encoder->SetDtx(false)); |
| } |
| -TEST_F(AudioEncoderOpusTest, SetBitrate) { |
| - CreateCodec(1); |
| - // Constants are replicated from audio_encoder_opus.cc. |
| +TEST(AudioEncoderOpusTest, SetBitrate) { |
| + auto states = CreateCodec(1); |
| + // Constants are replicated from audio_states.encoderopus.cc. |
| const int kMinBitrateBps = 500; |
| const int kMaxBitrateBps = 512000; |
| // Set a too low bitrate. |
| - encoder_->SetTargetBitrate(kMinBitrateBps - 1); |
| - EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); |
| + states.encoder->SetTargetBitrate(kMinBitrateBps - 1); |
| + EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate()); |
| // Set a too high bitrate. |
| - encoder_->SetTargetBitrate(kMaxBitrateBps + 1); |
| - EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); |
| + states.encoder->SetTargetBitrate(kMaxBitrateBps + 1); |
| + EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate()); |
| // Set the minimum rate. |
| - encoder_->SetTargetBitrate(kMinBitrateBps); |
| - EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); |
| + states.encoder->SetTargetBitrate(kMinBitrateBps); |
| + EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate()); |
| // Set the maximum rate. |
| - encoder_->SetTargetBitrate(kMaxBitrateBps); |
| - EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); |
| + states.encoder->SetTargetBitrate(kMaxBitrateBps); |
| + EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate()); |
| // Set rates from 1000 up to 32000 bps. |
| for (int rate = 1000; rate <= 32000; rate += 1000) { |
| - encoder_->SetTargetBitrate(rate); |
| - EXPECT_EQ(rate, encoder_->GetTargetBitrate()); |
| + states.encoder->SetTargetBitrate(rate); |
| + EXPECT_EQ(rate, states.encoder->GetTargetBitrate()); |
| } |
| } |
| @@ -128,26 +189,107 @@ void TestSetPacketLossRate(AudioEncoderOpus* encoder, |
| } // namespace |
| -TEST_F(AudioEncoderOpusTest, PacketLossRateOptimized) { |
| - CreateCodec(1); |
| +TEST(AudioEncoderOpusTest, PacketLossRateOptimized) { |
| + auto states = CreateCodec(1); |
| auto I = [](double a, double b) { return IntervalSteps(a, b, 10); }; |
| const double eps = 1e-15; |
| // Note that the order of the following calls is critical. |
| // clang-format off |
| - TestSetPacketLossRate(encoder_.get(), I(0.00 , 0.01 - eps), 0.00); |
| - TestSetPacketLossRate(encoder_.get(), I(0.01 + eps, 0.06 - eps), 0.01); |
| - TestSetPacketLossRate(encoder_.get(), I(0.06 + eps, 0.11 - eps), 0.05); |
| - TestSetPacketLossRate(encoder_.get(), I(0.11 + eps, 0.22 - eps), 0.10); |
| - TestSetPacketLossRate(encoder_.get(), I(0.22 + eps, 1.00 ), 0.20); |
| - |
| - TestSetPacketLossRate(encoder_.get(), I(1.00 , 0.18 + eps), 0.20); |
| - TestSetPacketLossRate(encoder_.get(), I(0.18 - eps, 0.09 + eps), 0.10); |
| - TestSetPacketLossRate(encoder_.get(), I(0.09 - eps, 0.04 + eps), 0.05); |
| - TestSetPacketLossRate(encoder_.get(), I(0.04 - eps, 0.01 + eps), 0.01); |
| - TestSetPacketLossRate(encoder_.get(), I(0.01 - eps, 0.00 ), 0.00); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.00 , 0.01 - eps), 0.00); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.01 + eps, 0.06 - eps), 0.01); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.06 + eps, 0.11 - eps), 0.05); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.11 + eps, 0.22 - eps), 0.10); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.22 + eps, 1.00 ), 0.20); |
| + |
| + TestSetPacketLossRate(states.encoder.get(), I(1.00 , 0.18 + eps), 0.20); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.18 - eps, 0.09 + eps), 0.10); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.09 - eps, 0.04 + eps), 0.05); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.04 - eps, 0.01 + eps), 0.01); |
| + TestSetPacketLossRate(states.encoder.get(), I(0.01 - eps, 0.00 ), 0.00); |
| // clang-format on |
| } |
| +TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetUplinkBandwidth) { |
| + auto states = CreateCodec(2, true); |
| + |
| + auto config = CreateEncoderRuntimeConfig(); |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) |
| + .WillOnce(Return(config)); |
| + |
| + // Since using mock audio network adaptor, any bandwidth value is fine. |
| + constexpr int kUplinkBandwidth = 50000; |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, |
| + SetUplinkBandwidth(kUplinkBandwidth)); |
| + states.encoder->OnReceivedUplinkBandwidth(kUplinkBandwidth); |
| + |
| + CheckEncoderRuntimeConfig(states.encoder.get(), config); |
| +} |
| + |
| +TEST(AudioEncoderOpusTest, |
| + InvokeAudioNetworkAdaptorOnSetUplinkPacketLossFraction) { |
| + auto states = CreateCodec(2, true); |
| + |
| + auto config = CreateEncoderRuntimeConfig(); |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) |
| + .WillOnce(Return(config)); |
| + |
| + // Since using mock audio network adaptor, any packet loss fraction is fine. |
| + constexpr float kUplinkPacketLoss = 0.1f; |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, |
| + SetUplinkPacketLossFraction(kUplinkPacketLoss)); |
| + states.encoder->OnReceivedUplinkPacketLossFraction(kUplinkPacketLoss); |
| + |
| + CheckEncoderRuntimeConfig(states.encoder.get(), config); |
| +} |
| + |
| +TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetTargetAudioBitrate) { |
| + auto states = CreateCodec(2, true); |
| + |
| + auto config = CreateEncoderRuntimeConfig(); |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) |
| + .WillOnce(Return(config)); |
| + |
| + // Since using mock audio network adaptor, any target audio bitrate is fine. |
| + constexpr int kTargetAudioBitrate = 30000; |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, |
| + SetTargetAudioBitrate(kTargetAudioBitrate)); |
| + states.encoder->OnReceivedTargetAudioBitrate(kTargetAudioBitrate); |
| + |
| + CheckEncoderRuntimeConfig(states.encoder.get(), config); |
| +} |
| + |
| +TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetRtt) { |
| + auto states = CreateCodec(2, true); |
| + |
| + auto config = CreateEncoderRuntimeConfig(); |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) |
| + .WillOnce(Return(config)); |
| + |
| + // Since using mock audio network adaptor, any rtt is fine. |
| + constexpr int kRtt = 30; |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, SetRtt(kRtt)); |
| + states.encoder->OnReceivedRtt(kRtt); |
| + |
| + CheckEncoderRuntimeConfig(states.encoder.get(), config); |
| +} |
| + |
| +TEST(AudioEncoderOpusTest, |
| + InvokeAudioNetworkAdaptorOnSetReceiverFrameLengthRange) { |
| + auto states = CreateCodec(2, true); |
| + |
| + auto config = CreateEncoderRuntimeConfig(); |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) |
| + .WillOnce(Return(config)); |
| + |
| + constexpr int kMinFrameLength = 10; |
| + constexpr int kMaxFrameLength = 60; |
| + EXPECT_CALL(*states.mock_audio_network_adaptor, |
| + SetReceiverFrameLengthRange(kMinFrameLength, kMaxFrameLength)); |
| + states.encoder->SetReceiverFrameLengthRange(kMinFrameLength, kMaxFrameLength); |
| + |
| + CheckEncoderRuntimeConfig(states.encoder.get(), config); |
| +} |
| + |
| } // namespace webrtc |