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}
diff --git a/webrtc/audio/BUILD.gn b/webrtc/audio/BUILD.gn
index fcb3372..4858c46 100644
--- a/webrtc/audio/BUILD.gn
+++ b/webrtc/audio/BUILD.gn
@@ -94,12 +94,28 @@
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 f383c14..1bace55 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 c78e889..c1b1a02 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 <algorithm>
-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<test::FakeAudioDevice::Capturer>
+ AudioQualityTest::CreateCapturer() {
+ return test::FakeAudioDevice::CreateWavFileReader(AudioInputFile());
+}
+
+std::unique_ptr<test::FakeAudioDevice::Renderer>
+ 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<AudioReceiveStream::Config>* 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<AudioReceiveStream::Config>* 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 0000000..eae650a
--- /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 <memory>
+#include <string>
+#include <vector>
+
+#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<test::FakeAudioDevice::Capturer> CreateCapturer() override;
+ std::unique_ptr<test::FakeAudioDevice::Renderer> 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<AudioReceiveStream::Config>* 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 aaba9d2..6482d3d 100755
--- a/webrtc/audio/test/low_bandwidth_audio_test.py
+++ b/webrtc/audio/test/low_bandwidth_audio_test.py
@@ -17,6 +17,7 @@
import argparse
import logging
import os
+import re
import subprocess
import sys
@@ -26,30 +27,96 @@
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 322f839..4a49ef7 100644
--- a/webrtc/test/BUILD.gn
+++ b/webrtc/test/BUILD.gn
@@ -255,6 +255,7 @@
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 @@
"//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 10c6438..ad55421 100644
--- a/webrtc/test/call_test.cc
+++ b/webrtc/test/call_test.cc
@@ -50,6 +50,9 @@
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 @@
DestroyCalls();
if (num_audio_streams_ > 0)
DestroyVoiceEngines();
+
+ test->OnTestFinished();
}
void CallTest::Start() {
@@ -298,11 +303,13 @@
VideoSendStream::DegradationPreference::kBalanced);
}
-void CallTest::CreateFakeAudioDevices() {
+void CallTest::CreateFakeAudioDevices(
+ std::unique_ptr<FakeAudioDevice::Capturer> capturer,
+ std::unique_ptr<FakeAudioDevice::Renderer> 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::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() {
}
+std::unique_ptr<FakeAudioDevice::Capturer> BaseTest::CreateCapturer() {
+ return FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000);
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer> 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 @@
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 f1540bf..78fbbfb 100644
--- a/webrtc/test/call_test.h
+++ b/webrtc/test/call_test.h
@@ -83,7 +83,9 @@
int width,
int height);
void CreateFrameGeneratorCapturer(int framerate, int width, int height);
- void CreateFakeAudioDevices();
+ void CreateFakeAudioDevices(
+ std::unique_ptr<FakeAudioDevice::Capturer> capturer,
+ std::unique_ptr<FakeAudioDevice::Renderer> renderer);
void CreateVideoStreams();
void CreateAudioStreams();
@@ -161,6 +163,11 @@
virtual size_t GetNumAudioStreams() const;
virtual size_t GetNumFlexfecStreams() const;
+ virtual std::unique_ptr<FakeAudioDevice::Capturer> CreateCapturer();
+ virtual std::unique_ptr<FakeAudioDevice::Renderer> 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 @@
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 7a3f0dd..91d5978 100644
--- a/webrtc/test/fake_audio_device.cc
+++ b/webrtc/test/fake_audio_device.cc
@@ -111,6 +111,69 @@
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<const int16_t> 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<int16_t> silent_audio_;
+ bool started_writing_;
+ size_t trailing_zeros_;
+};
+
+
class DiscardRenderer final : public test::FakeAudioDevice::Renderer {
public:
explicit DiscardRenderer(int sampling_frequency_in_hz)
@@ -162,6 +225,13 @@
}
std::unique_ptr<FakeAudioDevice::Renderer>
+ FakeAudioDevice::CreateBoundedWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Renderer>(
+ new BoundedWavFileWriter(filename, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer>
FakeAudioDevice::CreateDiscardRenderer(int sampling_frequency_in_hz) {
return std::unique_ptr<FakeAudioDevice::Renderer>(
new DiscardRenderer(sampling_frequency_in_hz));
diff --git a/webrtc/test/fake_audio_device.h b/webrtc/test/fake_audio_device.h
index e44ec54..f601744 100644
--- a/webrtc/test/fake_audio_device.h
+++ b/webrtc/test/fake_audio_device.h
@@ -89,6 +89,12 @@
static std::unique_ptr<Renderer> 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<Renderer> CreateBoundedWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz);
+
// Returns a Renderer instance that does nothing with the audio data.
static std::unique_ptr<Renderer> 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 0000000..d4f8acc
--- /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 <algorithm>
+#include <array>
+
+#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<int16_t>& input_samples,
+ const std::vector<int16_t>& 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<FakeAudioDevice::Renderer> writer =
+ FakeAudioDevice::CreateBoundedWavFileWriter(output_filename, 800);
+
+ for (size_t i = 0; i < input_samples.size(); i += kSamplesPerFrame) {
+ EXPECT_TRUE(writer->Render(rtc::ArrayView<const int16_t>(
+ &input_samples[i],
+ std::min(kSamplesPerFrame, input_samples.size() - i))));
+ }
+ }
+
+ {
+ WavReader reader(output_filename);
+ std::vector<int16_t> 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<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 3, 88,
+ 1222, -1213, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples = kInputSamples;
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, SomeStartSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 3, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 10,
+ kInputSamples.end());
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, NegativeStartSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, -4, -6, 0, 3, 0, 0, 0,
+ 0, 3, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 2,
+ kInputSamples.end());
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, SomeEndSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin(),
+ kInputSamples.end() - 9);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, DoubleEndSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 0, 0,
+ 0, -1213, -13222, -7, -3525, 5787, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin(),
+ kInputSamples.end() - 2);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, DoubleSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, -1213, -13222, -7, -3525, 5787, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 1,
+ kInputSamples.end() - 2);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, EndSilenceCutoff) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 1, 0,
+ 0, 0, 0
+ };
+ static const std::vector<int16_t> 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 5859c12..be12b07 100644
--- a/webrtc/video/BUILD.gn
+++ b/webrtc/video/BUILD.gn
@@ -93,9 +93,6 @@
"//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 @@
"../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" ]