Chromium Code Reviews| 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 // process basis. What this means is that the |number_of_frames| value may be |
|
Chris Rogers
2012/10/08 22:14:31
nit: "process process"
DaleCurtis
2012/10/08 22:21:56
Done.
| |
| 240 // downstream, so glitch if it's not enabled. | 241 // larger or smaller than the value set during Configure(). In this case |
| 241 if (!kDisableAudioOutputResampler && | 242 // either 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; | |
| 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 |