From 92220ffe9fe31698b9113f9e5347f7bd85b557e4 Mon Sep 17 00:00:00 2001 From: oprypin Date: Thu, 23 Mar 2017 03:40:03 -0700 Subject: [PATCH] Low-bandwidth audio testing The C++ part of the test uses CallTest to set up an audio-only call. It reads an audio file, plays it through a FakeAudioDevice which transfers data through a FakeNetworkPipe for another FakeAudioDevice to receive it and write it to a file. Information about these files is printed to stdout. The test cases are meant to try different network and audio configs (more are planned in the future). The Python part of the test runs the C++ part and scans stdout for tests to perform, runs the pairs of files (original and degraded) through the PESQ tool to receive a score and writes that to perf dashboard. BUG=webrtc:7229 NOTRY=True Review-Url: https://codereview.webrtc.org/2694203002 Cr-Commit-Position: refs/heads/master@{#17356} --- webrtc/audio/BUILD.gn | 22 ++- webrtc/audio/DEPS | 4 +- webrtc/audio/test/low_bandwidth_audio_test.cc | 143 +++++++++++++++++- webrtc/audio/test/low_bandwidth_audio_test.h | 61 ++++++++ webrtc/audio/test/low_bandwidth_audio_test.py | 81 +++++++++- webrtc/test/BUILD.gn | 4 + webrtc/test/call_test.cc | 29 +++- webrtc/test/call_test.h | 11 +- webrtc/test/fake_audio_device.cc | 70 +++++++++ webrtc/test/fake_audio_device.h | 6 + webrtc/test/fake_audio_device_unittest.cc | 131 ++++++++++++++++ webrtc/video/BUILD.gn | 6 - 12 files changed, 541 insertions(+), 27 deletions(-) create mode 100644 webrtc/audio/test/low_bandwidth_audio_test.h create mode 100644 webrtc/test/fake_audio_device_unittest.cc diff --git a/webrtc/audio/BUILD.gn b/webrtc/audio/BUILD.gn index fcb3372a54..4858c46571 100644 --- a/webrtc/audio/BUILD.gn +++ b/webrtc/audio/BUILD.gn @@ -94,12 +94,28 @@ if (rtc_include_tests) { sources = [ "test/low_bandwidth_audio_test.cc", + "test/low_bandwidth_audio_test.h", ] - deps = [] - + deps = [ + "../common_audio", + "../system_wrappers", + "../test:fake_audio_device", + "../test:run_test", + "../test:test_common", + "../test:test_main", + ] if (is_android) { - deps += [ "//testing/android/native_test:native_test_support" ] + deps += [ "//testing/android/native_test:native_test_native_code" ] + } + + data = [ + "//resources/voice_engine/audio_tiny16.wav", + ] + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163) + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] } } } diff --git a/webrtc/audio/DEPS b/webrtc/audio/DEPS index f383c1456b..1bace55a5a 100644 --- a/webrtc/audio/DEPS +++ b/webrtc/audio/DEPS @@ -1,9 +1,9 @@ include_rules = [ "+webrtc/base", "+webrtc/call", - "+webrtc/common_audio/resampler", + "+webrtc/common_audio", "+webrtc/logging/rtc_event_log", - "+webrtc/modules/audio_coding/codecs/mock", + "+webrtc/modules/audio_coding", "+webrtc/modules/audio_device", "+webrtc/modules/audio_mixer", "+webrtc/modules/audio_processing/include", diff --git a/webrtc/audio/test/low_bandwidth_audio_test.cc b/webrtc/audio/test/low_bandwidth_audio_test.cc index c78e8897a8..c1b1a02235 100644 --- a/webrtc/audio/test/low_bandwidth_audio_test.cc +++ b/webrtc/audio/test/low_bandwidth_audio_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * Copyright (c) 2017 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 @@ -8,9 +8,144 @@ * be found in the AUTHORS file in the root of the source tree. */ -// This is a placeholder for the work oprypin@ is doing on a low-bandwidth -// audio test executable. +#include -int main() { +#include "webrtc/audio/test/low_bandwidth_audio_test.h" +#include "webrtc/common_audio/wav_file.h" +#include "webrtc/test/gtest.h" +#include "webrtc/test/run_test.h" +#include "webrtc/system_wrappers/include/sleep.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace { +// Wait half a second between stopping sending and stopping receiving audio. +constexpr int kExtraRecordTimeMs = 500; + +// Large bitrate by default. +const webrtc::CodecInst kDefaultCodec{120, "OPUS", 48000, 960, 2, 64000}; + +// The best that can be done with PESQ. +constexpr int kAudioFileBitRate = 16000; +} + +namespace webrtc { +namespace test { + +AudioQualityTest::AudioQualityTest() + : EndToEndTest(CallTest::kDefaultTimeoutMs) {} + +size_t AudioQualityTest::GetNumVideoStreams() const { return 0; } +size_t AudioQualityTest::GetNumAudioStreams() const { + return 1; +} +size_t AudioQualityTest::GetNumFlexfecStreams() const { + return 0; +} + +std::string AudioQualityTest::AudioInputFile() { + return test::ResourcePath("voice_engine/audio_tiny16", "wav"); +} + +std::string AudioQualityTest::AudioOutputFile() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + return webrtc::test::OutputPath() + + "LowBandwidth_" + test_info->name() + ".wav"; +} + +std::unique_ptr + AudioQualityTest::CreateCapturer() { + return test::FakeAudioDevice::CreateWavFileReader(AudioInputFile()); +} + +std::unique_ptr + AudioQualityTest::CreateRenderer() { + return test::FakeAudioDevice::CreateBoundedWavFileWriter( + AudioOutputFile(), kAudioFileBitRate); +} + +void AudioQualityTest::OnFakeAudioDevicesCreated( + test::FakeAudioDevice* send_audio_device, + test::FakeAudioDevice* recv_audio_device) { + send_audio_device_ = send_audio_device; +} + +FakeNetworkPipe::Config AudioQualityTest::GetNetworkPipeConfig() { + return FakeNetworkPipe::Config(); +} + +test::PacketTransport* AudioQualityTest::CreateSendTransport( + Call* sender_call) { + return new test::PacketTransport( + sender_call, this, test::PacketTransport::kSender, + GetNetworkPipeConfig()); +} + +test::PacketTransport* AudioQualityTest::CreateReceiveTransport() { + return new test::PacketTransport(nullptr, this, + test::PacketTransport::kReceiver, GetNetworkPipeConfig()); +} + +void AudioQualityTest::ModifyAudioConfigs( + AudioSendStream::Config* send_config, + std::vector* receive_configs) { + send_config->send_codec_spec.codec_inst = kDefaultCodec; +} + +void AudioQualityTest::PerformTest() { + // Wait until the input audio file is done... + send_audio_device_->WaitForRecordingEnd(); + // and some extra time to account for network delay. + SleepMs(GetNetworkPipeConfig().queue_delay_ms + kExtraRecordTimeMs); +} + +void AudioQualityTest::OnTestFinished() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + // Output information about the input and output audio files so that further + // processing can be done by an external process. + printf("TEST %s %s:%s\n", test_info->name(), + AudioInputFile().c_str(), AudioOutputFile().c_str()); +} + + +using LowBandwidthAudioTest = CallTest; + +TEST_F(LowBandwidthAudioTest, GoodNetworkHighBitrate) { + AudioQualityTest test; + RunBaseTest(&test); +} + + +class Mobile2GNetworkTest : public AudioQualityTest { + void ModifyAudioConfigs(AudioSendStream::Config* send_config, + std::vector* receive_configs) override { + send_config->send_codec_spec.codec_inst = CodecInst{ + 120, // pltype + "OPUS", // plname + 48000, // plfreq + 2880, // pacsize + 1, // channels + 6000 // rate bits/sec + }; + } + + FakeNetworkPipe::Config GetNetworkPipeConfig() override { + FakeNetworkPipe::Config pipe_config; + pipe_config.link_capacity_kbps = 12; + pipe_config.queue_length_packets = 1500; + pipe_config.queue_delay_ms = 400; + return pipe_config; + } +}; + +TEST_F(LowBandwidthAudioTest, Mobile2GNetwork) { + Mobile2GNetworkTest test; + RunBaseTest(&test); +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/audio/test/low_bandwidth_audio_test.h b/webrtc/audio/test/low_bandwidth_audio_test.h new file mode 100644 index 0000000000..eae650af22 --- /dev/null +++ b/webrtc/audio/test/low_bandwidth_audio_test.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 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. + */ +#ifndef WEBRTC_AUDIO_TEST_LOW_BANDWIDTH_AUDIO_TEST_H_ +#define WEBRTC_AUDIO_TEST_LOW_BANDWIDTH_AUDIO_TEST_H_ + +#include +#include +#include + +#include "webrtc/test/call_test.h" +#include "webrtc/test/fake_audio_device.h" + +namespace webrtc { +namespace test { + +class AudioQualityTest : public test::EndToEndTest { + public: + AudioQualityTest(); + + protected: + virtual std::string AudioInputFile(); + virtual std::string AudioOutputFile(); + + virtual FakeNetworkPipe::Config GetNetworkPipeConfig(); + + size_t GetNumVideoStreams() const override; + size_t GetNumAudioStreams() const override; + size_t GetNumFlexfecStreams() const override; + + std::unique_ptr CreateCapturer() override; + std::unique_ptr CreateRenderer() override; + + void OnFakeAudioDevicesCreated( + test::FakeAudioDevice* send_audio_device, + test::FakeAudioDevice* recv_audio_device) override; + + test::PacketTransport* CreateSendTransport(Call* sender_call) override; + test::PacketTransport* CreateReceiveTransport() override; + + void ModifyAudioConfigs( + AudioSendStream::Config* send_config, + std::vector* receive_configs) override; + + void PerformTest() override; + void OnTestFinished() override; + + private: + test::FakeAudioDevice* send_audio_device_; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_AUDIO_TEST_LOW_BANDWIDTH_AUDIO_TEST_H_ diff --git a/webrtc/audio/test/low_bandwidth_audio_test.py b/webrtc/audio/test/low_bandwidth_audio_test.py index aaba9d2398..6482d3d020 100755 --- a/webrtc/audio/test/low_bandwidth_audio_test.py +++ b/webrtc/audio/test/low_bandwidth_audio_test.py @@ -17,6 +17,7 @@ output files will be performed. import argparse import logging import os +import re import subprocess import sys @@ -26,30 +27,96 @@ SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir, os.pardir)) -def _RunCommand(argv, cwd=SRC_DIR, **kwargs): - logging.info('Running %r', argv) - subprocess.check_call(argv, cwd=cwd, **kwargs) +def _LogCommand(command): + logging.info('Running %r', command) + return command def _ParseArgs(): parser = argparse.ArgumentParser(description='Run low-bandwidth audio tests.') parser.add_argument('build_dir', help='Path to the build directory (e.g. out/Release).') + parser.add_argument('--remove', action='store_true', + help='Remove output audio files after testing.') args = parser.parse_args() return args +def _GetPlatform(): + if sys.platform == 'win32': + return 'win' + elif sys.platform == 'darwin': + return 'mac' + elif sys.platform.startswith('linux'): + return 'linux' + + +def _GetExecutableExtension(): + if sys.platform == 'win32': + return '.exe' + else: + return '' + + +def _DownloadTools(): + tools_dir = os.path.join(SRC_DIR, 'tools-webrtc') + toolchain_dir = os.path.join(tools_dir, 'audio_quality') + + # Download pesq. + download_script = os.path.join(tools_dir, 'download_tools.py') + command = [sys.executable, download_script, toolchain_dir] + subprocess.check_call(_LogCommand(command)) + + pesq_path = os.path.join(toolchain_dir, _GetPlatform(), + 'pesq' + _GetExecutableExtension()) + return pesq_path + + def main(): # pylint: disable=W0101 logging.basicConfig(level=logging.INFO) args = _ParseArgs() - test_executable = os.path.join(args.build_dir, 'low_bandwidth_audio_test') - if sys.platform == 'win32': - test_executable += '.exe' + pesq_path = _DownloadTools() - _RunCommand([test_executable]) + test_executable_path = os.path.join(args.build_dir, + 'low_bandwidth_audio_test' + _GetExecutableExtension()) + + # Start the test executable that produces audio files. + command = [test_executable_path] + test_process = subprocess.Popen(_LogCommand(command), stdout=subprocess.PIPE) + + for line in iter(test_process.stdout.readline, ''): + # Echo the output to screen. + sys.stdout.write(line) + + # Extract specific lines that contain information about produced files. + match = re.search(r'^TEST (\w+) ([^:]+?):([^:]+?)\n?$', line) + if not match: + continue + test_name, reference_file, degraded_file = match.groups() + + # Analyze audio + command = [pesq_path, '+16000', reference_file, degraded_file] + pesq_output = subprocess.check_output(_LogCommand(command)) + + if args.remove: + os.remove(degraded_file) + + # Find the scores in stdout of pesq. + match = re.search( + r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)', + pesq_output) + if match: + raw_mos, _ = match.groups() + + # Output a result for the perf dashboard. + print 'RESULT pesq_mos: %s= %s score' % (test_name, raw_mos) + else: + logging.error('PESQ: %s', pesq_output.splitlines()[-1]) + + return test_process.wait() if __name__ == '__main__': diff --git a/webrtc/test/BUILD.gn b/webrtc/test/BUILD.gn index 322f8393f7..4a49ef7ad7 100644 --- a/webrtc/test/BUILD.gn +++ b/webrtc/test/BUILD.gn @@ -255,6 +255,7 @@ if (is_ios) { rtc_test("test_support_unittests") { deps = [] sources = [ + "fake_audio_device_unittest.cc", "fake_network_pipe_unittest.cc", "frame_generator_unittest.cc", "rtp_file_reader_unittest.cc", @@ -409,6 +410,9 @@ rtc_source_set("test_common") { "//testing/gmock", "//testing/gtest", ] + if (!is_android) { + deps += [ "../modules/video_capture:video_capture_internal_impl" ] + } } config("test_renderer_exported_config") { diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc index 10c6438a50..ad55421f66 100644 --- a/webrtc/test/call_test.cc +++ b/webrtc/test/call_test.cc @@ -50,6 +50,9 @@ void CallTest::RunBaseTest(BaseTest* test) { RTC_DCHECK(num_video_streams_ > 0 || num_audio_streams_ > 0); Call::Config send_config(test->GetSenderCallConfig()); if (num_audio_streams_ > 0) { + CreateFakeAudioDevices(test->CreateCapturer(), test->CreateRenderer()); + test->OnFakeAudioDevicesCreated(fake_send_audio_device_.get(), + fake_recv_audio_device_.get()); CreateVoiceEngines(); AudioState::Config audio_state_config; audio_state_config.voice_engine = voe_send_.voice_engine; @@ -132,6 +135,8 @@ void CallTest::RunBaseTest(BaseTest* test) { DestroyCalls(); if (num_audio_streams_ > 0) DestroyVoiceEngines(); + + test->OnTestFinished(); } void CallTest::Start() { @@ -298,11 +303,13 @@ void CallTest::CreateFrameGeneratorCapturer(int framerate, VideoSendStream::DegradationPreference::kBalanced); } -void CallTest::CreateFakeAudioDevices() { +void CallTest::CreateFakeAudioDevices( + std::unique_ptr capturer, + std::unique_ptr renderer) { fake_send_audio_device_.reset(new FakeAudioDevice( - FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000), nullptr, 1.f)); + std::move(capturer), nullptr, 1.f)); fake_recv_audio_device_.reset(new FakeAudioDevice( - nullptr, FakeAudioDevice::CreateDiscardRenderer(48000), 1.f)); + nullptr, std::move(renderer), 1.f)); } void CallTest::CreateVideoStreams() { @@ -361,7 +368,6 @@ void CallTest::DestroyStreams() { } void CallTest::CreateVoiceEngines() { - CreateFakeAudioDevices(); voe_send_.voice_engine = VoiceEngine::Create(); voe_send_.base = VoEBase::GetInterface(voe_send_.voice_engine); EXPECT_EQ(0, voe_send_.base->Init(fake_send_audio_device_.get(), nullptr, @@ -427,6 +433,18 @@ BaseTest::BaseTest(unsigned int timeout_ms) : RtpRtcpObserver(timeout_ms) { BaseTest::~BaseTest() { } +std::unique_ptr BaseTest::CreateCapturer() { + return FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000); +} + +std::unique_ptr BaseTest::CreateRenderer() { + return FakeAudioDevice::CreateDiscardRenderer(48000); +} + +void BaseTest::OnFakeAudioDevicesCreated(FakeAudioDevice* send_audio_device, + FakeAudioDevice* recv_audio_device) { +} + Call::Config BaseTest::GetSenderCallConfig() { return Call::Config(&event_log_); } @@ -491,6 +509,9 @@ void BaseTest::OnFrameGeneratorCapturerCreated( FrameGeneratorCapturer* frame_generator_capturer) { } +void BaseTest::OnTestFinished() { +} + SendTest::SendTest(unsigned int timeout_ms) : BaseTest(timeout_ms) { } diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h index f1540bf899..78fbbfbe43 100644 --- a/webrtc/test/call_test.h +++ b/webrtc/test/call_test.h @@ -83,7 +83,9 @@ class CallTest : public ::testing::Test { int width, int height); void CreateFrameGeneratorCapturer(int framerate, int width, int height); - void CreateFakeAudioDevices(); + void CreateFakeAudioDevices( + std::unique_ptr capturer, + std::unique_ptr renderer); void CreateVideoStreams(); void CreateAudioStreams(); @@ -161,6 +163,11 @@ class BaseTest : public RtpRtcpObserver { virtual size_t GetNumAudioStreams() const; virtual size_t GetNumFlexfecStreams() const; + virtual std::unique_ptr CreateCapturer(); + virtual std::unique_ptr CreateRenderer(); + virtual void OnFakeAudioDevicesCreated(FakeAudioDevice* send_audio_device, + FakeAudioDevice* recv_audio_device); + virtual Call::Config GetSenderCallConfig(); virtual Call::Config GetReceiverCallConfig(); virtual void OnCallsCreated(Call* sender_call, Call* receiver_call); @@ -194,6 +201,8 @@ class BaseTest : public RtpRtcpObserver { virtual void OnFrameGeneratorCapturerCreated( FrameGeneratorCapturer* frame_generator_capturer); + virtual void OnTestFinished(); + webrtc::RtcEventLogNullImpl event_log_; }; diff --git a/webrtc/test/fake_audio_device.cc b/webrtc/test/fake_audio_device.cc index 7a3f0dd740..91d5978b3f 100644 --- a/webrtc/test/fake_audio_device.cc +++ b/webrtc/test/fake_audio_device.cc @@ -111,6 +111,69 @@ class WavFileWriter final : public test::FakeAudioDevice::Renderer { WavWriter wav_writer_; }; +class BoundedWavFileWriter : public test::FakeAudioDevice::Renderer { + public: + BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz) + : sampling_frequency_in_hz_(sampling_frequency_in_hz), + wav_writer_(filename, sampling_frequency_in_hz, 1), + silent_audio_(test::FakeAudioDevice::SamplesPerFrame( + sampling_frequency_in_hz), 0), + started_writing_(false), + trailing_zeros_(0) {} + + int SamplingFrequency() const override { + return sampling_frequency_in_hz_; + } + + bool Render(rtc::ArrayView data) override { + const int16_t kAmplitudeThreshold = 5; + + const int16_t* begin = data.begin(); + const int16_t* end = data.end(); + if (!started_writing_) { + // Cut off silence at the beginning. + while (begin < end) { + if (std::abs(*begin) > kAmplitudeThreshold) { + started_writing_ = true; + break; + } + ++begin; + } + } + if (started_writing_) { + // Cut off silence at the end. + while (begin < end) { + if (*(end - 1) != 0) { + break; + } + --end; + } + if (begin < end) { + // If it turns out that the silence was not final, need to write all the + // skipped zeros and continue writing audio. + while (trailing_zeros_ > 0) { + const size_t zeros_to_write = std::min(trailing_zeros_, + silent_audio_.size()); + wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write); + trailing_zeros_ -= zeros_to_write; + } + wav_writer_.WriteSamples(begin, end - begin); + } + // Save the number of zeros we skipped in case this needs to be restored. + trailing_zeros_ += data.end() - end; + } + return true; + } + + private: + int sampling_frequency_in_hz_; + WavWriter wav_writer_; + std::vector silent_audio_; + bool started_writing_; + size_t trailing_zeros_; +}; + + class DiscardRenderer final : public test::FakeAudioDevice::Renderer { public: explicit DiscardRenderer(int sampling_frequency_in_hz) @@ -161,6 +224,13 @@ std::unique_ptr FakeAudioDevice::CreateWavFileWriter( new WavFileWriter(filename, sampling_frequency_in_hz)); } +std::unique_ptr + FakeAudioDevice::CreateBoundedWavFileWriter( + std::string filename, int sampling_frequency_in_hz) { + return std::unique_ptr( + new BoundedWavFileWriter(filename, sampling_frequency_in_hz)); +} + std::unique_ptr FakeAudioDevice::CreateDiscardRenderer(int sampling_frequency_in_hz) { return std::unique_ptr( diff --git a/webrtc/test/fake_audio_device.h b/webrtc/test/fake_audio_device.h index e44ec540f0..f6017443d7 100644 --- a/webrtc/test/fake_audio_device.h +++ b/webrtc/test/fake_audio_device.h @@ -89,6 +89,12 @@ class FakeAudioDevice : public FakeAudioDeviceModule { static std::unique_ptr CreateWavFileWriter( std::string filename, int sampling_frequency_in_hz); + // Returns a Renderer instance that writes its data to a WAV file, cutting + // off silence at the beginning (not necessarily perfect silence, see + // kAmplitudeThreshold) and at the end (only actual 0 samples in this case). + static std::unique_ptr CreateBoundedWavFileWriter( + std::string filename, int sampling_frequency_in_hz); + // Returns a Renderer instance that does nothing with the audio data. static std::unique_ptr CreateDiscardRenderer( int sampling_frequency_in_hz); diff --git a/webrtc/test/fake_audio_device_unittest.cc b/webrtc/test/fake_audio_device_unittest.cc new file mode 100644 index 0000000000..d4f8acc8ac --- /dev/null +++ b/webrtc/test/fake_audio_device_unittest.cc @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017 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 +#include + +#include "webrtc/common_audio/wav_file.h" +#include "webrtc/common_audio/wav_header.h" +#include "webrtc/test/fake_audio_device.h" +#include "webrtc/test/gtest.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace webrtc { +namespace test { + +namespace { +void RunTest(const std::vector& input_samples, + const std::vector& expected_samples, + size_t samples_per_frame) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + const std::string output_filename = test::OutputPath() + + "BoundedWavFileWriterTest_" + test_info->name() + ".wav"; + + static const size_t kSamplesPerFrame = 8; + static const int kSampleRate = kSamplesPerFrame * 100; + EXPECT_EQ(FakeAudioDevice::SamplesPerFrame(kSampleRate), kSamplesPerFrame); + + { + std::unique_ptr writer = + FakeAudioDevice::CreateBoundedWavFileWriter(output_filename, 800); + + for (size_t i = 0; i < input_samples.size(); i += kSamplesPerFrame) { + EXPECT_TRUE(writer->Render(rtc::ArrayView( + &input_samples[i], + std::min(kSamplesPerFrame, input_samples.size() - i)))); + } + } + + { + WavReader reader(output_filename); + std::vector read_samples(expected_samples.size()); + EXPECT_EQ(expected_samples.size(), + reader.ReadSamples(read_samples.size(), read_samples.data())); + EXPECT_EQ(expected_samples, read_samples); + + EXPECT_EQ(0u, reader.ReadSamples(read_samples.size(), read_samples.data())); + } + + remove(output_filename.c_str()); +} +} // namespace + +TEST(BoundedWavFileWriterTest, NoSilence) { + static const std::vector kInputSamples = { + 75, 1234, 243, -1231, -22222, 0, 3, 88, + 1222, -1213, -13222, -7, -3525, 5787, -25247, 8 + }; + static const std::vector kExpectedSamples = kInputSamples; + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, SomeStartSilence) { + static const std::vector kInputSamples = { + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 3, -13222, -7, -3525, 5787, -25247, 8 + }; + static const std::vector kExpectedSamples(kInputSamples.begin() + 10, + kInputSamples.end()); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, NegativeStartSilence) { + static const std::vector kInputSamples = { + 0, -4, -6, 0, 3, 0, 0, 0, + 0, 3, -13222, -7, -3525, 5787, -25247, 8 + }; + static const std::vector kExpectedSamples(kInputSamples.begin() + 2, + kInputSamples.end()); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, SomeEndSilence) { + static const std::vector kInputSamples = { + 75, 1234, 243, -1231, -22222, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + static const std::vector kExpectedSamples(kInputSamples.begin(), + kInputSamples.end() - 9); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, DoubleEndSilence) { + static const std::vector kInputSamples = { + 75, 1234, 243, -1231, -22222, 0, 0, 0, + 0, -1213, -13222, -7, -3525, 5787, 0, 0 + }; + static const std::vector kExpectedSamples(kInputSamples.begin(), + kInputSamples.end() - 2); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, DoubleSilence) { + static const std::vector kInputSamples = { + 0, -1213, -13222, -7, -3525, 5787, 0, 0 + }; + static const std::vector kExpectedSamples(kInputSamples.begin() + 1, + kInputSamples.end() - 2); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +TEST(BoundedWavFileWriterTest, EndSilenceCutoff) { + static const std::vector kInputSamples = { + 75, 1234, 243, -1231, -22222, 0, 1, 0, + 0, 0, 0 + }; + static const std::vector kExpectedSamples(kInputSamples.begin(), + kInputSamples.end() - 4); + RunTest(kInputSamples, kExpectedSamples, 8); +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/video/BUILD.gn b/webrtc/video/BUILD.gn index 5859c12ef8..be12b07d38 100644 --- a/webrtc/video/BUILD.gn +++ b/webrtc/video/BUILD.gn @@ -93,9 +93,6 @@ if (rtc_include_tests) { "//webrtc/test:test_renderer", "//webrtc/test:video_test_common", ] - if (!is_android) { - deps += [ "../modules/video_capture:video_capture_internal_impl" ] - } if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] @@ -178,9 +175,6 @@ if (rtc_include_tests) { "../test:test_renderer", "//third_party/gflags", ] - if (!is_android) { - deps += [ "../modules/video_capture:video_capture_internal_impl" ] - } if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]