Chromium Code Reviews| Index: webrtc/voice_engine/test/auto_test/voe_output_test.cc |
| diff --git a/webrtc/voice_engine/test/auto_test/voe_output_test.cc b/webrtc/voice_engine/test/auto_test/voe_output_test.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..521ed15c1036c070d0c69773dccaa570eaca7ef1 |
| --- /dev/null |
| +++ b/webrtc/voice_engine/test/auto_test/voe_output_test.cc |
| @@ -0,0 +1,215 @@ |
| +/* |
| + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| + * |
| + * Use of this source code is governed by a BSD-style license |
| + * that can be found in the LICENSE file in the root of the source |
| + * tree. An additional intellectual property rights grant can be found |
| + * in the file PATENTS. All contributing project authors may |
| + * be found in the AUTHORS file in the root of the source tree. |
| + */ |
| + |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "webrtc/base/checks.h" |
| +#include "webrtc/base/scoped_ptr.h" |
| +#include "webrtc/base/timeutils.h" |
| +#include "webrtc/system_wrappers/interface/sleep.h" |
| +#include "webrtc/test/channel_transport/include/channel_transport.h" |
| +#include "webrtc/test/random.h" |
| +#include "webrtc/test/testsupport/fileutils.h" |
| +#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" |
| + |
| +namespace { |
| + |
| +const char kIp[] = "127.0.0.1"; |
| +const int kPort = 1234; |
| +const webrtc::CodecInst kCodecInst = {120, "opus", 48000, 960, 2, 64000}; |
| + |
| +} // namespace |
| + |
| +namespace voetest { |
| + |
| +using webrtc::test::Random; |
| +using webrtc::test::VoiceChannelTransport; |
| + |
| +// This test allows a check on the output signal in an end-to-end call. |
| +class OutputTest { |
| + public: |
| + OutputTest(); |
| + ~OutputTest(); |
| + |
| + void Start(); |
| + |
| + void EnableOutputCheck(); |
| + void DisableOutputCheck(); |
| + void SetOutputBound(int16_t lower_bound, int16_t upper_bound); |
| + size_t GetOutBoundCount(); |
| + void Mute(); |
| + void Unmute(); |
| + void SetBitRate(int rate); |
| + |
| + private: |
| + // This class checks all output values and count the number of samples that |
| + // go out of a defined range. |
| + class VoEOutputCheckMediaProcess : public VoEMediaProcess { |
| + public: |
| + VoEOutputCheckMediaProcess(); |
| + void set_enabled(bool enabled) { enabled_ = enabled; } |
| + void set_lower_bound(int16_t lower_bound) { lower_bound_ = lower_bound; } |
| + void set_upper_bound(int16_t upper_bound) { upper_bound_ = upper_bound; } |
| + size_t out_bound_count() const { return out_bound_count_; } |
| + void Process(int channel, |
| + ProcessingTypes type, |
| + int16_t audio10ms[], |
| + size_t length, |
| + int samplingFreq, |
| + bool isStereo) override; |
| + |
| + private: |
| + bool enabled_; |
| + int16_t lower_bound_; |
| + int16_t upper_bound_; |
| + size_t out_bound_count_; |
| + }; |
| + |
| + VoETestManager manager_; |
| + VoEOutputCheckMediaProcess output_checker_; |
| + |
| + int channel_; |
| +}; |
| + |
| +OutputTest::OutputTest() { |
| + RTC_CHECK(manager_.Init()); |
| + manager_.GetInterfaces(); |
| + |
| + VoEBase* base = manager_.BasePtr(); |
| + VoECodec* codec = manager_.CodecPtr(); |
| + VoENetwork* network = manager_.NetworkPtr(); |
| + VoEVolumeControl* volume = manager_.VolumeControlPtr(); |
| + VoEExternalMedia* external = manager_.ExternalMediaPtr(); |
| + |
| + RTC_DCHECK_EQ(0, base->Init()); |
| + |
| + channel_ = base->CreateChannel(); |
| + |
| + // |network| will take care of the life time of |transport|. |
| + VoiceChannelTransport* transport = |
| + new VoiceChannelTransport(network, channel_); |
| + |
| + RTC_DCHECK_EQ(0, transport->SetSendDestination(kIp, kPort)); |
| + RTC_DCHECK_EQ(0, transport->SetLocalReceiver(kPort)); |
| + |
| + RTC_DCHECK_EQ(0, codec->SetSendCodec(channel_, kCodecInst)); |
| + RTC_DCHECK_EQ(0, codec->SetOpusDtx(channel_, true)); |
| + |
| + RTC_DCHECK_EQ(0, volume->SetSpeakerVolume(255)); |
| + |
| + external->RegisterExternalMediaProcessing( |
| + channel_, ProcessingTypes::kPlaybackPerChannel, output_checker_); |
| +} |
| + |
| +OutputTest::~OutputTest() { |
| + VoENetwork* network = manager_.NetworkPtr(); |
|
kwiberg-webrtc
2015/10/29 16:35:21
You don't need to bind this to a local variable.
minyue-webrtc
2015/10/30 14:06:46
you mean "manager_.NetworkPtr()->DeRegisterExterna
|
| + RTC_DCHECK_EQ(0, network->DeRegisterExternalTransport(channel_)); |
| + RTC_DCHECK_EQ(0, manager_.ReleaseInterfaces()); |
| +} |
| + |
| +void OutputTest::Start() { |
| + const std::string file_name = |
| + webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); |
| + const webrtc::FileFormats kInputFormat = webrtc::kFileFormatPcm32kHzFile; |
| + |
| + VoEFile* file = manager_.FilePtr(); |
| + RTC_DCHECK_EQ( |
| + 0, file->StartPlayingFileAsMicrophone(channel_, file_name.c_str(), true, |
| + false, kInputFormat, 1.0)); |
| + |
| + VoEBase* base = manager_.BasePtr(); |
| + RTC_DCHECK_EQ(0, base->StartPlayout(channel_)); |
| + RTC_DCHECK_EQ(0, base->StartSend(channel_)); |
| +} |
| + |
| +void OutputTest::EnableOutputCheck() { |
| + output_checker_.set_enabled(true); |
| +} |
| + |
| +void OutputTest::DisableOutputCheck() { |
| + output_checker_.set_enabled(false); |
| +} |
| + |
| +void OutputTest::SetOutputBound(int16_t lower_bound, int16_t upper_bound) { |
| + output_checker_.set_lower_bound(lower_bound); |
| + output_checker_.set_upper_bound(upper_bound); |
| +} |
| + |
| +size_t OutputTest::GetOutBoundCount() { |
| + return output_checker_.out_bound_count(); |
| +} |
| + |
| +void OutputTest::Mute() { |
| + VoEVolumeControl* volume = manager_.VolumeControlPtr(); |
| + volume->SetInputMute(channel_, true); |
| +} |
| + |
| +void OutputTest::Unmute() { |
| + VoEVolumeControl* volume = manager_.VolumeControlPtr(); |
| + volume->SetInputMute(channel_, false); |
| +} |
| + |
| +void OutputTest::SetBitRate(int rate) { |
| + VoECodec* codec = manager_.CodecPtr(); |
| + codec->SetBitRate(channel_, rate); |
| +} |
| + |
| +OutputTest::VoEOutputCheckMediaProcess::VoEOutputCheckMediaProcess() |
| + : enabled_(false), |
| + lower_bound_(-32768), |
| + upper_bound_(32767), |
| + out_bound_count_(0) {} |
| + |
| +void OutputTest::VoEOutputCheckMediaProcess::Process(int channel, |
| + ProcessingTypes type, |
| + int16_t* audio10ms, |
| + size_t length, |
| + int samplingFreq, |
| + bool isStereo) { |
| + if (!enabled_) |
| + return; |
| + const int num_channels = isStereo ? 2 : 1; |
| + for (size_t i = 0; i < length; ++i) { |
| + for (int c = 0; c < num_channels; ++c, ++audio10ms) { |
| + if (*audio10ms < lower_bound_ || *audio10ms > upper_bound_) { |
| + ++out_bound_count_; |
| + } |
| + } |
| + } |
| +} |
| + |
| +TEST(OutputTest, OpusDtxHasNoNoisePump) { |
| + const int kRuntimeMs = 20000; |
| + const int kUnmuteTimeMs = 1000; |
| + const int kCheckAfterMute = 2000; |
| + const int kCheckTimeMs = 2000; |
| + const int kMinOpusRate = 6000; |
| + const int kMaxOpusRate = 64000; |
| + const int16_t kDtxBoundForSilence = 2; |
| + |
| + OutputTest test; |
| + Random random(1234ull); |
| + |
| + uint32_t start_time = rtc::Time(); |
| + test.Start(); |
| + test.SetOutputBound(-kDtxBoundForSilence, kDtxBoundForSilence); |
| + while (rtc::TimeSince(start_time) < kRuntimeMs) { |
| + webrtc::SleepMs(kUnmuteTimeMs + random.Gaussian(0, 100)); |
|
kwiberg-webrtc
2015/10/29 16:35:21
Replace 100 with e.g. kUnmuteTimeMs/10 here, to ma
minyue-webrtc
2015/10/30 14:06:46
To avoid unlucky, we can use a bounded distributio
|
| + test.Mute(); |
| + webrtc::SleepMs(kCheckAfterMute); |
| + test.EnableOutputCheck(); |
| + webrtc::SleepMs(kCheckTimeMs + random.Gaussian(0, 100)); |
| + test.DisableOutputCheck(); |
| + test.SetBitRate(random.Rand(kMinOpusRate, kMaxOpusRate)); |
| + test.Unmute(); |
| + } |
| + EXPECT_EQ(0u, test.GetOutBoundCount()); |
| +} |
| + |
| +} // namespace voetest |