OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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" |
(...skipping 11 matching lines...) Expand all Loading... |
22 << "channels per frame: " << format.mChannelsPerFrame << std::endl | 22 << "channels per frame: " << format.mChannelsPerFrame << std::endl |
23 << "bits per channel : " << format.mBitsPerChannel; | 23 << "bits per channel : " << format.mBitsPerChannel; |
24 return os; | 24 return os; |
25 } | 25 } |
26 | 26 |
27 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" | 27 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" |
28 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html | 28 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html |
29 // for more details and background regarding this implementation. | 29 // for more details and background regarding this implementation. |
30 | 30 |
31 AUAudioInputStream::AUAudioInputStream( | 31 AUAudioInputStream::AUAudioInputStream( |
32 AudioManagerMac* manager, const AudioParameters& params) | 32 AudioManagerMac* manager, const AudioParameters& params, |
| 33 AudioDeviceID audio_device_id) |
33 : manager_(manager), | 34 : manager_(manager), |
34 sink_(NULL), | 35 sink_(NULL), |
35 audio_unit_(0), | 36 audio_unit_(0), |
36 input_device_id_(kAudioObjectUnknown), | 37 input_device_id_(audio_device_id), |
37 started_(false), | 38 started_(false), |
38 hardware_latency_frames_(0) { | 39 hardware_latency_frames_(0) { |
39 DCHECK(manager_); | 40 DCHECK(manager_); |
40 | 41 |
41 // Set up the desired (output) format specified by the client. | 42 // Set up the desired (output) format specified by the client. |
42 format_.mSampleRate = params.sample_rate; | 43 format_.mSampleRate = params.sample_rate; |
43 format_.mFormatID = kAudioFormatLinearPCM; | 44 format_.mFormatID = kAudioFormatLinearPCM; |
44 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | | 45 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | |
45 kLinearPCMFormatFlagIsSignedInteger; | 46 kLinearPCMFormatFlagIsSignedInteger; |
46 format_.mBitsPerChannel = params.bits_per_sample; | 47 format_.mBitsPerChannel = params.bits_per_sample; |
(...skipping 27 matching lines...) Expand all Loading... |
74 } | 75 } |
75 | 76 |
76 AUAudioInputStream::~AUAudioInputStream() {} | 77 AUAudioInputStream::~AUAudioInputStream() {} |
77 | 78 |
78 // Obtain and open the AUHAL AudioOutputUnit for recording. | 79 // Obtain and open the AUHAL AudioOutputUnit for recording. |
79 bool AUAudioInputStream::Open() { | 80 bool AUAudioInputStream::Open() { |
80 // Verify that we are not already opened. | 81 // Verify that we are not already opened. |
81 if (audio_unit_) | 82 if (audio_unit_) |
82 return false; | 83 return false; |
83 | 84 |
| 85 // Verify that we have a valid device. |
| 86 if (input_device_id_ == kAudioObjectUnknown) |
| 87 return false; |
| 88 |
84 // Start by obtaining an AudioOuputUnit using an AUHAL component description. | 89 // Start by obtaining an AudioOuputUnit using an AUHAL component description. |
85 | 90 |
86 Component comp; | 91 Component comp; |
87 ComponentDescription desc; | 92 ComponentDescription desc; |
88 | 93 |
89 // Description for the Audio Unit we want to use (AUHAL in this case). | 94 // Description for the Audio Unit we want to use (AUHAL in this case). |
90 desc.componentType = kAudioUnitType_Output; | 95 desc.componentType = kAudioUnitType_Output; |
91 desc.componentSubType = kAudioUnitSubType_HALOutput; | 96 desc.componentSubType = kAudioUnitSubType_HALOutput; |
92 desc.componentManufacturer = kAudioUnitManufacturer_Apple; | 97 desc.componentManufacturer = kAudioUnitManufacturer_Apple; |
93 desc.componentFlags = 0; | 98 desc.componentFlags = 0; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 kAudioOutputUnitProperty_EnableIO, | 135 kAudioOutputUnitProperty_EnableIO, |
131 kAudioUnitScope_Output, | 136 kAudioUnitScope_Output, |
132 0, // output element 0 | 137 0, // output element 0 |
133 &enableIO, // disable | 138 &enableIO, // disable |
134 sizeof(enableIO)); | 139 sizeof(enableIO)); |
135 if (result) { | 140 if (result) { |
136 HandleError(result); | 141 HandleError(result); |
137 return false; | 142 return false; |
138 } | 143 } |
139 | 144 |
140 // Set the current device of the AudioOuputUnit to default input device. | |
141 | |
142 // First, obtain the current input device selected by the user. | |
143 AudioObjectPropertyAddress default_intput_device_address = { | |
144 kAudioHardwarePropertyDefaultInputDevice, | |
145 kAudioObjectPropertyScopeGlobal, | |
146 kAudioObjectPropertyElementMaster | |
147 }; | |
148 AudioDeviceID input_device = kAudioObjectUnknown; | |
149 UInt32 size = sizeof(input_device); | |
150 result = AudioObjectGetPropertyData(kAudioObjectSystemObject, | |
151 &default_intput_device_address, | |
152 0, | |
153 0, | |
154 &size, | |
155 &input_device); | |
156 if (result) { | |
157 HandleError(result); | |
158 return false; | |
159 } | |
160 | |
161 input_device_id_ = input_device; | |
162 | |
163 // Next, set the audio device to be the Audio Unit's current device. | 145 // Next, set the audio device to be the Audio Unit's current device. |
164 // Note that, devices can only be set to the AUHAL after enabling IO. | 146 // Note that, devices can only be set to the AUHAL after enabling IO. |
165 result = AudioUnitSetProperty(audio_unit_, | 147 result = AudioUnitSetProperty(audio_unit_, |
166 kAudioOutputUnitProperty_CurrentDevice, | 148 kAudioOutputUnitProperty_CurrentDevice, |
167 kAudioUnitScope_Global, | 149 kAudioUnitScope_Global, |
168 0, | 150 0, |
169 &input_device_id_, | 151 &input_device_id_, |
170 sizeof(input_device)); | 152 sizeof(input_device_id_)); |
171 if (result) { | 153 if (result) { |
172 HandleError(result); | 154 HandleError(result); |
173 return false; | 155 return false; |
174 } | 156 } |
175 | 157 |
176 // Register the input procedure for the AUHAL. | 158 // Register the input procedure for the AUHAL. |
177 // This procedure will be called when the AUHAL has received new data | 159 // This procedure will be called when the AUHAL has received new data |
178 // from the input device. | 160 // from the input device. |
179 AURenderCallbackStruct callback; | 161 AURenderCallbackStruct callback; |
180 callback.inputProc = InputProc; | 162 callback.inputProc = InputProc; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 // Total latency is composed by the dynamic latency and the fixed | 432 // Total latency is composed by the dynamic latency and the fixed |
451 // hardware latency. | 433 // hardware latency. |
452 return (delay_frames + hardware_latency_frames_); | 434 return (delay_frames + hardware_latency_frames_); |
453 } | 435 } |
454 | 436 |
455 void AUAudioInputStream::HandleError(OSStatus err) { | 437 void AUAudioInputStream::HandleError(OSStatus err) { |
456 NOTREACHED() << "error code: " << err; | 438 NOTREACHED() << "error code: " << err; |
457 if (sink_) | 439 if (sink_) |
458 sink_->OnError(this, static_cast<int>(err)); | 440 sink_->OnError(this, static_cast<int>(err)); |
459 } | 441 } |
OLD | NEW |