| 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 |