OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_auhal_mac.h" | 5 #include "media/audio/mac/audio_auhal_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/bind.h" | 10 #include "base/bind.h" |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 // the stream are ok) because this is running on a real-time thread. | 210 // the stream are ok) because this is running on a real-time thread. |
211 OSStatus AUHALStream::Render( | 211 OSStatus AUHALStream::Render( |
212 AudioUnitRenderActionFlags* flags, | 212 AudioUnitRenderActionFlags* flags, |
213 const AudioTimeStamp* output_time_stamp, | 213 const AudioTimeStamp* output_time_stamp, |
214 UInt32 bus_number, | 214 UInt32 bus_number, |
215 UInt32 number_of_frames, | 215 UInt32 number_of_frames, |
216 AudioBufferList* io_data) { | 216 AudioBufferList* io_data) { |
217 TRACE_EVENT0("audio", "AUHALStream::Render"); | 217 TRACE_EVENT0("audio", "AUHALStream::Render"); |
218 | 218 |
219 // If the stream parameters change for any reason, we need to insert a FIFO | 219 // If the stream parameters change for any reason, we need to insert a FIFO |
220 // since the OnMoreData() pipeline can't handle frame size changes. Generally | 220 // since the OnMoreData() pipeline can't handle frame size changes. |
221 // this is a temporary situation which can occur after a device change has | |
222 // occurred but the AudioManager hasn't received the notification yet. | |
223 if (number_of_frames != number_of_frames_) { | 221 if (number_of_frames != number_of_frames_) { |
224 // Create a FIFO on the fly to handle any discrepancies in callback rates. | 222 // Create a FIFO on the fly to handle any discrepancies in callback rates. |
225 if (!audio_fifo_) { | 223 if (!audio_fifo_) { |
226 VLOG(1) << "Audio frame size change detected; adding FIFO to compensate."; | 224 VLOG(1) << "Audio frame size changed from " << number_of_frames_ << " to " |
| 225 << number_of_frames << "; adding FIFO to compensate."; |
227 audio_fifo_.reset(new AudioPullFifo( | 226 audio_fifo_.reset(new AudioPullFifo( |
228 output_channels_, | 227 output_channels_, |
229 number_of_frames_, | 228 number_of_frames_, |
230 base::Bind(&AUHALStream::ProvideInput, base::Unretained(this)))); | 229 base::Bind(&AUHALStream::ProvideInput, base::Unretained(this)))); |
231 } | 230 } |
232 | 231 |
233 // Synchronous IO is not supported in this state. | 232 // Synchronous IO is not supported in this state. |
234 if (input_channels_ > 0) | 233 if (input_channels_ > 0) |
235 input_bus_->Zero(); | 234 input_bus_->Zero(); |
236 } else { | 235 } else { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 | 501 |
503 if (output_channels_ > 0) { | 502 if (output_channels_ > 0) { |
504 if (!SetStreamFormat(&output_format_, | 503 if (!SetStreamFormat(&output_format_, |
505 output_channels_, | 504 output_channels_, |
506 kAudioUnitScope_Input, | 505 kAudioUnitScope_Input, |
507 0)) | 506 0)) |
508 return false; | 507 return false; |
509 } | 508 } |
510 | 509 |
511 // Set the buffer frame size. | 510 // Set the buffer frame size. |
512 // WARNING: Setting this value changes the frame size for all audio units in | 511 // WARNING: Setting this value changes the frame size for all output audio |
513 // the current process. It's imperative that the input and output frame sizes | 512 // units in the current process. As a result, the AURenderCallback must be |
514 // be the same as the frames_per_buffer() returned by | 513 // able to handle arbitrary buffer sizes and FIFO appropriately. |
515 // GetDefaultOutputStreamParameters(). | 514 UInt32 buffer_size = 0; |
516 // See http://crbug.com/154352 for details. | 515 UInt32 property_size = sizeof(buffer_size); |
517 UInt32 buffer_size = number_of_frames_; | 516 result = AudioUnitGetProperty(audio_unit_, |
518 result = AudioUnitSetProperty( | 517 kAudioDevicePropertyBufferFrameSize, |
519 audio_unit_, | 518 kAudioUnitScope_Output, |
520 kAudioDevicePropertyBufferFrameSize, | 519 0, |
521 kAudioUnitScope_Output, | 520 &buffer_size, |
522 0, | 521 &property_size); |
523 &buffer_size, | |
524 sizeof(buffer_size)); | |
525 if (result != noErr) { | 522 if (result != noErr) { |
526 OSSTATUS_DLOG(ERROR, result) | 523 OSSTATUS_DLOG(ERROR, result) |
527 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed."; | 524 << "AudioUnitGetProperty(kAudioDevicePropertyBufferFrameSize) failed."; |
528 return false; | 525 return false; |
529 } | 526 } |
530 | 527 |
| 528 // Only set the buffer size if we're the only active stream or the buffer size |
| 529 // is lower than the current buffer size. |
| 530 if (manager_->output_stream_count() == 1 || number_of_frames_ < buffer_size) { |
| 531 buffer_size = number_of_frames_; |
| 532 result = AudioUnitSetProperty(audio_unit_, |
| 533 kAudioDevicePropertyBufferFrameSize, |
| 534 kAudioUnitScope_Output, |
| 535 0, |
| 536 &buffer_size, |
| 537 sizeof(buffer_size)); |
| 538 if (result != noErr) { |
| 539 OSSTATUS_DLOG(ERROR, result) << "AudioUnitSetProperty(" |
| 540 "kAudioDevicePropertyBufferFrameSize) " |
| 541 "failed. Size: " << number_of_frames_; |
| 542 return false; |
| 543 } |
| 544 } |
| 545 |
531 // Setup callback. | 546 // Setup callback. |
532 AURenderCallbackStruct callback; | 547 AURenderCallbackStruct callback; |
533 callback.inputProc = InputProc; | 548 callback.inputProc = InputProc; |
534 callback.inputProcRefCon = this; | 549 callback.inputProcRefCon = this; |
535 result = AudioUnitSetProperty( | 550 result = AudioUnitSetProperty( |
536 audio_unit_, | 551 audio_unit_, |
537 kAudioUnitProperty_SetRenderCallback, | 552 kAudioUnitProperty_SetRenderCallback, |
538 kAudioUnitScope_Input, | 553 kAudioUnitScope_Input, |
539 0, | 554 0, |
540 &callback, | 555 &callback, |
541 sizeof(callback)); | 556 sizeof(callback)); |
542 if (result != noErr) | 557 if (result != noErr) |
543 return false; | 558 return false; |
544 | 559 |
545 result = AudioUnitInitialize(audio_unit_); | 560 result = AudioUnitInitialize(audio_unit_); |
546 if (result != noErr) { | 561 if (result != noErr) { |
547 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; | 562 OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed."; |
548 return false; | 563 return false; |
549 } | 564 } |
550 | 565 |
551 return true; | 566 return true; |
552 } | 567 } |
553 | 568 |
554 } // namespace media | 569 } // namespace media |
OLD | NEW |