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