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

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

Issue 501823002: Used native deinterleaved and float point format for the input streams. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added a CHECK. 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 | Annotate | Revision Log
« 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) {
(...skipping 16 matching lines...) Expand all
39 const AudioParameters& input_params, 40 const AudioParameters& input_params,
40 AudioDeviceID audio_device_id) 41 AudioDeviceID audio_device_id)
41 : manager_(manager), 42 : manager_(manager),
42 number_of_frames_(input_params.frames_per_buffer()), 43 number_of_frames_(input_params.frames_per_buffer()),
43 sink_(NULL), 44 sink_(NULL),
44 audio_unit_(0), 45 audio_unit_(0),
45 input_device_id_(audio_device_id), 46 input_device_id_(audio_device_id),
46 started_(false), 47 started_(false),
47 hardware_latency_frames_(0), 48 hardware_latency_frames_(0),
48 number_of_channels_in_frame_(0), 49 number_of_channels_in_frame_(0),
49 fifo_(input_params.channels(), 50 output_bus_(AudioBus::Create(input_params)) {
50 number_of_frames_,
51 kNumberOfBlocksBufferInFifo) {
52 DCHECK(manager_); 51 DCHECK(manager_);
53 52
54 // Set up the desired (output) format specified by the client. 53 // Set up the desired (output) format specified by the client.
55 format_.mSampleRate = input_params.sample_rate(); 54 format_.mSampleRate = input_params.sample_rate();
56 format_.mFormatID = kAudioFormatLinearPCM; 55 format_.mFormatID = kAudioFormatLinearPCM;
57 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | 56 format_.mFormatFlags =
58 kLinearPCMFormatFlagIsSignedInteger; 57 kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
59 format_.mBitsPerChannel = input_params.bits_per_sample(); 58 size_t bytes_per_sample = sizeof(Float32);
59 format_.mBitsPerChannel = bytes_per_sample * 8;
60 format_.mChannelsPerFrame = input_params.channels(); 60 format_.mChannelsPerFrame = input_params.channels();
61 format_.mFramesPerPacket = 1; // uncompressed audio 61 format_.mFramesPerPacket = 1;
62 format_.mBytesPerPacket = (format_.mBitsPerChannel * 62 format_.mBytesPerFrame = bytes_per_sample;
63 input_params.channels()) / 8; 63 format_.mBytesPerPacket = format_.mBytesPerFrame * format_.mFramesPerPacket;
64 format_.mBytesPerFrame = format_.mBytesPerPacket;
65 format_.mReserved = 0; 64 format_.mReserved = 0;
66 65
67 DVLOG(1) << "Desired ouput format: " << format_; 66 DVLOG(1) << "Desired ouput format: " << format_;
68 67
69 // Derive size (in bytes) of the buffers that we will render to. 68 // Allocate AudioBufferList based on the number of channels.
70 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame; 69 audio_buffer_list_.reset(static_cast<AudioBufferList*>(
71 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size; 70 malloc(sizeof(UInt32) + input_params.channels() * sizeof(AudioBuffer))));
71 audio_buffer_list_->mNumberBuffers = input_params.channels();
72 72
73 // Allocate AudioBuffers to be used as storage for the received audio. 73 // Allocate AudioBuffers to be used as storage for the received audio.
74 // The AudioBufferList structure works as a placeholder for the 74 // The AudioBufferList structure works as a placeholder for the
75 // AudioBuffer structure, which holds a pointer to the actual data buffer. 75 // AudioBuffer structure, which holds a pointer to the actual data buffer.
76 audio_data_buffer_.reset(new uint8[data_byte_size]); 76 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame;
77 audio_buffer_list_.mNumberBuffers = 1; 77 CHECK_LE(static_cast<int>(data_byte_size * input_params.channels()),
78 78 media::AudioBus::CalculateMemorySize(input_params));
79 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers; 79 AudioBuffer* audio_buffer = audio_buffer_list_->mBuffers;
80 audio_buffer->mNumberChannels = input_params.channels(); 80 for (UInt32 i = 0; i < audio_buffer_list_->mNumberBuffers; ++i) {
81 audio_buffer->mDataByteSize = data_byte_size; 81 audio_buffer[i].mNumberChannels = 1;
82 audio_buffer->mData = audio_data_buffer_.get(); 82 audio_buffer[i].mDataByteSize = data_byte_size;
83 audio_buffer[i].mData = output_bus_->channel(i);
84 }
83 } 85 }
84 86
85 AUAudioInputStream::~AUAudioInputStream() {} 87 AUAudioInputStream::~AUAudioInputStream() {
88 }
86 89
87 // Obtain and open the AUHAL AudioOutputUnit for recording. 90 // Obtain and open the AUHAL AudioOutputUnit for recording.
88 bool AUAudioInputStream::Open() { 91 bool AUAudioInputStream::Open() {
89 // Verify that we are not already opened. 92 // Verify that we are not already opened.
90 if (audio_unit_) 93 if (audio_unit_)
91 return false; 94 return false;
92 95
93 // Verify that we have a valid device. 96 // Verify that we have a valid device.
94 if (input_device_id_ == kAudioObjectUnknown) { 97 if (input_device_id_ == kAudioObjectUnknown) {
95 NOTREACHED() << "Device ID is unknown"; 98 NOTREACHED() << "Device ID is unknown";
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 kAudioOutputUnitProperty_CurrentDevice, 161 kAudioOutputUnitProperty_CurrentDevice,
159 kAudioUnitScope_Global, 162 kAudioUnitScope_Global,
160 0, 163 0,
161 &input_device_id_, 164 &input_device_id_,
162 sizeof(input_device_id_)); 165 sizeof(input_device_id_));
163 if (result) { 166 if (result) {
164 HandleError(result); 167 HandleError(result);
165 return false; 168 return false;
166 } 169 }
167 170
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. 171 // Set up the the desired (output) format.
186 // For obtaining input from a device, the device format is always expressed 172 // For obtaining input from a device, the device format is always expressed
187 // on the output scope of the AUHAL's Element 1. 173 // on the output scope of the AUHAL's Element 1.
188 result = AudioUnitSetProperty(audio_unit_, 174 result = AudioUnitSetProperty(audio_unit_,
189 kAudioUnitProperty_StreamFormat, 175 kAudioUnitProperty_StreamFormat,
190 kAudioUnitScope_Output, 176 kAudioUnitScope_Output,
191 1, 177 1,
192 &format_, 178 &format_,
193 sizeof(format_)); 179 sizeof(format_));
194 if (result) { 180 if (result) {
(...skipping 27 matching lines...) Expand all
222 kAudioUnitScope_Output, 208 kAudioUnitScope_Output,
223 1, 209 1,
224 &buffer_size, 210 &buffer_size,
225 sizeof(buffer_size)); 211 sizeof(buffer_size));
226 if (result != noErr) { 212 if (result != noErr) {
227 HandleError(result); 213 HandleError(result);
228 return false; 214 return false;
229 } 215 }
230 } 216 }
231 217
218 // Register the input procedure for the AUHAL.
219 // This procedure will be called when the AUHAL has received new data
220 // from the input device.
221 AURenderCallbackStruct callback;
222 callback.inputProc = InputProc;
223 callback.inputProcRefCon = this;
224 result = AudioUnitSetProperty(audio_unit_,
225 kAudioOutputUnitProperty_SetInputCallback,
226 kAudioUnitScope_Global,
227 0,
228 &callback,
229 sizeof(callback));
230 if (result) {
231 HandleError(result);
232 return false;
233 }
234
232 // Finally, initialize the audio unit and ensure that it is ready to render. 235 // Finally, initialize the audio unit and ensure that it is ready to render.
233 // Allocates memory according to the maximum number of audio frames 236 // Allocates memory according to the maximum number of audio frames
234 // it can produce in response to a single render call. 237 // it can produce in response to a single render call.
235 result = AudioUnitInitialize(audio_unit_); 238 result = AudioUnitInitialize(audio_unit_);
236 if (result) { 239 if (result) {
237 HandleError(result); 240 HandleError(result);
238 return false; 241 return false;
239 } 242 }
240 243
241 // The hardware latency is fixed and will not change during the call. 244 // 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); 338 DCHECK_LE(volume, 1.0);
336 339
337 // Verify that we have a valid device. 340 // Verify that we have a valid device.
338 if (input_device_id_ == kAudioObjectUnknown) { 341 if (input_device_id_ == kAudioObjectUnknown) {
339 NOTREACHED() << "Device ID is unknown"; 342 NOTREACHED() << "Device ID is unknown";
340 return; 343 return;
341 } 344 }
342 345
343 Float32 volume_float32 = static_cast<Float32>(volume); 346 Float32 volume_float32 = static_cast<Float32>(volume);
344 AudioObjectPropertyAddress property_address = { 347 AudioObjectPropertyAddress property_address = {
345 kAudioDevicePropertyVolumeScalar, 348 kAudioDevicePropertyVolumeScalar,
346 kAudioDevicePropertyScopeInput, 349 kAudioDevicePropertyScopeInput,
347 kAudioObjectPropertyElementMaster 350 kAudioObjectPropertyElementMaster
348 }; 351 };
349 352
350 // Try to set the volume for master volume channel. 353 // Try to set the volume for master volume channel.
351 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) { 354 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) {
352 OSStatus result = AudioObjectSetPropertyData(input_device_id_, 355 OSStatus result = AudioObjectSetPropertyData(input_device_id_,
353 &property_address, 356 &property_address,
354 0, 357 0,
355 NULL, 358 NULL,
356 sizeof(volume_float32), 359 sizeof(volume_float32),
357 &volume_float32); 360 &volume_float32);
(...skipping 25 matching lines...) Expand all
383 // Update the AGC volume level based on the last setting above. Note that, 386 // 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 387 // 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 388 // 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. 389 // used directly. Instead, a new query to the audio hardware is required.
387 // This method does nothing if AGC is disabled. 390 // This method does nothing if AGC is disabled.
388 UpdateAgcVolume(); 391 UpdateAgcVolume();
389 } 392 }
390 393
391 double AUAudioInputStream::GetVolume() { 394 double AUAudioInputStream::GetVolume() {
392 // Verify that we have a valid device. 395 // Verify that we have a valid device.
393 if (input_device_id_ == kAudioObjectUnknown){ 396 if (input_device_id_ == kAudioObjectUnknown) {
394 NOTREACHED() << "Device ID is unknown"; 397 NOTREACHED() << "Device ID is unknown";
395 return 0.0; 398 return 0.0;
396 } 399 }
397 400
398 AudioObjectPropertyAddress property_address = { 401 AudioObjectPropertyAddress property_address = {
399 kAudioDevicePropertyVolumeScalar, 402 kAudioDevicePropertyVolumeScalar,
400 kAudioDevicePropertyScopeInput, 403 kAudioDevicePropertyScopeInput,
401 kAudioObjectPropertyElementMaster 404 kAudioObjectPropertyElementMaster
402 }; 405 };
403 406
404 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 407 if (AudioObjectHasProperty(input_device_id_, &property_address)) {
405 // The device supports master volume control, get the volume from the 408 // The device supports master volume control, get the volume from the
406 // master channel. 409 // master channel.
407 Float32 volume_float32 = 0.0; 410 Float32 volume_float32 = 0.0;
408 UInt32 size = sizeof(volume_float32); 411 UInt32 size = sizeof(volume_float32);
409 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 412 OSStatus result = AudioObjectGetPropertyData(
410 &property_address, 413 input_device_id_, &property_address, 0, NULL, &size, &volume_float32);
411 0,
412 NULL,
413 &size,
414 &volume_float32);
415 if (result == noErr) 414 if (result == noErr)
416 return static_cast<double>(volume_float32); 415 return static_cast<double>(volume_float32);
417 } else { 416 } else {
418 // There is no master volume control, try to get the average volume of 417 // There is no master volume control, try to get the average volume of
419 // all the channels. 418 // all the channels.
420 Float32 volume_float32 = 0.0; 419 Float32 volume_float32 = 0.0;
421 int successful_channels = 0; 420 int successful_channels = 0;
422 for (int i = 1; i <= number_of_channels_in_frame_; ++i) { 421 for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
423 property_address.mElement = static_cast<UInt32>(i); 422 property_address.mElement = static_cast<UInt32>(i);
424 if (AudioObjectHasProperty(input_device_id_, &property_address)) { 423 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(), 464 OSStatus result = AudioUnitRender(audio_input->audio_unit(),
466 flags, 465 flags,
467 time_stamp, 466 time_stamp,
468 bus_number, 467 bus_number,
469 number_of_frames, 468 number_of_frames,
470 audio_input->audio_buffer_list()); 469 audio_input->audio_buffer_list());
471 if (result) 470 if (result)
472 return result; 471 return result;
473 472
474 // Deliver recorded data to the consumer as a callback. 473 // Deliver recorded data to the consumer as a callback.
475 return audio_input->Provide(number_of_frames, 474 return audio_input->Provide(
476 audio_input->audio_buffer_list(), 475 number_of_frames, audio_input->audio_buffer_list(), time_stamp);
477 time_stamp);
478 } 476 }
479 477
480 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, 478 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
481 AudioBufferList* io_data, 479 AudioBufferList* io_data,
482 const AudioTimeStamp* time_stamp) { 480 const AudioTimeStamp* time_stamp) {
483 // Update the capture latency. 481 // Update the capture latency.
484 double capture_latency_frames = GetCaptureLatency(time_stamp); 482 double capture_latency_frames = GetCaptureLatency(time_stamp);
485 483
486 // The AGC volume level is updated once every second on a separate thread. 484 // 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 485 // Note that, |volume| is also updated each time SetVolume() is called
488 // through IPC by the render-side AGC. 486 // through IPC by the render-side AGC.
489 double normalized_volume = 0.0; 487 double normalized_volume = 0.0;
490 GetAgcVolume(&normalized_volume); 488 GetAgcVolume(&normalized_volume);
491 489
492 AudioBuffer& buffer = io_data->mBuffers[0]; 490 AudioBuffer& buffer = io_data->mBuffers[0];
493 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); 491 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
494 uint32 capture_delay_bytes = static_cast<uint32> 492 uint32 capture_delay_bytes = static_cast<uint32>(
495 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); 493 (capture_latency_frames + 0.5) * format_.mBytesPerFrame);
496 DCHECK(audio_data); 494 DCHECK(audio_data);
497 if (!audio_data) 495 if (!audio_data)
498 return kAudioUnitErr_InvalidElement; 496 return kAudioUnitErr_InvalidElement;
499 497
500 // Copy captured (and interleaved) data into FIFO. 498 // If the stream parameters change for any reason, we need to insert a FIFO
501 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 499 // since the OnMoreData() pipeline can't handle frame size changes.
500 if (number_of_frames != number_of_frames_) {
501 // Create a FIFO on the fly to handle any discrepancies in callback rates.
502 if (!fifo_) {
503 fifo_.reset(new AudioBlockFifo(output_bus_->channels(),
504 number_of_frames_,
505 kNumberOfBlocksBufferInFifo));
506 }
507 }
502 508
509 // When FIFO does not kick in, data will be directly passed to the callback.
510 if (!fifo_) {
511 CHECK_EQ(output_bus_->frames(), static_cast<int>(number_of_frames_));
512 sink_->OnData(
513 this, output_bus_.get(), capture_delay_bytes, normalized_volume);
514 return noErr;
515 }
516
517 // Compensate the audio delay caused by the FIFO.
518 capture_delay_bytes += fifo_->GetAvailableFrames() * format_.mBytesPerFrame;
519
520 fifo_->Push(output_bus_.get());
503 // Consume and deliver the data when the FIFO has a block of available data. 521 // Consume and deliver the data when the FIFO has a block of available data.
504 while (fifo_.available_blocks()) { 522 while (fifo_->available_blocks()) {
505 const AudioBus* audio_bus = fifo_.Consume(); 523 const AudioBus* audio_bus = fifo_->Consume();
506 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 524 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); 525 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume);
511 } 526 }
512 527
513 return noErr; 528 return noErr;
514 } 529 }
515 530
516 int AUAudioInputStream::HardwareSampleRate() { 531 int AUAudioInputStream::HardwareSampleRate() {
517 // Determine the default input device's sample-rate. 532 // Determine the default input device's sample-rate.
518 AudioDeviceID device_id = kAudioObjectUnknown; 533 AudioDeviceID device_id = kAudioObjectUnknown;
519 UInt32 info_size = sizeof(device_id); 534 UInt32 info_size = sizeof(device_id);
520 535
521 AudioObjectPropertyAddress default_input_device_address = { 536 AudioObjectPropertyAddress default_input_device_address = {
522 kAudioHardwarePropertyDefaultInputDevice, 537 kAudioHardwarePropertyDefaultInputDevice,
523 kAudioObjectPropertyScopeGlobal, 538 kAudioObjectPropertyScopeGlobal,
524 kAudioObjectPropertyElementMaster 539 kAudioObjectPropertyElementMaster
525 }; 540 };
526 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, 541 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
527 &default_input_device_address, 542 &default_input_device_address,
528 0, 543 0,
529 0, 544 0,
530 &info_size, 545 &info_size,
531 &device_id); 546 &device_id);
532 if (result != noErr) 547 if (result != noErr)
533 return 0.0; 548 return 0.0;
534 549
535 Float64 nominal_sample_rate; 550 Float64 nominal_sample_rate;
536 info_size = sizeof(nominal_sample_rate); 551 info_size = sizeof(nominal_sample_rate);
537 552
538 AudioObjectPropertyAddress nominal_sample_rate_address = { 553 AudioObjectPropertyAddress nominal_sample_rate_address = {
539 kAudioDevicePropertyNominalSampleRate, 554 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
540 kAudioObjectPropertyScopeGlobal, 555 kAudioObjectPropertyElementMaster};
541 kAudioObjectPropertyElementMaster
542 };
543 result = AudioObjectGetPropertyData(device_id, 556 result = AudioObjectGetPropertyData(device_id,
544 &nominal_sample_rate_address, 557 &nominal_sample_rate_address,
545 0, 558 0,
546 0, 559 0,
547 &info_size, 560 &info_size,
548 &nominal_sample_rate); 561 &nominal_sample_rate);
549 if (result != noErr) 562 if (result != noErr)
550 return 0.0; 563 return 0.0;
551 564
552 return static_cast<int>(nominal_sample_rate); 565 return static_cast<int>(nominal_sample_rate);
(...skipping 12 matching lines...) Expand all
565 kAudioUnitProperty_Latency, 578 kAudioUnitProperty_Latency,
566 kAudioUnitScope_Global, 579 kAudioUnitScope_Global,
567 0, 580 0,
568 &audio_unit_latency_sec, 581 &audio_unit_latency_sec,
569 &size); 582 &size);
570 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) 583 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
571 << "Could not get audio unit latency"; 584 << "Could not get audio unit latency";
572 585
573 // Get input audio device latency. 586 // Get input audio device latency.
574 AudioObjectPropertyAddress property_address = { 587 AudioObjectPropertyAddress property_address = {
575 kAudioDevicePropertyLatency, 588 kAudioDevicePropertyLatency,
576 kAudioDevicePropertyScopeInput, 589 kAudioDevicePropertyScopeInput,
577 kAudioObjectPropertyElementMaster 590 kAudioObjectPropertyElementMaster
578 }; 591 };
579 UInt32 device_latency_frames = 0; 592 UInt32 device_latency_frames = 0;
580 size = sizeof(device_latency_frames); 593 size = sizeof(device_latency_frames);
581 result = AudioObjectGetPropertyData(input_device_id_, 594 result = AudioObjectGetPropertyData(input_device_id_,
582 &property_address, 595 &property_address,
583 0, 596 0,
584 NULL, 597 NULL,
585 &size, 598 &size,
586 &device_latency_frames); 599 &device_latency_frames);
587 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; 600 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
588 601
589 return static_cast<double>((audio_unit_latency_sec * 602 return static_cast<double>((audio_unit_latency_sec * format_.mSampleRate) +
590 format_.mSampleRate) + device_latency_frames); 603 device_latency_frames);
591 } 604 }
592 605
593 double AUAudioInputStream::GetCaptureLatency( 606 double AUAudioInputStream::GetCaptureLatency(
594 const AudioTimeStamp* input_time_stamp) { 607 const AudioTimeStamp* input_time_stamp) {
595 // Get the delay between between the actual recording instant and the time 608 // Get the delay between between the actual recording instant and the time
596 // when the data packet is provided as a callback. 609 // when the data packet is provided as a callback.
597 UInt64 capture_time_ns = AudioConvertHostTimeToNanos( 610 UInt64 capture_time_ns =
598 input_time_stamp->mHostTime); 611 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime);
599 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 612 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
600 double delay_frames = static_cast<double> 613 double delay_frames = static_cast<double>(1e-9 * (now_ns - capture_time_ns) *
601 (1e-9 * (now_ns - capture_time_ns) * format_.mSampleRate); 614 format_.mSampleRate);
602 615
603 // Total latency is composed by the dynamic latency and the fixed 616 // Total latency is composed by the dynamic latency and the fixed
604 // hardware latency. 617 // hardware latency.
605 return (delay_frames + hardware_latency_frames_); 618 return (delay_frames + hardware_latency_frames_);
606 } 619 }
607 620
608 int AUAudioInputStream::GetNumberOfChannelsFromStream() { 621 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
609 // Get the stream format, to be able to read the number of channels. 622 // Get the stream format, to be able to read the number of channels.
610 AudioObjectPropertyAddress property_address = { 623 AudioObjectPropertyAddress property_address = {
611 kAudioDevicePropertyStreamFormat, 624 kAudioDevicePropertyStreamFormat,
612 kAudioDevicePropertyScopeInput, 625 kAudioDevicePropertyScopeInput,
613 kAudioObjectPropertyElementMaster 626 kAudioObjectPropertyElementMaster
614 }; 627 };
615 AudioStreamBasicDescription stream_format; 628 AudioStreamBasicDescription stream_format;
616 UInt32 size = sizeof(stream_format); 629 UInt32 size = sizeof(stream_format);
617 OSStatus result = AudioObjectGetPropertyData(input_device_id_, 630 OSStatus result = AudioObjectGetPropertyData(
618 &property_address, 631 input_device_id_, &property_address, 0, NULL, &size, &stream_format);
619 0,
620 NULL,
621 &size,
622 &stream_format);
623 if (result != noErr) { 632 if (result != noErr) {
624 DLOG(WARNING) << "Could not get stream format"; 633 DLOG(WARNING) << "Could not get stream format";
625 return 0; 634 return 0;
626 } 635 }
627 636
628 return static_cast<int>(stream_format.mChannelsPerFrame); 637 return static_cast<int>(stream_format.mChannelsPerFrame);
629 } 638 }
630 639
631 void AUAudioInputStream::HandleError(OSStatus err) { 640 void AUAudioInputStream::HandleError(OSStatus err) {
632 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) 641 NOTREACHED() << "error " << GetMacOSStatusErrorString(err) << " (" << err
633 << " (" << err << ")"; 642 << ")";
634 if (sink_) 643 if (sink_)
635 sink_->OnError(this); 644 sink_->OnError(this);
636 } 645 }
637 646
638 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) { 647 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) {
639 Boolean is_settable = false; 648 Boolean is_settable = false;
640 AudioObjectPropertyAddress property_address = { 649 AudioObjectPropertyAddress property_address = {
641 kAudioDevicePropertyVolumeScalar, 650 kAudioDevicePropertyVolumeScalar,
642 kAudioDevicePropertyScopeInput, 651 kAudioDevicePropertyScopeInput,
643 static_cast<UInt32>(channel) 652 static_cast<UInt32>(channel)
644 }; 653 };
645 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, 654 OSStatus result = AudioObjectIsPropertySettable(
646 &property_address, 655 input_device_id_, &property_address, &is_settable);
647 &is_settable);
648 return (result == noErr) ? is_settable : false; 656 return (result == noErr) ? is_settable : false;
649 } 657 }
650 658
651 } // namespace media 659 } // 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