| Index: media/audio/audio_input_proxy.cc
|
| diff --git a/media/audio/audio_input_proxy.cc b/media/audio/audio_input_proxy.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..988a412db30f62c3415a0fbe39d7a0c1764b92c6
|
| --- /dev/null
|
| +++ b/media/audio/audio_input_proxy.cc
|
| @@ -0,0 +1,182 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "media/audio/audio_input_proxy.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/time/time.h"
|
| +#include "media/audio/audio_manager_base.h"
|
| +#include "media/base/audio_fifo.h"
|
| +
|
| +namespace media {
|
| +
|
| +AudioInputProxy::AudioInputProxy(AudioManagerBase* manager,
|
| + const AudioParameters& input_params,
|
| + const AudioParameters& output_params,
|
| + const std::string& device_id)
|
| + : audio_manager_(manager),
|
| + stream_(NULL),
|
| + input_params_(input_params),
|
| + output_params_(output_params),
|
| + device_id_(device_id),
|
| + callback_(NULL),
|
| + opened_(false),
|
| + agc_enabled_(false) {
|
| + DCHECK(input_params.IsValid());
|
| + DCHECK(output_params.IsValid());
|
| + DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
|
| +
|
| + Initialize(input_params);
|
| +}
|
| +
|
| +AudioInputProxy::~AudioInputProxy() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + Close();
|
| +}
|
| +
|
| +void AudioInputProxy::MaybeRestartStream(const AudioParameters& input_params) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + // Do nothing if the required input formats are the same.
|
| + if (input_params == input_params_)
|
| + return;
|
| +
|
| + // Do nothing if |stream_| has already been closed, which means this proxy
|
| + // is idle.
|
| + if (!stream_)
|
| + return;
|
| +
|
| + // Cache the |callback_| because Stop() will set it to NULL>
|
| + AudioInputStream::AudioInputCallback* callback = callback_;
|
| +
|
| + // Stop and Close the old stream.
|
| + Stop();
|
| + Close();
|
| + DCHECK(!stream_);
|
| +
|
| + // Initialize the new stream.
|
| + Initialize(input_params);
|
| +
|
| + // Create and restore the previous state for the new stream.
|
| + if (opened_)
|
| + Open();
|
| +
|
| + // AGC needs to be enabled before calling Start();
|
| + SetAutomaticGainControl(agc_enabled_);
|
| +
|
| + if (callback)
|
| + Start(callback);
|
| + DCHECK_EQ(callback, callback_);
|
| +}
|
| +
|
| +void AudioInputProxy::Initialize(const AudioParameters& input_params) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + // We do not support resampling and down/up-mixing yet.
|
| + // TODO(xians): Implement a push model AudioConverter and support resampling.
|
| + DCHECK_EQ(output_params_.sample_rate(), input_params.sample_rate());
|
| + DCHECK_EQ(output_params_.channels(), input_params.channels());
|
| + DCHECK(!stream_);
|
| +
|
| + input_params_ = input_params;
|
| +
|
| + // Create the required audio fifo and audio bus to deal with the
|
| + // mismatching between the input and output params.
|
| + // The size of the FIFO is input buffer size + output buffer size.
|
| + // When the input buffer size and the output buffer size are the same, FIFO
|
| + // is not needed.
|
| + if (input_params_.frames_per_buffer() != output_params_.frames_per_buffer()) {
|
| + int buffer_size =
|
| + input_params_.frames_per_buffer() + output_params_.frames_per_buffer();
|
| + fifo_.reset(new media::AudioFifo(input_params_.channels(), buffer_size));
|
| + audio_bus_ = media::AudioBus::Create(
|
| + output_params_.channels(), output_params_.frames_per_buffer());
|
| + }
|
| +
|
| + // Create a new audio input stream.
|
| + stream_ = audio_manager_->MakeLowLatencyInputStream(input_params, device_id_);
|
| +}
|
| +
|
| +bool AudioInputProxy::Open() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(!stream_);
|
| +
|
| + opened_ = true;
|
| + return stream_->Open();
|
| +}
|
| +
|
| +void AudioInputProxy::Start(AudioInputStream::AudioInputCallback* callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(!callback_ || callback_ == callback);
|
| +
|
| + stream_->Start(callback);
|
| + callback_ = callback;
|
| +}
|
| +
|
| +void AudioInputProxy::Stop() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + stream_->Stop();
|
| + callback_ = NULL;
|
| +}
|
| +
|
| +void AudioInputProxy::Close() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!stream_)
|
| + return;
|
| +
|
| + // AudioManager owns the |stream_|.
|
| + stream_->Close();
|
| + stream_ = NULL;
|
| +}
|
| +
|
| +double AudioInputProxy::GetMaxVolume() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return stream_->GetMaxVolume();
|
| +}
|
| +
|
| +void AudioInputProxy::SetVolume(double volume) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + stream_->SetVolume(volume);
|
| +}
|
| +
|
| +double AudioInputProxy::GetVolume() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return stream_->GetVolume();
|
| +}
|
| +
|
| +void AudioInputProxy::SetAutomaticGainControl(bool enabled) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + stream_->SetAutomaticGainControl(enabled);
|
| + agc_enabled_ = enabled;
|
| +}
|
| +
|
| +bool AudioInputProxy::GetAutomaticGainControl() {
|
| + return stream_->GetAutomaticGainControl();
|
| +}
|
| +
|
| +void AudioInputProxy::OnData(AudioInputStream* stream,
|
| + const media::AudioBus* src,
|
| + uint32 hardware_delay_bytes,
|
| + double volume) {
|
| + // TODO(xians) We need to handle the frames changing on the fly ??
|
| + DCHECK_EQ(src->frames(), input_params_.frames_per_buffer());
|
| + if (!fifo_.get())
|
| + callback_->OnData(stream, src, hardware_delay_bytes, volume);
|
| +
|
| + DCHECK_LE(fifo_->frames() + src->frames(), fifo_->max_frames());
|
| + fifo_->Push(src);
|
| +
|
| + // Consume the data if the FIFO has enough data.
|
| + while (fifo_->frames() >= output_params_.frames_per_buffer()) {
|
| + fifo_->Consume(audio_bus_.get(), 0, audio_bus_->frames());
|
| + callback_->OnData(stream, audio_bus_.get(), hardware_delay_bytes, volume);
|
| + }
|
| +}
|
| +
|
| +void AudioInputProxy::OnError(AudioInputStream* stream) {
|
| + callback_->OnError(stream);
|
| +}
|
| +
|
| +
|
| +
|
| +} // namespace media
|
|
|