| Index: media/audio/mac/audio_low_latency_input_mac.cc
|
| diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc
|
| index d7a3430f6d85edfcdf8d9ad9fa9d35effec6fe90..f0f6629185fb63fca4ebe97004231f47b18e31b6 100644
|
| --- a/media/audio/mac/audio_low_latency_input_mac.cc
|
| +++ b/media/audio/mac/audio_low_latency_input_mac.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/mac/mac_logging.h"
|
| #include "media/audio/mac/audio_manager_mac.h"
|
| #include "media/base/audio_bus.h"
|
| +#include "media/base/audio_fifo.h"
|
| #include "media/base/data_buffer.h"
|
|
|
| namespace media {
|
| @@ -34,17 +35,17 @@ static std::ostream& operator<<(std::ostream& os,
|
|
|
| AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager,
|
| const AudioParameters& input_params,
|
| - const AudioParameters& output_params,
|
| AudioDeviceID audio_device_id)
|
| : manager_(manager),
|
| + number_of_frames_(input_params.frames_per_buffer()),
|
| sink_(NULL),
|
| audio_unit_(0),
|
| input_device_id_(audio_device_id),
|
| started_(false),
|
| hardware_latency_frames_(0),
|
| - fifo_delay_bytes_(0),
|
| number_of_channels_in_frame_(0),
|
| - audio_bus_(media::AudioBus::Create(input_params)) {
|
| + audio_bus_(media::AudioBus::Create(input_params)),
|
| + audio_wrapper_(media::AudioBus::Create(input_params)) {
|
| DCHECK(manager_);
|
|
|
| // Set up the desired (output) format specified by the client.
|
| @@ -62,12 +63,6 @@ AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager,
|
|
|
| DVLOG(1) << "Desired ouput format: " << format_;
|
|
|
| - // Set number of sample frames per callback used by the internal audio layer.
|
| - // An internal FIFO is then utilized to adapt the internal size to the size
|
| - // requested by the client.
|
| - number_of_frames_ = output_params.frames_per_buffer();
|
| - DVLOG(1) << "Size of data buffer in frames : " << number_of_frames_;
|
| -
|
| // Derive size (in bytes) of the buffers that we will render to.
|
| UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame;
|
| DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size;
|
| @@ -82,38 +77,6 @@ AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager,
|
| audio_buffer->mNumberChannels = input_params.channels();
|
| audio_buffer->mDataByteSize = data_byte_size;
|
| audio_buffer->mData = audio_data_buffer_.get();
|
| -
|
| - // Set up an internal FIFO buffer that will accumulate recorded audio frames
|
| - // until a requested size is ready to be sent to the client.
|
| - // It is not possible to ask for less than |kAudioFramesPerCallback| number of
|
| - // audio frames.
|
| - size_t requested_size_frames =
|
| - input_params.GetBytesPerBuffer() / format_.mBytesPerPacket;
|
| - if (requested_size_frames < number_of_frames_) {
|
| - // For devices that only support a low sample rate like 8kHz, we adjust the
|
| - // buffer size to match number_of_frames_. The value of number_of_frames_
|
| - // in this case has not been calculated based on hardware settings but
|
| - // rather our hardcoded defaults (see ChooseBufferSize).
|
| - requested_size_frames = number_of_frames_;
|
| - }
|
| -
|
| - requested_size_bytes_ = requested_size_frames * format_.mBytesPerFrame;
|
| - DVLOG(1) << "Requested buffer size in bytes : " << requested_size_bytes_;
|
| - DVLOG_IF(0, requested_size_frames > number_of_frames_) << "FIFO is used";
|
| -
|
| - const int number_of_bytes = number_of_frames_ * format_.mBytesPerFrame;
|
| - fifo_delay_bytes_ = requested_size_bytes_ - number_of_bytes;
|
| -
|
| - // Allocate some extra memory to avoid memory reallocations.
|
| - // Ensure that the size is an even multiple of |number_of_frames_ and
|
| - // larger than |requested_size_frames|.
|
| - // Example: number_of_frames_=128, requested_size_frames=480 =>
|
| - // allocated space equals 4*128=512 audio frames
|
| - const int max_forward_capacity = number_of_bytes *
|
| - ((requested_size_frames / number_of_frames_) + 1);
|
| - fifo_.reset(new media::SeekableBuffer(0, max_forward_capacity));
|
| -
|
| - data_ = new media::DataBuffer(requested_size_bytes_);
|
| }
|
|
|
| AUAudioInputStream::~AUAudioInputStream() {}
|
| @@ -132,20 +95,20 @@ bool AUAudioInputStream::Open() {
|
|
|
| // Start by obtaining an AudioOuputUnit using an AUHAL component description.
|
|
|
| - Component comp;
|
| - ComponentDescription desc;
|
| -
|
| // Description for the Audio Unit we want to use (AUHAL in this case).
|
| - desc.componentType = kAudioUnitType_Output;
|
| - desc.componentSubType = kAudioUnitSubType_HALOutput;
|
| - desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
| - desc.componentFlags = 0;
|
| - desc.componentFlagsMask = 0;
|
| - comp = FindNextComponent(0, &desc);
|
| + AudioComponentDescription desc = {
|
| + kAudioUnitType_Output,
|
| + kAudioUnitSubType_HALOutput,
|
| + kAudioUnitManufacturer_Apple,
|
| + 0,
|
| + 0
|
| + };
|
| +
|
| + AudioComponent comp = AudioComponentFindNext(0, &desc);
|
| DCHECK(comp);
|
|
|
| // Get access to the service provided by the specified Audio Unit.
|
| - OSStatus result = OpenAComponent(comp, &audio_unit_);
|
| + OSStatus result = AudioComponentInstanceNew(comp, &audio_unit_);
|
| if (result) {
|
| HandleError(result);
|
| return false;
|
| @@ -527,27 +490,45 @@ OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
|
| uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
|
| uint32 capture_delay_bytes = static_cast<uint32>
|
| ((capture_latency_frames + 0.5) * format_.mBytesPerFrame);
|
| - // Account for the extra delay added by the FIFO.
|
| - capture_delay_bytes += fifo_delay_bytes_;
|
| DCHECK(audio_data);
|
| if (!audio_data)
|
| return kAudioUnitErr_InvalidElement;
|
|
|
| - // Accumulate captured audio in FIFO until we can match the output size
|
| - // requested by the client.
|
| - fifo_->Append(audio_data, buffer.mDataByteSize);
|
| + if (number_of_frames != number_of_frames_) {
|
| + // Create a FIFO on the fly to handle any discrepancies in callback rates.
|
| + if (!fifo_) {
|
| + VLOG(1) << "Audio frame size changed from " << number_of_frames_ << " to "
|
| + << number_of_frames << "; adding FIFO to compensate.";
|
| + fifo_.reset(new AudioFifo(
|
| + format_.mChannelsPerFrame, number_of_frames_ + number_of_frames));
|
| + }
|
| +
|
| + if (audio_wrapper_->frames() != static_cast<int>(number_of_frames)) {
|
| + audio_wrapper_ = media::AudioBus::Create(format_.mChannelsPerFrame,
|
| + number_of_frames);
|
| + }
|
| + }
|
| +
|
| + // Copy captured (and interleaved) data into deinterleaved audio bus.
|
| + audio_wrapper_->FromInterleaved(
|
| + audio_data, audio_wrapper_->frames(), format_.mBitsPerChannel / 8);
|
|
|
| - // Deliver recorded data to the client as soon as the FIFO contains a
|
| - // sufficient amount.
|
| - if (fifo_->forward_bytes() >= requested_size_bytes_) {
|
| - // Read from FIFO into temporary data buffer.
|
| - fifo_->Read(data_->writable_data(), requested_size_bytes_);
|
| + // When FIFO does not kick in, data will be directly passed to the callback.
|
| + if (!fifo_) {
|
| + CHECK_EQ(audio_wrapper_->frames(), static_cast<int>(number_of_frames_));
|
| + sink_->OnData(
|
| + this, audio_wrapper_.get(), capture_delay_bytes, normalized_volume);
|
| + return noErr;
|
| + }
|
|
|
| - // Copy captured (and interleaved) data into deinterleaved audio bus.
|
| - audio_bus_->FromInterleaved(
|
| - data_->data(), audio_bus_->frames(), format_.mBitsPerChannel / 8);
|
| + // Compensate the audio delay caused by the FIFO.
|
| + capture_delay_bytes += fifo_->frames() * format_.mBytesPerFrame;
|
| + fifo_->Push(audio_wrapper_.get());
|
| + if (fifo_->frames() >= static_cast<int>(number_of_frames_)) {
|
| + // Consume the audio from the FIFO.
|
| + fifo_->Consume(audio_bus_.get(), 0, audio_bus_->frames());
|
| + DCHECK(fifo_->frames() < static_cast<int>(number_of_frames_));
|
|
|
| - // Deliver data packet, delay estimation and volume level to the user.
|
| sink_->OnData(
|
| this, audio_bus_.get(), capture_delay_bytes, normalized_volume);
|
| }
|
|
|