audio_auhal_mac.h revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4// 5// Implementation notes: 6// 7// - It is recommended to first acquire the native sample rate of the default 8// output device and then use the same rate when creating this object. 9// Use AudioManagerMac::HardwareSampleRate() to retrieve the sample rate. 10// - Calling Close() also leads to self destruction. 11// - The latency consists of two parts: 12// 1) Hardware latency, which includes Audio Unit latency, audio device 13// latency; 14// 2) The delay between the moment getting the callback and the scheduled time 15// stamp that tells when the data is going to be played out. 16// 17#ifndef MEDIA_AUDIO_MAC_AUDIO_AUHAL_MAC_H_ 18#define MEDIA_AUDIO_MAC_AUDIO_AUHAL_MAC_H_ 19 20#include <AudioUnit/AudioUnit.h> 21#include <CoreAudio/CoreAudio.h> 22 23#include "base/cancelable_callback.h" 24#include "base/compiler_specific.h" 25#include "base/synchronization/lock.h" 26#include "media/audio/audio_io.h" 27#include "media/audio/audio_parameters.h" 28 29namespace media { 30 31class AudioManagerMac; 32class AudioPullFifo; 33 34// Implementation of AudioOuputStream for Mac OS X using the 35// AUHAL Audio Unit present in OS 10.4 and later. 36// It is useful for low-latency output with optional synchronized 37// input. 38// 39// Overview of operation: 40// 1) An object of AUHALStream is created by the AudioManager 41// factory: audio_man->MakeAudioStream(). 42// 2) Next some thread will call Open(), at that point the underlying 43// AUHAL Audio Unit is created and configured to use the |device|. 44// 3) Then some thread will call Start(source). 45// Then the AUHAL is started which creates its own thread which 46// periodically will call the source for more data as buffers are being 47// consumed. 48// 4) At some point some thread will call Stop(), which we handle by directly 49// stopping the default output Audio Unit. 50// 6) The same thread that called stop will call Close() where we cleanup 51// and notify the audio manager, which likely will destroy this object. 52 53class AUHALStream : public AudioOutputStream { 54 public: 55 // |manager| creates this object. 56 // |device| is the CoreAudio device to use for the stream. 57 // It will often be the default output device. 58 AUHALStream(AudioManagerMac* manager, 59 const AudioParameters& params, 60 AudioDeviceID device); 61 // The dtor is typically called by the AudioManager only and it is usually 62 // triggered by calling AudioOutputStream::Close(). 63 virtual ~AUHALStream(); 64 65 // Implementation of AudioOutputStream. 66 virtual bool Open() OVERRIDE; 67 virtual void Close() OVERRIDE; 68 virtual void Start(AudioSourceCallback* callback) OVERRIDE; 69 virtual void Stop() OVERRIDE; 70 virtual void SetVolume(double volume) OVERRIDE; 71 virtual void GetVolume(double* volume) OVERRIDE; 72 73 private: 74 // AUHAL callback. 75 static OSStatus InputProc(void* user_data, 76 AudioUnitRenderActionFlags* flags, 77 const AudioTimeStamp* time_stamp, 78 UInt32 bus_number, 79 UInt32 number_of_frames, 80 AudioBufferList* io_data); 81 82 OSStatus Render(AudioUnitRenderActionFlags* flags, 83 const AudioTimeStamp* output_time_stamp, 84 UInt32 bus_number, 85 UInt32 number_of_frames, 86 AudioBufferList* io_data); 87 88 // Called by either |audio_fifo_| or Render() to provide audio data. 89 void ProvideInput(int frame_delay, AudioBus* dest); 90 91 // Helper method to enable input and output. 92 bool EnableIO(bool enable, UInt32 scope); 93 94 // Sets the stream format on the AUHAL to PCM Float32 non-interleaved 95 // for the given number of channels on the given scope and element. 96 // The created stream description will be stored in |desc|. 97 bool SetStreamFormat(AudioStreamBasicDescription* desc, 98 int channels, 99 UInt32 scope, 100 UInt32 element); 101 102 // Creates the AUHAL, sets its stream format, buffer-size, etc. 103 bool ConfigureAUHAL(); 104 105 // Creates the input and output busses. 106 void CreateIOBusses(); 107 108 // Gets the fixed playout device hardware latency and stores it. Returns 0 109 // if not available. 110 double GetHardwareLatency(); 111 112 // Gets the current playout latency value. 113 double GetPlayoutLatency(const AudioTimeStamp* output_time_stamp); 114 115 // Our creator, the audio manager needs to be notified when we close. 116 AudioManagerMac* const manager_; 117 118 const AudioParameters params_; 119 // For convenience - same as in params_. 120 const int input_channels_; 121 const int output_channels_; 122 123 // Buffer-size. 124 const size_t number_of_frames_; 125 126 // Pointer to the object that will provide the audio samples. 127 AudioSourceCallback* source_; 128 129 // Protects |source_|. Necessary since Render() calls seem to be in flight 130 // when |audio_unit_| is supposedly stopped. See http://crbug.com/178765. 131 base::Lock source_lock_; 132 133 // Holds the stream format details such as bitrate. 134 AudioStreamBasicDescription input_format_; 135 AudioStreamBasicDescription output_format_; 136 137 // The audio device to use with the AUHAL. 138 // We can potentially handle both input and output with this device. 139 const AudioDeviceID device_; 140 141 // The AUHAL Audio Unit which talks to |device_|. 142 AudioUnit audio_unit_; 143 144 // Volume level from 0 to 1. 145 float volume_; 146 147 // Fixed playout hardware latency in frames. 148 double hardware_latency_frames_; 149 150 // The flag used to stop the streaming. 151 bool stopped_; 152 153 // The input AudioUnit renders its data here. 154 scoped_ptr<uint8[]> input_buffer_list_storage_; 155 AudioBufferList* input_buffer_list_; 156 157 // Holds the actual data for |input_buffer_list_|. 158 scoped_ptr<AudioBus> input_bus_; 159 160 // Container for retrieving data from AudioSourceCallback::OnMoreIOData(). 161 scoped_ptr<AudioBus> output_bus_; 162 163 // Dynamically allocated FIFO used when CoreAudio asks for unexpected frame 164 // sizes. 165 scoped_ptr<AudioPullFifo> audio_fifo_; 166 167 // Current buffer delay. Set by Render(). 168 uint32 current_hardware_pending_bytes_; 169 170 // Used to defer Start() to workaround http://crbug.com/160920. 171 base::CancelableClosure deferred_start_cb_; 172 173 DISALLOW_COPY_AND_ASSIGN(AUHALStream); 174}; 175 176} // namespace media 177 178#endif // MEDIA_AUDIO_MAC_AUDIO_AUHAL_MAC_H_ 179