diff --git a/modules/audio_device/BUILD.gn b/modules/audio_device/BUILD.gn index 216ced8d8e..4a6a0ab41c 100644 --- a/modules/audio_device/BUILD.gn +++ b/modules/audio_device/BUILD.gn @@ -192,7 +192,6 @@ rtc_library("audio_device_impl") { "../../api:scoped_refptr", "../../api:sequence_checker", "../../api/task_queue", - "../../api/units:time_delta", "../../common_audio", "../../common_audio:common_audio_c", "../../rtc_base:buffer", @@ -218,7 +217,6 @@ rtc_library("audio_device_impl") { absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/strings:strings", - "//third_party/abseil-cpp/absl/types:optional", ] if (rtc_include_internal_audio_device && is_ios) { deps += [ "../../sdk:audio_device" ] @@ -230,6 +228,8 @@ rtc_library("audio_device_impl") { "dummy/file_audio_device.cc", "dummy/file_audio_device.h", "include/fake_audio_device.h", + "include/test_audio_device.cc", + "include/test_audio_device.h", ] if (build_with_mozilla) { @@ -253,10 +253,6 @@ rtc_library("audio_device_impl") { "audio_device_impl.cc", "audio_device_impl.h", "include/audio_device_data_observer.h", - "include/test_audio_device.cc", - "include/test_audio_device.h", - "test_audio_device_impl.cc", - "test_audio_device_impl.h", ] if (is_android) { sources += [ @@ -418,12 +414,10 @@ if (rtc_include_tests && !build_with_chromium) { sources = [ "fine_audio_buffer_unittest.cc", "include/test_audio_device_unittest.cc", - "test_audio_device_impl_test.cc", ] deps = [ ":audio_device", ":audio_device_buffer", - ":audio_device_generic", ":audio_device_impl", ":mock_audio_device", "../../api:array_view", @@ -431,8 +425,6 @@ if (rtc_include_tests && !build_with_chromium) { "../../api:sequence_checker", "../../api/task_queue", "../../api/task_queue:default_task_queue_factory", - "../../api/units:time_delta", - "../../api/units:timestamp", "../../common_audio", "../../rtc_base:buffer", "../../rtc_base:checks", @@ -447,7 +439,6 @@ if (rtc_include_tests && !build_with_chromium) { "../../system_wrappers", "../../test:fileutils", "../../test:test_support", - "../../test/time_controller", ] absl_deps = [ "//third_party/abseil-cpp/absl/strings", diff --git a/modules/audio_device/audio_device_buffer.cc b/modules/audio_device/audio_device_buffer.cc index f1bd8e823b..91964d1edd 100644 --- a/modules/audio_device/audio_device_buffer.cc +++ b/modules/audio_device/audio_device_buffer.cc @@ -41,8 +41,7 @@ static const size_t kMinValidCallTimeTimeInMilliseconds = static const double k2Pi = 6.28318530717959; #endif -AudioDeviceBuffer::AudioDeviceBuffer(TaskQueueFactory* task_queue_factory, - bool create_detached) +AudioDeviceBuffer::AudioDeviceBuffer(TaskQueueFactory* task_queue_factory) : task_queue_(task_queue_factory->CreateTaskQueue( kTimerQueueName, TaskQueueFactory::Priority::NORMAL)), @@ -68,9 +67,6 @@ AudioDeviceBuffer::AudioDeviceBuffer(TaskQueueFactory* task_queue_factory, phase_ = 0.0; RTC_LOG(LS_WARNING) << "AUDIO_DEVICE_PLAYS_SINUS_TONE is defined!"; #endif - if (create_detached) { - main_thread_checker_.Detach(); - } } AudioDeviceBuffer::~AudioDeviceBuffer() { diff --git a/modules/audio_device/audio_device_buffer.h b/modules/audio_device/audio_device_buffer.h index 5e02cb218c..f7c4ecdcff 100644 --- a/modules/audio_device/audio_device_buffer.h +++ b/modules/audio_device/audio_device_buffer.h @@ -78,11 +78,7 @@ class AudioDeviceBuffer { int16_t max_play_level = 0; }; - // If `create_detached` is true, created buffer can be used on another - // thread compared to the one on which it was created. It's useful for - // testing. - explicit AudioDeviceBuffer(TaskQueueFactory* task_queue_factory, - bool create_detached = false); + explicit AudioDeviceBuffer(TaskQueueFactory* task_queue_factory); virtual ~AudioDeviceBuffer(); int32_t RegisterAudioCallback(AudioTransport* audio_callback); diff --git a/modules/audio_device/audio_device_impl.cc b/modules/audio_device/audio_device_impl.cc index 25abc180de..092b98f2bf 100644 --- a/modules/audio_device/audio_device_impl.cc +++ b/modules/audio_device/audio_device_impl.cc @@ -121,17 +121,6 @@ AudioDeviceModuleImpl::AudioDeviceModuleImpl( RTC_DLOG(LS_INFO) << __FUNCTION__; } -AudioDeviceModuleImpl::AudioDeviceModuleImpl( - AudioLayer audio_layer, - std::unique_ptr audio_device, - TaskQueueFactory* task_queue_factory, - bool create_detached) - : audio_layer_(audio_layer), - audio_device_buffer_(task_queue_factory, create_detached), - audio_device_(std::move(audio_device)) { - RTC_DLOG(LS_INFO) << __FUNCTION__; -} - int32_t AudioDeviceModuleImpl::CheckPlatform() { RTC_DLOG(LS_INFO) << __FUNCTION__; // Ensure that the current platform is supported @@ -151,9 +140,6 @@ int32_t AudioDeviceModuleImpl::CheckPlatform() { #elif defined(WEBRTC_MAC) platform = kPlatformMac; RTC_LOG(LS_INFO) << "current platform is Mac"; -#elif defined(WEBRTC_FUCHSIA) - platform = kPlatformFuchsia; - RTC_LOG(LS_INFO) << "current platform is Fuchsia"; #endif if (platform == kPlatformNotSupported) { RTC_LOG(LS_ERROR) @@ -167,10 +153,6 @@ int32_t AudioDeviceModuleImpl::CheckPlatform() { int32_t AudioDeviceModuleImpl::CreatePlatformSpecificObjects() { RTC_LOG(LS_INFO) << __FUNCTION__; - if (audio_device_ != nullptr) { - RTC_LOG(LS_INFO) << "Reusing provided audio device"; - return 0; - } // Dummy ADM implementations if build flags are set. #if defined(WEBRTC_DUMMY_AUDIO_BUILD) audio_device_.reset(new AudioDeviceDummy()); diff --git a/modules/audio_device/audio_device_impl.h b/modules/audio_device/audio_device_impl.h index c5005e93b1..45f73dcd65 100644 --- a/modules/audio_device/audio_device_impl.h +++ b/modules/audio_device/audio_device_impl.h @@ -35,12 +35,7 @@ class AudioDeviceModuleImpl : public AudioDeviceModuleForTest { kPlatformLinux = 3, kPlatformMac = 4, kPlatformAndroid = 5, - kPlatformIOS = 6, - // Fuchsia isn't fully supported, as there is no implementation for - // AudioDeviceGeneric which will be created for Fuchsia, so - // `CreatePlatformSpecificObjects()` call will fail unless usable - // implementation will be provided by the user. - kPlatformFuchsia = 7, + kPlatformIOS = 6 }; int32_t CheckPlatform(); @@ -49,12 +44,6 @@ class AudioDeviceModuleImpl : public AudioDeviceModuleForTest { AudioDeviceModuleImpl(AudioLayer audio_layer, TaskQueueFactory* task_queue_factory); - // If `create_detached` is true, created ADM can be used on another thread - // compared to the one on which it was created. It's useful for testing. - AudioDeviceModuleImpl(AudioLayer audio_layer, - std::unique_ptr audio_device, - TaskQueueFactory* task_queue_factory, - bool create_detached); ~AudioDeviceModuleImpl() override; // Retrieve the currently utilized audio layer diff --git a/modules/audio_device/include/test_audio_device.cc b/modules/audio_device/include/test_audio_device.cc index fa4f3fe9d3..76406448a0 100644 --- a/modules/audio_device/include/test_audio_device.cc +++ b/modules/audio_device/include/test_audio_device.cc @@ -22,9 +22,7 @@ #include "api/array_view.h" #include "api/make_ref_counted.h" #include "common_audio/wav_file.h" -#include "modules/audio_device/audio_device_impl.h" #include "modules/audio_device/include/audio_device_default.h" -#include "modules/audio_device/test_audio_device_impl.h" #include "rtc_base/buffer.h" #include "rtc_base/checks.h" #include "rtc_base/event.h" @@ -45,23 +43,164 @@ namespace { constexpr int kFrameLengthUs = 10000; constexpr int kFramesPerSecond = rtc::kNumMicrosecsPerSec / kFrameLengthUs; -class TestAudioDeviceModuleImpl : public AudioDeviceModuleImpl { +// TestAudioDeviceModule implements an AudioDevice module that can act both as a +// capturer and a renderer. It will use 10ms audio frames. +class TestAudioDeviceModuleImpl + : public webrtc_impl::AudioDeviceModuleDefault { public: - TestAudioDeviceModuleImpl( - TaskQueueFactory* task_queue_factory, - std::unique_ptr capturer, - std::unique_ptr renderer, - float speed = 1) - : AudioDeviceModuleImpl( - AudioLayer::kDummyAudio, - std::make_unique(task_queue_factory, - std::move(capturer), - std::move(renderer), - speed), - task_queue_factory, - /*create_detached=*/true) {} + // Creates a new TestAudioDeviceModule. When capturing or playing, 10 ms audio + // frames will be processed every 10ms / `speed`. + // `capturer` is an object that produces audio data. Can be nullptr if this + // device is never used for recording. + // `renderer` is an object that receives audio data that would have been + // played out. Can be nullptr if this device is never used for playing. + // Use one of the Create... functions to get these instances. + TestAudioDeviceModuleImpl(TaskQueueFactory* task_queue_factory, + std::unique_ptr capturer, + std::unique_ptr renderer, + float speed = 1) + : task_queue_factory_(task_queue_factory), + capturer_(std::move(capturer)), + renderer_(std::move(renderer)), + process_interval_us_(kFrameLengthUs / speed), + audio_callback_(nullptr), + rendering_(false), + capturing_(false) { + auto good_sample_rate = [](int sr) { + return sr == 8000 || sr == 16000 || sr == 32000 || sr == 44100 || + sr == 48000; + }; - ~TestAudioDeviceModuleImpl() override = default; + if (renderer_) { + const int sample_rate = renderer_->SamplingFrequency(); + playout_buffer_.resize( + SamplesPerFrame(sample_rate) * renderer_->NumChannels(), 0); + RTC_CHECK(good_sample_rate(sample_rate)); + } + if (capturer_) { + RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency())); + } + } + + ~TestAudioDeviceModuleImpl() override { + StopPlayout(); + StopRecording(); + } + + int32_t Init() override { + task_queue_ = + std::make_unique(task_queue_factory_->CreateTaskQueue( + "TestAudioDeviceModuleImpl", TaskQueueFactory::Priority::NORMAL)); + + RepeatingTaskHandle::Start(task_queue_->Get(), [this]() { + ProcessAudio(); + return TimeDelta::Micros(process_interval_us_); + }); + return 0; + } + + int32_t RegisterAudioCallback(AudioTransport* callback) override { + MutexLock lock(&lock_); + RTC_DCHECK(callback || audio_callback_); + audio_callback_ = callback; + return 0; + } + + int32_t StartPlayout() override { + MutexLock lock(&lock_); + RTC_CHECK(renderer_); + rendering_ = true; + return 0; + } + + int32_t StopPlayout() override { + MutexLock lock(&lock_); + rendering_ = false; + return 0; + } + + int32_t StartRecording() override { + MutexLock lock(&lock_); + RTC_CHECK(capturer_); + capturing_ = true; + return 0; + } + + int32_t StopRecording() override { + MutexLock lock(&lock_); + capturing_ = false; + return 0; + } + + bool Playing() const override { + MutexLock lock(&lock_); + return rendering_; + } + + bool Recording() const override { + MutexLock lock(&lock_); + return capturing_; + } + + // Blocks forever until the Recorder stops producing data. + void WaitForRecordingEnd() override { + done_capturing_.Wait(rtc::Event::kForever); + } + + private: + void ProcessAudio() { + MutexLock lock(&lock_); + if (capturing_) { + // Capture 10ms of audio. 2 bytes per sample. + const bool keep_capturing = capturer_->Capture(&recording_buffer_); + uint32_t new_mic_level = 0; + if (recording_buffer_.size() > 0) { + audio_callback_->RecordedDataIsAvailable( + recording_buffer_.data(), + recording_buffer_.size() / capturer_->NumChannels(), + 2 * capturer_->NumChannels(), capturer_->NumChannels(), + capturer_->SamplingFrequency(), /*totalDelayMS=*/0, + /*clockDrift=*/0, + /*currentMicLevel=*/0, /*keyPressed=*/false, new_mic_level, + absl::make_optional(rtc::TimeNanos())); + } + if (!keep_capturing) { + capturing_ = false; + done_capturing_.Set(); + } + } + if (rendering_) { + size_t samples_out = 0; + int64_t elapsed_time_ms = -1; + int64_t ntp_time_ms = -1; + const int sampling_frequency = renderer_->SamplingFrequency(); + audio_callback_->NeedMorePlayData( + SamplesPerFrame(sampling_frequency), 2 * renderer_->NumChannels(), + renderer_->NumChannels(), sampling_frequency, playout_buffer_.data(), + samples_out, &elapsed_time_ms, &ntp_time_ms); + const bool keep_rendering = renderer_->Render( + rtc::ArrayView(playout_buffer_.data(), samples_out)); + if (!keep_rendering) { + rendering_ = false; + done_rendering_.Set(); + } + } + } + TaskQueueFactory* const task_queue_factory_; + const std::unique_ptr capturer_ RTC_GUARDED_BY(lock_); + const std::unique_ptr renderer_ RTC_GUARDED_BY(lock_); + const int64_t process_interval_us_; + + mutable Mutex lock_; + AudioTransport* audio_callback_ RTC_GUARDED_BY(lock_); + bool rendering_ RTC_GUARDED_BY(lock_); + bool capturing_ RTC_GUARDED_BY(lock_); + rtc::Event done_rendering_; + rtc::Event done_capturing_; + + std::vector playout_buffer_ RTC_GUARDED_BY(lock_); + rtc::BufferT recording_buffer_ RTC_GUARDED_BY(lock_); + std::unique_ptr task_queue_; }; // A fake capturer that generates pulses with random samples between @@ -305,26 +444,8 @@ rtc::scoped_refptr TestAudioDeviceModule::Create( std::unique_ptr capturer, std::unique_ptr renderer, float speed) { - auto audio_device = rtc::make_ref_counted( + return rtc::make_ref_counted( task_queue_factory, std::move(capturer), std::move(renderer), speed); - - // Ensure that the current platform is supported. - if (audio_device->CheckPlatform() == -1) { - return nullptr; - } - - // Create the platform-dependent implementation. - if (audio_device->CreatePlatformSpecificObjects() == -1) { - return nullptr; - } - - // Ensure that the generic audio buffer can communicate with the platform - // specific parts. - if (audio_device->AttachAudioBuffer() == -1) { - return nullptr; - } - - return audio_device; } std::unique_ptr diff --git a/modules/audio_device/include/test_audio_device.h b/modules/audio_device/include/test_audio_device.h index 751eae6b7b..87ba9cfbae 100644 --- a/modules/audio_device/include/test_audio_device.h +++ b/modules/audio_device/include/test_audio_device.h @@ -29,10 +29,9 @@ namespace webrtc { // This is test API and is in development, so it can be changed/removed without // notice. -// This class exists for historical reasons. For now it only contains static -// methods to create test AudioDeviceModule. Implementation details of that -// module are considered private. This class isn't intended to be instantiated. -class TestAudioDeviceModule { +// TestAudioDeviceModule implements an AudioDevice module that can act both as a +// capturer and a renderer. It will use 10ms audio frames. +class TestAudioDeviceModule : public AudioDeviceModule { public: // Returns the number of samples that Capturers and Renderers with this // sampling frequency will work with every time Capture or Render is called. @@ -74,6 +73,8 @@ class TestAudioDeviceModule { virtual void SetMaxAmplitude(int16_t amplitude) = 0; }; + ~TestAudioDeviceModule() override {} + // Creates a new TestAudioDeviceModule. When capturing or playing, 10 ms audio // frames will be processed every 10ms / `speed`. // `capturer` is an object that produces audio data. Can be nullptr if this @@ -131,8 +132,19 @@ class TestAudioDeviceModule { int sampling_frequency_in_hz, int num_channels = 1); - private: - TestAudioDeviceModule() = default; + int32_t Init() override = 0; + int32_t RegisterAudioCallback(AudioTransport* callback) override = 0; + + int32_t StartPlayout() override = 0; + int32_t StopPlayout() override = 0; + int32_t StartRecording() override = 0; + int32_t StopRecording() override = 0; + + bool Playing() const override = 0; + bool Recording() const override = 0; + + // Blocks forever until the Recorder stops producing data. + virtual void WaitForRecordingEnd() = 0; }; } // namespace webrtc diff --git a/modules/audio_device/include/test_audio_device_unittest.cc b/modules/audio_device/include/test_audio_device_unittest.cc index 54ede808b1..2975b11325 100644 --- a/modules/audio_device/include/test_audio_device_unittest.cc +++ b/modules/audio_device/include/test_audio_device_unittest.cc @@ -12,26 +12,17 @@ #include #include -#include -#include -#include "absl/types/optional.h" #include "api/array_view.h" -#include "api/task_queue/task_queue_factory.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" #include "common_audio/wav_file.h" #include "common_audio/wav_header.h" -#include "modules/audio_device/include/audio_device_defines.h" -#include "rtc_base/checks.h" #include "rtc_base/logging.h" -#include "rtc_base/synchronization/mutex.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/testsupport/file_utils.h" -#include "test/time_controller/simulated_time_controller.h" namespace webrtc { + namespace { void RunTest(const std::vector& input_samples, @@ -73,6 +64,7 @@ void RunTest(const std::vector& input_samples, remove(output_filename.c_str()); } +} // namespace TEST(BoundedWavFileWriterTest, NoSilence) { static const std::vector kInputSamples = { @@ -197,185 +189,4 @@ TEST(PulsedNoiseCapturerTest, SetMaxAmplitude) { EXPECT_GT(max_sample, kAmplitude); } -using ::testing::ElementsAre; - -constexpr Timestamp kStartTime = Timestamp::Millis(10000); - -class TestAudioTransport : public AudioTransport { - public: - enum class Mode { kPlaying, kRecording }; - - explicit TestAudioTransport(Mode mode) : mode_(mode) {} - ~TestAudioTransport() override = default; - - int32_t RecordedDataIsAvailable( - const void* audioSamples, - size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - uint32_t total_delay_ms, - int32_t clock_drift, - uint32_t current_mic_level, - bool key_pressed, - uint32_t& new_mic_level, - absl::optional estimated_capture_time_ns) override { - new_mic_level = 1; - - if (mode_ != Mode::kRecording) { - EXPECT_TRUE(false) - << "NeedMorePlayData mustn't be called when mode isn't kRecording"; - return -1; - } - - MutexLock lock(&mutex_); - samples_per_channel_.push_back(samples_per_channel); - number_of_channels_.push_back(number_of_channels); - bytes_per_sample_.push_back(bytes_per_sample); - samples_per_second_.push_back(samples_per_second); - return 0; - } - - int32_t NeedMorePlayData(size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - void* audio_samples, - size_t& samples_out, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) override { - const size_t num_bytes = samples_per_channel * number_of_channels; - std::memset(audio_samples, 1, num_bytes); - samples_out = samples_per_channel * number_of_channels; - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - if (mode_ != Mode::kPlaying) { - EXPECT_TRUE(false) - << "NeedMorePlayData mustn't be called when mode isn't kPlaying"; - return -1; - } - - MutexLock lock(&mutex_); - samples_per_channel_.push_back(samples_per_channel); - number_of_channels_.push_back(number_of_channels); - bytes_per_sample_.push_back(bytes_per_sample); - samples_per_second_.push_back(samples_per_second); - return 0; - } - - int32_t RecordedDataIsAvailable(const void* audio_samples, - size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - uint32_t total_delay_ms, - int32_t clockDrift, - uint32_t current_mic_level, - bool key_pressed, - uint32_t& new_mic_level) override { - RTC_CHECK(false) << "This methods should be never executed"; - } - - void PullRenderData(int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames, - void* audio_data, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) override { - RTC_CHECK(false) << "This methods should be never executed"; - } - - std::vector samples_per_channel() const { - MutexLock lock(&mutex_); - return samples_per_channel_; - } - std::vector number_of_channels() const { - MutexLock lock(&mutex_); - return number_of_channels_; - } - std::vector bytes_per_sample() const { - MutexLock lock(&mutex_); - return bytes_per_sample_; - } - std::vector samples_per_second() const { - MutexLock lock(&mutex_); - return samples_per_second_; - } - - private: - const Mode mode_; - - mutable Mutex mutex_; - std::vector samples_per_channel_ RTC_GUARDED_BY(mutex_); - std::vector number_of_channels_ RTC_GUARDED_BY(mutex_); - std::vector bytes_per_sample_ RTC_GUARDED_BY(mutex_); - std::vector samples_per_second_ RTC_GUARDED_BY(mutex_); -}; - -TEST(TestAudioDeviceModuleTest, CreatedADMCanRecord) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioTransport audio_transport(TestAudioTransport::Mode::kRecording); - std::unique_ptr capturer = - TestAudioDeviceModule::CreatePulsedNoiseCapturer( - /*max_amplitude=*/1000, - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - rtc::scoped_refptr adm = TestAudioDeviceModule::Create( - time_controller.GetTaskQueueFactory(), std::move(capturer), - /*renderer=*/nullptr); - - ASSERT_EQ(adm->RegisterAudioCallback(&audio_transport), 0); - ASSERT_EQ(adm->Init(), 0); - - EXPECT_FALSE(adm->RecordingIsInitialized()); - ASSERT_EQ(adm->InitRecording(), 0); - EXPECT_TRUE(adm->RecordingIsInitialized()); - ASSERT_EQ(adm->StartRecording(), 0); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_TRUE(adm->Recording()); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_EQ(adm->StopRecording(), 0); - - EXPECT_THAT(audio_transport.samples_per_channel(), - ElementsAre(480, 480, 480)); - EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2)); - EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4)); - EXPECT_THAT(audio_transport.samples_per_second(), - ElementsAre(48000, 48000, 48000)); -} - -TEST(TestAudioDeviceModuleTest, CreatedADMCanPlay) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioTransport audio_transport(TestAudioTransport::Mode::kPlaying); - std::unique_ptr renderer = - TestAudioDeviceModule::CreateDiscardRenderer( - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - rtc::scoped_refptr adm = - TestAudioDeviceModule::Create(time_controller.GetTaskQueueFactory(), - /*capturer=*/nullptr, std::move(renderer)); - - ASSERT_EQ(adm->RegisterAudioCallback(&audio_transport), 0); - ASSERT_EQ(adm->Init(), 0); - - EXPECT_FALSE(adm->PlayoutIsInitialized()); - ASSERT_EQ(adm->InitPlayout(), 0); - EXPECT_TRUE(adm->PlayoutIsInitialized()); - ASSERT_EQ(adm->StartPlayout(), 0); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_TRUE(adm->Playing()); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_EQ(adm->StopPlayout(), 0); - - EXPECT_THAT(audio_transport.samples_per_channel(), - ElementsAre(480, 480, 480)); - EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2)); - EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4)); - EXPECT_THAT(audio_transport.samples_per_second(), - ElementsAre(48000, 48000, 48000)); -} - -} // namespace } // namespace webrtc diff --git a/modules/audio_device/test_audio_device_impl.cc b/modules/audio_device/test_audio_device_impl.cc deleted file mode 100644 index c5de40c79a..0000000000 --- a/modules/audio_device/test_audio_device_impl.cc +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2023 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 "modules/audio_device/test_audio_device_impl.h" - -#include -#include - -#include "absl/types/optional.h" -#include "api/array_view.h" -#include "api/task_queue/task_queue_factory.h" -#include "api/units/time_delta.h" -#include "modules/audio_device/include/test_audio_device.h" -#include "rtc_base/checks.h" -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/task_queue.h" -#include "rtc_base/task_utils/repeating_task.h" - -namespace webrtc { -namespace { - -constexpr int kFrameLengthUs = 10000; - -} - -TestAudioDevice::TestAudioDevice( - TaskQueueFactory* task_queue_factory, - std::unique_ptr capturer, - std::unique_ptr renderer, - float speed) - : task_queue_factory_(task_queue_factory), - capturer_(std::move(capturer)), - renderer_(std::move(renderer)), - process_interval_us_(kFrameLengthUs / speed), - audio_buffer_(nullptr), - rendering_(false), - capturing_(false) { - auto good_sample_rate = [](int sr) { - return sr == 8000 || sr == 16000 || sr == 32000 || sr == 44100 || - sr == 48000; - }; - - if (renderer_) { - const int sample_rate = renderer_->SamplingFrequency(); - playout_buffer_.resize(TestAudioDeviceModule::SamplesPerFrame(sample_rate) * - renderer_->NumChannels(), - 0); - RTC_CHECK(good_sample_rate(sample_rate)); - } - if (capturer_) { - RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency())); - } -} - -AudioDeviceGeneric::InitStatus TestAudioDevice::Init() { - task_queue_ = - std::make_unique(task_queue_factory_->CreateTaskQueue( - "TestAudioDeviceModuleImpl", TaskQueueFactory::Priority::NORMAL)); - - RepeatingTaskHandle::Start(task_queue_->Get(), [this]() { - ProcessAudio(); - return TimeDelta::Micros(process_interval_us_); - }); - return InitStatus::OK; -} - -int32_t TestAudioDevice::PlayoutIsAvailable(bool& available) { - MutexLock lock(&lock_); - available = renderer_ != nullptr; - return 0; -} - -int32_t TestAudioDevice::InitPlayout() { - MutexLock lock(&lock_); - - if (rendering_) { - return -1; - } - - if (audio_buffer_ != nullptr && renderer_ != nullptr) { - // Update webrtc audio buffer with the selected parameters - audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency()); - audio_buffer_->SetPlayoutChannels(renderer_->NumChannels()); - } - rendering_initialized_ = true; - return 0; -} - -bool TestAudioDevice::PlayoutIsInitialized() const { - MutexLock lock(&lock_); - return rendering_initialized_; -} - -int32_t TestAudioDevice::StartPlayout() { - MutexLock lock(&lock_); - RTC_CHECK(renderer_); - rendering_ = true; - return 0; -} - -int32_t TestAudioDevice::StopPlayout() { - MutexLock lock(&lock_); - rendering_ = false; - return 0; -} - -int32_t TestAudioDevice::RecordingIsAvailable(bool& available) { - MutexLock lock(&lock_); - available = capturer_ != nullptr; - return 0; -} - -int32_t TestAudioDevice::InitRecording() { - MutexLock lock(&lock_); - - if (capturing_) { - return -1; - } - - if (audio_buffer_ != nullptr && capturer_ != nullptr) { - // Update webrtc audio buffer with the selected parameters - audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency()); - audio_buffer_->SetRecordingChannels(capturer_->NumChannels()); - } - capturing_initialized_ = true; - return 0; -} - -bool TestAudioDevice::RecordingIsInitialized() const { - MutexLock lock(&lock_); - return capturing_initialized_; -} - -int32_t TestAudioDevice::StartRecording() { - MutexLock lock(&lock_); - RTC_CHECK(capturer_); - capturing_ = true; - return 0; -} - -int32_t TestAudioDevice::StopRecording() { - MutexLock lock(&lock_); - capturing_ = false; - return 0; -} - -bool TestAudioDevice::Playing() const { - MutexLock lock(&lock_); - return rendering_; -} - -bool TestAudioDevice::Recording() const { - MutexLock lock(&lock_); - return capturing_; -} - -void TestAudioDevice::ProcessAudio() { - MutexLock lock(&lock_); - if (audio_buffer_ == nullptr) { - return; - } - if (capturing_) { - // Capture 10ms of audio. 2 bytes per sample. - const bool keep_capturing = capturer_->Capture(&recording_buffer_); - if (recording_buffer_.size() > 0) { - audio_buffer_->SetRecordedBuffer( - recording_buffer_.data(), - recording_buffer_.size() / capturer_->NumChannels(), - absl::make_optional(rtc::TimeNanos())); - audio_buffer_->DeliverRecordedData(); - } - if (!keep_capturing) { - capturing_ = false; - } - } - if (rendering_) { - const int sampling_frequency = renderer_->SamplingFrequency(); - int32_t samples_per_channel = audio_buffer_->RequestPlayoutData( - TestAudioDeviceModule::SamplesPerFrame(sampling_frequency)); - audio_buffer_->GetPlayoutData(playout_buffer_.data()); - size_t samples_out = samples_per_channel * renderer_->NumChannels(); - RTC_CHECK_LE(samples_out, playout_buffer_.size()); - const bool keep_rendering = renderer_->Render( - rtc::ArrayView(playout_buffer_.data(), samples_out)); - if (!keep_rendering) { - rendering_ = false; - } - } -} - -void TestAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audio_buffer) { - MutexLock lock(&lock_); - RTC_DCHECK(audio_buffer || audio_buffer_); - audio_buffer_ = audio_buffer; - - if (renderer_ != nullptr) { - audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency()); - audio_buffer_->SetPlayoutChannels(renderer_->NumChannels()); - } - if (capturer_ != nullptr) { - audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency()); - audio_buffer_->SetRecordingChannels(capturer_->NumChannels()); - } -} - -} // namespace webrtc diff --git a/modules/audio_device/test_audio_device_impl.h b/modules/audio_device/test_audio_device_impl.h deleted file mode 100644 index 36192b7f7f..0000000000 --- a/modules/audio_device/test_audio_device_impl.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2023 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 MODULES_AUDIO_DEVICE_TEST_AUDIO_DEVICE_IMPL_H_ -#define MODULES_AUDIO_DEVICE_TEST_AUDIO_DEVICE_IMPL_H_ - -#include -#include - -#include "api/task_queue/task_queue_factory.h" -#include "modules/audio_device/audio_device_buffer.h" -#include "modules/audio_device/audio_device_generic.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_device/include/audio_device_defines.h" -#include "modules/audio_device/include/test_audio_device.h" -#include "rtc_base/buffer.h" -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/task_queue.h" - -namespace webrtc { - -class TestAudioDevice : public AudioDeviceGeneric { - public: - // Creates a new TestAudioDevice. When capturing or playing, 10 ms audio - // frames will be processed every 10ms / `speed`. - // `capturer` is an object that produces audio data. Can be nullptr if this - // device is never used for recording. - // `renderer` is an object that receives audio data that would have been - // played out. Can be nullptr if this device is never used for playing. - TestAudioDevice(TaskQueueFactory* task_queue_factory, - std::unique_ptr capturer, - std::unique_ptr renderer, - float speed = 1); - TestAudioDevice(const TestAudioDevice&) = delete; - TestAudioDevice& operator=(const TestAudioDevice&) = delete; - ~TestAudioDevice() override = default; - - // Retrieve the currently utilized audio layer - int32_t ActiveAudioLayer( - AudioDeviceModule::AudioLayer& audioLayer) const override { - return 0; - } - - // Main initializaton and termination - InitStatus Init() override; - int32_t Terminate() override { return 0; } - bool Initialized() const override { return true; } - - // Device enumeration - int16_t PlayoutDevices() override { return 0; } - int16_t RecordingDevices() override { return 0; } - int32_t PlayoutDeviceName(uint16_t index, - char name[kAdmMaxDeviceNameSize], - char guid[kAdmMaxGuidSize]) override { - return 0; - } - int32_t RecordingDeviceName(uint16_t index, - char name[kAdmMaxDeviceNameSize], - char guid[kAdmMaxGuidSize]) override { - return 0; - } - - // Device selection - int32_t SetPlayoutDevice(uint16_t index) override { return 0; } - int32_t SetPlayoutDevice( - AudioDeviceModule::WindowsDeviceType device) override { - return 0; - } - int32_t SetRecordingDevice(uint16_t index) override { return 0; } - int32_t SetRecordingDevice( - AudioDeviceModule::WindowsDeviceType device) override { - return 0; - } - - // Audio transport initialization - int32_t PlayoutIsAvailable(bool& available) override; - int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override; - int32_t RecordingIsAvailable(bool& available) override; - int32_t InitRecording() override; - bool RecordingIsInitialized() const override; - - // Audio transport control - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; - - // Audio mixer initialization - int32_t InitSpeaker() override { return 0; } - bool SpeakerIsInitialized() const override { return true; } - int32_t InitMicrophone() override { return 0; } - bool MicrophoneIsInitialized() const override { return true; } - - // Speaker volume controls - int32_t SpeakerVolumeIsAvailable(bool& available) override { return 0; } - int32_t SetSpeakerVolume(uint32_t volume) override { return 0; } - int32_t SpeakerVolume(uint32_t& volume) const override { return 0; } - int32_t MaxSpeakerVolume(uint32_t& maxVolume) const override { return 0; } - int32_t MinSpeakerVolume(uint32_t& minVolume) const override { return 0; } - - // Microphone volume controls - int32_t MicrophoneVolumeIsAvailable(bool& available) override { return 0; } - int32_t SetMicrophoneVolume(uint32_t volume) override { return 0; } - int32_t MicrophoneVolume(uint32_t& volume) const override { return 0; } - int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const override { return 0; } - int32_t MinMicrophoneVolume(uint32_t& minVolume) const override { return 0; } - - // Speaker mute control - int32_t SpeakerMuteIsAvailable(bool& available) override { return 0; } - int32_t SetSpeakerMute(bool enable) override { return 0; } - int32_t SpeakerMute(bool& enabled) const override { return 0; } - - // Microphone mute control - int32_t MicrophoneMuteIsAvailable(bool& available) override { return 0; } - int32_t SetMicrophoneMute(bool enable) override { return 0; } - int32_t MicrophoneMute(bool& enabled) const override { return 0; } - - // Stereo support - int32_t StereoPlayoutIsAvailable(bool& available) override { - available = false; - return 0; - } - int32_t SetStereoPlayout(bool enable) override { return 0; } - int32_t StereoPlayout(bool& enabled) const override { return 0; } - int32_t StereoRecordingIsAvailable(bool& available) override { - available = false; - return 0; - } - int32_t SetStereoRecording(bool enable) override { return 0; } - int32_t StereoRecording(bool& enabled) const override { return 0; } - - // Delay information and control - int32_t PlayoutDelay(uint16_t& delayMS) const override { - delayMS = 0; - return 0; - } - - // Android only - bool BuiltInAECIsAvailable() const override { return false; } - bool BuiltInAGCIsAvailable() const override { return false; } - bool BuiltInNSIsAvailable() const override { return false; } - - // Windows Core Audio and Android only. - int32_t EnableBuiltInAEC(bool enable) override { return -1; } - int32_t EnableBuiltInAGC(bool enable) override { return -1; } - int32_t EnableBuiltInNS(bool enable) override { return -1; } - - // Play underrun count. - int32_t GetPlayoutUnderrunCount() const override { return -1; } - -// iOS only. -// TODO(henrika): add Android support. -#if defined(WEBRTC_IOS) - int GetPlayoutAudioParameters(AudioParameters* params) const override { - return -1; - } - int GetRecordAudioParameters(AudioParameters* params) const override { - return -1; - } -#endif // WEBRTC_IOS - - void AttachAudioBuffer(AudioDeviceBuffer* audio_buffer) override; - - private: - void ProcessAudio(); - - TaskQueueFactory* const task_queue_factory_; - const std::unique_ptr capturer_ - RTC_GUARDED_BY(lock_); - const std::unique_ptr renderer_ - RTC_GUARDED_BY(lock_); - const int64_t process_interval_us_; - - mutable Mutex lock_; - AudioDeviceBuffer* audio_buffer_ RTC_GUARDED_BY(lock_) = nullptr; - bool rendering_ RTC_GUARDED_BY(lock_) = false; - bool capturing_ RTC_GUARDED_BY(lock_) = false; - bool rendering_initialized_ RTC_GUARDED_BY(lock_) = false; - bool capturing_initialized_ RTC_GUARDED_BY(lock_) = false; - - std::vector playout_buffer_ RTC_GUARDED_BY(lock_); - rtc::BufferT recording_buffer_ RTC_GUARDED_BY(lock_); - std::unique_ptr task_queue_; -}; - -} // namespace webrtc - -#endif // MODULES_AUDIO_DEVICE_TEST_AUDIO_DEVICE_IMPL_H_ diff --git a/modules/audio_device/test_audio_device_impl_test.cc b/modules/audio_device/test_audio_device_impl_test.cc deleted file mode 100644 index 46f1419738..0000000000 --- a/modules/audio_device/test_audio_device_impl_test.cc +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2023 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 "modules/audio_device/test_audio_device_impl.h" - -#include -#include - -#include "absl/types/optional.h" -#include "api/task_queue/task_queue_factory.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "modules/audio_device/audio_device_buffer.h" -#include "modules/audio_device/audio_device_generic.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_device/include/audio_device_defines.h" -#include "modules/audio_device/include/test_audio_device.h" -#include "rtc_base/checks.h" -#include "rtc_base/synchronization/mutex.h" -#include "test/gmock.h" -#include "test/gtest.h" -#include "test/time_controller/simulated_time_controller.h" - -namespace webrtc { -namespace { - -using ::testing::ElementsAre; - -constexpr Timestamp kStartTime = Timestamp::Millis(10000); - -class TestAudioTransport : public AudioTransport { - public: - enum class Mode { kPlaying, kRecording }; - - explicit TestAudioTransport(Mode mode) : mode_(mode) {} - ~TestAudioTransport() override = default; - - int32_t RecordedDataIsAvailable( - const void* audioSamples, - size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - uint32_t total_delay_ms, - int32_t clock_drift, - uint32_t current_mic_level, - bool key_pressed, - uint32_t& new_mic_level, - absl::optional estimated_capture_time_ns) override { - new_mic_level = 1; - - if (mode_ != Mode::kRecording) { - EXPECT_TRUE(false) - << "NeedMorePlayData mustn't be called when mode isn't kRecording"; - return -1; - } - - MutexLock lock(&mutex_); - samples_per_channel_.push_back(samples_per_channel); - number_of_channels_.push_back(number_of_channels); - bytes_per_sample_.push_back(bytes_per_sample); - samples_per_second_.push_back(samples_per_second); - return 0; - } - - int32_t NeedMorePlayData(size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - void* audio_samples, - size_t& samples_out, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) override { - const size_t num_bytes = samples_per_channel * number_of_channels; - std::memset(audio_samples, 1, num_bytes); - samples_out = samples_per_channel * number_of_channels; - *elapsed_time_ms = 0; - *ntp_time_ms = 0; - - if (mode_ != Mode::kPlaying) { - EXPECT_TRUE(false) - << "NeedMorePlayData mustn't be called when mode isn't kPlaying"; - return -1; - } - - MutexLock lock(&mutex_); - samples_per_channel_.push_back(samples_per_channel); - number_of_channels_.push_back(number_of_channels); - bytes_per_sample_.push_back(bytes_per_sample); - samples_per_second_.push_back(samples_per_second); - return 0; - } - - int32_t RecordedDataIsAvailable(const void* audio_samples, - size_t samples_per_channel, - size_t bytes_per_sample, - size_t number_of_channels, - uint32_t samples_per_second, - uint32_t total_delay_ms, - int32_t clockDrift, - uint32_t current_mic_level, - bool key_pressed, - uint32_t& new_mic_level) override { - RTC_CHECK(false) << "This methods should be never executed"; - } - - void PullRenderData(int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames, - void* audio_data, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) override { - RTC_CHECK(false) << "This methods should be never executed"; - } - - std::vector samples_per_channel() const { - MutexLock lock(&mutex_); - return samples_per_channel_; - } - std::vector number_of_channels() const { - MutexLock lock(&mutex_); - return number_of_channels_; - } - std::vector bytes_per_sample() const { - MutexLock lock(&mutex_); - return bytes_per_sample_; - } - std::vector samples_per_second() const { - MutexLock lock(&mutex_); - return samples_per_second_; - } - - private: - const Mode mode_; - - mutable Mutex mutex_; - std::vector samples_per_channel_ RTC_GUARDED_BY(mutex_); - std::vector number_of_channels_ RTC_GUARDED_BY(mutex_); - std::vector bytes_per_sample_ RTC_GUARDED_BY(mutex_); - std::vector samples_per_second_ RTC_GUARDED_BY(mutex_); -}; - -TEST(TestAudioDeviceTest, EnablingRecordingProducesAudio) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioTransport audio_transport(TestAudioTransport::Mode::kRecording); - AudioDeviceBuffer audio_buffer(time_controller.GetTaskQueueFactory()); - ASSERT_EQ(audio_buffer.RegisterAudioCallback(&audio_transport), 0); - std::unique_ptr capturer = - TestAudioDeviceModule::CreatePulsedNoiseCapturer( - /*max_amplitude=*/1000, - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - std::move(capturer), - /*renderer=*/nullptr); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - audio_device.AttachAudioBuffer(&audio_buffer); - - EXPECT_FALSE(audio_device.RecordingIsInitialized()); - ASSERT_EQ(audio_device.InitRecording(), 0); - EXPECT_TRUE(audio_device.RecordingIsInitialized()); - audio_buffer.StartRecording(); - ASSERT_EQ(audio_device.StartRecording(), 0); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_TRUE(audio_device.Recording()); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_EQ(audio_device.StopRecording(), 0); - audio_buffer.StopRecording(); - - EXPECT_THAT(audio_transport.samples_per_channel(), - ElementsAre(480, 480, 480)); - EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2)); - EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4)); - EXPECT_THAT(audio_transport.samples_per_second(), - ElementsAre(48000, 48000, 48000)); -} - -TEST(TestAudioDeviceTest, RecordingIsAvailableWhenCapturerIsSet) { - GlobalSimulatedTimeController time_controller(kStartTime); - std::unique_ptr capturer = - TestAudioDeviceModule::CreatePulsedNoiseCapturer( - /*max_amplitude=*/1000, - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - std::move(capturer), - /*renderer=*/nullptr); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - - bool available; - EXPECT_EQ(audio_device.RecordingIsAvailable(available), 0); - EXPECT_TRUE(available); -} - -TEST(TestAudioDeviceTest, RecordingIsNotAvailableWhenCapturerIsNotSet) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - /*capturer=*/nullptr, - /*renderer=*/nullptr); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - - bool available; - EXPECT_EQ(audio_device.RecordingIsAvailable(available), 0); - EXPECT_FALSE(available); -} - -TEST(TestAudioDeviceTest, EnablingPlayoutProducesAudio) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioTransport audio_transport(TestAudioTransport::Mode::kPlaying); - AudioDeviceBuffer audio_buffer(time_controller.GetTaskQueueFactory()); - ASSERT_EQ(audio_buffer.RegisterAudioCallback(&audio_transport), 0); - std::unique_ptr renderer = - TestAudioDeviceModule::CreateDiscardRenderer( - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - /*capturer=*/nullptr, std::move(renderer)); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - audio_device.AttachAudioBuffer(&audio_buffer); - - EXPECT_FALSE(audio_device.PlayoutIsInitialized()); - ASSERT_EQ(audio_device.InitPlayout(), 0); - EXPECT_TRUE(audio_device.PlayoutIsInitialized()); - audio_buffer.StartPlayout(); - ASSERT_EQ(audio_device.StartPlayout(), 0); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_TRUE(audio_device.Playing()); - time_controller.AdvanceTime(TimeDelta::Millis(10)); - ASSERT_EQ(audio_device.StopPlayout(), 0); - audio_buffer.StopPlayout(); - - EXPECT_THAT(audio_transport.samples_per_channel(), - ElementsAre(480, 480, 480)); - EXPECT_THAT(audio_transport.number_of_channels(), ElementsAre(2, 2, 2)); - EXPECT_THAT(audio_transport.bytes_per_sample(), ElementsAre(4, 4, 4)); - EXPECT_THAT(audio_transport.samples_per_second(), - ElementsAre(48000, 48000, 48000)); -} - -TEST(TestAudioDeviceTest, PlayoutIsAvailableWhenRendererIsSet) { - GlobalSimulatedTimeController time_controller(kStartTime); - std::unique_ptr renderer = - TestAudioDeviceModule::CreateDiscardRenderer( - /*sampling_frequency_in_hz=*/48000, /*num_channels=*/2); - - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - /*capturer=*/nullptr, std::move(renderer)); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - - bool available; - EXPECT_EQ(audio_device.PlayoutIsAvailable(available), 0); - EXPECT_TRUE(available); -} - -TEST(TestAudioDeviceTest, PlayoutIsNotAvailableWhenRendererIsNotSet) { - GlobalSimulatedTimeController time_controller(kStartTime); - TestAudioDevice audio_device(time_controller.GetTaskQueueFactory(), - /*capturer=*/nullptr, - /*renderer=*/nullptr); - ASSERT_EQ(audio_device.Init(), AudioDeviceGeneric::InitStatus::OK); - - bool available; - EXPECT_EQ(audio_device.PlayoutIsAvailable(available), 0); - EXPECT_FALSE(available); -} - -} // namespace -} // namespace webrtc