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_input_mac.h" | 5 #include "media/audio/mac/audio_low_latency_input_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/logging.h" | 10 #include "base/logging.h" |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 reinterpret_cast<AUAudioInputStream*>(user_data); | 459 reinterpret_cast<AUAudioInputStream*>(user_data); |
460 DCHECK(audio_input); | 460 DCHECK(audio_input); |
461 if (!audio_input) | 461 if (!audio_input) |
462 return kAudioUnitErr_InvalidElement; | 462 return kAudioUnitErr_InvalidElement; |
463 | 463 |
464 // Update the |mDataByteSize| value in the audio_buffer_list() since | 464 // Update the |mDataByteSize| value in the audio_buffer_list() since |
465 // |number_of_frames| can be changed on the fly. | 465 // |number_of_frames| can be changed on the fly. |
466 // |mDataByteSize| needs to be exactly mapping to |number_of_frames|, | 466 // |mDataByteSize| needs to be exactly mapping to |number_of_frames|, |
467 // otherwise it will put CoreAudio into bad state and results in | 467 // otherwise it will put CoreAudio into bad state and results in |
468 // AudioUnitRender() returning -50 for the new created stream. | 468 // AudioUnitRender() returning -50 for the new created stream. |
| 469 // We have also seen kAudioUnitErr_TooManyFramesToProcess (-10874) and |
| 470 // kAudioUnitErr_CannotDoInCurrentContext (-10863) as error codes. |
469 // See crbug/428706 for details. | 471 // See crbug/428706 for details. |
470 UInt32 new_size = number_of_frames * audio_input->format_.mBytesPerFrame; | 472 UInt32 new_size = number_of_frames * audio_input->format_.mBytesPerFrame; |
471 AudioBuffer* audio_buffer = audio_input->audio_buffer_list()->mBuffers; | 473 AudioBuffer* audio_buffer = audio_input->audio_buffer_list()->mBuffers; |
472 if (new_size != audio_buffer->mDataByteSize) { | 474 if (new_size != audio_buffer->mDataByteSize) { |
473 if (new_size > audio_buffer->mDataByteSize) { | 475 if (new_size > audio_buffer->mDataByteSize) { |
474 // This can happen iff the device is unpluged during recording. In such | 476 // This can happen if the device is unpluged during recording. We |
475 // case the buffer will not be used anymore since |audio_unit_| becomes | 477 // allocate enough memory here to avoid depending on how CoreAudio |
476 // invalid. We allocate enough memory here to avoid depending on | 478 // handles it. |
477 // how CoreAudio handles it. | 479 // See See http://www.crbug.com/434681 for one example when we can enter |
| 480 // this scope. |
478 audio_input->audio_data_buffer_.reset(new uint8[new_size]); | 481 audio_input->audio_data_buffer_.reset(new uint8[new_size]); |
479 audio_buffer->mData = audio_input->audio_data_buffer_.get(); | 482 audio_buffer->mData = audio_input->audio_data_buffer_.get(); |
480 } | 483 } |
481 | 484 |
482 // Update the |mDataByteSize| to match |number_of_frames|. | 485 // Update the |mDataByteSize| to match |number_of_frames|. |
483 audio_buffer->mDataByteSize = new_size; | 486 audio_buffer->mDataByteSize = new_size; |
484 } | 487 } |
485 | 488 |
486 // Receive audio from the AUHAL from the output scope of the Audio Unit. | 489 // Receive audio from the AUHAL from the output scope of the Audio Unit. |
487 OSStatus result = AudioUnitRender(audio_input->audio_unit(), | 490 OSStatus result = AudioUnitRender(audio_input->audio_unit(), |
488 flags, | 491 flags, |
489 time_stamp, | 492 time_stamp, |
490 bus_number, | 493 bus_number, |
491 number_of_frames, | 494 number_of_frames, |
492 audio_input->audio_buffer_list()); | 495 audio_input->audio_buffer_list()); |
493 if (result) { | 496 if (result) { |
494 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.AudioInputCbErrorMac", result); | 497 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.AudioInputCbErrorMac", result); |
495 OSSTATUS_DLOG(ERROR, result) << "AudioUnitRender() failed."; | 498 OSSTATUS_DLOG(ERROR, result) << "AudioUnitRender() failed "; |
496 return result; | 499 return result; |
497 } | 500 } |
498 | 501 |
499 // Deliver recorded data to the consumer as a callback. | 502 // Deliver recorded data to the consumer as a callback. |
500 return audio_input->Provide(number_of_frames, | 503 return audio_input->Provide(number_of_frames, |
501 audio_input->audio_buffer_list(), | 504 audio_input->audio_buffer_list(), |
502 time_stamp); | 505 time_stamp); |
503 } | 506 } |
504 | 507 |
505 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, | 508 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, |
506 AudioBufferList* io_data, | 509 AudioBufferList* io_data, |
507 const AudioTimeStamp* time_stamp) { | 510 const AudioTimeStamp* time_stamp) { |
508 // Update the capture latency. | 511 // Update the capture latency. |
509 double capture_latency_frames = GetCaptureLatency(time_stamp); | 512 double capture_latency_frames = GetCaptureLatency(time_stamp); |
510 | 513 |
511 // The AGC volume level is updated once every second on a separate thread. | 514 // The AGC volume level is updated once every second on a separate thread. |
512 // Note that, |volume| is also updated each time SetVolume() is called | 515 // Note that, |volume| is also updated each time SetVolume() is called |
513 // through IPC by the render-side AGC. | 516 // through IPC by the render-side AGC. |
514 double normalized_volume = 0.0; | 517 double normalized_volume = 0.0; |
515 GetAgcVolume(&normalized_volume); | 518 GetAgcVolume(&normalized_volume); |
516 | 519 |
517 AudioBuffer& buffer = io_data->mBuffers[0]; | 520 AudioBuffer& buffer = io_data->mBuffers[0]; |
518 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); | 521 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); |
519 uint32 capture_delay_bytes = static_cast<uint32> | 522 uint32 capture_delay_bytes = static_cast<uint32> |
520 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); | 523 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); |
521 DCHECK(audio_data); | 524 DCHECK(audio_data); |
522 if (!audio_data) | 525 if (!audio_data) |
523 return kAudioUnitErr_InvalidElement; | 526 return kAudioUnitErr_InvalidElement; |
524 | 527 |
| 528 // Dynamically increase capacity of the FIFO to handle larger buffers from |
| 529 // CoreAudio. This can happen in combination with Apple Thunderbolt Displays |
| 530 // when the Display Audio is used as capture source and the cable is first |
| 531 // remove and then inserted again. |
| 532 // See http://www.crbug.com/434681 for details. |
| 533 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) { |
| 534 // Derive required increase in number of FIFO blocks. The increase is |
| 535 // typically one block. |
| 536 const int blocks = |
| 537 static_cast<int>((number_of_frames - fifo_.GetUnfilledFrames()) / |
| 538 number_of_frames_) + 1; |
| 539 DLOG(WARNING) << "Increasing FIFO capacity by " << blocks << " blocks"; |
| 540 fifo_.IncreaseCapacity(blocks); |
| 541 } |
| 542 |
525 // Copy captured (and interleaved) data into FIFO. | 543 // Copy captured (and interleaved) data into FIFO. |
526 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); | 544 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); |
527 | 545 |
528 // Consume and deliver the data when the FIFO has a block of available data. | 546 // Consume and deliver the data when the FIFO has a block of available data. |
529 while (fifo_.available_blocks()) { | 547 while (fifo_.available_blocks()) { |
530 const AudioBus* audio_bus = fifo_.Consume(); | 548 const AudioBus* audio_bus = fifo_.Consume(); |
531 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); | 549 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); |
532 | 550 |
533 // Compensate the audio delay caused by the FIFO. | 551 // Compensate the audio delay caused by the FIFO. |
534 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; | 552 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 kAudioDevicePropertyScopeInput, | 685 kAudioDevicePropertyScopeInput, |
668 static_cast<UInt32>(channel) | 686 static_cast<UInt32>(channel) |
669 }; | 687 }; |
670 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, | 688 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, |
671 &property_address, | 689 &property_address, |
672 &is_settable); | 690 &is_settable); |
673 return (result == noErr) ? is_settable : false; | 691 return (result == noErr) ? is_settable : false; |
674 } | 692 } |
675 | 693 |
676 } // namespace media | 694 } // namespace media |
OLD | NEW |