| Index: media/audio/virtual_audio_input_stream.cc
|
| diff --git a/media/audio/virtual_audio_input_stream.cc b/media/audio/virtual_audio_input_stream.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4f2f9bd04fb84a4619766597777c75665b5641c6
|
| --- /dev/null
|
| +++ b/media/audio/virtual_audio_input_stream.cc
|
| @@ -0,0 +1,173 @@
|
| +// Copyright (c) 2012 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/virtual_audio_input_stream.h"
|
| +
|
| +#include <algorithm>
|
| +#include <utility>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop.h"
|
| +#include "media/audio/virtual_audio_output_stream.h"
|
| +
|
| +namespace media {
|
| +
|
| +// LoopbackAudioConverter works similar to AudioConverter and converts input
|
| +// streams to different audio parameters. Then, the LoopbackAudioConverter can
|
| +// be used as an input to another AudioConverter. This allows us to
|
| +// use converted audio from AudioOutputStreams as input to an AudioConverter.
|
| +// For example, this allows converting multiple streams into a common format and
|
| +// using the converted audio as input to another AudioConverter (i.e. a mixer).
|
| +class LoopbackAudioConverter : public AudioConverter::InputCallback {
|
| + public:
|
| + LoopbackAudioConverter(const AudioParameters& input_params,
|
| + const AudioParameters& output_params)
|
| + : audio_converter_(input_params, output_params, false) {}
|
| +
|
| + virtual ~LoopbackAudioConverter() {}
|
| +
|
| + void AddInput(AudioConverter::InputCallback* input) {
|
| + audio_converter_.AddInput(input);
|
| + }
|
| +
|
| + void RemoveInput(AudioConverter::InputCallback* input) {
|
| + audio_converter_.RemoveInput(input);
|
| + }
|
| +
|
| + private:
|
| + virtual double ProvideInput(AudioBus* audio_bus,
|
| + base::TimeDelta buffer_delay) OVERRIDE {
|
| + audio_converter_.Convert(audio_bus);
|
| + return 1.0;
|
| + }
|
| +
|
| + AudioConverter audio_converter_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter);
|
| +};
|
| +
|
| +VirtualAudioInputStream* VirtualAudioInputStream::MakeStream(
|
| + AudioManagerBase* manager, const AudioParameters& params,
|
| + base::MessageLoopProxy* message_loop) {
|
| + return new VirtualAudioInputStream(manager, params, message_loop);
|
| +}
|
| +
|
| +VirtualAudioInputStream::VirtualAudioInputStream(
|
| + AudioManagerBase* manager, const AudioParameters& params,
|
| + base::MessageLoopProxy* message_loop)
|
| + : audio_manager_(manager),
|
| + message_loop_(message_loop),
|
| + callback_(NULL),
|
| + buffer_duration_ms_(base::TimeDelta::FromMilliseconds(
|
| + params.frames_per_buffer() * base::Time::kMillisecondsPerSecond /
|
| + static_cast<float>(params.sample_rate()))),
|
| + buffer_(new uint8[params.GetBytesPerBuffer()]),
|
| + params_(params),
|
| + audio_bus_(AudioBus::Create(params_)),
|
| + mixer_(params_, params_, false),
|
| + num_attached_outputs_streams_(0) {
|
| +}
|
| +
|
| +VirtualAudioInputStream::~VirtualAudioInputStream() {
|
| + for (AudioConvertersMap::iterator it = converters_.begin();
|
| + it != converters_.end(); ++it)
|
| + delete it->second;
|
| +
|
| + DCHECK_EQ(0, num_attached_outputs_streams_);
|
| +}
|
| +
|
| +bool VirtualAudioInputStream::Open() {
|
| + memset(buffer_.get(), 0, params_.GetBytesPerBuffer());
|
| + return true;
|
| +}
|
| +
|
| +void VirtualAudioInputStream::Start(AudioInputCallback* callback) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + callback_ = callback;
|
| + on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio,
|
| + base::Unretained(this)));
|
| + audio_manager_->GetMessageLoop()->PostTask(FROM_HERE,
|
| + on_more_data_cb_.callback());
|
| +}
|
| +
|
| +void VirtualAudioInputStream::Stop() {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + on_more_data_cb_.Cancel();
|
| +}
|
| +
|
| +void VirtualAudioInputStream::AddOutputStream(
|
| + VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| +
|
| + AudioConvertersMap::iterator converter = converters_.find(output_params);
|
| + if (converter == converters_.end()) {
|
| + std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert(
|
| + std::make_pair(output_params,
|
| + new LoopbackAudioConverter(output_params, params_)));
|
| + converter = result.first;
|
| +
|
| + // Add to main mixer if we just added a new AudioTransform.
|
| + mixer_.AddInput(converter->second);
|
| + }
|
| + converter->second->AddInput(stream);
|
| + ++num_attached_outputs_streams_;
|
| +}
|
| +
|
| +void VirtualAudioInputStream::RemoveOutputStream(
|
| + VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| +
|
| + DCHECK(converters_.find(output_params) != converters_.end());
|
| + converters_[output_params]->RemoveInput(stream);
|
| +
|
| + --num_attached_outputs_streams_;
|
| +}
|
| +
|
| +void VirtualAudioInputStream::ReadAudio() {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + DCHECK(callback_);
|
| +
|
| + mixer_.Convert(audio_bus_.get());
|
| + audio_bus_->ToInterleaved(params_.frames_per_buffer(),
|
| + params_.bits_per_sample() / 8,
|
| + buffer_.get());
|
| +
|
| + callback_->OnData(this,
|
| + buffer_.get(),
|
| + params_.GetBytesPerBuffer(),
|
| + params_.GetBytesPerBuffer(),
|
| + 1.0);
|
| +
|
| + message_loop_->PostDelayedTask(FROM_HERE,
|
| + on_more_data_cb_.callback(),
|
| + buffer_duration_ms_);
|
| +}
|
| +
|
| +void VirtualAudioInputStream::Close() {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + if (callback_) {
|
| + DCHECK(on_more_data_cb_.IsCancelled());
|
| + callback_->OnClose(this);
|
| + callback_ = NULL;
|
| + }
|
| + audio_manager_->ReleaseInputStream(this);
|
| +}
|
| +
|
| +double VirtualAudioInputStream::GetMaxVolume() {
|
| + return 1.0;
|
| +}
|
| +
|
| +void VirtualAudioInputStream::SetVolume(double volume) {}
|
| +
|
| +double VirtualAudioInputStream::GetVolume() {
|
| + return 1.0;
|
| +}
|
| +
|
| +void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {}
|
| +
|
| +bool VirtualAudioInputStream::GetAutomaticGainControl() {
|
| + return false;
|
| +}
|
| +
|
| +} // namespace media
|
|
|