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

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: uint8 -> float 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())));
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<float*>(base::AlignedAlloc(
78 95 data_byte_size * audio_buffer_list_->mNumberBuffers,
79 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers; 96 AudioBus::kChannelAlignment)));
80 audio_buffer->mNumberChannels = input_params.channels(); 97 AudioBuffer* audio_buffer = audio_buffer_list_->mBuffers;
81 audio_buffer->mDataByteSize = data_byte_size; 98 for (UInt32 i = 0; i < audio_buffer_list_->mNumberBuffers; ++i) {
82 audio_buffer->mData = audio_data_buffer_.get(); 99 audio_buffer[i].mNumberChannels = 1;
100 audio_buffer[i].mDataByteSize = data_byte_size;
101 audio_buffer[i].mData = audio_data_buffer_.get() + i * data_byte_size;
102 }
83 } 103 }
84 104
85 AUAudioInputStream::~AUAudioInputStream() {} 105 AUAudioInputStream::~AUAudioInputStream() {
106 }
86 107
87 // Obtain and open the AUHAL AudioOutputUnit for recording. 108 // Obtain and open the AUHAL AudioOutputUnit for recording.
88 bool AUAudioInputStream::Open() { 109 bool AUAudioInputStream::Open() {
89 // Verify that we are not already opened. 110 // Verify that we are not already opened.
90 if (audio_unit_) 111 if (audio_unit_)
91 return false; 112 return false;
92 113
93 // Verify that we have a valid device. 114 // Verify that we have a valid device.
94 if (input_device_id_ == kAudioObjectUnknown) { 115 if (input_device_id_ == kAudioObjectUnknown) {
95 NOTREACHED() << "Device ID is unknown"; 116 NOTREACHED() << "Device ID is unknown";
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 kAudioOutputUnitProperty_CurrentDevice, 179 kAudioOutputUnitProperty_CurrentDevice,
159 kAudioUnitScope_Global, 180 kAudioUnitScope_Global,
160 0, 181 0,
161 &input_device_id_, 182 &input_device_id_,
162 sizeof(input_device_id_)); 183 sizeof(input_device_id_));
163 if (result) { 184 if (result) {
164 HandleError(result); 185 HandleError(result);
165 return false; 186 return false;
166 } 187 }
167 188
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. 189 // Set up the the desired (output) format.
186 // For obtaining input from a device, the device format is always expressed 190 // For obtaining input from a device, the device format is always expressed
187 // on the output scope of the AUHAL's Element 1. 191 // on the output scope of the AUHAL's Element 1.
188 result = AudioUnitSetProperty(audio_unit_, 192 result = AudioUnitSetProperty(audio_unit_,
189 kAudioUnitProperty_StreamFormat, 193 kAudioUnitProperty_StreamFormat,
190 kAudioUnitScope_Output, 194 kAudioUnitScope_Output,
191 1, 195 1,
192 &format_, 196 &format_,
193 sizeof(format_)); 197 sizeof(format_));
194 if (result) { 198 if (result) {
(...skipping 27 matching lines...) Expand all
222 kAudioUnitScope_Output, 226 kAudioUnitScope_Output,
223 1, 227 1,
224 &buffer_size, 228 &buffer_size,
225 sizeof(buffer_size)); 229 sizeof(buffer_size));
226 if (result != noErr) { 230 if (result != noErr) {
227 HandleError(result); 231 HandleError(result);
228 return false; 232 return false;
229 } 233 }
230 } 234 }
231 235
236 // Register the input procedure for the AUHAL.
237 // This procedure will be called when the AUHAL has received new data
238 // from the input device.
239 AURenderCallbackStruct callback;
240 callback.inputProc = InputProc;
241 callback.inputProcRefCon = this;
242 result = AudioUnitSetProperty(audio_unit_,
243 kAudioOutputUnitProperty_SetInputCallback,
244 kAudioUnitScope_Global,
245 0,
246 &callback,
247 sizeof(callback));
248 if (result) {
249 HandleError(result);
250 return false;
251 }
252
232 // Finally, initialize the audio unit and ensure that it is ready to render. 253 // Finally, initialize the audio unit and ensure that it is ready to render.
233 // Allocates memory according to the maximum number of audio frames 254 // Allocates memory according to the maximum number of audio frames
234 // it can produce in response to a single render call. 255 // it can produce in response to a single render call.
235 result = AudioUnitInitialize(audio_unit_); 256 result = AudioUnitInitialize(audio_unit_);
236 if (result) { 257 if (result) {
237 HandleError(result); 258 HandleError(result);
238 return false; 259 return false;
239 } 260 }
240 261
241 // The hardware latency is fixed and will not change during the call. 262 // 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); 356 DCHECK_LE(volume, 1.0);
336 357
337 // Verify that we have a valid device. 358 // Verify that we have a valid device.
338 if (input_device_id_ == kAudioObjectUnknown) { 359 if (input_device_id_ == kAudioObjectUnknown) {
339 NOTREACHED() << "Device ID is unknown"; 360 NOTREACHED() << "Device ID is unknown";
340 return; 361 return;
341 } 362 }
342 363
343 Float32 volume_float32 = static_cast<Float32>(volume); 364 Float32 volume_float32 = static_cast<Float32>(volume);
344 AudioObjectPropertyAddress property_address = { 365 AudioObjectPropertyAddress property_address = {
345 kAudioDevicePropertyVolumeScalar, 366 kAudioDevicePropertyVolumeScalar,
346 kAudioDevicePropertyScopeInput, 367 kAudioDevicePropertyScopeInput,
347 kAudioObjectPropertyElementMaster 368 kAudioObjectPropertyElementMaster
348 }; 369 };
349 370
350 // Try to set the volume for master volume channel. 371 // Try to set the volume for master volume channel.
351 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) { 372 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) {
352 OSStatus result = AudioObjectSetPropertyData(input_device_id_, 373 OSStatus result = AudioObjectSetPropertyData(input_device_id_,
353 &property_address, 374 &property_address,
354 0, 375 0,
355 NULL, 376 NULL,
356 sizeof(volume_float32), 377 sizeof(volume_float32),
357 &volume_float32); 378 &volume_float32);
(...skipping 25 matching lines...) Expand all
383 // Update the AGC volume level based on the last setting above. Note that, 404 // 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 405 // 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 406 // 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. 407 // used directly. Instead, a new query to the audio hardware is required.
387 // This method does nothing if AGC is disabled. 408 // This method does nothing if AGC is disabled.
388 UpdateAgcVolume(); 409 UpdateAgcVolume();
389 } 410 }
390 411
391 double AUAudioInputStream::GetVolume() { 412 double AUAudioInputStream::GetVolume() {
392 // Verify that we have a valid device. 413 // Verify that we have a valid device.
393 if (input_device_id_ == kAudioObjectUnknown){ 414 if (input_device_id_ == kAudioObjectUnknown) {
394 NOTREACHED() << "Device ID is unknown"; 415 NOTREACHED() << "Device ID is unknown";
395 return 0.0; 416 return 0.0;
396 } 417 }
397 418
398 AudioObjectPropertyAddress property_address = { 419 AudioObjectPropertyAddress property_address = {
399 kAudioDevicePropertyVolumeScalar, 420 kAudioDevicePropertyVolumeScalar,
400 kAudioDevicePropertyScopeInput, 421 kAudioDevicePropertyScopeInput,
401 kAudioObjectPropertyElementMaster 422 kAudioObjectPropertyElementMaster
402 }; 423 };
403 424
404 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 425 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
405 // The device supports master volume control, get the volume from the 426 // The device supports master volume control, get the volume from the
406 // master channel. 427 // master channel.
407 Float32 volume_float32 = 0.0; 428 Float32 volume_float32 = 0.0;
408 UInt32 size = sizeof(volume_float32); 429 UInt32 size = sizeof(volume_float32);
409 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 430 OSStatus result = AudioObjectGetPropertyData(
410 &property_address, 431 input_device_id_, &property_address, 0, NULL, &size, &volume_float32);
411 0,
412 NULL,
413 &size,
414 &volume_float32);
415 if (result == noErr) 432 if (result == noErr)
416 return static_cast<double>(volume_float32); 433 return static_cast<double>(volume_float32);
417 } else { 434 } else {
418 // There is no master volume control, try to get the average volume of 435 // There is no master volume control, try to get the average volume of
419 // all the channels. 436 // all the channels.
420 Float32 volume_float32 = 0.0; 437 Float32 volume_float32 = 0.0;
421 int successful_channels = 0; 438 int successful_channels = 0;
422 for (int i = 1; i <= number_of_channels_in_frame_; ++i) { 439 for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
423 property_address.mElement = static_cast<UInt32>(i); 440 property_address.mElement = static_cast<UInt32>(i);
424 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 441 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(), 482 OSStatus result = AudioUnitRender(audio_input->audio_unit(),
466 flags, 483 flags,
467 time_stamp, 484 time_stamp,
468 bus_number, 485 bus_number,
469 number_of_frames, 486 number_of_frames,
470 audio_input->audio_buffer_list()); 487 audio_input->audio_buffer_list());
471 if (result) 488 if (result)
472 return result; 489 return result;
473 490
474 // Deliver recorded data to the consumer as a callback. 491 // Deliver recorded data to the consumer as a callback.
475 return audio_input->Provide(number_of_frames, 492 return audio_input->Provide(
476 audio_input->audio_buffer_list(), 493 number_of_frames, audio_input->audio_buffer_list(), time_stamp);
477 time_stamp);
478 } 494 }
479 495
480 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, 496 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
481 AudioBufferList* io_data, 497 AudioBufferList* io_data,
482 const AudioTimeStamp* time_stamp) { 498 const AudioTimeStamp* time_stamp) {
483 // Update the capture latency. 499 // Update the capture latency.
484 double capture_latency_frames = GetCaptureLatency(time_stamp); 500 double capture_latency_frames = GetCaptureLatency(time_stamp);
485 501
486 // The AGC volume level is updated once every second on a separate thread. 502 // 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 503 // Note that, |volume| is also updated each time SetVolume() is called
488 // through IPC by the render-side AGC. 504 // through IPC by the render-side AGC.
489 double normalized_volume = 0.0; 505 double normalized_volume = 0.0;
490 GetAgcVolume(&normalized_volume); 506 GetAgcVolume(&normalized_volume);
491 507
492 AudioBuffer& buffer = io_data->mBuffers[0]; 508 AudioBuffer& buffer = io_data->mBuffers[0];
493 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); 509 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
494 uint32 capture_delay_bytes = static_cast<uint32> 510 uint32 capture_delay_bytes = static_cast<uint32>(
495 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); 511 (capture_latency_frames + 0.5) * format_.mBytesPerFrame);
496 DCHECK(audio_data); 512 DCHECK(audio_data);
497 if (!audio_data) 513 if (!audio_data)
498 return kAudioUnitErr_InvalidElement; 514 return kAudioUnitErr_InvalidElement;
499 515
500 // Copy captured (and interleaved) data into FIFO. 516 // Wrap the output AudioBufferList to |audio_wrapper_|.
501 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 517 WrapBufferList(io_data, audio_wrapper_.get(), number_of_frames);
502 518
519 // If the stream parameters change for any reason, we need to insert a FIFO
520 // since the OnMoreData() pipeline can't handle frame size changes.
521 if (number_of_frames != number_of_frames_) {
522 // Create a FIFO on the fly to handle any discrepancies in callback rates.
523 if (!fifo_) {
524 fifo_.reset(new AudioBlockFifo(audio_wrapper_->channels(),
525 number_of_frames_,
526 kNumberOfBlocksBufferInFifo));
527 }
528 }
529
530 // When FIFO does not kick in, data will be directly passed to the callback.
531 if (!fifo_) {
532 CHECK_EQ(audio_wrapper_->frames(), static_cast<int>(number_of_frames_));
533 sink_->OnData(
534 this, audio_wrapper_.get(), capture_delay_bytes, normalized_volume);
535 return noErr;
536 }
537
538 // Compensate the audio delay caused by the FIFO.
539 capture_delay_bytes += fifo_->GetAvailableFrames() * format_.mBytesPerFrame;
540
541 fifo_->Push(audio_wrapper_.get());
503 // Consume and deliver the data when the FIFO has a block of available data. 542 // Consume and deliver the data when the FIFO has a block of available data.
504 while (fifo_.available_blocks()) { 543 while (fifo_->available_blocks()) {
505 const AudioBus* audio_bus = fifo_.Consume(); 544 const AudioBus* audio_bus = fifo_->Consume();
506 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 545 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); 546 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume);
511 } 547 }
512 548
513 return noErr; 549 return noErr;
514 } 550 }
515 551
516 int AUAudioInputStream::HardwareSampleRate() { 552 int AUAudioInputStream::HardwareSampleRate() {
517 // Determine the default input device's sample-rate. 553 // Determine the default input device's sample-rate.
518 AudioDeviceID device_id = kAudioObjectUnknown; 554 AudioDeviceID device_id = kAudioObjectUnknown;
519 UInt32 info_size = sizeof(device_id); 555 UInt32 info_size = sizeof(device_id);
520 556
521 AudioObjectPropertyAddress default_input_device_address = { 557 AudioObjectPropertyAddress default_input_device_address = {
522 kAudioHardwarePropertyDefaultInputDevice, 558 kAudioHardwarePropertyDefaultInputDevice,
523 kAudioObjectPropertyScopeGlobal, 559 kAudioObjectPropertyScopeGlobal,
524 kAudioObjectPropertyElementMaster 560 kAudioObjectPropertyElementMaster
525 }; 561 };
526 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, 562 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
527 &default_input_device_address, 563 &default_input_device_address,
528 0, 564 0,
529 0, 565 0,
530 &info_size, 566 &info_size,
531 &device_id); 567 &device_id);
532 if (result != noErr) 568 if (result != noErr)
533 return 0.0; 569 return 0.0;
534 570
535 Float64 nominal_sample_rate; 571 Float64 nominal_sample_rate;
536 info_size = sizeof(nominal_sample_rate); 572 info_size = sizeof(nominal_sample_rate);
537 573
538 AudioObjectPropertyAddress nominal_sample_rate_address = { 574 AudioObjectPropertyAddress nominal_sample_rate_address = {
539 kAudioDevicePropertyNominalSampleRate, 575 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
540 kAudioObjectPropertyScopeGlobal, 576 kAudioObjectPropertyElementMaster};
541 kAudioObjectPropertyElementMaster
542 };
543 result = AudioObjectGetPropertyData(device_id, 577 result = AudioObjectGetPropertyData(device_id,
544 &nominal_sample_rate_address, 578 &nominal_sample_rate_address,
545 0, 579 0,
546 0, 580 0,
547 &info_size, 581 &info_size,
548 &nominal_sample_rate); 582 &nominal_sample_rate);
549 if (result != noErr) 583 if (result != noErr)
550 return 0.0; 584 return 0.0;
551 585
552 return static_cast<int>(nominal_sample_rate); 586 return static_cast<int>(nominal_sample_rate);
(...skipping 12 matching lines...) Expand all
565 kAudioUnitProperty_Latency, 599 kAudioUnitProperty_Latency,
566 kAudioUnitScope_Global, 600 kAudioUnitScope_Global,
567 0, 601 0,
568 &audio_unit_latency_sec, 602 &audio_unit_latency_sec,
569 &size); 603 &size);
570 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) 604 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
571 << "Could not get audio unit latency"; 605 << "Could not get audio unit latency";
572 606
573 // Get input audio device latency. 607 // Get input audio device latency.
574 AudioObjectPropertyAddress property_address = { 608 AudioObjectPropertyAddress property_address = {
575 kAudioDevicePropertyLatency, 609 kAudioDevicePropertyLatency,
576 kAudioDevicePropertyScopeInput, 610 kAudioDevicePropertyScopeInput,
577 kAudioObjectPropertyElementMaster 611 kAudioObjectPropertyElementMaster
578 }; 612 };
579 UInt32 device_latency_frames = 0; 613 UInt32 device_latency_frames = 0;
580 size = sizeof(device_latency_frames); 614 size = sizeof(device_latency_frames);
581 result = AudioObjectGetPropertyData(input_device_id_, 615 result = AudioObjectGetPropertyData(input_device_id_,
582 &property_address, 616 &property_address,
583 0, 617 0,
584 NULL, 618 NULL,
585 &size, 619 &size,
586 &device_latency_frames); 620 &device_latency_frames);
587 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; 621 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
588 622
589 return static_cast<double>((audio_unit_latency_sec * 623 return static_cast<double>((audio_unit_latency_sec * format_.mSampleRate) +
590 format_.mSampleRate) + device_latency_frames); 624 device_latency_frames);
591 } 625 }
592 626
593 double AUAudioInputStream::GetCaptureLatency( 627 double AUAudioInputStream::GetCaptureLatency(
594 const AudioTimeStamp* input_time_stamp) { 628 const AudioTimeStamp* input_time_stamp) {
595 // Get the delay between between the actual recording instant and the time 629 // Get the delay between between the actual recording instant and the time
596 // when the data packet is provided as a callback. 630 // when the data packet is provided as a callback.
597 UInt64 capture_time_ns = AudioConvertHostTimeToNanos( 631 UInt64 capture_time_ns =
598 input_time_stamp->mHostTime); 632 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime);
599 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 633 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
600 double delay_frames = static_cast<double> 634 double delay_frames = static_cast<double>(1e-9 * (now_ns - capture_time_ns) *
601 (1e-9 * (now_ns - capture_time_ns) * format_.mSampleRate); 635 format_.mSampleRate);
602 636
603 // Total latency is composed by the dynamic latency and the fixed 637 // Total latency is composed by the dynamic latency and the fixed
604 // hardware latency. 638 // hardware latency.
605 return (delay_frames + hardware_latency_frames_); 639 return (delay_frames + hardware_latency_frames_);
606 } 640 }
607 641
608 int AUAudioInputStream::GetNumberOfChannelsFromStream() { 642 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
609 // Get the stream format, to be able to read the number of channels. 643 // Get the stream format, to be able to read the number of channels.
610 AudioObjectPropertyAddress property_address = { 644 AudioObjectPropertyAddress property_address = {
611 kAudioDevicePropertyStreamFormat, 645 kAudioDevicePropertyStreamFormat,
612 kAudioDevicePropertyScopeInput, 646 kAudioDevicePropertyScopeInput,
613 kAudioObjectPropertyElementMaster 647 kAudioObjectPropertyElementMaster
614 }; 648 };
615 AudioStreamBasicDescription stream_format; 649 AudioStreamBasicDescription stream_format;
616 UInt32 size = sizeof(stream_format); 650 UInt32 size = sizeof(stream_format);
617 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 651 OSStatus result = AudioObjectGetPropertyData(
618 &property_address, 652 input_device_id_, &property_address, 0, NULL, &size, &stream_format);
619 0,
620 NULL,
621 &size,
622 &stream_format);
623 if (result != noErr) { 653 if (result != noErr) {
624 DLOG(WARNING) << "Could not get stream format"; 654 DLOG(WARNING) << "Could not get stream format";
625 return 0; 655 return 0;
626 } 656 }
627 657
628 return static_cast<int>(stream_format.mChannelsPerFrame); 658 return static_cast<int>(stream_format.mChannelsPerFrame);
629 } 659 }
630 660
631 void AUAudioInputStream::HandleError(OSStatus err) { 661 void AUAudioInputStream::HandleError(OSStatus err) {
632 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) 662 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) << " (" << err
633 << " (" << err << ")"; 663 << ")";
634 if (sink_) 664 if (sink_)
635 sink_->OnError(this); 665 sink_->OnError(this);
636 } 666 }
637 667
638 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) { 668 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) {
639 Boolean is_settable = false; 669 Boolean is_settable = false;
640 AudioObjectPropertyAddress property_address = { 670 AudioObjectPropertyAddress property_address = {
641 kAudioDevicePropertyVolumeScalar, 671 kAudioDevicePropertyVolumeScalar,
642 kAudioDevicePropertyScopeInput, 672 kAudioDevicePropertyScopeInput,
643 static_cast<UInt32>(channel) 673 static_cast<UInt32>(channel)
644 }; 674 };
645 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, 675 OSStatus result = AudioObjectIsPropertySettable(
646 &property_address, 676 input_device_id_, &property_address, &is_settable);
647 &is_settable);
648 return (result == noErr) ? is_settable : false; 677 return (result == noErr) ? is_settable : false;
649 } 678 }
650 679
651 } // namespace media 680 } // 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