| 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/virtual_audio_input_stream.h" |    5 #include "media/audio/virtual_audio_input_stream.h" | 
|    6  |    6  | 
|    7 #include <algorithm> |    7 #include <algorithm> | 
|    8 #include <utility> |    8 #include <utility> | 
|    9  |    9  | 
|   10 #include "base/bind.h" |   10 #include "base/bind.h" | 
 |   11 #include "base/message_loop.h" | 
|   11 #include "base/message_loop/message_loop_proxy.h" |   12 #include "base/message_loop/message_loop_proxy.h" | 
|   12 #include "media/audio/virtual_audio_output_stream.h" |   13 #include "media/audio/virtual_audio_output_stream.h" | 
|   13  |   14  | 
|   14 namespace media { |   15 namespace media { | 
|   15  |   16  | 
|   16 // LoopbackAudioConverter works similar to AudioConverter and converts input |   17 // LoopbackAudioConverter works similar to AudioConverter and converts input | 
|   17 // streams to different audio parameters. Then, the LoopbackAudioConverter can |   18 // streams to different audio parameters. Then, the LoopbackAudioConverter can | 
|   18 // be used as an input to another AudioConverter. This allows us to |   19 // be used as an input to another AudioConverter. This allows us to | 
|   19 // use converted audio from AudioOutputStreams as input to an AudioConverter. |   20 // use converted audio from AudioOutputStreams as input to an AudioConverter. | 
|   20 // For example, this allows converting multiple streams into a common format and |   21 // For example, this allows converting multiple streams into a common format and | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   42     return 1.0; |   43     return 1.0; | 
|   43   } |   44   } | 
|   44  |   45  | 
|   45   AudioConverter audio_converter_; |   46   AudioConverter audio_converter_; | 
|   46  |   47  | 
|   47   DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); |   48   DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); | 
|   48 }; |   49 }; | 
|   49  |   50  | 
|   50 VirtualAudioInputStream::VirtualAudioInputStream( |   51 VirtualAudioInputStream::VirtualAudioInputStream( | 
|   51     const AudioParameters& params, |   52     const AudioParameters& params, | 
|   52     const scoped_refptr<base::MessageLoopProxy>& message_loop, |   53     const scoped_refptr<base::MessageLoopProxy>& worker_loop, | 
|   53     const AfterCloseCallback& after_close_cb) |   54     const AfterCloseCallback& after_close_cb) | 
|   54     : message_loop_(message_loop), |   55     : worker_loop_(worker_loop), | 
|   55       after_close_cb_(after_close_cb), |   56       after_close_cb_(after_close_cb), | 
|   56       callback_(NULL), |   57       callback_(NULL), | 
|   57       buffer_(new uint8[params.GetBytesPerBuffer()]), |   58       buffer_(new uint8[params.GetBytesPerBuffer()]), | 
|   58       params_(params), |   59       params_(params), | 
|   59       mixer_(params_, params_, false), |   60       mixer_(params_, params_, false), | 
|   60       num_attached_output_streams_(0), |   61       num_attached_output_streams_(0), | 
|   61       fake_consumer_(message_loop_, params_) { |   62       fake_consumer_(worker_loop_, params_) { | 
|   62   DCHECK(params_.IsValid()); |   63   DCHECK(params_.IsValid()); | 
|   63   DCHECK(message_loop_.get()); |   64   DCHECK(worker_loop_.get()); | 
 |   65  | 
 |   66   // VAIS can be constructed on any thread, but will DCHECK that all | 
 |   67   // AudioInputStream methods are called from the same thread. | 
 |   68   thread_checker_.DetachFromThread(); | 
|   64 } |   69 } | 
|   65  |   70  | 
|   66 VirtualAudioInputStream::~VirtualAudioInputStream() { |   71 VirtualAudioInputStream::~VirtualAudioInputStream() { | 
 |   72   DCHECK(!callback_); | 
 |   73  | 
 |   74   // Sanity-check: Contract for Add/RemoveOutputStream() requires that all | 
 |   75   // output streams be removed before VirtualAudioInputStream is destroyed. | 
 |   76   DCHECK_EQ(0, num_attached_output_streams_); | 
 |   77  | 
|   67   for (AudioConvertersMap::iterator it = converters_.begin(); |   78   for (AudioConvertersMap::iterator it = converters_.begin(); | 
|   68        it != converters_.end(); ++it) { |   79        it != converters_.end(); ++it) { | 
|   69     delete it->second; |   80     delete it->second; | 
|   70   } |   81   } | 
|   71  |  | 
|   72   DCHECK_EQ(0, num_attached_output_streams_); |  | 
|   73 } |   82 } | 
|   74  |   83  | 
|   75 bool VirtualAudioInputStream::Open() { |   84 bool VirtualAudioInputStream::Open() { | 
|   76   DCHECK(message_loop_->BelongsToCurrentThread()); |   85   DCHECK(thread_checker_.CalledOnValidThread()); | 
|   77   memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); |   86   memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); | 
|   78   return true; |   87   return true; | 
|   79 } |   88 } | 
|   80  |   89  | 
|   81 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { |   90 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { | 
|   82   DCHECK(message_loop_->BelongsToCurrentThread()); |   91   DCHECK(thread_checker_.CalledOnValidThread()); | 
|   83   callback_ = callback; |   92   callback_ = callback; | 
|   84   fake_consumer_.Start(base::Bind( |   93   fake_consumer_.Start(base::Bind( | 
|   85       &VirtualAudioInputStream::ReadAudio, base::Unretained(this))); |   94       &VirtualAudioInputStream::PumpAudio, base::Unretained(this))); | 
|   86 } |   95 } | 
|   87  |   96  | 
|   88 void VirtualAudioInputStream::Stop() { |   97 void VirtualAudioInputStream::Stop() { | 
|   89   DCHECK(message_loop_->BelongsToCurrentThread()); |   98   DCHECK(thread_checker_.CalledOnValidThread()); | 
|   90   fake_consumer_.Stop(); |   99   fake_consumer_.Stop(); | 
|   91 } |  100 } | 
|   92  |  101  | 
|   93 void VirtualAudioInputStream::AddOutputStream( |  102 void VirtualAudioInputStream::AddOutputStream( | 
|   94     VirtualAudioOutputStream* stream, const AudioParameters& output_params) { |  103     VirtualAudioOutputStream* stream, const AudioParameters& output_params) { | 
|   95   DCHECK(message_loop_->BelongsToCurrentThread()); |  104   DCHECK(thread_checker_.CalledOnValidThread()); | 
 |  105  | 
 |  106   base::AutoLock scoped_lock(converter_network_lock_); | 
|   96  |  107  | 
|   97   AudioConvertersMap::iterator converter = converters_.find(output_params); |  108   AudioConvertersMap::iterator converter = converters_.find(output_params); | 
|   98   if (converter == converters_.end()) { |  109   if (converter == converters_.end()) { | 
|   99     std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( |  110     std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( | 
|  100         std::make_pair(output_params, |  111         std::make_pair(output_params, | 
|  101                        new LoopbackAudioConverter(output_params, params_))); |  112                        new LoopbackAudioConverter(output_params, params_))); | 
|  102     converter = result.first; |  113     converter = result.first; | 
|  103  |  114  | 
|  104     // Add to main mixer if we just added a new AudioTransform. |  115     // Add to main mixer if we just added a new AudioTransform. | 
|  105     mixer_.AddInput(converter->second); |  116     mixer_.AddInput(converter->second); | 
|  106   } |  117   } | 
|  107   converter->second->AddInput(stream); |  118   converter->second->AddInput(stream); | 
|  108   ++num_attached_output_streams_; |  119   ++num_attached_output_streams_; | 
|  109 } |  120 } | 
|  110  |  121  | 
|  111 void VirtualAudioInputStream::RemoveOutputStream( |  122 void VirtualAudioInputStream::RemoveOutputStream( | 
|  112     VirtualAudioOutputStream* stream, const AudioParameters& output_params) { |  123     VirtualAudioOutputStream* stream, const AudioParameters& output_params) { | 
|  113   DCHECK(message_loop_->BelongsToCurrentThread()); |  124   DCHECK(thread_checker_.CalledOnValidThread()); | 
 |  125  | 
 |  126   base::AutoLock scoped_lock(converter_network_lock_); | 
|  114  |  127  | 
|  115   DCHECK(converters_.find(output_params) != converters_.end()); |  128   DCHECK(converters_.find(output_params) != converters_.end()); | 
|  116   converters_[output_params]->RemoveInput(stream); |  129   converters_[output_params]->RemoveInput(stream); | 
|  117  |  130  | 
|  118   --num_attached_output_streams_; |  131   --num_attached_output_streams_; | 
|  119   DCHECK_LE(0, num_attached_output_streams_); |  132   DCHECK_LE(0, num_attached_output_streams_); | 
|  120 } |  133 } | 
|  121  |  134  | 
|  122 void VirtualAudioInputStream::ReadAudio(AudioBus* audio_bus) { |  135 void VirtualAudioInputStream::PumpAudio(AudioBus* audio_bus) { | 
|  123   DCHECK(message_loop_->BelongsToCurrentThread()); |  136   DCHECK(worker_loop_->BelongsToCurrentThread()); | 
|  124   DCHECK(callback_); |  137   DCHECK(callback_); | 
|  125  |  138  | 
|  126   mixer_.Convert(audio_bus); |  139   { | 
 |  140     base::AutoLock scoped_lock(converter_network_lock_); | 
 |  141     mixer_.Convert(audio_bus); | 
 |  142   } | 
|  127   audio_bus->ToInterleaved(params_.frames_per_buffer(), |  143   audio_bus->ToInterleaved(params_.frames_per_buffer(), | 
|  128                            params_.bits_per_sample() / 8, |  144                            params_.bits_per_sample() / 8, | 
|  129                            buffer_.get()); |  145                            buffer_.get()); | 
|  130  |  | 
|  131   callback_->OnData(this, |  146   callback_->OnData(this, | 
|  132                     buffer_.get(), |  147                     buffer_.get(), | 
|  133                     params_.GetBytesPerBuffer(), |  148                     params_.GetBytesPerBuffer(), | 
|  134                     params_.GetBytesPerBuffer(), |  149                     params_.GetBytesPerBuffer(), | 
|  135                     1.0); |  150                     1.0); | 
|  136 } |  151 } | 
|  137  |  152  | 
|  138 void VirtualAudioInputStream::Close() { |  153 void VirtualAudioInputStream::Close() { | 
|  139   DCHECK(message_loop_->BelongsToCurrentThread()); |  154   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  140  |  155  | 
 |  156   Stop();  // Make sure callback_ is no longer being used. | 
|  141   if (callback_) { |  157   if (callback_) { | 
|  142     callback_->OnClose(this); |  158     callback_->OnClose(this); | 
|  143     callback_ = NULL; |  159     callback_ = NULL; | 
|  144   } |  160   } | 
|  145  |  161  | 
|  146   // If a non-null AfterCloseCallback was provided to the constructor, invoke it |  162   // 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 |  163   // here.  The callback is moved to a stack-local first since |this| could be | 
|  148   // destroyed during Run(). |  164   // destroyed during Run(). | 
|  149   if (!after_close_cb_.is_null()) { |  165   if (!after_close_cb_.is_null()) { | 
|  150     const AfterCloseCallback cb = after_close_cb_; |  166     const AfterCloseCallback cb = after_close_cb_; | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  163   return 1.0; |  179   return 1.0; | 
|  164 } |  180 } | 
|  165  |  181  | 
|  166 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} |  182 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} | 
|  167  |  183  | 
|  168 bool VirtualAudioInputStream::GetAutomaticGainControl() { |  184 bool VirtualAudioInputStream::GetAutomaticGainControl() { | 
|  169   return false; |  185   return false; | 
|  170 } |  186 } | 
|  171  |  187  | 
|  172 }  // namespace media |  188 }  // namespace media | 
| OLD | NEW |