| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MEDIA_AUDIO_MAC_AUDIO_MANAGER_MAC_H_ |
| #define MEDIA_AUDIO_MAC_AUDIO_MANAGER_MAC_H_ |
| |
| #include <AudioUnit/AudioUnit.h> |
| #include <CoreAudio/AudioHardware.h> |
| #include <stddef.h> |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/compiler_specific.h" |
| #include "base/memory/weak_ptr.h" |
| #include "media/audio/audio_manager_base.h" |
| #include "media/audio/mac/audio_auhal_mac.h" |
| #include "media/audio/mac/audio_device_listener_mac.h" |
| |
| namespace media { |
| |
| class AUAudioInputStream; |
| class AUHALStream; |
| |
| // Mac OS X implementation of the AudioManager singleton. This class is internal |
| // to the audio output and only internal users can call methods not exposed by |
| // the AudioManager class. |
| class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase, |
| public AudioIOStreamClient { |
| public: |
| AudioManagerMac(std::unique_ptr<AudioThread> audio_thread, |
| AudioLogFactory* audio_log_factory); |
| |
| AudioManagerMac(const AudioManagerMac&) = delete; |
| AudioManagerMac& operator=(const AudioManagerMac&) = delete; |
| |
| ~AudioManagerMac() override; |
| |
| // Implementation of AudioManager. |
| bool HasAudioOutputDevices() override; |
| bool HasAudioInputDevices() override; |
| void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; |
| void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; |
| AudioParameters GetInputStreamParameters( |
| const std::string& device_id) override; |
| std::string GetAssociatedOutputDeviceID( |
| const std::string& input_device_id) override; |
| const char* GetName() override; |
| |
| // Implementation of AudioManagerBase. |
| AudioOutputStream* MakeLinearOutputStream( |
| const AudioParameters& params, |
| const LogCallback& log_callback) override; |
| AudioOutputStream* MakeLowLatencyOutputStream( |
| const AudioParameters& params, |
| const std::string& device_id, |
| const LogCallback& log_callback) override; |
| AudioInputStream* MakeLinearInputStream( |
| const AudioParameters& params, |
| const std::string& device_id, |
| const LogCallback& log_callback) override; |
| AudioInputStream* MakeLowLatencyInputStream( |
| const AudioParameters& params, |
| const std::string& device_id, |
| const LogCallback& log_callback) override; |
| |
| std::string GetDefaultInputDeviceID() override; |
| std::string GetDefaultOutputDeviceID() override; |
| |
| // Used to track destruction of input and output streams. |
| void ReleaseOutputStream(AudioOutputStream* stream) override; |
| void ReleaseInputStream(AudioInputStream* stream) override; |
| |
| // Called by AUHALStream::Close() before releasing the stream. |
| // This method is a special contract between the real stream and the audio |
| // manager and it ensures that we only try to increase the IO buffer size |
| // for real streams and not for fake or mocked streams. |
| void ReleaseOutputStreamUsingRealDevice(AudioOutputStream* stream, |
| AudioDeviceID device_id) override; |
| void ReleaseInputStreamUsingRealDevice(AudioInputStream* stream) override; |
| |
| // Changes the I/O buffer size for |device_id| if |desired_buffer_size| is |
| // lower than the current device buffer size. The buffer size can also be |
| // modified under other conditions. See comments in the corresponding cc-file |
| // for more details. |
| // Returns false if an error occurred. |
| bool MaybeChangeBufferSize(AudioDeviceID device_id, |
| AudioUnit audio_unit, |
| AudioUnitElement element, |
| size_t desired_buffer_size) override; |
| base::TimeDelta GetDeferStreamStartTimeout() const override; |
| base::SingleThreadTaskRunner* GetTaskRunner() const override; |
| void StopAmplitudePeakTrace() override; |
| |
| static int HardwareSampleRateForDevice(AudioDeviceID device_id); |
| static int HardwareSampleRate(); |
| static bool GetDefaultOutputDevice(AudioDeviceID* device); |
| static AudioDeviceID GetAudioDeviceIdByUId(bool is_input, |
| const std::string& device_id); |
| |
| // Returns a vector with the IDs of all devices related to the given |
| // |device_id|. The vector is empty if there are no related devices or |
| // if there is an error. |
| std::vector<AudioObjectID> GetRelatedDeviceIDs(AudioObjectID device_id); |
| |
| // OSX has issues with starting streams as the system goes into suspend and |
| // immediately after it wakes up from resume. See http://crbug.com/160920. |
| // As a workaround we delay Start() when it occurs after suspend and for a |
| // small amount of time after resume. |
| // |
| // Streams should consult ShouldDeferStreamStart() and if true check the value |
| // again after |kStartDelayInSecsForPowerEvents| has elapsed. If false, the |
| // stream may be started immediately. |
| // TODO(henrika): track UMA statistics related to defer start to come up with |
| // a suitable delay value. |
| enum { kStartDelayInSecsForPowerEvents = 5 }; |
| bool ShouldDeferStreamStart() const; |
| |
| // True if the device is on battery power. |
| bool IsOnBatteryPower() const; |
| |
| // Number of times the device has resumed from power suspension. |
| size_t GetNumberOfResumeNotifications() const; |
| |
| // True if the device is suspending. |
| bool IsSuspending() const; |
| |
| // Number of constructed output and input streams. |
| size_t output_streams() const { return output_streams_.size(); } |
| size_t low_latency_input_streams() const { |
| return low_latency_input_streams_.size(); |
| } |
| size_t basic_input_streams() const { return basic_input_streams_.size(); } |
| |
| bool DeviceSupportsAmbientNoiseReduction(AudioDeviceID device_id); |
| bool SuppressNoiseReduction(AudioDeviceID device_id); |
| void UnsuppressNoiseReduction(AudioDeviceID device_id); |
| |
| // The state of a single device for which we've tried to disable Ambient Noise |
| // Reduction. If the device initially has ANR enabled, it will be turned off |
| // as the suppression count goes from 0 to 1 and turned on again as the count |
| // returns to 0. |
| struct NoiseReductionState { |
| enum State { DISABLED, ENABLED }; |
| State initial_state = DISABLED; |
| int suppression_count = 0; |
| }; |
| |
| // Keep track of the devices that we've changed the Ambient Noise Reduction |
| // setting on. |
| std::map<AudioDeviceID, NoiseReductionState> device_noise_reduction_states_; |
| |
| protected: |
| AudioParameters GetPreferredOutputStreamParameters( |
| const std::string& output_device_id, |
| const AudioParameters& input_params) override; |
| |
| // Returns a vector with the IDs of all bluetooth devices related to the given |
| // |device_id|, which is also a bluetooth device. The vector is empty if there |
| // are no related devices or if there is an error. |
| std::vector<AudioObjectID> GetRelatedBluetoothDeviceIDs( |
| AudioObjectID device_id); |
| |
| // Virtual for testing. |
| |
| // Returns a vector with the IDs of all audio devices in the system. |
| // The vector is empty if there are no devices or if there is an error. |
| virtual std::vector<AudioObjectID> GetAllAudioDeviceIDs(); |
| |
| // Returns a vector with the IDs of all non-bluetooth devices related to the |
| // given |device_id|, which is also a non-bluetooth device. The vector is |
| // empty if there are no related devices or if there is an error. |
| virtual std::vector<AudioObjectID> GetRelatedNonBluetoothDeviceIDs( |
| AudioObjectID device_id); |
| |
| // Returns a string with a unique device ID for the given |device_id|, or no |
| // value if there is an error. |
| virtual absl::optional<std::string> GetDeviceUniqueID( |
| AudioObjectID device_id); |
| |
| // Returns the transport type of the given |device_id|, or no value if |
| // |device_id| has no source or if there is an error. |
| virtual absl::optional<uint32_t> GetDeviceTransportType( |
| AudioObjectID device_id); |
| void ShutdownOnAudioThread() override; |
| |
| private: |
| void InitializeOnAudioThread(); |
| |
| int ChooseBufferSize(bool is_input, int sample_rate); |
| |
| // Notify streams of a device change if the default output device or its |
| // sample rate has changed, otherwise does nothing. |
| void HandleDeviceChanges(); |
| |
| // Returns true if any active input stream is using the specified |device_id|. |
| bool AudioDeviceIsUsedForInput(AudioDeviceID device_id); |
| |
| std::string GetDefaultDeviceID(bool is_input); |
| |
| std::unique_ptr<AudioDeviceListenerMac> output_device_listener_; |
| |
| // Track the output sample-rate and the default output device |
| // so we can intelligently handle device notifications only when necessary. |
| int current_sample_rate_; |
| AudioDeviceID current_output_device_; |
| |
| // Helper class which monitors power events to determine if output streams |
| // should defer Start() calls. Required to workaround an OSX bug. See |
| // http://crbug.com/160920 for more details. |
| class AudioPowerObserver; |
| std::unique_ptr<AudioPowerObserver> power_observer_; |
| |
| // Tracks all constructed input and output streams. |
| // TODO(alokp): We used to track these streams to close before destruction. |
| // We no longer close the streams, so we may be able to get rid of these |
| // member variables. They are currently used by MaybeChangeBufferSize(). |
| // Investigate if we can remove these. |
| std::list<AudioInputStream*> basic_input_streams_; |
| std::list<AUAudioInputStream*> low_latency_input_streams_; |
| std::list<AUHALStream*> output_streams_; |
| |
| // Set to true in the destructor. Ensures that methods that touches native |
| // Core Audio APIs are not executed during shutdown. |
| bool in_shutdown_; |
| |
| base::WeakPtrFactory<AudioManagerMac> weak_ptr_factory_; |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_AUDIO_MAC_AUDIO_MANAGER_MAC_H_ |