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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 switches::kDisableAudioOutputResampler); | 232 switches::kDisableAudioOutputResampler); |
| 228 | 233 |
| 229 // Update the playout latency. | 234 // Update the playout latency. |
| 230 double playout_latency_frames = GetPlayoutLatency(output_time_stamp); | 235 double playout_latency_frames = GetPlayoutLatency(output_time_stamp); |
| 231 | 236 |
| 232 AudioBuffer& buffer = io_data->mBuffers[0]; | 237 AudioBuffer& buffer = io_data->mBuffers[0]; |
| 233 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); | 238 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); |
| 234 uint32 hardware_pending_bytes = static_cast<uint32> | 239 uint32 hardware_pending_bytes = static_cast<uint32> |
| 235 ((playout_latency_frames + 0.5) * format_.mBytesPerFrame); | 240 ((playout_latency_frames + 0.5) * format_.mBytesPerFrame); |
| 236 | 241 |
| 237 // If we specify a buffer size which is too low, the OS will ask for more data | 242 // Unfortunately AUAudioInputStream and AUAudioOutputStream share the frame |
| 238 // to fulfill the hardware request, so resize the AudioBus as appropriate. | 243 // size set by kAudioDevicePropertyBufferFrameSize above on a per process |
| 239 // This change requires AudioOutputResampler to prevent buffer size mismatches | 244 // process basis. What this means is that the |number_of_frames| value may be |
| 240 // downstream, so glitch if it's not enabled. | 245 // larger or smaller than the value set during Configure(). The downstream |
| 241 if (!kDisableAudioOutputResampler && | 246 // audio pipeline does not support dynamic frame size changes, as such we must |
| 242 static_cast<UInt32>(audio_bus_->frames()) != number_of_frames) { | 247 // clip |frames_filled| as necessary, this will result in bad audio, but the |
| 243 audio_bus_ = AudioBus::Create(audio_bus_->channels(), number_of_frames); | 248 // alternative is a browser crash. |
| 244 } | 249 // TODO(henrika): This should never happen so long as we're always using the |
| 245 | 250 // hardware sample rate and the input/output streams configure the same frame |
| 251 // size. This is currently not true. See http://crbug.com/154352. Once | |
| 252 // fixed, a CHECK() should be added and the clipping + wall of text removed. | |
| 246 int frames_filled = std::min(source_->OnMoreData( | 253 int frames_filled = std::min(source_->OnMoreData( |
| 247 audio_bus_.get(), AudioBuffersState(0, hardware_pending_bytes)), | 254 audio_bus_.get(), AudioBuffersState(0, hardware_pending_bytes)), |
| 248 static_cast<int>(number_of_frames)); | 255 static_cast<int>(number_of_frames)); |
| 256 | |
| 249 // Note: If this ever changes to output raw float the data must be clipped and | 257 // 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. | 258 // sanitized since it may come from an untrusted source such as NaCl. |
| 251 audio_bus_->ToInterleaved( | 259 audio_bus_->ToInterleaved( |
| 252 frames_filled, format_.mBitsPerChannel / 8, audio_data); | 260 frames_filled, format_.mBitsPerChannel / 8, audio_data); |
|
Chris Rogers
2012/10/08 21:29:57
It looks like the ToInterleaved() call might write
DaleCurtis
2012/10/08 21:48:04
It will only write frames_filled which is clipped
| |
| 253 uint32 filled = frames_filled * format_.mBytesPerFrame; | 261 uint32 filled = frames_filled * format_.mBytesPerFrame; |
| 254 | 262 |
| 255 // Handle channel order for 5.1 audio. | 263 // Handle channel order for 5.1 audio. |
| 256 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; | 264 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; |
| 257 // volume adjust should use SSE optimized vector_fmul() prior to interleave. | 265 // volume adjust should use SSE optimized vector_fmul() prior to interleave. |
| 258 if (format_.mChannelsPerFrame == 6) { | 266 if (format_.mChannelsPerFrame == 6) { |
| 259 if (format_.mBitsPerChannel == 8) { | 267 if (format_.mBitsPerChannel == 8) { |
| 260 SwizzleCoreAudioLayout5_1(reinterpret_cast<uint8*>(audio_data), filled); | 268 SwizzleCoreAudioLayout5_1(reinterpret_cast<uint8*>(audio_data), filled); |
| 261 } else if (format_.mBitsPerChannel == 16) { | 269 } else if (format_.mBitsPerChannel == 16) { |
| 262 SwizzleCoreAudioLayout5_1(reinterpret_cast<int16*>(audio_data), filled); | 270 SwizzleCoreAudioLayout5_1(reinterpret_cast<int16*>(audio_data), filled); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 UInt64 output_time_ns = AudioConvertHostTimeToNanos( | 379 UInt64 output_time_ns = AudioConvertHostTimeToNanos( |
| 372 output_time_stamp->mHostTime); | 380 output_time_stamp->mHostTime); |
| 373 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); | 381 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); |
| 374 double delay_frames = static_cast<double> | 382 double delay_frames = static_cast<double> |
| 375 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); | 383 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); |
| 376 | 384 |
| 377 return (delay_frames + hardware_latency_frames_); | 385 return (delay_frames + hardware_latency_frames_); |
| 378 } | 386 } |
| 379 | 387 |
| 380 } // namespace media | 388 } // namespace media |
| OLD | NEW |