// Copyright 2017 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_system_helper.h" #include "base/single_thread_task_runner.h" #include "media/audio/audio_manager.h" #include "media/base/limits.h" namespace media { namespace { base::Optional TryToFixChannels( const AudioParameters& params) { DCHECK(!params.IsValid()); AudioParameters params_copy(params); // If the number of output channels is greater than the maximum, use the // maximum allowed value. Hardware channels are ignored upstream, so it is // better to report a valid value if this is the only problem. if (params.channels() > limits::kMaxChannels) { DCHECK(params.channel_layout() == CHANNEL_LAYOUT_DISCRETE); params_copy.set_channels_for_discrete(limits::kMaxChannels); } return params_copy.IsValid() ? params_copy : base::Optional(); } } // namespace AudioSystemHelper::AudioSystemHelper(AudioManager* audio_manager) : audio_manager_(audio_manager) { DCHECK(audio_manager_); } AudioSystemHelper::~AudioSystemHelper() = default; void AudioSystemHelper::GetInputStreamParameters( const std::string& device_id, AudioSystem::OnAudioParamsCallback on_params_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); std::move(on_params_cb).Run(ComputeInputParameters(device_id)); } void AudioSystemHelper::GetOutputStreamParameters( const std::string& device_id, AudioSystem::OnAudioParamsCallback on_params_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); std::move(on_params_cb).Run(ComputeOutputParameters(device_id)); } void AudioSystemHelper::HasInputDevices( AudioSystem::OnBoolCallback on_has_devices_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); std::move(on_has_devices_cb).Run(audio_manager_->HasAudioInputDevices()); } void AudioSystemHelper::HasOutputDevices( AudioSystem::OnBoolCallback on_has_devices_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); std::move(on_has_devices_cb).Run(audio_manager_->HasAudioOutputDevices()); } void AudioSystemHelper::GetDeviceDescriptions( bool for_input, AudioSystem::OnDeviceDescriptionsCallback on_descriptions_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); AudioDeviceDescriptions descriptions; if (for_input) audio_manager_->GetAudioInputDeviceDescriptions(&descriptions); else audio_manager_->GetAudioOutputDeviceDescriptions(&descriptions); std::move(on_descriptions_cb).Run(std::move(descriptions)); } void AudioSystemHelper::GetAssociatedOutputDeviceID( const std::string& input_device_id, AudioSystem::OnDeviceIdCallback on_device_id_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); const std::string associated_output_device_id = audio_manager_->GetAssociatedOutputDeviceID(input_device_id); std::move(on_device_id_cb) .Run(associated_output_device_id.empty() ? base::Optional() : associated_output_device_id); } void AudioSystemHelper::GetInputDeviceInfo( const std::string& input_device_id, AudioSystem::OnInputDeviceInfoCallback on_input_device_info_cb) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); const std::string associated_output_device_id = audio_manager_->GetAssociatedOutputDeviceID(input_device_id); std::move(on_input_device_info_cb) .Run(ComputeInputParameters(input_device_id), associated_output_device_id.empty() ? base::Optional() : associated_output_device_id); } base::Optional AudioSystemHelper::ComputeInputParameters( const std::string& device_id) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); // TODO(olka): remove this when AudioManager::GetInputStreamParameters() // returns invalid parameters if the device is not found. if (AudioDeviceDescription::IsLoopbackDevice(device_id)) { // For system audio capture, we need an output device (namely speaker) // instead of an input device (namely microphone) to work. // AudioManager::GetInputStreamParameters will check |device_id| and // query the correct device for audio parameters by itself. if (!audio_manager_->HasAudioOutputDevices()) return base::Optional(); } else { if (!audio_manager_->HasAudioInputDevices()) return base::Optional(); } AudioParameters params = audio_manager_->GetInputStreamParameters(device_id); return params.IsValid() ? params : TryToFixChannels(params); } base::Optional AudioSystemHelper::ComputeOutputParameters( const std::string& device_id) { DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); // TODO(olka): remove this when // AudioManager::Get[Default]OutputStreamParameters() returns invalid // parameters if the device is not found. if (!audio_manager_->HasAudioOutputDevices()) return base::Optional(); AudioParameters params = AudioDeviceDescription::IsDefaultDevice(device_id) ? audio_manager_->GetDefaultOutputStreamParameters() : audio_manager_->GetOutputStreamParameters(device_id); if (params.IsValid()) return params; return TryToFixChannels(params); } } // namespace media