virtual_audio_input_stream.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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 3// found in the LICENSE file. 4 5#include "media/audio/virtual_audio_input_stream.h" 6 7#include <algorithm> 8#include <utility> 9 10#include "base/bind.h" 11#include "base/message_loop/message_loop_proxy.h" 12#include "media/audio/virtual_audio_output_stream.h" 13 14namespace media { 15 16// LoopbackAudioConverter works similar to AudioConverter and converts input 17// streams to different audio parameters. Then, the LoopbackAudioConverter can 18// be used as an input to another AudioConverter. This allows us to 19// use converted audio from AudioOutputStreams as input to an AudioConverter. 20// For example, this allows converting multiple streams into a common format and 21// using the converted audio as input to another AudioConverter (i.e. a mixer). 22class LoopbackAudioConverter : public AudioConverter::InputCallback { 23 public: 24 LoopbackAudioConverter(const AudioParameters& input_params, 25 const AudioParameters& output_params) 26 : audio_converter_(input_params, output_params, false) {} 27 28 virtual ~LoopbackAudioConverter() {} 29 30 void AddInput(AudioConverter::InputCallback* input) { 31 audio_converter_.AddInput(input); 32 } 33 34 void RemoveInput(AudioConverter::InputCallback* input) { 35 audio_converter_.RemoveInput(input); 36 } 37 38 private: 39 virtual double ProvideInput(AudioBus* audio_bus, 40 base::TimeDelta buffer_delay) OVERRIDE { 41 audio_converter_.Convert(audio_bus); 42 return 1.0; 43 } 44 45 AudioConverter audio_converter_; 46 47 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); 48}; 49 50VirtualAudioInputStream::VirtualAudioInputStream( 51 const AudioParameters& params, 52 const scoped_refptr<base::MessageLoopProxy>& message_loop, 53 const AfterCloseCallback& after_close_cb) 54 : message_loop_(message_loop), 55 after_close_cb_(after_close_cb), 56 callback_(NULL), 57 buffer_(new uint8[params.GetBytesPerBuffer()]), 58 params_(params), 59 mixer_(params_, params_, false), 60 num_attached_output_streams_(0), 61 fake_consumer_(message_loop_, params_) { 62 DCHECK(params_.IsValid()); 63 DCHECK(message_loop_.get()); 64} 65 66VirtualAudioInputStream::~VirtualAudioInputStream() { 67 for (AudioConvertersMap::iterator it = converters_.begin(); 68 it != converters_.end(); ++it) { 69 delete it->second; 70 } 71 72 DCHECK_EQ(0, num_attached_output_streams_); 73} 74 75bool VirtualAudioInputStream::Open() { 76 DCHECK(message_loop_->BelongsToCurrentThread()); 77 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); 78 return true; 79} 80 81void VirtualAudioInputStream::Start(AudioInputCallback* callback) { 82 DCHECK(message_loop_->BelongsToCurrentThread()); 83 callback_ = callback; 84 fake_consumer_.Start(base::Bind( 85 &VirtualAudioInputStream::ReadAudio, base::Unretained(this))); 86} 87 88void VirtualAudioInputStream::Stop() { 89 DCHECK(message_loop_->BelongsToCurrentThread()); 90 fake_consumer_.Stop(); 91} 92 93void VirtualAudioInputStream::AddOutputStream( 94 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 95 DCHECK(message_loop_->BelongsToCurrentThread()); 96 97 AudioConvertersMap::iterator converter = converters_.find(output_params); 98 if (converter == converters_.end()) { 99 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( 100 std::make_pair(output_params, 101 new LoopbackAudioConverter(output_params, params_))); 102 converter = result.first; 103 104 // Add to main mixer if we just added a new AudioTransform. 105 mixer_.AddInput(converter->second); 106 } 107 converter->second->AddInput(stream); 108 ++num_attached_output_streams_; 109} 110 111void VirtualAudioInputStream::RemoveOutputStream( 112 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 113 DCHECK(message_loop_->BelongsToCurrentThread()); 114 115 DCHECK(converters_.find(output_params) != converters_.end()); 116 converters_[output_params]->RemoveInput(stream); 117 118 --num_attached_output_streams_; 119 DCHECK_LE(0, num_attached_output_streams_); 120} 121 122void VirtualAudioInputStream::ReadAudio(AudioBus* audio_bus) { 123 DCHECK(message_loop_->BelongsToCurrentThread()); 124 DCHECK(callback_); 125 126 mixer_.Convert(audio_bus); 127 audio_bus->ToInterleaved(params_.frames_per_buffer(), 128 params_.bits_per_sample() / 8, 129 buffer_.get()); 130 131 callback_->OnData(this, 132 buffer_.get(), 133 params_.GetBytesPerBuffer(), 134 params_.GetBytesPerBuffer(), 135 1.0); 136} 137 138void VirtualAudioInputStream::Close() { 139 DCHECK(message_loop_->BelongsToCurrentThread()); 140 141 if (callback_) { 142 callback_->OnClose(this); 143 callback_ = NULL; 144 } 145 146 // If a non-null AfterCloseCallback was provided to the constructor, invoke it 147 // here. The callback is moved to a stack-local first since |this| could be 148 // destroyed during Run(). 149 if (!after_close_cb_.is_null()) { 150 const AfterCloseCallback cb = after_close_cb_; 151 after_close_cb_.Reset(); 152 cb.Run(this); 153 } 154} 155 156double VirtualAudioInputStream::GetMaxVolume() { 157 return 1.0; 158} 159 160void VirtualAudioInputStream::SetVolume(double volume) {} 161 162double VirtualAudioInputStream::GetVolume() { 163 return 1.0; 164} 165 166void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} 167 168bool VirtualAudioInputStream::GetAutomaticGainControl() { 169 return false; 170} 171 172} // namespace media 173