OLD | NEW |
1 // Copyright (c) 2011 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_output_mac.h" | 5 #include "media/audio/mac/audio_low_latency_output_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 "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
12 #include "media/audio/mac/audio_manager_mac.h" | 13 #include "media/audio/mac/audio_manager_mac.h" |
13 | 14 |
14 // Reorder PCM from AAC layout to Core Audio 5.1 layout. | 15 // Reorder PCM from AAC layout to Core Audio 5.1 layout. |
15 // TODO(fbarchard): Switch layout when ffmpeg is updated. | 16 // TODO(fbarchard): Switch layout when ffmpeg is updated. |
16 template<class Format> | 17 template<class Format> |
17 static void SwizzleCoreAudioLayout5_1(Format* b, uint32 filled) { | 18 static void SwizzleCoreAudioLayout5_1(Format* b, uint32 filled) { |
18 static const int kNumSurroundChannels = 6; | 19 static const int kNumSurroundChannels = 6; |
19 Format aac[kNumSurroundChannels]; | 20 Format aac[kNumSurroundChannels]; |
20 for (uint32 i = 0; i < filled; i += sizeof(aac), b += kNumSurroundChannels) { | 21 for (uint32 i = 0; i < filled; i += sizeof(aac), b += kNumSurroundChannels) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 kAudioHardwarePropertyDefaultOutputDevice, | 81 kAudioHardwarePropertyDefaultOutputDevice, |
81 kAudioObjectPropertyScopeGlobal, | 82 kAudioObjectPropertyScopeGlobal, |
82 kAudioObjectPropertyElementMaster | 83 kAudioObjectPropertyElementMaster |
83 }; | 84 }; |
84 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, | 85 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
85 &default_output_device_address, | 86 &default_output_device_address, |
86 0, | 87 0, |
87 0, | 88 0, |
88 &size, | 89 &size, |
89 &output_device_id_); | 90 &output_device_id_); |
90 DCHECK_EQ(result, 0); | 91 OSSTATUS_DCHECK(result == noErr, result); |
91 if (result) | 92 if (result) |
92 return false; | 93 return false; |
93 | 94 |
94 // Open and initialize the DefaultOutputUnit. | 95 // Open and initialize the DefaultOutputUnit. |
95 Component comp; | 96 Component comp; |
96 ComponentDescription desc; | 97 ComponentDescription desc; |
97 | 98 |
98 desc.componentType = kAudioUnitType_Output; | 99 desc.componentType = kAudioUnitType_Output; |
99 desc.componentSubType = kAudioUnitSubType_DefaultOutput; | 100 desc.componentSubType = kAudioUnitSubType_DefaultOutput; |
100 desc.componentManufacturer = kAudioUnitManufacturer_Apple; | 101 desc.componentManufacturer = kAudioUnitManufacturer_Apple; |
101 desc.componentFlags = 0; | 102 desc.componentFlags = 0; |
102 desc.componentFlagsMask = 0; | 103 desc.componentFlagsMask = 0; |
103 comp = FindNextComponent(0, &desc); | 104 comp = FindNextComponent(0, &desc); |
104 DCHECK(comp); | 105 DCHECK(comp); |
105 | 106 |
106 result = OpenAComponent(comp, &output_unit_); | 107 result = OpenAComponent(comp, &output_unit_); |
107 DCHECK_EQ(result, 0); | 108 OSSTATUS_DCHECK(result == noErr, result); |
108 if (result) | 109 if (result) |
109 return false; | 110 return false; |
110 | 111 |
111 result = AudioUnitInitialize(output_unit_); | 112 result = AudioUnitInitialize(output_unit_); |
112 | 113 OSSTATUS_DCHECK(result == noErr, result); |
113 DCHECK_EQ(result, 0); | |
114 if (result) | 114 if (result) |
115 return false; | 115 return false; |
116 | 116 |
117 hardware_latency_frames_ = GetHardwareLatency(); | 117 hardware_latency_frames_ = GetHardwareLatency(); |
118 | 118 |
119 return Configure(); | 119 return Configure(); |
120 } | 120 } |
121 | 121 |
122 bool AUAudioOutputStream::Configure() { | 122 bool AUAudioOutputStream::Configure() { |
123 // Set the render callback. | 123 // Set the render callback. |
124 AURenderCallbackStruct input; | 124 AURenderCallbackStruct input; |
125 input.inputProc = InputProc; | 125 input.inputProc = InputProc; |
126 input.inputProcRefCon = this; | 126 input.inputProcRefCon = this; |
127 OSStatus result = AudioUnitSetProperty( | 127 OSStatus result = AudioUnitSetProperty( |
128 output_unit_, | 128 output_unit_, |
129 kAudioUnitProperty_SetRenderCallback, | 129 kAudioUnitProperty_SetRenderCallback, |
130 kAudioUnitScope_Global, | 130 kAudioUnitScope_Global, |
131 0, | 131 0, |
132 &input, | 132 &input, |
133 sizeof(input)); | 133 sizeof(input)); |
134 | 134 OSSTATUS_DCHECK(result == noErr, result); |
135 DCHECK_EQ(result, 0); | |
136 if (result) | 135 if (result) |
137 return false; | 136 return false; |
138 | 137 |
139 // Set the stream format. | 138 // Set the stream format. |
140 result = AudioUnitSetProperty( | 139 result = AudioUnitSetProperty( |
141 output_unit_, | 140 output_unit_, |
142 kAudioUnitProperty_StreamFormat, | 141 kAudioUnitProperty_StreamFormat, |
143 kAudioUnitScope_Input, | 142 kAudioUnitScope_Input, |
144 0, | 143 0, |
145 &format_, | 144 &format_, |
146 sizeof(format_)); | 145 sizeof(format_)); |
147 DCHECK_EQ(result, 0); | 146 OSSTATUS_DCHECK(result == noErr, result); |
148 if (result) | 147 if (result) |
149 return false; | 148 return false; |
150 | 149 |
151 // Set the buffer frame size. | 150 // Set the buffer frame size. |
152 UInt32 buffer_size = number_of_frames_; | 151 UInt32 buffer_size = number_of_frames_; |
153 result = AudioUnitSetProperty( | 152 result = AudioUnitSetProperty( |
154 output_unit_, | 153 output_unit_, |
155 kAudioDevicePropertyBufferFrameSize, | 154 kAudioDevicePropertyBufferFrameSize, |
156 kAudioUnitScope_Output, | 155 kAudioUnitScope_Output, |
157 0, | 156 0, |
158 &buffer_size, | 157 &buffer_size, |
159 sizeof(buffer_size)); | 158 sizeof(buffer_size)); |
160 DCHECK_EQ(result, 0); | 159 OSSTATUS_DCHECK(result == noErr, result); |
161 if (result) | 160 if (result) |
162 return false; | 161 return false; |
163 | 162 |
164 return true; | 163 return true; |
165 } | 164 } |
166 | 165 |
167 void AUAudioOutputStream::Close() { | 166 void AUAudioOutputStream::Close() { |
168 if (output_unit_) | 167 if (output_unit_) |
169 CloseComponent(output_unit_); | 168 CloseComponent(output_unit_); |
170 | 169 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 kAudioHardwarePropertyDefaultOutputDevice, | 261 kAudioHardwarePropertyDefaultOutputDevice, |
263 kAudioObjectPropertyScopeGlobal, | 262 kAudioObjectPropertyScopeGlobal, |
264 kAudioObjectPropertyElementMaster | 263 kAudioObjectPropertyElementMaster |
265 }; | 264 }; |
266 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, | 265 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
267 &default_output_device_address, | 266 &default_output_device_address, |
268 0, | 267 0, |
269 0, | 268 0, |
270 &info_size, | 269 &info_size, |
271 &device_id); | 270 &device_id); |
272 DCHECK_EQ(result, 0); | 271 OSSTATUS_DCHECK(result == noErr, result); |
273 if (result) | 272 if (result) |
274 return 0.0; // error | 273 return 0.0; // error |
275 | 274 |
276 Float64 nominal_sample_rate; | 275 Float64 nominal_sample_rate; |
277 info_size = sizeof(nominal_sample_rate); | 276 info_size = sizeof(nominal_sample_rate); |
278 | 277 |
279 AudioObjectPropertyAddress nominal_sample_rate_address = { | 278 AudioObjectPropertyAddress nominal_sample_rate_address = { |
280 kAudioDevicePropertyNominalSampleRate, | 279 kAudioDevicePropertyNominalSampleRate, |
281 kAudioObjectPropertyScopeGlobal, | 280 kAudioObjectPropertyScopeGlobal, |
282 kAudioObjectPropertyElementMaster | 281 kAudioObjectPropertyElementMaster |
283 }; | 282 }; |
284 result = AudioObjectGetPropertyData(device_id, | 283 result = AudioObjectGetPropertyData(device_id, |
285 &nominal_sample_rate_address, | 284 &nominal_sample_rate_address, |
286 0, | 285 0, |
287 0, | 286 0, |
288 &info_size, | 287 &info_size, |
289 &nominal_sample_rate); | 288 &nominal_sample_rate); |
290 DCHECK_EQ(result, 0); | 289 OSSTATUS_DCHECK(result == noErr, result); |
291 if (result) | 290 if (result) |
292 return 0.0; // error | 291 return 0.0; // error |
293 | 292 |
294 return nominal_sample_rate; | 293 return nominal_sample_rate; |
295 } | 294 } |
296 | 295 |
297 double AUAudioOutputStream::GetHardwareLatency() { | 296 double AUAudioOutputStream::GetHardwareLatency() { |
298 if (!output_unit_ || output_device_id_ == kAudioObjectUnknown) { | 297 if (!output_unit_ || output_device_id_ == kAudioObjectUnknown) { |
299 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown"; | 298 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown"; |
300 return 0.0; | 299 return 0.0; |
301 } | 300 } |
302 | 301 |
303 // Get audio unit latency. | 302 // Get audio unit latency. |
304 Float64 audio_unit_latency_sec = 0.0; | 303 Float64 audio_unit_latency_sec = 0.0; |
305 UInt32 size = sizeof(audio_unit_latency_sec); | 304 UInt32 size = sizeof(audio_unit_latency_sec); |
306 OSStatus result = AudioUnitGetProperty(output_unit_, | 305 OSStatus result = AudioUnitGetProperty(output_unit_, |
307 kAudioUnitProperty_Latency, | 306 kAudioUnitProperty_Latency, |
308 kAudioUnitScope_Global, | 307 kAudioUnitScope_Global, |
309 0, | 308 0, |
310 &audio_unit_latency_sec, | 309 &audio_unit_latency_sec, |
311 &size); | 310 &size); |
312 DLOG_IF(WARNING, result != noErr) << "Could not get audio unit latency."; | 311 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) |
| 312 << "Could not get audio unit latency"; |
313 | 313 |
314 // Get output audio device latency. | 314 // Get output audio device latency. |
315 AudioObjectPropertyAddress property_address = { | 315 AudioObjectPropertyAddress property_address = { |
316 kAudioDevicePropertyLatency, | 316 kAudioDevicePropertyLatency, |
317 kAudioDevicePropertyScopeOutput, | 317 kAudioDevicePropertyScopeOutput, |
318 kAudioObjectPropertyElementMaster | 318 kAudioObjectPropertyElementMaster |
319 }; | 319 }; |
320 UInt32 device_latency_frames = 0; | 320 UInt32 device_latency_frames = 0; |
321 size = sizeof(device_latency_frames); | 321 size = sizeof(device_latency_frames); |
322 result = AudioObjectGetPropertyData(output_device_id_, | 322 result = AudioObjectGetPropertyData(output_device_id_, |
323 &property_address, | 323 &property_address, |
324 0, | 324 0, |
325 NULL, | 325 NULL, |
326 &size, | 326 &size, |
327 &device_latency_frames); | 327 &device_latency_frames); |
328 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; | 328 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) |
| 329 << "Could not get audio device latency"; |
329 | 330 |
330 // Get the stream latency. | 331 // Get the stream latency. |
331 property_address.mSelector = kAudioDevicePropertyStreams; | 332 property_address.mSelector = kAudioDevicePropertyStreams; |
332 UInt32 stream_latency_frames = 0; | 333 UInt32 stream_latency_frames = 0; |
333 result = AudioObjectGetPropertyDataSize(output_device_id_, | 334 result = AudioObjectGetPropertyDataSize(output_device_id_, |
334 &property_address, | 335 &property_address, |
335 0, | 336 0, |
336 NULL, | 337 NULL, |
337 &size); | 338 &size); |
338 if (!result) { | 339 if (!result) { |
339 scoped_ptr_malloc<AudioStreamID> | 340 scoped_ptr_malloc<AudioStreamID> |
340 streams(reinterpret_cast<AudioStreamID*>(malloc(size))); | 341 streams(reinterpret_cast<AudioStreamID*>(malloc(size))); |
341 AudioStreamID* stream_ids = streams.get(); | 342 AudioStreamID* stream_ids = streams.get(); |
342 result = AudioObjectGetPropertyData(output_device_id_, | 343 result = AudioObjectGetPropertyData(output_device_id_, |
343 &property_address, | 344 &property_address, |
344 0, | 345 0, |
345 NULL, | 346 NULL, |
346 &size, | 347 &size, |
347 stream_ids); | 348 stream_ids); |
348 if (!result) { | 349 if (!result) { |
349 property_address.mSelector = kAudioStreamPropertyLatency; | 350 property_address.mSelector = kAudioStreamPropertyLatency; |
350 result = AudioObjectGetPropertyData(stream_ids[0], | 351 result = AudioObjectGetPropertyData(stream_ids[0], |
351 &property_address, | 352 &property_address, |
352 0, | 353 0, |
353 NULL, | 354 NULL, |
354 &size, | 355 &size, |
355 &stream_latency_frames); | 356 &stream_latency_frames); |
356 } | 357 } |
357 } | 358 } |
358 DLOG_IF(WARNING, result != noErr) << "Could not get audio stream latency."; | 359 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) |
| 360 << "Could not get audio stream latency"; |
359 | 361 |
360 return static_cast<double>((audio_unit_latency_sec * | 362 return static_cast<double>((audio_unit_latency_sec * |
361 format_.mSampleRate) + device_latency_frames + stream_latency_frames); | 363 format_.mSampleRate) + device_latency_frames + stream_latency_frames); |
362 } | 364 } |
363 | 365 |
364 double AUAudioOutputStream::GetPlayoutLatency( | 366 double AUAudioOutputStream::GetPlayoutLatency( |
365 const AudioTimeStamp* output_time_stamp) { | 367 const AudioTimeStamp* output_time_stamp) { |
366 // Get the delay between the moment getting the callback and the scheduled | 368 // Get the delay between the moment getting the callback and the scheduled |
367 // time stamp that tells when the data is going to be played out. | 369 // time stamp that tells when the data is going to be played out. |
368 UInt64 output_time_ns = AudioConvertHostTimeToNanos( | 370 UInt64 output_time_ns = AudioConvertHostTimeToNanos( |
369 output_time_stamp->mHostTime); | 371 output_time_stamp->mHostTime); |
370 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); | 372 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); |
371 double delay_frames = static_cast<double> | 373 double delay_frames = static_cast<double> |
372 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); | 374 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); |
373 | 375 |
374 return (delay_frames + hardware_latency_frames_); | 376 return (delay_frames + hardware_latency_frames_); |
375 } | 377 } |
OLD | NEW |