Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / media / audio / mac / audio_low_latency_input_mac.cc
blobf7e39a8693ca41ac7c69f9577be1a8fc406f299a
1 // Copyright (c) 2012 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.
5 #include "media/audio/mac/audio_low_latency_input_mac.h"
7 #include <CoreServices/CoreServices.h>
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/mac/mac_logging.h"
12 #include "media/audio/audio_util.h"
13 #include "media/audio/mac/audio_manager_mac.h"
14 #include "media/base/data_buffer.h"
16 namespace media {
18 static const int kMinIntervalBetweenVolumeUpdatesMs = 1000;
20 static std::ostream& operator<<(std::ostream& os,
21 const AudioStreamBasicDescription& format) {
22 os << "sample rate : " << format.mSampleRate << std::endl
23 << "format ID : " << format.mFormatID << std::endl
24 << "format flags : " << format.mFormatFlags << std::endl
25 << "bytes per packet : " << format.mBytesPerPacket << std::endl
26 << "frames per packet : " << format.mFramesPerPacket << std::endl
27 << "bytes per frame : " << format.mBytesPerFrame << std::endl
28 << "channels per frame: " << format.mChannelsPerFrame << std::endl
29 << "bits per channel : " << format.mBitsPerChannel;
30 return os;
33 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit"
34 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
35 // for more details and background regarding this implementation.
37 AUAudioInputStream::AUAudioInputStream(
38 AudioManagerMac* manager, const AudioParameters& params,
39 AudioDeviceID audio_device_id)
40 : manager_(manager),
41 sink_(NULL),
42 audio_unit_(0),
43 input_device_id_(audio_device_id),
44 started_(false),
45 hardware_latency_frames_(0),
46 number_of_channels_in_frame_(0) {
47 DCHECK(manager_);
49 // Set up the desired (output) format specified by the client.
50 format_.mSampleRate = params.sample_rate();
51 format_.mFormatID = kAudioFormatLinearPCM;
52 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked |
53 kLinearPCMFormatFlagIsSignedInteger;
54 format_.mBitsPerChannel = params.bits_per_sample();
55 format_.mChannelsPerFrame = params.channels();
56 format_.mFramesPerPacket = 1; // uncompressed audio
57 format_.mBytesPerPacket = (format_.mBitsPerChannel *
58 params.channels()) / 8;
59 format_.mBytesPerFrame = format_.mBytesPerPacket;
60 format_.mReserved = 0;
62 DVLOG(1) << "Desired ouput format: " << format_;
64 // Set number of sample frames per callback used by the internal audio layer.
65 // An internal FIFO is then utilized to adapt the internal size to the size
66 // requested by the client.
67 // Note that we use the same native buffer size as for the output side here
68 // since the AUHAL implementation requires that both capture and render side
69 // use the same buffer size. See http://crbug.com/154352 for more details.
70 // TODO(xians): Get the audio parameters from the right device.
71 const AudioParameters parameters =
72 manager_->GetInputStreamParameters(AudioManagerBase::kDefaultDeviceId);
73 number_of_frames_ = parameters.frames_per_buffer();
74 DVLOG(1) << "Size of data buffer in frames : " << number_of_frames_;
76 // Derive size (in bytes) of the buffers that we will render to.
77 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame;
78 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size;
80 // Allocate AudioBuffers to be used as storage for the received audio.
81 // The AudioBufferList structure works as a placeholder for the
82 // AudioBuffer structure, which holds a pointer to the actual data buffer.
83 audio_data_buffer_.reset(new uint8[data_byte_size]);
84 audio_buffer_list_.mNumberBuffers = 1;
86 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers;
87 audio_buffer->mNumberChannels = params.channels();
88 audio_buffer->mDataByteSize = data_byte_size;
89 audio_buffer->mData = audio_data_buffer_.get();
91 // Set up an internal FIFO buffer that will accumulate recorded audio frames
92 // until a requested size is ready to be sent to the client.
93 // It is not possible to ask for less than |kAudioFramesPerCallback| number of
94 // audio frames.
95 const size_t requested_size_frames =
96 params.GetBytesPerBuffer() / format_.mBytesPerPacket;
97 DCHECK_GE(requested_size_frames, number_of_frames_);
98 requested_size_bytes_ = requested_size_frames * format_.mBytesPerFrame;
99 DVLOG(1) << "Requested buffer size in bytes : " << requested_size_bytes_;
100 DLOG_IF(INFO, requested_size_frames > number_of_frames_) << "FIFO is used";
102 // Allocate some extra memory to avoid memory reallocations.
103 // Ensure that the size is an even multiple of |number_of_frames_ and
104 // larger than |requested_size_frames|.
105 // Example: number_of_frames_=128, requested_size_frames=480 =>
106 // allocated space equals 4*128=512 audio frames
107 const int max_forward_capacity = format_.mBytesPerFrame * number_of_frames_ *
108 ((requested_size_frames / number_of_frames_) + 1);
109 fifo_.reset(new media::SeekableBuffer(0, max_forward_capacity));
111 data_ = new media::DataBuffer(requested_size_bytes_);
114 AUAudioInputStream::~AUAudioInputStream() {}
116 // Obtain and open the AUHAL AudioOutputUnit for recording.
117 bool AUAudioInputStream::Open() {
118 // Verify that we are not already opened.
119 if (audio_unit_)
120 return false;
122 // Verify that we have a valid device.
123 if (input_device_id_ == kAudioObjectUnknown) {
124 NOTREACHED() << "Device ID is unknown";
125 return false;
128 // Start by obtaining an AudioOuputUnit using an AUHAL component description.
130 Component comp;
131 ComponentDescription desc;
133 // Description for the Audio Unit we want to use (AUHAL in this case).
134 desc.componentType = kAudioUnitType_Output;
135 desc.componentSubType = kAudioUnitSubType_HALOutput;
136 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
137 desc.componentFlags = 0;
138 desc.componentFlagsMask = 0;
139 comp = FindNextComponent(0, &desc);
140 DCHECK(comp);
142 // Get access to the service provided by the specified Audio Unit.
143 OSStatus result = OpenAComponent(comp, &audio_unit_);
144 if (result) {
145 HandleError(result);
146 return false;
149 // Enable IO on the input scope of the Audio Unit.
151 // After creating the AUHAL object, we must enable IO on the input scope
152 // of the Audio Unit to obtain the device input. Input must be explicitly
153 // enabled with the kAudioOutputUnitProperty_EnableIO property on Element 1
154 // of the AUHAL. Beacause the AUHAL can be used for both input and output,
155 // we must also disable IO on the output scope.
157 UInt32 enableIO = 1;
159 // Enable input on the AUHAL.
160 result = AudioUnitSetProperty(audio_unit_,
161 kAudioOutputUnitProperty_EnableIO,
162 kAudioUnitScope_Input,
163 1, // input element 1
164 &enableIO, // enable
165 sizeof(enableIO));
166 if (result) {
167 HandleError(result);
168 return false;
171 // Disable output on the AUHAL.
172 enableIO = 0;
173 result = AudioUnitSetProperty(audio_unit_,
174 kAudioOutputUnitProperty_EnableIO,
175 kAudioUnitScope_Output,
176 0, // output element 0
177 &enableIO, // disable
178 sizeof(enableIO));
179 if (result) {
180 HandleError(result);
181 return false;
184 // Next, set the audio device to be the Audio Unit's current device.
185 // Note that, devices can only be set to the AUHAL after enabling IO.
186 result = AudioUnitSetProperty(audio_unit_,
187 kAudioOutputUnitProperty_CurrentDevice,
188 kAudioUnitScope_Global,
190 &input_device_id_,
191 sizeof(input_device_id_));
192 if (result) {
193 HandleError(result);
194 return false;
197 // Register the input procedure for the AUHAL.
198 // This procedure will be called when the AUHAL has received new data
199 // from the input device.
200 AURenderCallbackStruct callback;
201 callback.inputProc = InputProc;
202 callback.inputProcRefCon = this;
203 result = AudioUnitSetProperty(audio_unit_,
204 kAudioOutputUnitProperty_SetInputCallback,
205 kAudioUnitScope_Global,
207 &callback,
208 sizeof(callback));
209 if (result) {
210 HandleError(result);
211 return false;
214 // Set up the the desired (output) format.
215 // For obtaining input from a device, the device format is always expressed
216 // on the output scope of the AUHAL's Element 1.
217 result = AudioUnitSetProperty(audio_unit_,
218 kAudioUnitProperty_StreamFormat,
219 kAudioUnitScope_Output,
221 &format_,
222 sizeof(format_));
223 if (result) {
224 HandleError(result);
225 return false;
228 // Set the desired number of frames in the IO buffer (output scope).
229 // WARNING: Setting this value changes the frame size for all audio units in
230 // the current process. It's imperative that the input and output frame sizes
231 // be the same as the frames_per_buffer() returned by
232 // GetInputStreamParameters().
233 // TODO(henrika): Due to http://crrev.com/159666 this is currently not true
234 // and should be fixed, a CHECK() should be added at that time.
235 result = AudioUnitSetProperty(audio_unit_,
236 kAudioDevicePropertyBufferFrameSize,
237 kAudioUnitScope_Output,
239 &number_of_frames_, // size is set in the ctor
240 sizeof(number_of_frames_));
241 if (result) {
242 HandleError(result);
243 return false;
246 // Finally, initialize the audio unit and ensure that it is ready to render.
247 // Allocates memory according to the maximum number of audio frames
248 // it can produce in response to a single render call.
249 result = AudioUnitInitialize(audio_unit_);
250 if (result) {
251 HandleError(result);
252 return false;
255 // The hardware latency is fixed and will not change during the call.
256 hardware_latency_frames_ = GetHardwareLatency();
258 // The master channel is 0, Left and right are channels 1 and 2.
259 // And the master channel is not counted in |number_of_channels_in_frame_|.
260 number_of_channels_in_frame_ = GetNumberOfChannelsFromStream();
262 return true;
265 void AUAudioInputStream::Start(AudioInputCallback* callback) {
266 DCHECK(callback);
267 DLOG_IF(ERROR, !audio_unit_) << "Open() has not been called successfully";
268 if (started_ || !audio_unit_)
269 return;
270 sink_ = callback;
271 OSStatus result = AudioOutputUnitStart(audio_unit_);
272 if (result == noErr) {
273 started_ = true;
275 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
276 << "Failed to start acquiring data";
279 void AUAudioInputStream::Stop() {
280 if (!started_)
281 return;
282 OSStatus result = AudioOutputUnitStop(audio_unit_);
283 if (result == noErr) {
284 started_ = false;
286 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
287 << "Failed to stop acquiring data";
290 void AUAudioInputStream::Close() {
291 // It is valid to call Close() before calling open or Start().
292 // It is also valid to call Close() after Start() has been called.
293 if (started_) {
294 Stop();
296 if (audio_unit_) {
297 // Deallocate the audio unit’s resources.
298 AudioUnitUninitialize(audio_unit_);
300 // Terminates our connection to the AUHAL component.
301 CloseComponent(audio_unit_);
302 audio_unit_ = 0;
304 if (sink_) {
305 sink_->OnClose(this);
306 sink_ = NULL;
309 // Inform the audio manager that we have been closed. This can cause our
310 // destruction.
311 manager_->ReleaseInputStream(this);
314 double AUAudioInputStream::GetMaxVolume() {
315 // Verify that we have a valid device.
316 if (input_device_id_ == kAudioObjectUnknown) {
317 NOTREACHED() << "Device ID is unknown";
318 return 0.0;
321 // Query if any of the master, left or right channels has volume control.
322 for (int i = 0; i <= number_of_channels_in_frame_; ++i) {
323 // If the volume is settable, the valid volume range is [0.0, 1.0].
324 if (IsVolumeSettableOnChannel(i))
325 return 1.0;
328 // Volume control is not available for the audio stream.
329 return 0.0;
332 void AUAudioInputStream::SetVolume(double volume) {
333 DVLOG(1) << "SetVolume(volume=" << volume << ")";
334 DCHECK_GE(volume, 0.0);
335 DCHECK_LE(volume, 1.0);
337 // Verify that we have a valid device.
338 if (input_device_id_ == kAudioObjectUnknown) {
339 NOTREACHED() << "Device ID is unknown";
340 return;
343 Float32 volume_float32 = static_cast<Float32>(volume);
344 AudioObjectPropertyAddress property_address = {
345 kAudioDevicePropertyVolumeScalar,
346 kAudioDevicePropertyScopeInput,
347 kAudioObjectPropertyElementMaster
350 // Try to set the volume for master volume channel.
351 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) {
352 OSStatus result = AudioObjectSetPropertyData(input_device_id_,
353 &property_address,
355 NULL,
356 sizeof(volume_float32),
357 &volume_float32);
358 if (result != noErr) {
359 DLOG(WARNING) << "Failed to set volume to " << volume_float32;
361 return;
364 // There is no master volume control, try to set volume for each channel.
365 int successful_channels = 0;
366 for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
367 property_address.mElement = static_cast<UInt32>(i);
368 if (IsVolumeSettableOnChannel(i)) {
369 OSStatus result = AudioObjectSetPropertyData(input_device_id_,
370 &property_address,
372 NULL,
373 sizeof(volume_float32),
374 &volume_float32);
375 if (result == noErr)
376 ++successful_channels;
380 DLOG_IF(WARNING, successful_channels == 0)
381 << "Failed to set volume to " << volume_float32;
383 // Update the AGC volume level based on the last setting above. Note that,
384 // the volume-level resolution is not infinite and it is therefore not
385 // possible to assume that the volume provided as input parameter can be
386 // used directly. Instead, a new query to the audio hardware is required.
387 // This method does nothing if AGC is disabled.
388 UpdateAgcVolume();
391 double AUAudioInputStream::GetVolume() {
392 // Verify that we have a valid device.
393 if (input_device_id_ == kAudioObjectUnknown){
394 NOTREACHED() << "Device ID is unknown";
395 return 0.0;
398 AudioObjectPropertyAddress property_address = {
399 kAudioDevicePropertyVolumeScalar,
400 kAudioDevicePropertyScopeInput,
401 kAudioObjectPropertyElementMaster
404 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
405 // The device supports master volume control, get the volume from the
406 // master channel.
407 Float32 volume_float32 = 0.0;
408 UInt32 size = sizeof(volume_float32);
409 OSStatus result = AudioObjectGetPropertyData(input_device_id_,
410 &property_address,
412 NULL,
413 &size,
414 &volume_float32);
415 if (result == noErr)
416 return static_cast<double>(volume_float32);
417 } else {
418 // There is no master volume control, try to get the average volume of
419 // all the channels.
420 Float32 volume_float32 = 0.0;
421 int successful_channels = 0;
422 for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
423 property_address.mElement = static_cast<UInt32>(i);
424 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
425 Float32 channel_volume = 0;
426 UInt32 size = sizeof(channel_volume);
427 OSStatus result = AudioObjectGetPropertyData(input_device_id_,
428 &property_address,
430 NULL,
431 &size,
432 &channel_volume);
433 if (result == noErr) {
434 volume_float32 += channel_volume;
435 ++successful_channels;
440 // Get the average volume of the channels.
441 if (successful_channels != 0)
442 return static_cast<double>(volume_float32 / successful_channels);
445 DLOG(WARNING) << "Failed to get volume";
446 return 0.0;
449 // AUHAL AudioDeviceOutput unit callback
450 OSStatus AUAudioInputStream::InputProc(void* user_data,
451 AudioUnitRenderActionFlags* flags,
452 const AudioTimeStamp* time_stamp,
453 UInt32 bus_number,
454 UInt32 number_of_frames,
455 AudioBufferList* io_data) {
456 // Verify that the correct bus is used (Input bus/Element 1)
457 DCHECK_EQ(bus_number, static_cast<UInt32>(1));
458 AUAudioInputStream* audio_input =
459 reinterpret_cast<AUAudioInputStream*>(user_data);
460 DCHECK(audio_input);
461 if (!audio_input)
462 return kAudioUnitErr_InvalidElement;
464 // Receive audio from the AUHAL from the output scope of the Audio Unit.
465 OSStatus result = AudioUnitRender(audio_input->audio_unit(),
466 flags,
467 time_stamp,
468 bus_number,
469 number_of_frames,
470 audio_input->audio_buffer_list());
471 if (result)
472 return result;
474 // Deliver recorded data to the consumer as a callback.
475 return audio_input->Provide(number_of_frames,
476 audio_input->audio_buffer_list(),
477 time_stamp);
480 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
481 AudioBufferList* io_data,
482 const AudioTimeStamp* time_stamp) {
483 // Update the capture latency.
484 double capture_latency_frames = GetCaptureLatency(time_stamp);
486 // Update the AGC volume level once every second. Note that, |volume| is
487 // also updated each time SetVolume() is called through IPC by the
488 // render-side AGC.
489 double normalized_volume = 0.0;
490 QueryAgcVolume(&normalized_volume);
492 AudioBuffer& buffer = io_data->mBuffers[0];
493 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
494 uint32 capture_delay_bytes = static_cast<uint32>
495 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame);
496 DCHECK(audio_data);
497 if (!audio_data)
498 return kAudioUnitErr_InvalidElement;
500 // Accumulate captured audio in FIFO until we can match the output size
501 // requested by the client.
502 fifo_->Append(audio_data, buffer.mDataByteSize);
504 // Deliver recorded data to the client as soon as the FIFO contains a
505 // sufficient amount.
506 while (fifo_->forward_bytes() >= requested_size_bytes_) {
507 // Read from FIFO into temporary data buffer.
508 fifo_->Read(data_->GetWritableData(), requested_size_bytes_);
510 // Deliver data packet, delay estimation and volume level to the user.
511 sink_->OnData(this,
512 data_->GetData(),
513 requested_size_bytes_,
514 capture_delay_bytes,
515 normalized_volume);
518 return noErr;
521 int AUAudioInputStream::HardwareSampleRate() {
522 // Determine the default input device's sample-rate.
523 AudioDeviceID device_id = kAudioObjectUnknown;
524 UInt32 info_size = sizeof(device_id);
526 AudioObjectPropertyAddress default_input_device_address = {
527 kAudioHardwarePropertyDefaultInputDevice,
528 kAudioObjectPropertyScopeGlobal,
529 kAudioObjectPropertyElementMaster
531 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
532 &default_input_device_address,
535 &info_size,
536 &device_id);
537 if (result != noErr)
538 return 0.0;
540 Float64 nominal_sample_rate;
541 info_size = sizeof(nominal_sample_rate);
543 AudioObjectPropertyAddress nominal_sample_rate_address = {
544 kAudioDevicePropertyNominalSampleRate,
545 kAudioObjectPropertyScopeGlobal,
546 kAudioObjectPropertyElementMaster
548 result = AudioObjectGetPropertyData(device_id,
549 &nominal_sample_rate_address,
552 &info_size,
553 &nominal_sample_rate);
554 if (result != noErr)
555 return 0.0;
557 return static_cast<int>(nominal_sample_rate);
560 double AUAudioInputStream::GetHardwareLatency() {
561 if (!audio_unit_ || input_device_id_ == kAudioObjectUnknown) {
562 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown";
563 return 0.0;
566 // Get audio unit latency.
567 Float64 audio_unit_latency_sec = 0.0;
568 UInt32 size = sizeof(audio_unit_latency_sec);
569 OSStatus result = AudioUnitGetProperty(audio_unit_,
570 kAudioUnitProperty_Latency,
571 kAudioUnitScope_Global,
573 &audio_unit_latency_sec,
574 &size);
575 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
576 << "Could not get audio unit latency";
578 // Get input audio device latency.
579 AudioObjectPropertyAddress property_address = {
580 kAudioDevicePropertyLatency,
581 kAudioDevicePropertyScopeInput,
582 kAudioObjectPropertyElementMaster
584 UInt32 device_latency_frames = 0;
585 size = sizeof(device_latency_frames);
586 result = AudioObjectGetPropertyData(input_device_id_,
587 &property_address,
589 NULL,
590 &size,
591 &device_latency_frames);
592 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
594 return static_cast<double>((audio_unit_latency_sec *
595 format_.mSampleRate) + device_latency_frames);
598 double AUAudioInputStream::GetCaptureLatency(
599 const AudioTimeStamp* input_time_stamp) {
600 // Get the delay between between the actual recording instant and the time
601 // when the data packet is provided as a callback.
602 UInt64 capture_time_ns = AudioConvertHostTimeToNanos(
603 input_time_stamp->mHostTime);
604 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
605 double delay_frames = static_cast<double>
606 (1e-9 * (now_ns - capture_time_ns) * format_.mSampleRate);
608 // Total latency is composed by the dynamic latency and the fixed
609 // hardware latency.
610 return (delay_frames + hardware_latency_frames_);
613 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
614 // Get the stream format, to be able to read the number of channels.
615 AudioObjectPropertyAddress property_address = {
616 kAudioDevicePropertyStreamFormat,
617 kAudioDevicePropertyScopeInput,
618 kAudioObjectPropertyElementMaster
620 AudioStreamBasicDescription stream_format;
621 UInt32 size = sizeof(stream_format);
622 OSStatus result = AudioObjectGetPropertyData(input_device_id_,
623 &property_address,
625 NULL,
626 &size,
627 &stream_format);
628 if (result != noErr) {
629 DLOG(WARNING) << "Could not get stream format";
630 return 0;
633 return static_cast<int>(stream_format.mChannelsPerFrame);
636 void AUAudioInputStream::HandleError(OSStatus err) {
637 NOTREACHED() << "error " << GetMacOSStatusErrorString(err)
638 << " (" << err << ")";
639 if (sink_)
640 sink_->OnError(this);
643 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) {
644 Boolean is_settable = false;
645 AudioObjectPropertyAddress property_address = {
646 kAudioDevicePropertyVolumeScalar,
647 kAudioDevicePropertyScopeInput,
648 static_cast<UInt32>(channel)
650 OSStatus result = AudioObjectIsPropertySettable(input_device_id_,
651 &property_address,
652 &is_settable);
653 return (result == noErr) ? is_settable : false;
656 } // namespace media