diff --git a/webrtc/call/call_perf_tests.cc b/webrtc/call/call_perf_tests.cc index 782b45c9f2..b6a8fe6047 100644 --- a/webrtc/call/call_perf_tests.cc +++ b/webrtc/call/call_perf_tests.cc @@ -146,11 +146,7 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec, metrics::Reset(); VoiceEngine* voice_engine = VoiceEngine::Create(); VoEBase* voe_base = VoEBase::GetInterface(voice_engine); - const std::string audio_filename = - test::ResourcePath("voice_engine/audio_long16", "pcm"); - ASSERT_STRNE("", audio_filename.c_str()); - FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(), audio_filename, - audio_rtp_speed); + FakeAudioDevice fake_audio_device(audio_rtp_speed, 48000, 256); EXPECT_EQ(0, voe_base->Init(&fake_audio_device, nullptr, decoder_factory_)); VoEBase::ChannelConfig config; config.enable_voice_pacing = true; @@ -264,16 +260,14 @@ void CallPerfTest::TestAudioVideoSync(FecMode fec, Start(); - fake_audio_device.Start(); + audio_send_stream->Start(); audio_receive_stream->Start(); - EXPECT_EQ(0, voe_base->StartSend(send_channel_id)); EXPECT_TRUE(observer.Wait()) << "Timed out while waiting for audio and video to be synchronized."; - EXPECT_EQ(0, voe_base->StopSend(send_channel_id)); - EXPECT_EQ(0, voe_base->StopPlayout(recv_channel_id)); - fake_audio_device.Stop(); + audio_send_stream->Stop(); + audio_receive_stream->Stop(); Stop(); video_send_transport.StopSending(); diff --git a/webrtc/modules/audio_device/include/fake_audio_device.h b/webrtc/modules/audio_device/include/fake_audio_device.h index 98fd2f46f6..a28ad86464 100644 --- a/webrtc/modules/audio_device/include/fake_audio_device.h +++ b/webrtc/modules/audio_device/include/fake_audio_device.h @@ -21,6 +21,8 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual ~FakeAudioDeviceModule() {} virtual int32_t AddRef() const { return 0; } virtual int32_t Release() const { return 0; } + + private: virtual int32_t RegisterEventObserver(AudioDeviceObserver* eventCallback) { return 0; } @@ -121,7 +123,10 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual int32_t PlayoutBuffer(BufferType* type, uint16_t* sizeMS) const { return 0; } - virtual int32_t PlayoutDelay(uint16_t* delayMS) const { return 0; } + virtual int32_t PlayoutDelay(uint16_t* delayMS) const { + *delayMS = 0; + return 0; + } virtual int32_t RecordingDelay(uint16_t* delayMS) const { return 0; } virtual int32_t CPULoad(uint16_t* load) const { return 0; } virtual int32_t StartRawOutputFileRecording( diff --git a/webrtc/test/BUILD.gn b/webrtc/test/BUILD.gn index 9893814748..352eb371a8 100644 --- a/webrtc/test/BUILD.gn +++ b/webrtc/test/BUILD.gn @@ -332,7 +332,6 @@ rtc_source_set("test_common") { "../modules/audio_device:mock_audio_device", "../modules/audio_mixer:audio_mixer_impl", "../modules/audio_processing", - "../modules/media_file", "../modules/video_capture:video_capture", "../modules/video_capture:video_capture_module", "../video", diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc index c1c7355b1b..87bbea7d8d 100644 --- a/webrtc/test/call_test.cc +++ b/webrtc/test/call_test.cc @@ -140,16 +140,10 @@ void CallTest::Start() { for (VideoReceiveStream* video_recv_stream : video_receive_streams_) video_recv_stream->Start(); if (audio_send_stream_) { - fake_send_audio_device_->Start(); audio_send_stream_->Start(); - EXPECT_EQ(0, voe_send_.base->StartSend(voe_send_.channel_id)); } for (AudioReceiveStream* audio_recv_stream : audio_receive_streams_) audio_recv_stream->Start(); - if (!audio_receive_streams_.empty()) { - fake_recv_audio_device_->Start(); - EXPECT_EQ(0, voe_recv_.base->StartPlayout(voe_recv_.channel_id)); - } for (FlexfecReceiveStream* flexfec_recv_stream : flexfec_receive_streams_) flexfec_recv_stream->Start(); if (frame_generator_capturer_.get() != NULL) @@ -161,15 +155,9 @@ void CallTest::Stop() { frame_generator_capturer_->Stop(); for (FlexfecReceiveStream* flexfec_recv_stream : flexfec_receive_streams_) flexfec_recv_stream->Stop(); - if (!audio_receive_streams_.empty()) { - fake_recv_audio_device_->Stop(); - EXPECT_EQ(0, voe_recv_.base->StopPlayout(voe_recv_.channel_id)); - } for (AudioReceiveStream* audio_recv_stream : audio_receive_streams_) audio_recv_stream->Stop(); if (audio_send_stream_) { - fake_send_audio_device_->Stop(); - EXPECT_EQ(0, voe_send_.base->StopSend(voe_send_.channel_id)); audio_send_stream_->Stop(); } for (VideoReceiveStream* video_recv_stream : video_receive_streams_) @@ -309,12 +297,8 @@ void CallTest::CreateFrameGeneratorCapturer(int framerate, } void CallTest::CreateFakeAudioDevices() { - fake_send_audio_device_.reset(new FakeAudioDevice( - clock_, test::ResourcePath("voice_engine/audio_long16", "pcm"), - DriftingClock::kNoDrift)); - fake_recv_audio_device_.reset(new FakeAudioDevice( - clock_, test::ResourcePath("voice_engine/audio_long16", "pcm"), - DriftingClock::kNoDrift)); + fake_send_audio_device_.reset(new FakeAudioDevice(1.f, 48000, 256)); + fake_recv_audio_device_.reset(new FakeAudioDevice(1.f, 48000, 256)); } void CallTest::CreateVideoStreams() { diff --git a/webrtc/test/fake_audio_device.cc b/webrtc/test/fake_audio_device.cc index 9e5e95fb0d..623ff518d7 100644 --- a/webrtc/test/fake_audio_device.cc +++ b/webrtc/test/fake_audio_device.cc @@ -12,49 +12,104 @@ #include -#include "webrtc/base/platform_thread.h" -#include "webrtc/modules/media_file/media_file_utility.h" -#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/base/array_view.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/random.h" #include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/system_wrappers/include/file_wrapper.h" -#include "webrtc/test/gtest.h" namespace webrtc { + +namespace { + +constexpr int kFrameLengthMs = 10; +constexpr int kFramesPerSecond = 1000 / kFrameLengthMs; + +} // namespace namespace test { -FakeAudioDevice::FakeAudioDevice(Clock* clock, - const std::string& filename, - float speed) - : audio_callback_(NULL), - capturing_(false), - captured_audio_(), - playout_buffer_(), +// Assuming 10ms audio packets.. +class FakeAudioDevice::PulsedNoiseCapturer { + public: + PulsedNoiseCapturer(size_t num_samples_per_frame, int16_t max_amplitude) + : fill_with_zero_(false), + random_generator_(1), + max_amplitude_(max_amplitude), + random_audio_(num_samples_per_frame), + silent_audio_(num_samples_per_frame, 0) { + RTC_DCHECK_GT(max_amplitude, 0); + } + + rtc::ArrayView Capture() { + fill_with_zero_ = !fill_with_zero_; + if (!fill_with_zero_) { + std::generate(random_audio_.begin(), random_audio_.end(), [&]() { + return random_generator_.Rand(-max_amplitude_, max_amplitude_); + }); + } + return fill_with_zero_ ? silent_audio_ : random_audio_; + } + + private: + bool fill_with_zero_; + Random random_generator_; + const int16_t max_amplitude_; + std::vector random_audio_; + std::vector silent_audio_; +}; + +FakeAudioDevice::FakeAudioDevice(float speed, + int sampling_frequency_in_hz, + int16_t max_amplitude) + : sampling_frequency_in_hz_(sampling_frequency_in_hz), + num_samples_per_frame_( + rtc::CheckedDivExact(sampling_frequency_in_hz_, kFramesPerSecond)), speed_(speed), - last_playout_ms_(-1), - clock_(clock, speed), + audio_callback_(nullptr), + rendering_(false), + capturing_(false), + capturer_(new FakeAudioDevice::PulsedNoiseCapturer(num_samples_per_frame_, + max_amplitude)), + playout_buffer_(num_samples_per_frame_, 0), tick_(EventTimerWrapper::Create()), - thread_(FakeAudioDevice::Run, this, "FakeAudioDevice"), - file_utility_(new ModuleFileUtility(0)), - input_stream_(FileWrapper::Create()) { - memset(captured_audio_, 0, sizeof(captured_audio_)); - memset(playout_buffer_, 0, sizeof(playout_buffer_)); - // Open audio input file as read-only and looping. - EXPECT_TRUE(input_stream_->OpenFile(filename.c_str(), true)) << filename; + thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") { + RTC_DCHECK( + sampling_frequency_in_hz == 8000 || sampling_frequency_in_hz == 16000 || + sampling_frequency_in_hz == 32000 || sampling_frequency_in_hz == 44100 || + sampling_frequency_in_hz == 48000); } FakeAudioDevice::~FakeAudioDevice() { - Stop(); - + StopPlayout(); + StopRecording(); thread_.Stop(); } -int32_t FakeAudioDevice::Init() { +int32_t FakeAudioDevice::StartPlayout() { rtc::CritScope cs(&lock_); - if (file_utility_->InitPCMReading(*input_stream_.get()) != 0) - return -1; + rendering_ = true; + return 0; +} - if (!tick_->StartTimer(true, 10 / speed_)) - return -1; +int32_t FakeAudioDevice::StopPlayout() { + rtc::CritScope cs(&lock_); + rendering_ = false; + return 0; +} + +int32_t FakeAudioDevice::StartRecording() { + rtc::CritScope cs(&lock_); + capturing_ = true; + return 0; +} + +int32_t FakeAudioDevice::StopRecording() { + rtc::CritScope cs(&lock_); + capturing_ = false; + return 0; +} + +int32_t FakeAudioDevice::Init() { + RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_)); thread_.Start(); thread_.SetPriority(rtc::kHighPriority); return 0; @@ -62,18 +117,14 @@ int32_t FakeAudioDevice::Init() { int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { rtc::CritScope cs(&lock_); + RTC_DCHECK(callback || audio_callback_ != nullptr); audio_callback_ = callback; return 0; } bool FakeAudioDevice::Playing() const { rtc::CritScope cs(&lock_); - return capturing_; -} - -int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { - *delay_ms = 0; - return 0; + return rendering_; } bool FakeAudioDevice::Recording() const { @@ -82,65 +133,33 @@ bool FakeAudioDevice::Recording() const { } bool FakeAudioDevice::Run(void* obj) { - static_cast(obj)->CaptureAudio(); + static_cast(obj)->ProcessAudio(); return true; } -void FakeAudioDevice::CaptureAudio() { +void FakeAudioDevice::ProcessAudio() { { rtc::CritScope cs(&lock_); if (capturing_) { - int bytes_read = file_utility_->ReadPCMData( - *input_stream_.get(), captured_audio_, kBufferSizeBytes); - if (bytes_read <= 0) - return; - // 2 bytes per sample. - size_t num_samples = static_cast(bytes_read / 2); - uint32_t new_mic_level; - EXPECT_EQ(0, - audio_callback_->RecordedDataIsAvailable(captured_audio_, - num_samples, - 2, - 1, - kFrequencyHz, - 0, - 0, - 0, - false, - new_mic_level)); - size_t samples_needed = kFrequencyHz / 100; - int64_t now_ms = clock_.TimeInMilliseconds(); - uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_; - if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) { - samples_needed = std::min( - static_cast(kFrequencyHz / time_since_last_playout_ms), - kBufferSizeBytes / 2); - } + // Capture 10ms of audio. 2 bytes per sample. + rtc::ArrayView audio_data = capturer_->Capture(); + uint32_t new_mic_level = 0; + audio_callback_->RecordedDataIsAvailable( + audio_data.data(), audio_data.size(), 2, 1, sampling_frequency_in_hz_, + 0, 0, 0, false, new_mic_level); + } + if (rendering_) { size_t samples_out = 0; int64_t elapsed_time_ms = -1; int64_t ntp_time_ms = -1; - EXPECT_EQ(0, - audio_callback_->NeedMorePlayData(samples_needed, - 2, - 1, - kFrequencyHz, - playout_buffer_, - samples_out, - &elapsed_time_ms, - &ntp_time_ms)); + audio_callback_->NeedMorePlayData( + num_samples_per_frame_, 2, 1, sampling_frequency_in_hz_, + playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms); } } tick_->Wait(WEBRTC_EVENT_INFINITE); } -void FakeAudioDevice::Start() { - rtc::CritScope cs(&lock_); - capturing_ = true; -} -void FakeAudioDevice::Stop() { - rtc::CritScope cs(&lock_); - capturing_ = false; -} } // namespace test } // namespace webrtc diff --git a/webrtc/test/fake_audio_device.h b/webrtc/test/fake_audio_device.h index 77a74bac8f..4daeab4365 100644 --- a/webrtc/test/fake_audio_device.h +++ b/webrtc/test/fake_audio_device.h @@ -12,58 +12,65 @@ #include #include +#include #include "webrtc/base/criticalsection.h" #include "webrtc/base/platform_thread.h" #include "webrtc/modules/audio_device/include/fake_audio_device.h" -#include "webrtc/test/drifting_clock.h" #include "webrtc/typedefs.h" namespace webrtc { -class Clock; class EventTimerWrapper; -class FileWrapper; -class ModuleFileUtility; namespace test { +// FakeAudioDevice implements an AudioDevice module that can act both as a +// capturer and a renderer. It will use 10ms audio frames. class FakeAudioDevice : public FakeAudioDeviceModule { public: - FakeAudioDevice(Clock* clock, const std::string& filename, float speed); - - virtual ~FakeAudioDevice(); + // Creates a new FakeAudioDevice. When capturing or playing, 10 ms audio + // frames will be processed every 100ms / |speed|. + // |sampling_frequency_in_hz| can be 8, 16, 32, 44.1 or 48kHz. + // When recording is started, it will generates a signal where every second + // frame is zero and every second frame is evenly distributed random noise + // with max amplitude |max_amplitude|. + FakeAudioDevice(float speed, + int sampling_frequency_in_hz, + int16_t max_amplitude); + ~FakeAudioDevice() override; + private: int32_t Init() override; int32_t RegisterAudioCallback(AudioTransport* callback) override; + int32_t StartPlayout() override; + int32_t StopPlayout() override; + int32_t StartRecording() override; + int32_t StopRecording() override; + bool Playing() const override; - int32_t PlayoutDelay(uint16_t* delay_ms) const override; bool Recording() const override; - void Start(); - void Stop(); - - private: static bool Run(void* obj); - void CaptureAudio(); + void ProcessAudio(); - static const uint32_t kFrequencyHz = 16000; - static const size_t kBufferSizeBytes = 2 * kFrequencyHz; - - AudioTransport* audio_callback_; - bool capturing_; - int8_t captured_audio_[kBufferSizeBytes]; - int8_t playout_buffer_[kBufferSizeBytes]; + const int sampling_frequency_in_hz_; + const size_t num_samples_per_frame_; const float speed_; - int64_t last_playout_ms_; - DriftingClock clock_; - std::unique_ptr tick_; rtc::CriticalSection lock_; + AudioTransport* audio_callback_ GUARDED_BY(lock_); + bool rendering_ GUARDED_BY(lock_); + bool capturing_ GUARDED_BY(lock_); + + class PulsedNoiseCapturer; + const std::unique_ptr capturer_ GUARDED_BY(lock_); + + std::vector playout_buffer_ GUARDED_BY(lock_); + + std::unique_ptr tick_; rtc::PlatformThread thread_; - std::unique_ptr file_utility_; - std::unique_ptr input_stream_; }; } // namespace test } // namespace webrtc