OLD | NEW |
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_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/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 kAudioUnitProperty_StreamFormat, | 147 kAudioUnitProperty_StreamFormat, |
148 kAudioUnitScope_Input, | 148 kAudioUnitScope_Input, |
149 0, | 149 0, |
150 &format_, | 150 &format_, |
151 sizeof(format_)); | 151 sizeof(format_)); |
152 OSSTATUS_DCHECK(result == noErr, result); | 152 OSSTATUS_DCHECK(result == noErr, result); |
153 if (result) | 153 if (result) |
154 return false; | 154 return false; |
155 | 155 |
156 // Set the buffer frame size. | 156 // Set the buffer frame size. |
| 157 // WARNING: Setting this value changes the frame size for all audio units in |
| 158 // the current process. It's imperative that the input and output frame sizes |
| 159 // be the same as audio_util::GetAudioHardwareBufferSize(). |
| 160 // TODO(henrika): Due to http://crrev.com/159666 this is currently not true |
| 161 // and should be fixed, a CHECK() should be added at that time. |
157 UInt32 buffer_size = number_of_frames_; | 162 UInt32 buffer_size = number_of_frames_; |
158 result = AudioUnitSetProperty( | 163 result = AudioUnitSetProperty( |
159 output_unit_, | 164 output_unit_, |
160 kAudioDevicePropertyBufferFrameSize, | 165 kAudioDevicePropertyBufferFrameSize, |
161 kAudioUnitScope_Output, | 166 kAudioUnitScope_Output, |
162 0, | 167 0, |
163 &buffer_size, | 168 &buffer_size, |
164 sizeof(buffer_size)); | 169 sizeof(buffer_size)); |
165 OSSTATUS_DCHECK(result == noErr, result); | 170 OSSTATUS_DCHECK(result == noErr, result); |
166 if (result) | 171 if (result) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 return; | 220 return; |
216 *volume = volume_; | 221 *volume = volume_; |
217 } | 222 } |
218 | 223 |
219 // Pulls on our provider to get rendered audio stream. | 224 // Pulls on our provider to get rendered audio stream. |
220 // Note to future hackers of this function: Do not add locks here because this | 225 // Note to future hackers of this function: Do not add locks here because this |
221 // is running on a real-time thread (for low-latency). | 226 // is running on a real-time thread (for low-latency). |
222 OSStatus AUAudioOutputStream::Render(UInt32 number_of_frames, | 227 OSStatus AUAudioOutputStream::Render(UInt32 number_of_frames, |
223 AudioBufferList* io_data, | 228 AudioBufferList* io_data, |
224 const AudioTimeStamp* output_time_stamp) { | 229 const AudioTimeStamp* output_time_stamp) { |
225 static const bool kDisableAudioOutputResampler = | |
226 CommandLine::ForCurrentProcess()->HasSwitch( | |
227 switches::kDisableAudioOutputResampler); | |
228 | |
229 // Update the playout latency. | 230 // Update the playout latency. |
230 double playout_latency_frames = GetPlayoutLatency(output_time_stamp); | 231 double playout_latency_frames = GetPlayoutLatency(output_time_stamp); |
231 | 232 |
232 AudioBuffer& buffer = io_data->mBuffers[0]; | 233 AudioBuffer& buffer = io_data->mBuffers[0]; |
233 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); | 234 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); |
234 uint32 hardware_pending_bytes = static_cast<uint32> | 235 uint32 hardware_pending_bytes = static_cast<uint32> |
235 ((playout_latency_frames + 0.5) * format_.mBytesPerFrame); | 236 ((playout_latency_frames + 0.5) * format_.mBytesPerFrame); |
236 | 237 |
237 // If we specify a buffer size which is too low, the OS will ask for more data | 238 // Unfortunately AUAudioInputStream and AUAudioOutputStream share the frame |
238 // to fulfill the hardware request, so resize the AudioBus as appropriate. | 239 // size set by kAudioDevicePropertyBufferFrameSize above on a per process |
239 // This change requires AudioOutputResampler to prevent buffer size mismatches | 240 // basis. What this means is that the |number_of_frames| value may be larger |
240 // downstream, so glitch if it's not enabled. | 241 // or smaller than the value set during Configure(). In this case either |
241 if (!kDisableAudioOutputResampler && | 242 // audio input or audio output will be broken, so just output silence. |
242 static_cast<UInt32>(audio_bus_->frames()) != number_of_frames) { | 243 // TODO(henrika): This should never happen so long as we're always using the |
243 audio_bus_ = AudioBus::Create(audio_bus_->channels(), number_of_frames); | 244 // hardware sample rate and the input/output streams configure the same frame |
| 245 // size. This is currently not true. See http://crbug.com/154352. Once |
| 246 // fixed, a CHECK() should be added and this wall of text removed. |
| 247 if (number_of_frames != static_cast<UInt32>(audio_bus_->frames())) { |
| 248 memset(audio_data, 0, number_of_frames * format_.mBytesPerFrame); |
| 249 return noErr; |
244 } | 250 } |
245 | 251 |
246 int frames_filled = std::min(source_->OnMoreData( | 252 int frames_filled = source_->OnMoreData( |
247 audio_bus_.get(), AudioBuffersState(0, hardware_pending_bytes)), | 253 audio_bus_.get(), AudioBuffersState(0, hardware_pending_bytes)); |
248 static_cast<int>(number_of_frames)); | 254 |
249 // Note: If this ever changes to output raw float the data must be clipped and | 255 // Note: If this ever changes to output raw float the data must be clipped and |
250 // sanitized since it may come from an untrusted source such as NaCl. | 256 // sanitized since it may come from an untrusted source such as NaCl. |
251 audio_bus_->ToInterleaved( | 257 audio_bus_->ToInterleaved( |
252 frames_filled, format_.mBitsPerChannel / 8, audio_data); | 258 frames_filled, format_.mBitsPerChannel / 8, audio_data); |
253 uint32 filled = frames_filled * format_.mBytesPerFrame; | 259 uint32 filled = frames_filled * format_.mBytesPerFrame; |
254 | 260 |
255 // Handle channel order for 5.1 audio. | 261 // Handle channel order for 5.1 audio. |
256 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; | 262 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; |
257 // volume adjust should use SSE optimized vector_fmul() prior to interleave. | 263 // volume adjust should use SSE optimized vector_fmul() prior to interleave. |
258 if (format_.mChannelsPerFrame == 6) { | 264 if (format_.mChannelsPerFrame == 6) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 UInt64 output_time_ns = AudioConvertHostTimeToNanos( | 377 UInt64 output_time_ns = AudioConvertHostTimeToNanos( |
372 output_time_stamp->mHostTime); | 378 output_time_stamp->mHostTime); |
373 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); | 379 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); |
374 double delay_frames = static_cast<double> | 380 double delay_frames = static_cast<double> |
375 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); | 381 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); |
376 | 382 |
377 return (delay_frames + hardware_latency_frames_); | 383 return (delay_frames + hardware_latency_frames_); |
378 } | 384 } |
379 | 385 |
380 } // namespace media | 386 } // namespace media |
OLD | NEW |