123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/audio/audio_manager_base.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/command_line.h"
- #include "base/memory/raw_ptr.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/observer_list.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/stringprintf.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "build/build_config.h"
- #include "build/buildflag.h"
- #include "media/audio/audio_device_description.h"
- #include "media/audio/audio_output_dispatcher_impl.h"
- #include "media/audio/audio_output_proxy.h"
- #include "media/audio/audio_output_resampler.h"
- #include "media/audio/fake_audio_input_stream.h"
- #include "media/audio/fake_audio_output_stream.h"
- #include "media/base/media_switches.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "base/logging.h"
- #include "media/audio/audio_input_stream_data_interceptor.h"
- namespace media {
- namespace {
- const int kStreamCloseDelaySeconds = 5;
- // Default maximum number of output streams that can be open simultaneously
- // for all platforms.
- const int kDefaultMaxOutputStreams = 16;
- // Default maximum number of input streams that can be open simultaneously
- // for all platforms.
- const int kMaxInputStreams = 16;
- const int kMaxInputChannels = 3;
- // Helper function to pass as callback when the audio debug recording is not
- // enabled.
- std::unique_ptr<AudioDebugRecorder> GetNullptrAudioDebugRecorder(
- const AudioParameters& params) {
- return nullptr;
- }
- // This enum must match the numbering for AudioOutputProxyStreamFormat in
- // enums.xml. Do not reorder or remove items, only add new items before
- // STREAM_FORMAT_MAX.
- enum StreamFormat {
- STREAM_FORMAT_BITSTREAM = 0,
- STREAM_FORMAT_PCM_LINEAR = 1,
- STREAM_FORMAT_PCM_LOW_LATENCY = 2,
- STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE = 3,
- STREAM_FORMAT_FAKE = 4,
- STREAM_FORMAT_MAX = 4,
- };
- PRINTF_FORMAT(2, 3)
- void SendLogMessage(const AudioManagerBase::LogCallback& callback,
- const char* format,
- ...) {
- if (callback.is_null())
- return;
- va_list args;
- va_start(args, format);
- callback.Run("AMB::" + base::StringPrintV(format, args));
- va_end(args);
- }
- } // namespace
- struct AudioManagerBase::DispatcherParams {
- DispatcherParams(const AudioParameters& input,
- const AudioParameters& output,
- const std::string& output_device_id)
- : input_params(input),
- output_params(output),
- output_device_id(output_device_id) {}
- DispatcherParams(const DispatcherParams&) = delete;
- DispatcherParams& operator=(const DispatcherParams&) = delete;
- ~DispatcherParams() = default;
- const AudioParameters input_params;
- const AudioParameters output_params;
- const std::string output_device_id;
- std::unique_ptr<AudioOutputDispatcher> dispatcher;
- };
- class AudioManagerBase::CompareByParams {
- public:
- explicit CompareByParams(const DispatcherParams* dispatcher)
- : dispatcher_(dispatcher) {}
- bool operator()(
- const std::unique_ptr<DispatcherParams>& dispatcher_in) const {
- // We will reuse the existing dispatcher when:
- // 1) Unified IO is not used, input_params and output_params of the
- // existing dispatcher are the same as the requested dispatcher.
- // 2) Unified IO is used, input_params and output_params of the existing
- // dispatcher are the same as the request dispatcher.
- return (dispatcher_->input_params.Equals(dispatcher_in->input_params) &&
- dispatcher_->output_params.Equals(dispatcher_in->output_params) &&
- dispatcher_->output_device_id == dispatcher_in->output_device_id);
- }
- private:
- raw_ptr<const DispatcherParams> dispatcher_;
- };
- AudioManagerBase::AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,
- AudioLogFactory* audio_log_factory)
- : AudioManager(std::move(audio_thread)),
- max_num_output_streams_(kDefaultMaxOutputStreams),
- num_output_streams_(0),
- // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we
- // don't block the UI thread when swapping devices.
- output_listeners_(base::ObserverListPolicy::EXISTING_ONLY),
- audio_log_factory_(audio_log_factory) {}
- AudioManagerBase::~AudioManagerBase() {
- // All the output streams should have been deleted.
- CHECK_EQ(0, num_output_streams_);
- // All the input streams should have been deleted.
- CHECK(input_streams_.empty());
- }
- void AudioManagerBase::GetAudioInputDeviceDescriptions(
- AudioDeviceDescriptions* device_descriptions) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- GetAudioDeviceDescriptions(device_descriptions,
- &AudioManagerBase::GetAudioInputDeviceNames,
- &AudioManagerBase::GetDefaultInputDeviceID,
- &AudioManagerBase::GetCommunicationsInputDeviceID,
- &AudioManagerBase::GetGroupIDInput);
- }
- void AudioManagerBase::GetAudioOutputDeviceDescriptions(
- AudioDeviceDescriptions* device_descriptions) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- GetAudioDeviceDescriptions(device_descriptions,
- &AudioManagerBase::GetAudioOutputDeviceNames,
- &AudioManagerBase::GetDefaultOutputDeviceID,
- &AudioManagerBase::GetCommunicationsOutputDeviceID,
- &AudioManagerBase::GetGroupIDOutput);
- }
- void AudioManagerBase::GetAudioDeviceDescriptions(
- AudioDeviceDescriptions* device_descriptions,
- void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
- std::string (AudioManagerBase::*get_default_device_id)(),
- std::string (AudioManagerBase::*get_communications_device_id)(),
- std::string (AudioManagerBase::*get_group_id)(const std::string&)) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- AudioDeviceNames device_names;
- (this->*get_device_names)(&device_names);
- std::string real_default_device_id = (this->*get_default_device_id)();
- std::string real_communications_device_id =
- (this->*get_communications_device_id)();
- std::string real_default_name;
- std::string real_communications_name;
- // Find the names for the real devices that are mapped to the default and
- // communications devices.
- for (const auto& name : device_names) {
- if (name.unique_id == real_default_device_id)
- real_default_name = name.device_name;
- if (name.unique_id == real_communications_device_id)
- real_communications_name = name.device_name;
- }
- for (auto& name : device_names) {
- if (AudioDeviceDescription::IsDefaultDevice(name.unique_id))
- name.device_name = real_default_name;
- else if (AudioDeviceDescription::IsCommunicationsDevice(name.unique_id))
- name.device_name = real_communications_name;
- std::string group_id = (this->*get_group_id)(name.unique_id);
- device_descriptions->emplace_back(std::move(name.device_name),
- std::move(name.unique_id),
- std::move(group_id));
- }
- }
- AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
- const AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- DCHECK(params.IsValid());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kFailAudioStreamCreation)) {
- return nullptr;
- }
- SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
- device_id.c_str(), params.AsHumanReadableString().c_str());
- // Limit the number of audio streams opened. This is to prevent using
- // excessive resources for a large number of audio streams. More
- // importantly it prevents instability on certain systems.
- // See bug: http://crbug.com/30242.
- if (num_output_streams_ >= max_num_output_streams_) {
- LOG(ERROR) << "Number of opened output audio streams "
- << num_output_streams_ << " exceed the max allowed number "
- << max_num_output_streams_;
- return nullptr;
- }
- AudioOutputStream* stream;
- switch (params.format()) {
- case AudioParameters::AUDIO_PCM_LINEAR:
- DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id))
- << "AUDIO_PCM_LINEAR supports only the default device.";
- stream = MakeLinearOutputStream(params, log_callback);
- break;
- case AudioParameters::AUDIO_PCM_LOW_LATENCY:
- stream = MakeLowLatencyOutputStream(params, device_id, log_callback);
- break;
- case AudioParameters::AUDIO_BITSTREAM_AC3:
- case AudioParameters::AUDIO_BITSTREAM_EAC3:
- case AudioParameters::AUDIO_BITSTREAM_DTS:
- case AudioParameters::AUDIO_BITSTREAM_DTS_HD:
- case AudioParameters::AUDIO_BITSTREAM_DTSX_P2:
- case AudioParameters::AUDIO_BITSTREAM_IEC61937:
- stream = MakeBitstreamOutputStream(params, device_id, log_callback);
- break;
- case AudioParameters::AUDIO_FAKE:
- stream = FakeAudioOutputStream::MakeFakeStream(this, params);
- break;
- default:
- stream = nullptr;
- break;
- }
- if (stream) {
- ++num_output_streams_;
- SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
- output_stream_count());
- }
- return stream;
- }
- AudioOutputStream* AudioManagerBase::MakeBitstreamOutputStream(
- const AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback) {
- return nullptr;
- }
- AudioInputStream* AudioManagerBase::MakeAudioInputStream(
- const AudioParameters& params,
- const std::string& device_id,
- const LogCallback& log_callback) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kFailAudioStreamCreation)) {
- return nullptr;
- }
- SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
- device_id.c_str(), params.AsHumanReadableString().c_str());
- if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
- device_id.empty()) {
- DLOG(ERROR) << "Audio parameters are invalid for device " << device_id
- << ", params: " << params.AsHumanReadableString();
- return nullptr;
- }
- if (input_stream_count() >= kMaxInputStreams) {
- LOG(ERROR) << "Number of opened input audio streams "
- << input_stream_count() << " exceed the max allowed number "
- << kMaxInputStreams;
- return nullptr;
- }
- DVLOG(2) << "Creating a new AudioInputStream with buffer size = "
- << params.frames_per_buffer();
- AudioInputStream* stream;
- switch (params.format()) {
- case AudioParameters::AUDIO_PCM_LINEAR:
- stream = MakeLinearInputStream(params, device_id, log_callback);
- break;
- case AudioParameters::AUDIO_PCM_LOW_LATENCY:
- stream = MakeLowLatencyInputStream(params, device_id, log_callback);
- break;
- case AudioParameters::AUDIO_FAKE:
- stream = FakeAudioInputStream::MakeFakeStream(this, params);
- break;
- default:
- stream = nullptr;
- break;
- }
- if (stream) {
- input_streams_.insert(stream);
- if (!log_callback.is_null()) {
- SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
- input_stream_count());
- }
- if (!params.IsBitstreamFormat() && debug_recording_manager_) {
- // Using unretained for |debug_recording_manager_| is safe since it
- // outlives the audio thread, on which streams are operated.
- // Note: The AudioInputStreamDataInterceptor takes ownership of the
- // created stream and cleans it up when it is Close()d, transparently to
- // the user of the stream. I the case where the audio manager closes the
- // stream (Mac), this will result in a dangling pointer.
- stream = new AudioInputStreamDataInterceptor(
- base::BindRepeating(
- &AudioDebugRecordingManager::RegisterDebugRecordingSource,
- base::Unretained(debug_recording_manager_.get()),
- AudioDebugRecordingStreamType::kInput, params),
- stream);
- }
- }
- return stream;
- }
- AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
- const AudioParameters& params,
- const std::string& device_id) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- DCHECK(params.IsValid());
- absl::optional<StreamFormat> uma_stream_format;
- // If the caller supplied an empty device id to select the default device,
- // we fetch the actual device id of the default device so that the lookup
- // will find the correct device regardless of whether it was opened as
- // "default" or via the specific id.
- // NOTE: Implementations that don't yet support opening non-default output
- // devices may return an empty string from GetDefaultOutputDeviceID().
- std::string output_device_id =
- AudioDeviceDescription::IsDefaultDevice(device_id)
- ?
- #if BUILDFLAG(IS_CHROMEOS)
- // On ChromeOS, it is expected that, if the default device is given,
- // no specific device ID should be used since the actual output device
- // should change dynamically if the system default device changes.
- // See http://crbug.com/750614.
- std::string()
- #else
- GetDefaultOutputDeviceID()
- #endif
- : device_id;
- // If we're not using AudioOutputResampler our output parameters are the same
- // as our input parameters.
- AudioParameters output_params = params;
- // If audio has been disabled force usage of a fake audio stream.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableAudioOutput)) {
- output_params.set_format(AudioParameters::AUDIO_FAKE);
- }
- if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY &&
- output_params.format() != AudioParameters::AUDIO_FAKE) {
- output_params =
- GetPreferredOutputStreamParameters(output_device_id, params);
- // Ensure we only pass on valid output parameters.
- if (output_params.IsValid()) {
- if (params.effects() & AudioParameters::MULTIZONE) {
- // Never turn off the multizone effect even if it is not preferred.
- output_params.set_effects(output_params.effects() |
- AudioParameters::MULTIZONE);
- }
- if (params.effects() != output_params.effects()) {
- // Turn off effects that weren't requested.
- output_params.set_effects(params.effects() & output_params.effects());
- }
- uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY;
- } else {
- // We've received invalid audio output parameters, so switch to a mock
- // output device based on the input parameters. This may happen if the OS
- // provided us junk values for the hardware configuration.
- LOG(ERROR) << "Invalid audio output parameters received; using fake "
- << "audio path: " << output_params.AsHumanReadableString();
- // Tell the AudioManager to create a fake output device.
- output_params = params;
- output_params.set_format(AudioParameters::AUDIO_FAKE);
- uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE;
- }
- output_params.set_latency_tag(params.latency_tag());
- } else {
- switch (output_params.format()) {
- case AudioParameters::AUDIO_PCM_LINEAR:
- uma_stream_format = STREAM_FORMAT_PCM_LINEAR;
- break;
- case AudioParameters::AUDIO_FAKE:
- uma_stream_format = STREAM_FORMAT_FAKE;
- break;
- default:
- if (output_params.IsBitstreamFormat())
- uma_stream_format = STREAM_FORMAT_BITSTREAM;
- else
- NOTREACHED();
- }
- }
- if (uma_stream_format) {
- UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputStreamProxy.StreamFormat",
- *uma_stream_format, STREAM_FORMAT_MAX + 1);
- } else {
- NOTREACHED();
- }
- std::unique_ptr<DispatcherParams> dispatcher_params =
- std::make_unique<DispatcherParams>(params, output_params,
- output_device_id);
- auto it = std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
- CompareByParams(dispatcher_params.get()));
- if (it != output_dispatchers_.end())
- return (*it)->dispatcher->CreateStreamProxy();
- const base::TimeDelta kCloseDelay = base::Seconds(kStreamCloseDelaySeconds);
- std::unique_ptr<AudioOutputDispatcher> dispatcher;
- if (output_params.format() != AudioParameters::AUDIO_FAKE &&
- !output_params.IsBitstreamFormat()) {
- // Using unretained for |debug_recording_manager_| is safe since it
- // outlives the dispatchers (cleared in ShutdownOnAudioThread()).
- dispatcher = std::make_unique<AudioOutputResampler>(
- this, params, output_params, output_device_id, kCloseDelay,
- debug_recording_manager_
- ? base::BindRepeating(
- &AudioDebugRecordingManager::RegisterDebugRecordingSource,
- base::Unretained(debug_recording_manager_.get()),
- AudioDebugRecordingStreamType::kOutput)
- : base::BindRepeating(&GetNullptrAudioDebugRecorder));
- } else {
- dispatcher = std::make_unique<AudioOutputDispatcherImpl>(
- this, output_params, output_device_id, kCloseDelay);
- }
- dispatcher_params->dispatcher = std::move(dispatcher);
- output_dispatchers_.push_back(std::move(dispatcher_params));
- return output_dispatchers_.back()->dispatcher->CreateStreamProxy();
- }
- void AudioManagerBase::GetAudioInputDeviceNames(
- AudioDeviceNames* device_names) {
- }
- void AudioManagerBase::GetAudioOutputDeviceNames(
- AudioDeviceNames* device_names) {
- }
- void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- DCHECK(stream);
- CHECK_GT(num_output_streams_, 0);
- // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
- // For example, pass the ownership to AudioManager so it can delete the
- // streams.
- --num_output_streams_;
- delete stream;
- }
- void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
- CHECK(GetTaskRunner()->BelongsToCurrentThread());
- DCHECK(stream);
- // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
- CHECK_EQ(1u, input_streams_.erase(stream));
- delete stream;
- }
- void AudioManagerBase::ShutdownOnAudioThread() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- // Close all output streams.
- output_dispatchers_.clear();
- }
- void AudioManagerBase::AddOutputDeviceChangeListener(
- AudioDeviceListener* listener) {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- output_listeners_.AddObserver(listener);
- }
- void AudioManagerBase::RemoveOutputDeviceChangeListener(
- AudioDeviceListener* listener) {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- output_listeners_.RemoveObserver(listener);
- }
- void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- DVLOG(1) << "Firing OnDeviceChange() notifications.";
- for (auto& observer : output_listeners_)
- observer.OnDeviceChange();
- }
- AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
- return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(),
- AudioParameters());
- }
- AudioParameters AudioManagerBase::GetOutputStreamParameters(
- const std::string& device_id) {
- return GetPreferredOutputStreamParameters(device_id,
- AudioParameters());
- }
- AudioParameters AudioManagerBase::GetInputStreamParameters(
- const std::string& device_id) {
- NOTREACHED();
- return AudioParameters();
- }
- std::string AudioManagerBase::GetAssociatedOutputDeviceID(
- const std::string& input_device_id) {
- return std::string();
- }
- std::string AudioManagerBase::GetGroupIDOutput(
- const std::string& output_device_id) {
- if (output_device_id == AudioDeviceDescription::kDefaultDeviceId) {
- std::string real_device_id = GetDefaultOutputDeviceID();
- if (!real_device_id.empty())
- return real_device_id;
- } else if (output_device_id ==
- AudioDeviceDescription::kCommunicationsDeviceId) {
- std::string real_device_id = GetCommunicationsOutputDeviceID();
- if (!real_device_id.empty())
- return real_device_id;
- }
- return output_device_id;
- }
- std::string AudioManagerBase::GetGroupIDInput(
- const std::string& input_device_id) {
- const std::string& real_input_device_id =
- input_device_id == AudioDeviceDescription::kDefaultDeviceId
- ? GetDefaultInputDeviceID()
- : input_device_id == AudioDeviceDescription::kCommunicationsDeviceId
- ? GetCommunicationsInputDeviceID()
- : input_device_id;
- std::string output_device_id =
- GetAssociatedOutputDeviceID(real_input_device_id);
- if (output_device_id.empty()) {
- // Some characters are added to avoid accidentally
- // giving the input the same group id as an output.
- return real_input_device_id + "input";
- }
- return GetGroupIDOutput(output_device_id);
- }
- void AudioManagerBase::CloseAllInputStreams() {
- for (auto iter = input_streams_.begin(); iter != input_streams_.end();) {
- // Note: Closing the stream will invalidate the iterator.
- // Increment the iterator before closing the stream.
- AudioInputStream* stream = *iter++;
- stream->Close();
- }
- CHECK(input_streams_.empty());
- }
- std::string AudioManagerBase::GetDefaultInputDeviceID() {
- return std::string();
- }
- std::string AudioManagerBase::GetDefaultOutputDeviceID() {
- return std::string();
- }
- std::string AudioManagerBase::GetCommunicationsInputDeviceID() {
- return std::string();
- }
- std::string AudioManagerBase::GetCommunicationsOutputDeviceID() {
- return std::string();
- }
- // static
- int AudioManagerBase::GetUserBufferSize() {
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- int buffer_size = 0;
- std::string buffer_size_str(cmd_line->GetSwitchValueASCII(
- switches::kAudioBufferSize));
- if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0)
- return buffer_size;
- return 0;
- }
- std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
- AudioLogFactory::AudioComponent component,
- int component_id) {
- return audio_log_factory_->CreateAudioLog(component, component_id);
- }
- void AudioManagerBase::InitializeDebugRecording() {
- if (!GetTaskRunner()->BelongsToCurrentThread()) {
- // AudioManager is deleted on the audio thread, so it's safe to post
- // unretained.
- GetTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&AudioManagerBase::InitializeDebugRecording,
- base::Unretained(this)));
- return;
- }
- DCHECK(!debug_recording_manager_);
- debug_recording_manager_ = CreateAudioDebugRecordingManager(GetTaskRunner());
- }
- std::unique_ptr<AudioDebugRecordingManager>
- AudioManagerBase::CreateAudioDebugRecordingManager(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- return std::make_unique<AudioDebugRecordingManager>(std::move(task_runner));
- }
- AudioDebugRecordingManager* AudioManagerBase::GetAudioDebugRecordingManager() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- return debug_recording_manager_.get();
- }
- } // namespace media
|