| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 format_.mBitsPerChannel = params.bits_per_sample(); | 72 format_.mBitsPerChannel = params.bits_per_sample(); |
| 73 format_.mChannelsPerFrame = params.channels(); | 73 format_.mChannelsPerFrame = params.channels(); |
| 74 format_.mFramesPerPacket = 1; | 74 format_.mFramesPerPacket = 1; |
| 75 format_.mBytesPerPacket = (format_.mBitsPerChannel * params.channels()) / 8; | 75 format_.mBytesPerPacket = (format_.mBitsPerChannel * params.channels()) / 8; |
| 76 format_.mBytesPerFrame = format_.mBytesPerPacket; | 76 format_.mBytesPerFrame = format_.mBytesPerPacket; |
| 77 format_.mReserved = 0; | 77 format_.mReserved = 0; |
| 78 | 78 |
| 79 DVLOG(1) << "Desired ouput format: " << format_; | 79 DVLOG(1) << "Desired ouput format: " << format_; |
| 80 | 80 |
| 81 // Calculate the number of sample frames per callback. | 81 // Calculate the number of sample frames per callback. |
| 82 number_of_frames_ = params.GetBytesPerBuffer() / format_.mBytesPerPacket; | 82 number_of_frames_ = params.frames_per_buffer(); |
| 83 DVLOG(1) << "Number of frames per callback: " << number_of_frames_; | 83 DVLOG(1) << "Number of frames per callback: " << number_of_frames_; |
| 84 const AudioParameters parameters = | |
| 85 manager_->GetDefaultOutputStreamParameters(); | |
| 86 CHECK_EQ(number_of_frames_, | |
| 87 static_cast<size_t>(parameters.frames_per_buffer())); | |
| 88 } | 84 } |
| 89 | 85 |
| 90 AUAudioOutputStream::~AUAudioOutputStream() { | 86 AUAudioOutputStream::~AUAudioOutputStream() { |
| 91 } | 87 } |
| 92 | 88 |
| 93 bool AUAudioOutputStream::Open() { | 89 bool AUAudioOutputStream::Open() { |
| 94 // Obtain the current input device selected by the user. | 90 // Obtain the current input device selected by the user. |
| 95 UInt32 size = sizeof(output_device_id_); | 91 UInt32 size = sizeof(output_device_id_); |
| 96 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, | 92 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
| 97 &kDefaultOutputDeviceAddress, | 93 &kDefaultOutputDeviceAddress, |
| 98 0, | 94 0, |
| 99 0, | 95 0, |
| 100 &size, | 96 &size, |
| 101 &output_device_id_); | 97 &output_device_id_); |
| 102 if (result != noErr || output_device_id_ == kAudioObjectUnknown) { | 98 if (result != noErr || output_device_id_ == kAudioObjectUnknown) { |
| 103 OSSTATUS_DLOG(WARNING, result) | 99 OSSTATUS_DLOG(ERROR, result) |
| 104 << "Could not get default audio output device."; | 100 << "Could not get default audio output device."; |
| 105 return false; | 101 return false; |
| 106 } | 102 } |
| 107 | 103 |
| 108 // Open and initialize the DefaultOutputUnit. | 104 // Open and initialize the DefaultOutputUnit. |
| 109 AudioComponent comp; | 105 AudioComponent comp; |
| 110 AudioComponentDescription desc; | 106 AudioComponentDescription desc; |
| 111 | 107 |
| 112 desc.componentType = kAudioUnitType_Output; | 108 desc.componentType = kAudioUnitType_Output; |
| 113 desc.componentSubType = kAudioUnitSubType_DefaultOutput; | 109 desc.componentSubType = kAudioUnitSubType_DefaultOutput; |
| 114 desc.componentManufacturer = kAudioUnitManufacturer_Apple; | 110 desc.componentManufacturer = kAudioUnitManufacturer_Apple; |
| 115 desc.componentFlags = 0; | 111 desc.componentFlags = 0; |
| 116 desc.componentFlagsMask = 0; | 112 desc.componentFlagsMask = 0; |
| 117 comp = AudioComponentFindNext(0, &desc); | 113 comp = AudioComponentFindNext(0, &desc); |
| 118 if (!comp) | 114 if (!comp) |
| 119 return false; | 115 return false; |
| 120 | 116 |
| 121 result = AudioComponentInstanceNew(comp, &output_unit_); | 117 result = AudioComponentInstanceNew(comp, &output_unit_); |
| 122 if (result != noErr) { | 118 if (result != noErr) { |
| 123 OSSTATUS_DLOG(WARNING, result) << "AudioComponentInstanceNew() failed."; | 119 OSSTATUS_DLOG(ERROR, result) << "AudioComponentInstanceNew() failed."; |
| 124 return false; | 120 return false; |
| 125 } | 121 } |
| 126 | 122 |
| 127 result = AudioUnitInitialize(output_unit_); | 123 result = AudioUnitInitialize(output_unit_); |
| 128 if (result != noErr) { | 124 if (result != noErr) { |
| 129 OSSTATUS_DLOG(WARNING, result) << "AudioUnitInitialize() failed."; | 125 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; |
| 130 return false; | 126 return false; |
| 131 } | 127 } |
| 132 | 128 |
| 133 hardware_latency_frames_ = GetHardwareLatency(); | 129 hardware_latency_frames_ = GetHardwareLatency(); |
| 134 | 130 |
| 135 return Configure(); | 131 return Configure(); |
| 136 } | 132 } |
| 137 | 133 |
| 138 bool AUAudioOutputStream::Configure() { | 134 bool AUAudioOutputStream::Configure() { |
| 139 // Set the render callback. | 135 // Set the render callback. |
| 140 AURenderCallbackStruct input; | 136 AURenderCallbackStruct input; |
| 141 input.inputProc = InputProc; | 137 input.inputProc = InputProc; |
| 142 input.inputProcRefCon = this; | 138 input.inputProcRefCon = this; |
| 143 OSStatus result = AudioUnitSetProperty( | 139 OSStatus result = AudioUnitSetProperty( |
| 144 output_unit_, | 140 output_unit_, |
| 145 kAudioUnitProperty_SetRenderCallback, | 141 kAudioUnitProperty_SetRenderCallback, |
| 146 kAudioUnitScope_Global, | 142 kAudioUnitScope_Global, |
| 147 0, | 143 0, |
| 148 &input, | 144 &input, |
| 149 sizeof(input)); | 145 sizeof(input)); |
| 150 if (result != noErr) { | 146 if (result != noErr) { |
| 151 OSSTATUS_DLOG(WARNING, result) | 147 OSSTATUS_DLOG(ERROR, result) |
| 152 << "AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed."; | 148 << "AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed."; |
| 153 return false; | 149 return false; |
| 154 } | 150 } |
| 155 | 151 |
| 156 // Set the stream format. | 152 // Set the stream format. |
| 157 result = AudioUnitSetProperty( | 153 result = AudioUnitSetProperty( |
| 158 output_unit_, | 154 output_unit_, |
| 159 kAudioUnitProperty_StreamFormat, | 155 kAudioUnitProperty_StreamFormat, |
| 160 kAudioUnitScope_Input, | 156 kAudioUnitScope_Input, |
| 161 0, | 157 0, |
| 162 &format_, | 158 &format_, |
| 163 sizeof(format_)); | 159 sizeof(format_)); |
| 164 if (result != noErr) { | 160 if (result != noErr) { |
| 165 OSSTATUS_DLOG(WARNING, result) | 161 OSSTATUS_DLOG(ERROR, result) |
| 166 << "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed."; | 162 << "AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed."; |
| 167 return false; | 163 return false; |
| 168 } | 164 } |
| 169 | 165 |
| 170 // Set the buffer frame size. | 166 // Set the buffer frame size. |
| 171 // WARNING: Setting this value changes the frame size for all audio units in | 167 // WARNING: Setting this value changes the frame size for all audio units in |
| 172 // the current process. It's imperative that the input and output frame sizes | 168 // the current process. It's imperative that the input and output frame sizes |
| 173 // be the same as the frames_per_buffer() returned by | 169 // be the same as the frames_per_buffer() returned by |
| 174 // GetDefaultOutputStreamParameters. | 170 // GetDefaultOutputStreamParameters. |
| 175 // See http://crbug.com/154352 for details. | 171 // See http://crbug.com/154352 for details. |
| 172 const AudioParameters hw_params = |
| 173 manager_->GetDefaultOutputStreamParameters(); |
| 174 if (number_of_frames_ != static_cast<size_t>(hw_params.frames_per_buffer())) { |
| 175 DLOG(ERROR) << "Audio buffer size does not match hardware buffer size."; |
| 176 return false; |
| 177 } |
| 178 |
| 176 UInt32 buffer_size = number_of_frames_; | 179 UInt32 buffer_size = number_of_frames_; |
| 177 result = AudioUnitSetProperty( | 180 result = AudioUnitSetProperty( |
| 178 output_unit_, | 181 output_unit_, |
| 179 kAudioDevicePropertyBufferFrameSize, | 182 kAudioDevicePropertyBufferFrameSize, |
| 180 kAudioUnitScope_Output, | 183 kAudioUnitScope_Output, |
| 181 0, | 184 0, |
| 182 &buffer_size, | 185 &buffer_size, |
| 183 sizeof(buffer_size)); | 186 sizeof(buffer_size)); |
| 184 if (result != noErr) { | 187 if (result != noErr) { |
| 185 OSSTATUS_DLOG(WARNING, result) | 188 OSSTATUS_DLOG(ERROR, result) |
| 186 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed."; | 189 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed."; |
| 187 return false; | 190 return false; |
| 188 } | 191 } |
| 189 | 192 |
| 190 return true; | 193 return true; |
| 191 } | 194 } |
| 192 | 195 |
| 193 void AUAudioOutputStream::Close() { | 196 void AUAudioOutputStream::Close() { |
| 194 if (output_unit_) | 197 if (output_unit_) |
| 195 AudioComponentInstanceDispose(output_unit_); | 198 AudioComponentInstanceDispose(output_unit_); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 if (now_ns > output_time_ns) | 415 if (now_ns > output_time_ns) |
| 413 return 0; | 416 return 0; |
| 414 | 417 |
| 415 double delay_frames = static_cast<double> | 418 double delay_frames = static_cast<double> |
| 416 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); | 419 (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate); |
| 417 | 420 |
| 418 return (delay_frames + hardware_latency_frames_); | 421 return (delay_frames + hardware_latency_frames_); |
| 419 } | 422 } |
| 420 | 423 |
| 421 } // namespace media | 424 } // namespace media |
| OLD | NEW |