Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: media/audio/mac/audio_low_latency_input_mac.cc

Issue 510073002: Reland 501823002: Used native deinterleaved and float point format for the input streams (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: switched to AudioBus wrapper and fixed Mac ASan 64b bot Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/audio/mac/audio_low_latency_input_mac.h ('k') | media/base/audio_block_fifo.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/mac/audio_low_latency_input_mac.h" 5 #include "media/audio/mac/audio_low_latency_input_mac.h"
6 6
7 #include <CoreServices/CoreServices.h> 7 #include <CoreServices/CoreServices.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/mac/mac_logging.h" 11 #include "base/mac/mac_logging.h"
12 #include "media/audio/mac/audio_manager_mac.h" 12 #include "media/audio/mac/audio_manager_mac.h"
13 #include "media/base/audio_block_fifo.h"
13 #include "media/base/audio_bus.h" 14 #include "media/base/audio_bus.h"
14 #include "media/base/data_buffer.h" 15 #include "media/base/data_buffer.h"
15 16
16 namespace media { 17 namespace media {
17 18
18 // Number of blocks of buffers used in the |fifo_|. 19 // Number of blocks of buffers used in the |fifo_|.
19 const int kNumberOfBlocksBufferInFifo = 2; 20 const int kNumberOfBlocksBufferInFifo = 2;
20 21
21 static std::ostream& operator<<(std::ostream& os, 22 static std::ostream& operator<<(std::ostream& os,
22 const AudioStreamBasicDescription& format) { 23 const AudioStreamBasicDescription& format) {
23 os << "sample rate : " << format.mSampleRate << std::endl 24 os << "sample rate : " << format.mSampleRate << std::endl
24 << "format ID : " << format.mFormatID << std::endl 25 << "format ID : " << format.mFormatID << std::endl
25 << "format flags : " << format.mFormatFlags << std::endl 26 << "format flags : " << format.mFormatFlags << std::endl
26 << "bytes per packet : " << format.mBytesPerPacket << std::endl 27 << "bytes per packet : " << format.mBytesPerPacket << std::endl
27 << "frames per packet : " << format.mFramesPerPacket << std::endl 28 << "frames per packet : " << format.mFramesPerPacket << std::endl
28 << "bytes per frame : " << format.mBytesPerFrame << std::endl 29 << "bytes per frame : " << format.mBytesPerFrame << std::endl
29 << "channels per frame: " << format.mChannelsPerFrame << std::endl 30 << "channels per frame: " << format.mChannelsPerFrame << std::endl
30 << "bits per channel : " << format.mBitsPerChannel; 31 << "bits per channel : " << format.mBitsPerChannel;
31 return os; 32 return os;
32 } 33 }
33 34
35 static void WrapBufferList(AudioBufferList* buffer_list,
36 AudioBus* bus,
37 int frames) {
38 DCHECK(buffer_list);
39 DCHECK(bus);
40 const int channels = bus->channels();
41 const int buffer_list_channels = buffer_list->mNumberBuffers;
42 CHECK_EQ(channels, buffer_list_channels);
43
44 // Copy pointers from AudioBufferList.
45 for (int i = 0; i < channels; ++i)
46 bus->SetChannelData(i, static_cast<float*>(buffer_list->mBuffers[i].mData));
47
48 // Finally set the actual length.
49 bus->set_frames(frames);
50 }
51
34 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" 52 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit"
35 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html 53 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
36 // for more details and background regarding this implementation. 54 // for more details and background regarding this implementation.
37 55
38 AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, 56 AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager,
39 const AudioParameters& input_params, 57 const AudioParameters& input_params,
40 AudioDeviceID audio_device_id) 58 AudioDeviceID audio_device_id)
41 : manager_(manager), 59 : manager_(manager),
42 number_of_frames_(input_params.frames_per_buffer()), 60 number_of_frames_(input_params.frames_per_buffer()),
43 sink_(NULL), 61 sink_(NULL),
44 audio_unit_(0), 62 audio_unit_(0),
45 input_device_id_(audio_device_id), 63 input_device_id_(audio_device_id),
46 started_(false), 64 started_(false),
47 hardware_latency_frames_(0), 65 hardware_latency_frames_(0),
48 number_of_channels_in_frame_(0), 66 number_of_channels_in_frame_(0),
49 fifo_(input_params.channels(), 67 audio_wrapper_(AudioBus::CreateWrapper(input_params.channels())) {
50 number_of_frames_,
51 kNumberOfBlocksBufferInFifo) {
52 DCHECK(manager_); 68 DCHECK(manager_);
53 69
54 // Set up the desired (output) format specified by the client. 70 // Set up the desired (output) format specified by the client.
55 format_.mSampleRate = input_params.sample_rate(); 71 format_.mSampleRate = input_params.sample_rate();
56 format_.mFormatID = kAudioFormatLinearPCM; 72 format_.mFormatID = kAudioFormatLinearPCM;
57 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | 73 format_.mFormatFlags =
58 kLinearPCMFormatFlagIsSignedInteger; 74 kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
59 format_.mBitsPerChannel = input_params.bits_per_sample(); 75 size_t bytes_per_sample = sizeof(Float32);
76 format_.mBitsPerChannel = bytes_per_sample * 8;
60 format_.mChannelsPerFrame = input_params.channels(); 77 format_.mChannelsPerFrame = input_params.channels();
61 format_.mFramesPerPacket = 1; // uncompressed audio 78 format_.mFramesPerPacket = 1;
62 format_.mBytesPerPacket = (format_.mBitsPerChannel * 79 format_.mBytesPerFrame = bytes_per_sample;
63 input_params.channels()) / 8; 80 format_.mBytesPerPacket = format_.mBytesPerFrame * format_.mFramesPerPacket;
64 format_.mBytesPerFrame = format_.mBytesPerPacket;
65 format_.mReserved = 0; 81 format_.mReserved = 0;
66 82
67 DVLOG(1) << "Desired ouput format: " << format_; 83 DVLOG(1) << "Desired ouput format: " << format_;
68 84
69 // Derive size (in bytes) of the buffers that we will render to. 85 // Allocate AudioBufferList based on the number of channels.
70 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame; 86 audio_buffer_list_.reset(static_cast<AudioBufferList*>(
71 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size; 87 malloc(sizeof(AudioBufferList) * input_params.channels())));
DaleCurtis 2014/08/27 20:22:52 This will oversize the buffer slightly, but should
no longer working on chromium 2014/08/28 16:12:20 Thanks, I read this, and decided to go for the exi
88 audio_buffer_list_->mNumberBuffers = input_params.channels();
72 89
73 // Allocate AudioBuffers to be used as storage for the received audio. 90 // Allocate AudioBuffers to be used as storage for the received audio.
74 // The AudioBufferList structure works as a placeholder for the 91 // The AudioBufferList structure works as a placeholder for the
75 // AudioBuffer structure, which holds a pointer to the actual data buffer. 92 // AudioBuffer structure, which holds a pointer to the actual data buffer.
76 audio_data_buffer_.reset(new uint8[data_byte_size]); 93 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame;
77 audio_buffer_list_.mNumberBuffers = 1; 94 audio_data_buffer_.reset(static_cast<uint8*>(base::AlignedAlloc(
78 95 data_byte_size, AudioBus::kChannelAlignment)));
79 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers; 96 CHECK_LE(static_cast<int>(data_byte_size * input_params.channels()),
80 audio_buffer->mNumberChannels = input_params.channels(); 97 media::AudioBus::CalculateMemorySize(input_params));
81 audio_buffer->mDataByteSize = data_byte_size; 98 AudioBuffer* audio_buffer = audio_buffer_list_->mBuffers;
82 audio_buffer->mData = audio_data_buffer_.get(); 99 for (UInt32 i = 0; i < audio_buffer_list_->mNumberBuffers; ++i) {
100 audio_buffer[i].mNumberChannels = 1;
101 audio_buffer[i].mDataByteSize = data_byte_size;
102 audio_buffer[i].mData = audio_data_buffer_.get() + i * data_byte_size;
103 }
83 } 104 }
84 105
85 AUAudioInputStream::~AUAudioInputStream() {} 106 AUAudioInputStream::~AUAudioInputStream() {
107 }
86 108
87 // Obtain and open the AUHAL AudioOutputUnit for recording. 109 // Obtain and open the AUHAL AudioOutputUnit for recording.
88 bool AUAudioInputStream::Open() { 110 bool AUAudioInputStream::Open() {
89 // Verify that we are not already opened. 111 // Verify that we are not already opened.
90 if (audio_unit_) 112 if (audio_unit_)
91 return false; 113 return false;
92 114
93 // Verify that we have a valid device. 115 // Verify that we have a valid device.
94 if (input_device_id_ == kAudioObjectUnknown) { 116 if (input_device_id_ == kAudioObjectUnknown) {
95 NOTREACHED() << "Device ID is unknown"; 117 NOTREACHED() << "Device ID is unknown";
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 kAudioOutputUnitProperty_CurrentDevice, 180 kAudioOutputUnitProperty_CurrentDevice,
159 kAudioUnitScope_Global, 181 kAudioUnitScope_Global,
160 0, 182 0,
161 &input_device_id_, 183 &input_device_id_,
162 sizeof(input_device_id_)); 184 sizeof(input_device_id_));
163 if (result) { 185 if (result) {
164 HandleError(result); 186 HandleError(result);
165 return false; 187 return false;
166 } 188 }
167 189
168 // Register the input procedure for the AUHAL.
169 // This procedure will be called when the AUHAL has received new data
170 // from the input device.
171 AURenderCallbackStruct callback;
172 callback.inputProc = InputProc;
173 callback.inputProcRefCon = this;
174 result = AudioUnitSetProperty(audio_unit_,
175 kAudioOutputUnitProperty_SetInputCallback,
176 kAudioUnitScope_Global,
177 0,
178 &callback,
179 sizeof(callback));
180 if (result) {
181 HandleError(result);
182 return false;
183 }
184
185 // Set up the the desired (output) format. 190 // Set up the the desired (output) format.
186 // For obtaining input from a device, the device format is always expressed 191 // For obtaining input from a device, the device format is always expressed
187 // on the output scope of the AUHAL's Element 1. 192 // on the output scope of the AUHAL's Element 1.
188 result = AudioUnitSetProperty(audio_unit_, 193 result = AudioUnitSetProperty(audio_unit_,
189 kAudioUnitProperty_StreamFormat, 194 kAudioUnitProperty_StreamFormat,
190 kAudioUnitScope_Output, 195 kAudioUnitScope_Output,
191 1, 196 1,
192 &format_, 197 &format_,
193 sizeof(format_)); 198 sizeof(format_));
194 if (result) { 199 if (result) {
(...skipping 27 matching lines...) Expand all
222 kAudioUnitScope_Output, 227 kAudioUnitScope_Output,
223 1, 228 1,
224 &buffer_size, 229 &buffer_size,
225 sizeof(buffer_size)); 230 sizeof(buffer_size));
226 if (result != noErr) { 231 if (result != noErr) {
227 HandleError(result); 232 HandleError(result);
228 return false; 233 return false;
229 } 234 }
230 } 235 }
231 236
237 // Register the input procedure for the AUHAL.
238 // This procedure will be called when the AUHAL has received new data
239 // from the input device.
240 AURenderCallbackStruct callback;
241 callback.inputProc = InputProc;
242 callback.inputProcRefCon = this;
243 result = AudioUnitSetProperty(audio_unit_,
244 kAudioOutputUnitProperty_SetInputCallback,
245 kAudioUnitScope_Global,
246 0,
247 &callback,
248 sizeof(callback));
249 if (result) {
250 HandleError(result);
251 return false;
252 }
253
232 // Finally, initialize the audio unit and ensure that it is ready to render. 254 // Finally, initialize the audio unit and ensure that it is ready to render.
233 // Allocates memory according to the maximum number of audio frames 255 // Allocates memory according to the maximum number of audio frames
234 // it can produce in response to a single render call. 256 // it can produce in response to a single render call.
235 result = AudioUnitInitialize(audio_unit_); 257 result = AudioUnitInitialize(audio_unit_);
236 if (result) { 258 if (result) {
237 HandleError(result); 259 HandleError(result);
238 return false; 260 return false;
239 } 261 }
240 262
241 // The hardware latency is fixed and will not change during the call. 263 // The hardware latency is fixed and will not change during the call.
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 DCHECK_LE(volume, 1.0); 357 DCHECK_LE(volume, 1.0);
336 358
337 // Verify that we have a valid device. 359 // Verify that we have a valid device.
338 if (input_device_id_ == kAudioObjectUnknown) { 360 if (input_device_id_ == kAudioObjectUnknown) {
339 NOTREACHED() << "Device ID is unknown"; 361 NOTREACHED() << "Device ID is unknown";
340 return; 362 return;
341 } 363 }
342 364
343 Float32 volume_float32 = static_cast<Float32>(volume); 365 Float32 volume_float32 = static_cast<Float32>(volume);
344 AudioObjectPropertyAddress property_address = { 366 AudioObjectPropertyAddress property_address = {
345 kAudioDevicePropertyVolumeScalar, 367 kAudioDevicePropertyVolumeScalar,
346 kAudioDevicePropertyScopeInput, 368 kAudioDevicePropertyScopeInput,
347 kAudioObjectPropertyElementMaster 369 kAudioObjectPropertyElementMaster
348 }; 370 };
349 371
350 // Try to set the volume for master volume channel. 372 // Try to set the volume for master volume channel.
351 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) { 373 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) {
352 OSStatus result = AudioObjectSetPropertyData(input_device_id_, 374 OSStatus result = AudioObjectSetPropertyData(input_device_id_,
353 &property_address, 375 &property_address,
354 0, 376 0,
355 NULL, 377 NULL,
356 sizeof(volume_float32), 378 sizeof(volume_float32),
357 &volume_float32); 379 &volume_float32);
(...skipping 25 matching lines...) Expand all
383 // Update the AGC volume level based on the last setting above. Note that, 405 // 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 406 // 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 407 // 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. 408 // used directly. Instead, a new query to the audio hardware is required.
387 // This method does nothing if AGC is disabled. 409 // This method does nothing if AGC is disabled.
388 UpdateAgcVolume(); 410 UpdateAgcVolume();
389 } 411 }
390 412
391 double AUAudioInputStream::GetVolume() { 413 double AUAudioInputStream::GetVolume() {
392 // Verify that we have a valid device. 414 // Verify that we have a valid device.
393 if (input_device_id_ == kAudioObjectUnknown){ 415 if (input_device_id_ == kAudioObjectUnknown) {
394 NOTREACHED() << "Device ID is unknown"; 416 NOTREACHED() << "Device ID is unknown";
395 return 0.0; 417 return 0.0;
396 } 418 }
397 419
398 AudioObjectPropertyAddress property_address = { 420 AudioObjectPropertyAddress property_address = {
399 kAudioDevicePropertyVolumeScalar, 421 kAudioDevicePropertyVolumeScalar,
400 kAudioDevicePropertyScopeInput, 422 kAudioDevicePropertyScopeInput,
401 kAudioObjectPropertyElementMaster 423 kAudioObjectPropertyElementMaster
402 }; 424 };
403 425
404 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 426 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
405 // The device supports master volume control, get the volume from the 427 // The device supports master volume control, get the volume from the
406 // master channel. 428 // master channel.
407 Float32 volume_float32 = 0.0; 429 Float32 volume_float32 = 0.0;
408 UInt32 size = sizeof(volume_float32); 430 UInt32 size = sizeof(volume_float32);
409 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 431 OSStatus result = AudioObjectGetPropertyData(
410 &property_address, 432 input_device_id_, &property_address, 0, NULL, &size, &volume_float32);
411 0,
412 NULL,
413 &size,
414 &volume_float32);
415 if (result == noErr) 433 if (result == noErr)
416 return static_cast<double>(volume_float32); 434 return static_cast<double>(volume_float32);
417 } else { 435 } else {
418 // There is no master volume control, try to get the average volume of 436 // There is no master volume control, try to get the average volume of
419 // all the channels. 437 // all the channels.
420 Float32 volume_float32 = 0.0; 438 Float32 volume_float32 = 0.0;
421 int successful_channels = 0; 439 int successful_channels = 0;
422 for (int i = 1; i <= number_of_channels_in_frame_; ++i) { 440 for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
423 property_address.mElement = static_cast<UInt32>(i); 441 property_address.mElement = static_cast<UInt32>(i);
424 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 442 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 OSStatus result = AudioUnitRender(audio_input->audio_unit(), 483 OSStatus result = AudioUnitRender(audio_input->audio_unit(),
466 flags, 484 flags,
467 time_stamp, 485 time_stamp,
468 bus_number, 486 bus_number,
469 number_of_frames, 487 number_of_frames,
470 audio_input->audio_buffer_list()); 488 audio_input->audio_buffer_list());
471 if (result) 489 if (result)
472 return result; 490 return result;
473 491
474 // Deliver recorded data to the consumer as a callback. 492 // Deliver recorded data to the consumer as a callback.
475 return audio_input->Provide(number_of_frames, 493 return audio_input->Provide(
476 audio_input->audio_buffer_list(), 494 number_of_frames, audio_input->audio_buffer_list(), time_stamp);
477 time_stamp);
478 } 495 }
479 496
480 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, 497 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
481 AudioBufferList* io_data, 498 AudioBufferList* io_data,
482 const AudioTimeStamp* time_stamp) { 499 const AudioTimeStamp* time_stamp) {
483 // Update the capture latency. 500 // Update the capture latency.
484 double capture_latency_frames = GetCaptureLatency(time_stamp); 501 double capture_latency_frames = GetCaptureLatency(time_stamp);
485 502
486 // The AGC volume level is updated once every second on a separate thread. 503 // The AGC volume level is updated once every second on a separate thread.
487 // Note that, |volume| is also updated each time SetVolume() is called 504 // Note that, |volume| is also updated each time SetVolume() is called
488 // through IPC by the render-side AGC. 505 // through IPC by the render-side AGC.
489 double normalized_volume = 0.0; 506 double normalized_volume = 0.0;
490 GetAgcVolume(&normalized_volume); 507 GetAgcVolume(&normalized_volume);
491 508
492 AudioBuffer& buffer = io_data->mBuffers[0]; 509 AudioBuffer& buffer = io_data->mBuffers[0];
493 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); 510 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
494 uint32 capture_delay_bytes = static_cast<uint32> 511 uint32 capture_delay_bytes = static_cast<uint32>(
495 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); 512 (capture_latency_frames + 0.5) * format_.mBytesPerFrame);
496 DCHECK(audio_data); 513 DCHECK(audio_data);
497 if (!audio_data) 514 if (!audio_data)
498 return kAudioUnitErr_InvalidElement; 515 return kAudioUnitErr_InvalidElement;
499 516
500 // Copy captured (and interleaved) data into FIFO. 517 // Wrap the output AudioBufferList to |audio_wrapper_|.
501 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 518 WrapBufferList(io_data, audio_wrapper_.get(), number_of_frames);
502 519
520 // If the stream parameters change for any reason, we need to insert a FIFO
521 // since the OnMoreData() pipeline can't handle frame size changes.
522 if (number_of_frames != number_of_frames_) {
523 // Create a FIFO on the fly to handle any discrepancies in callback rates.
524 if (!fifo_) {
525 fifo_.reset(new AudioBlockFifo(audio_wrapper_->channels(),
526 number_of_frames_,
527 kNumberOfBlocksBufferInFifo));
528 }
529 }
530
531 // When FIFO does not kick in, data will be directly passed to the callback.
532 if (!fifo_) {
533 CHECK_EQ(audio_wrapper_->frames(), static_cast<int>(number_of_frames_));
534 sink_->OnData(
535 this, audio_wrapper_.get(), capture_delay_bytes, normalized_volume);
536 return noErr;
537 }
538
539 // Compensate the audio delay caused by the FIFO.
540 capture_delay_bytes += fifo_->GetAvailableFrames() * format_.mBytesPerFrame;
541
542 fifo_->Push(audio_wrapper_.get());
503 // Consume and deliver the data when the FIFO has a block of available data. 543 // Consume and deliver the data when the FIFO has a block of available data.
504 while (fifo_.available_blocks()) { 544 while (fifo_->available_blocks()) {
505 const AudioBus* audio_bus = fifo_.Consume(); 545 const AudioBus* audio_bus = fifo_->Consume();
506 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 546 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_));
507
508 // Compensate the audio delay caused by the FIFO.
509 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame;
510 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume); 547 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume);
511 } 548 }
512 549
513 return noErr; 550 return noErr;
514 } 551 }
515 552
516 int AUAudioInputStream::HardwareSampleRate() { 553 int AUAudioInputStream::HardwareSampleRate() {
517 // Determine the default input device's sample-rate. 554 // Determine the default input device's sample-rate.
518 AudioDeviceID device_id = kAudioObjectUnknown; 555 AudioDeviceID device_id = kAudioObjectUnknown;
519 UInt32 info_size = sizeof(device_id); 556 UInt32 info_size = sizeof(device_id);
520 557
521 AudioObjectPropertyAddress default_input_device_address = { 558 AudioObjectPropertyAddress default_input_device_address = {
522 kAudioHardwarePropertyDefaultInputDevice, 559 kAudioHardwarePropertyDefaultInputDevice,
523 kAudioObjectPropertyScopeGlobal, 560 kAudioObjectPropertyScopeGlobal,
524 kAudioObjectPropertyElementMaster 561 kAudioObjectPropertyElementMaster
525 }; 562 };
526 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, 563 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
527 &default_input_device_address, 564 &default_input_device_address,
528 0, 565 0,
529 0, 566 0,
530 &info_size, 567 &info_size,
531 &device_id); 568 &device_id);
532 if (result != noErr) 569 if (result != noErr)
533 return 0.0; 570 return 0.0;
534 571
535 Float64 nominal_sample_rate; 572 Float64 nominal_sample_rate;
536 info_size = sizeof(nominal_sample_rate); 573 info_size = sizeof(nominal_sample_rate);
537 574
538 AudioObjectPropertyAddress nominal_sample_rate_address = { 575 AudioObjectPropertyAddress nominal_sample_rate_address = {
539 kAudioDevicePropertyNominalSampleRate, 576 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
540 kAudioObjectPropertyScopeGlobal, 577 kAudioObjectPropertyElementMaster};
541 kAudioObjectPropertyElementMaster
542 };
543 result = AudioObjectGetPropertyData(device_id, 578 result = AudioObjectGetPropertyData(device_id,
544 &nominal_sample_rate_address, 579 &nominal_sample_rate_address,
545 0, 580 0,
546 0, 581 0,
547 &info_size, 582 &info_size,
548 &nominal_sample_rate); 583 &nominal_sample_rate);
549 if (result != noErr) 584 if (result != noErr)
550 return 0.0; 585 return 0.0;
551 586
552 return static_cast<int>(nominal_sample_rate); 587 return static_cast<int>(nominal_sample_rate);
(...skipping 12 matching lines...) Expand all
565 kAudioUnitProperty_Latency, 600 kAudioUnitProperty_Latency,
566 kAudioUnitScope_Global, 601 kAudioUnitScope_Global,
567 0, 602 0,
568 &audio_unit_latency_sec, 603 &audio_unit_latency_sec,
569 &size); 604 &size);
570 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) 605 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
571 << "Could not get audio unit latency"; 606 << "Could not get audio unit latency";
572 607
573 // Get input audio device latency. 608 // Get input audio device latency.
574 AudioObjectPropertyAddress property_address = { 609 AudioObjectPropertyAddress property_address = {
575 kAudioDevicePropertyLatency, 610 kAudioDevicePropertyLatency,
576 kAudioDevicePropertyScopeInput, 611 kAudioDevicePropertyScopeInput,
577 kAudioObjectPropertyElementMaster 612 kAudioObjectPropertyElementMaster
578 }; 613 };
579 UInt32 device_latency_frames = 0; 614 UInt32 device_latency_frames = 0;
580 size = sizeof(device_latency_frames); 615 size = sizeof(device_latency_frames);
581 result = AudioObjectGetPropertyData(input_device_id_, 616 result = AudioObjectGetPropertyData(input_device_id_,
582 &property_address, 617 &property_address,
583 0, 618 0,
584 NULL, 619 NULL,
585 &size, 620 &size,
586 &device_latency_frames); 621 &device_latency_frames);
587 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; 622 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
588 623
589 return static_cast<double>((audio_unit_latency_sec * 624 return static_cast<double>((audio_unit_latency_sec * format_.mSampleRate) +
590 format_.mSampleRate) + device_latency_frames); 625 device_latency_frames);
591 } 626 }
592 627
593 double AUAudioInputStream::GetCaptureLatency( 628 double AUAudioInputStream::GetCaptureLatency(
594 const AudioTimeStamp* input_time_stamp) { 629 const AudioTimeStamp* input_time_stamp) {
595 // Get the delay between between the actual recording instant and the time 630 // Get the delay between between the actual recording instant and the time
596 // when the data packet is provided as a callback. 631 // when the data packet is provided as a callback.
597 UInt64 capture_time_ns = AudioConvertHostTimeToNanos( 632 UInt64 capture_time_ns =
598 input_time_stamp->mHostTime); 633 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime);
599 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 634 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
600 double delay_frames = static_cast<double> 635 double delay_frames = static_cast<double>(1e-9 * (now_ns - capture_time_ns) *
601 (1e-9 * (now_ns - capture_time_ns) * format_.mSampleRate); 636 format_.mSampleRate);
602 637
603 // Total latency is composed by the dynamic latency and the fixed 638 // Total latency is composed by the dynamic latency and the fixed
604 // hardware latency. 639 // hardware latency.
605 return (delay_frames + hardware_latency_frames_); 640 return (delay_frames + hardware_latency_frames_);
606 } 641 }
607 642
608 int AUAudioInputStream::GetNumberOfChannelsFromStream() { 643 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
609 // Get the stream format, to be able to read the number of channels. 644 // Get the stream format, to be able to read the number of channels.
610 AudioObjectPropertyAddress property_address = { 645 AudioObjectPropertyAddress property_address = {
611 kAudioDevicePropertyStreamFormat, 646 kAudioDevicePropertyStreamFormat,
612 kAudioDevicePropertyScopeInput, 647 kAudioDevicePropertyScopeInput,
613 kAudioObjectPropertyElementMaster 648 kAudioObjectPropertyElementMaster
614 }; 649 };
615 AudioStreamBasicDescription stream_format; 650 AudioStreamBasicDescription stream_format;
616 UInt32 size = sizeof(stream_format); 651 UInt32 size = sizeof(stream_format);
617 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 652 OSStatus result = AudioObjectGetPropertyData(
618 &property_address, 653 input_device_id_, &property_address, 0, NULL, &size, &stream_format);
619 0,
620 NULL,
621 &size,
622 &stream_format);
623 if (result != noErr) { 654 if (result != noErr) {
624 DLOG(WARNING) << "Could not get stream format"; 655 DLOG(WARNING) << "Could not get stream format";
625 return 0; 656 return 0;
626 } 657 }
627 658
628 return static_cast<int>(stream_format.mChannelsPerFrame); 659 return static_cast<int>(stream_format.mChannelsPerFrame);
629 } 660 }
630 661
631 void AUAudioInputStream::HandleError(OSStatus err) { 662 void AUAudioInputStream::HandleError(OSStatus err) {
632 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) 663 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) << " (" << err
633 << " (" << err << ")"; 664 << ")";
634 if (sink_) 665 if (sink_)
635 sink_->OnError(this); 666 sink_->OnError(this);
636 } 667 }
637 668
638 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) { 669 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) {
639 Boolean is_settable = false; 670 Boolean is_settable = false;
640 AudioObjectPropertyAddress property_address = { 671 AudioObjectPropertyAddress property_address = {
641 kAudioDevicePropertyVolumeScalar, 672 kAudioDevicePropertyVolumeScalar,
642 kAudioDevicePropertyScopeInput, 673 kAudioDevicePropertyScopeInput,
643 static_cast<UInt32>(channel) 674 static_cast<UInt32>(channel)
644 }; 675 };
645 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, 676 OSStatus result = AudioObjectIsPropertySettable(
646 &property_address, 677 input_device_id_, &property_address, &is_settable);
647 &is_settable);
648 return (result == noErr) ? is_settable : false; 678 return (result == noErr) ? is_settable : false;
649 } 679 }
650 680
651 } // namespace media 681 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_low_latency_input_mac.h ('k') | media/base/audio_block_fifo.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698