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..54bfe80d0e02489f45823bc535b3bb0796bc9291 |
--- /dev/null |
+++ b/webrtc/voice_engine/test/auto_test/voe_output_test.cc |
@@ -0,0 +1,203 @@ |
+/* |
+ * 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/scoped_ptr.h" |
+#include "webrtc/base/timeutils.h" |
+#include "webrtc/system_wrappers/include/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(int16_t lower_bound, int16_t upper_bound); |
+ ~OutputTest(); |
+ |
+ void Start(); |
+ |
+ void EnableOutputCheck(); |
+ void DisableOutputCheck(); |
+ void SetOutputBound(int16_t lower_bound, int16_t upper_bound); |
+ 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(int16_t lower_bound, int16_t upper_bound); |
+ |
+ void set_enabled(bool enabled) { enabled_ = enabled; } |
+ 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_; |
+ }; |
+ |
+ VoETestManager manager_; |
+ VoEOutputCheckMediaProcess output_checker_; |
+ |
+ int channel_; |
+}; |
+ |
+OutputTest::OutputTest(int16_t lower_bound, int16_t upper_bound) |
+ : output_checker_(lower_bound, upper_bound) { |
+ EXPECT_TRUE(manager_.Init()); |
+ manager_.GetInterfaces(); |
+ |
+ VoEBase* base = manager_.BasePtr(); |
+ VoECodec* codec = manager_.CodecPtr(); |
+ VoENetwork* network = manager_.NetworkPtr(); |
+ |
+ EXPECT_EQ(0, base->Init()); |
+ |
+ channel_ = base->CreateChannel(); |
+ |
+ // |network| will take care of the life time of |transport|. |
+ VoiceChannelTransport* transport = |
+ new VoiceChannelTransport(network, channel_); |
+ |
+ EXPECT_EQ(0, transport->SetSendDestination(kIp, kPort)); |
+ EXPECT_EQ(0, transport->SetLocalReceiver(kPort)); |
+ |
+ EXPECT_EQ(0, codec->SetSendCodec(channel_, kCodecInst)); |
+ EXPECT_EQ(0, codec->SetOpusDtx(channel_, true)); |
+ |
+ EXPECT_EQ(0, manager_.VolumeControlPtr()->SetSpeakerVolume(255)); |
+ |
+ manager_.ExternalMediaPtr()->RegisterExternalMediaProcessing( |
+ channel_, ProcessingTypes::kPlaybackPerChannel, output_checker_); |
+} |
+ |
+OutputTest::~OutputTest() { |
+ EXPECT_EQ(0, manager_.NetworkPtr()->DeRegisterExternalTransport(channel_)); |
+ EXPECT_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; |
+ |
+ ASSERT_EQ(0, manager_.FilePtr()->StartPlayingFileAsMicrophone( |
+ channel_, file_name.c_str(), true, false, kInputFormat, 1.0)); |
+ |
+ VoEBase* base = manager_.BasePtr(); |
+ ASSERT_EQ(0, base->StartPlayout(channel_)); |
+ ASSERT_EQ(0, base->StartSend(channel_)); |
+} |
+ |
+void OutputTest::EnableOutputCheck() { |
+ output_checker_.set_enabled(true); |
+} |
+ |
+void OutputTest::DisableOutputCheck() { |
+ output_checker_.set_enabled(false); |
+} |
+ |
+void OutputTest::Mute() { |
+ manager_.VolumeControlPtr()->SetInputMute(channel_, true); |
+} |
+ |
+void OutputTest::Unmute() { |
+ manager_.VolumeControlPtr()->SetInputMute(channel_, false); |
+} |
+ |
+void OutputTest::SetBitRate(int rate) { |
+ manager_.CodecPtr()->SetBitRate(channel_, rate); |
+} |
+ |
+OutputTest::VoEOutputCheckMediaProcess::VoEOutputCheckMediaProcess( |
+ int16_t lower_bound, int16_t upper_bound) |
+ : enabled_(false), |
+ lower_bound_(lower_bound), |
+ upper_bound_(upper_bound) {} |
+ |
+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) { |
+ ASSERT_GE(audio10ms[i * num_channels + c], lower_bound_); |
+ ASSERT_LE(audio10ms[i * num_channels + c], upper_bound_); |
+ } |
+ } |
+} |
+ |
+// This test checks if the Opus does not produce high noise (noise pump) when |
+// DTX is enabled. The microphone is toggled on and off, and values of the |
+// output signal during muting should be bounded. |
+// We do not run this test on bots. Developers that want to see the result |
+// and/or listen to sound quality can run this test manually. |
+TEST(OutputTest, DISABLED_OpusDtxHasNoNoisePump) { |
+ const int kRuntimeMs = 20000; |
+ const uint32_t kUnmuteTimeMs = 1000; |
+ const int kCheckAfterMute = 2000; |
+ const uint32_t kCheckTimeMs = 2000; |
+ const int kMinOpusRate = 6000; |
+ const int kMaxOpusRate = 64000; |
+ |
+#if defined(OPUS_FIXED_POINT) |
+ const int16_t kDtxBoundForSilence = 20; |
+#else |
+ const int16_t kDtxBoundForSilence = 2; |
+#endif |
+ |
+ OutputTest test(-kDtxBoundForSilence, kDtxBoundForSilence); |
+ Random random(1234ull); |
+ |
+ uint32_t start_time = rtc::Time(); |
+ test.Start(); |
+ while (rtc::TimeSince(start_time) < kRuntimeMs) { |
+ webrtc::SleepMs(random.Rand(kUnmuteTimeMs - kUnmuteTimeMs / 10, |
+ kUnmuteTimeMs + kUnmuteTimeMs / 10)); |
+ test.Mute(); |
+ webrtc::SleepMs(kCheckAfterMute); |
+ test.EnableOutputCheck(); |
+ webrtc::SleepMs(random.Rand(kCheckTimeMs - kCheckTimeMs / 10, |
+ kCheckTimeMs + kCheckTimeMs / 10)); |
+ test.DisableOutputCheck(); |
+ test.SetBitRate(random.Rand(kMinOpusRate, kMaxOpusRate)); |
+ test.Unmute(); |
+ } |
+} |
+ |
+} // namespace voetest |