| OLD | NEW | 
|    1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2013 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 "content/browser/renderer_host/media/web_contents_audio_input_stream.h" |    5 #include "content/browser/renderer_host/media/web_contents_audio_input_stream.h" | 
|    6  |    6  | 
|    7 #include <string> |    7 #include <string> | 
|    8  |    8  | 
|    9 #include "base/bind.h" |    9 #include "base/bind.h" | 
|   10 #include "base/bind_helpers.h" |   10 #include "base/bind_helpers.h" | 
|   11 #include "base/logging.h" |   11 #include "base/logging.h" | 
|   12 #include "base/memory/scoped_ptr.h" |   12 #include "base/memory/scoped_ptr.h" | 
|   13 #include "base/message_loop/message_loop_proxy.h" |   13 #include "base/threading/thread_checker.h" | 
|   14 #include "content/browser/browser_main_loop.h" |   14 #include "content/browser/browser_main_loop.h" | 
|   15 #include "content/browser/renderer_host/media/audio_mirroring_manager.h" |   15 #include "content/browser/renderer_host/media/audio_mirroring_manager.h" | 
|   16 #include "content/browser/renderer_host/media/web_contents_capture_util.h" |   16 #include "content/browser/renderer_host/media/web_contents_capture_util.h" | 
|   17 #include "content/browser/renderer_host/media/web_contents_tracker.h" |   17 #include "content/browser/renderer_host/media/web_contents_tracker.h" | 
|   18 #include "content/public/browser/browser_thread.h" |   18 #include "content/public/browser/browser_thread.h" | 
|   19 #include "media/audio/virtual_audio_input_stream.h" |   19 #include "media/audio/virtual_audio_input_stream.h" | 
|   20 #include "media/audio/virtual_audio_output_stream.h" |   20 #include "media/audio/virtual_audio_output_stream.h" | 
|   21  |   21  | 
|   22 namespace content { |   22 namespace content { | 
|   23  |   23  | 
|   24 class WebContentsAudioInputStream::Impl |   24 class WebContentsAudioInputStream::Impl | 
|   25     : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>, |   25     : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>, | 
|   26       public AudioMirroringManager::MirroringDestination { |   26       public AudioMirroringManager::MirroringDestination { | 
|   27  public: |   27  public: | 
|   28   // Takes ownership of |mixer_stream|.  The rest outlive this instance. |   28   // Takes ownership of |mixer_stream|.  The rest outlive this instance. | 
|   29   Impl(int render_process_id, int render_view_id, |   29   Impl(int render_process_id, int render_view_id, | 
|   30        const scoped_refptr<base::MessageLoopProxy>& message_loop, |  | 
|   31        AudioMirroringManager* mirroring_manager, |   30        AudioMirroringManager* mirroring_manager, | 
|   32        const scoped_refptr<WebContentsTracker>& tracker, |   31        const scoped_refptr<WebContentsTracker>& tracker, | 
|   33        media::VirtualAudioInputStream* mixer_stream); |   32        media::VirtualAudioInputStream* mixer_stream); | 
|   34  |   33  | 
|   35   // Open underlying VirtualAudioInputStream and start tracker. |   34   // Open underlying VirtualAudioInputStream and start tracker. | 
|   36   bool Open(); |   35   bool Open(); | 
|   37  |   36  | 
|   38   // Start the underlying VirtualAudioInputStream and instruct |   37   // Start the underlying VirtualAudioInputStream and instruct | 
|   39   // AudioMirroringManager to begin a mirroring session. |   38   // AudioMirroringManager to begin a mirroring session. | 
|   40   void Start(AudioInputCallback* callback); |   39   void Start(AudioInputCallback* callback); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   79       const media::AudioParameters& params) OVERRIDE; |   78       const media::AudioParameters& params) OVERRIDE; | 
|   80  |   79  | 
|   81   // Callback which is run when |stream| is closed.  Deletes |stream|. |   80   // Callback which is run when |stream| is closed.  Deletes |stream|. | 
|   82   void ReleaseInput(media::VirtualAudioOutputStream* stream); |   81   void ReleaseInput(media::VirtualAudioOutputStream* stream); | 
|   83  |   82  | 
|   84   // Called by WebContentsTracker when the target of the audio mirroring has |   83   // Called by WebContentsTracker when the target of the audio mirroring has | 
|   85   // changed. |   84   // changed. | 
|   86   void OnTargetChanged(int render_process_id, int render_view_id); |   85   void OnTargetChanged(int render_process_id, int render_view_id); | 
|   87  |   86  | 
|   88   // Injected dependencies. |   87   // Injected dependencies. | 
|   89   const scoped_refptr<base::MessageLoopProxy> message_loop_; |  | 
|   90   AudioMirroringManager* const mirroring_manager_; |   88   AudioMirroringManager* const mirroring_manager_; | 
|   91   const scoped_refptr<WebContentsTracker> tracker_; |   89   const scoped_refptr<WebContentsTracker> tracker_; | 
|   92   // The AudioInputStream implementation that handles the audio conversion and |   90   // The AudioInputStream implementation that handles the audio conversion and | 
|   93   // mixing details. |   91   // mixing details. | 
|   94   const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_; |   92   const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_; | 
|   95  |   93  | 
|   96   State state_; |   94   State state_; | 
|   97  |   95  | 
|   98   // Current audio mirroring target. |   96   // Current audio mirroring target. | 
|   99   int target_render_process_id_; |   97   int target_render_process_id_; | 
|  100   int target_render_view_id_; |   98   int target_render_view_id_; | 
|  101  |   99  | 
|  102   // Current callback used to consume the resulting mixed audio data. |  100   // Current callback used to consume the resulting mixed audio data. | 
|  103   AudioInputCallback* callback_; |  101   AudioInputCallback* callback_; | 
|  104  |  102  | 
 |  103   base::ThreadChecker thread_checker_; | 
 |  104  | 
|  105   DISALLOW_COPY_AND_ASSIGN(Impl); |  105   DISALLOW_COPY_AND_ASSIGN(Impl); | 
|  106 }; |  106 }; | 
|  107  |  107  | 
|  108 WebContentsAudioInputStream::Impl::Impl( |  108 WebContentsAudioInputStream::Impl::Impl( | 
|  109     int render_process_id, int render_view_id, |  109     int render_process_id, int render_view_id, | 
|  110     const scoped_refptr<base::MessageLoopProxy>& message_loop, |  | 
|  111     AudioMirroringManager* mirroring_manager, |  110     AudioMirroringManager* mirroring_manager, | 
|  112     const scoped_refptr<WebContentsTracker>& tracker, |  111     const scoped_refptr<WebContentsTracker>& tracker, | 
|  113     media::VirtualAudioInputStream* mixer_stream) |  112     media::VirtualAudioInputStream* mixer_stream) | 
|  114     : message_loop_(message_loop), mirroring_manager_(mirroring_manager), |  113     : mirroring_manager_(mirroring_manager), | 
|  115       tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED), |  114       tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED), | 
|  116       target_render_process_id_(render_process_id), |  115       target_render_process_id_(render_process_id), | 
|  117       target_render_view_id_(render_view_id), |  116       target_render_view_id_(render_view_id), | 
|  118       callback_(NULL) { |  117       callback_(NULL) { | 
|  119   DCHECK(message_loop_.get()); |  | 
|  120   DCHECK(mirroring_manager_); |  118   DCHECK(mirroring_manager_); | 
|  121   DCHECK(tracker_.get()); |  119   DCHECK(tracker_.get()); | 
|  122   DCHECK(mixer_stream_.get()); |  120   DCHECK(mixer_stream_.get()); | 
 |  121  | 
 |  122   // WAIS::Impl can be constructed on any thread, but will DCHECK that all | 
 |  123   // its methods from here on are called from the same thread. | 
 |  124   thread_checker_.DetachFromThread(); | 
|  123 } |  125 } | 
|  124  |  126  | 
|  125 WebContentsAudioInputStream::Impl::~Impl() { |  127 WebContentsAudioInputStream::Impl::~Impl() { | 
|  126   DCHECK(state_ == CONSTRUCTED || state_ == CLOSED); |  128   DCHECK(state_ == CONSTRUCTED || state_ == CLOSED); | 
|  127 } |  129 } | 
|  128  |  130  | 
|  129 bool WebContentsAudioInputStream::Impl::Open() { |  131 bool WebContentsAudioInputStream::Impl::Open() { | 
|  130   DCHECK(message_loop_->BelongsToCurrentThread()); |  132   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  131  |  133  | 
|  132   DCHECK_EQ(CONSTRUCTED, state_) << "Illegal to Open more than once."; |  134   DCHECK_EQ(CONSTRUCTED, state_) << "Illegal to Open more than once."; | 
|  133  |  135  | 
|  134   if (!mixer_stream_->Open()) |  136   if (!mixer_stream_->Open()) | 
|  135     return false; |  137     return false; | 
|  136  |  138  | 
|  137   state_ = OPENED; |  139   state_ = OPENED; | 
|  138  |  140  | 
|  139   tracker_->Start( |  141   tracker_->Start( | 
|  140       target_render_process_id_, target_render_view_id_, |  142       target_render_process_id_, target_render_view_id_, | 
|  141       base::Bind(&Impl::OnTargetChanged, this)); |  143       base::Bind(&Impl::OnTargetChanged, this)); | 
|  142  |  144  | 
|  143   return true; |  145   return true; | 
|  144 } |  146 } | 
|  145  |  147  | 
|  146 void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) { |  148 void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) { | 
|  147   DCHECK(message_loop_->BelongsToCurrentThread()); |  149   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  148   DCHECK(callback); |  150   DCHECK(callback); | 
|  149  |  151  | 
|  150   if (state_ != OPENED) |  152   if (state_ != OPENED) | 
|  151     return; |  153     return; | 
|  152  |  154  | 
|  153   callback_ = callback; |  155   callback_ = callback; | 
|  154   if (IsTargetLost()) { |  156   if (IsTargetLost()) { | 
|  155     ReportError(); |  157     ReportError(); | 
|  156     callback_ = NULL; |  158     callback_ = NULL; | 
|  157     return; |  159     return; | 
|  158   } |  160   } | 
|  159  |  161  | 
|  160   state_ = MIRRORING; |  162   state_ = MIRRORING; | 
|  161   mixer_stream_->Start(callback); |  163   mixer_stream_->Start(callback); | 
|  162  |  164  | 
|  163   StartMirroring(); |  165   StartMirroring(); | 
|  164 } |  166 } | 
|  165  |  167  | 
|  166 void WebContentsAudioInputStream::Impl::Stop() { |  168 void WebContentsAudioInputStream::Impl::Stop() { | 
|  167   DCHECK(message_loop_->BelongsToCurrentThread()); |  169   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  168  |  170  | 
|  169   if (state_ != MIRRORING) |  171   if (state_ != MIRRORING) | 
|  170     return; |  172     return; | 
|  171  |  173  | 
|  172   state_ = OPENED; |  174   state_ = OPENED; | 
|  173  |  175  | 
|  174   mixer_stream_->Stop(); |  176   mixer_stream_->Stop(); | 
|  175   callback_ = NULL; |  177   callback_ = NULL; | 
|  176  |  178  | 
|  177   if (!IsTargetLost()) |  179   if (!IsTargetLost()) | 
|  178     StopMirroring(); |  180     StopMirroring(); | 
|  179 } |  181 } | 
|  180  |  182  | 
|  181 void WebContentsAudioInputStream::Impl::Close() { |  183 void WebContentsAudioInputStream::Impl::Close() { | 
|  182   DCHECK(message_loop_->BelongsToCurrentThread()); |  184   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  183  |  185  | 
|  184   Stop(); |  186   Stop(); | 
|  185  |  187  | 
|  186   if (state_ == OPENED) { |  188   if (state_ == OPENED) { | 
|  187     state_ = CONSTRUCTED; |  189     state_ = CONSTRUCTED; | 
|  188     tracker_->Stop(); |  190     tracker_->Stop(); | 
|  189     mixer_stream_->Close(); |  191     mixer_stream_->Close(); | 
|  190   } |  192   } | 
|  191  |  193  | 
|  192   DCHECK_EQ(CONSTRUCTED, state_); |  194   DCHECK_EQ(CONSTRUCTED, state_); | 
|  193   state_ = CLOSED; |  195   state_ = CLOSED; | 
|  194 } |  196 } | 
|  195  |  197  | 
|  196 bool WebContentsAudioInputStream::Impl::IsTargetLost() const { |  198 bool WebContentsAudioInputStream::Impl::IsTargetLost() const { | 
|  197   DCHECK(message_loop_->BelongsToCurrentThread()); |  199   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  198  |  200  | 
|  199   return target_render_process_id_ <= 0 || target_render_view_id_ <= 0; |  201   return target_render_process_id_ <= 0 || target_render_view_id_ <= 0; | 
|  200 } |  202 } | 
|  201  |  203  | 
|  202 void WebContentsAudioInputStream::Impl::ReportError() { |  204 void WebContentsAudioInputStream::Impl::ReportError() { | 
|  203   DCHECK(message_loop_->BelongsToCurrentThread()); |  205   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  204  |  206  | 
|  205   // TODO(miu): Need clean-up of AudioInputCallback interface in a future |  207   // TODO(miu): Need clean-up of AudioInputCallback interface in a future | 
|  206   // change, since its only implementation ignores the first argument entirely |  208   // change, since its only implementation ignores the first argument entirely | 
|  207   callback_->OnError(NULL); |  209   callback_->OnError(NULL); | 
|  208 } |  210 } | 
|  209  |  211  | 
|  210 void WebContentsAudioInputStream::Impl::StartMirroring() { |  212 void WebContentsAudioInputStream::Impl::StartMirroring() { | 
|  211   DCHECK(message_loop_->BelongsToCurrentThread()); |  213   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  212  |  214  | 
|  213   BrowserThread::PostTask( |  215   BrowserThread::PostTask( | 
|  214       BrowserThread::IO, |  216       BrowserThread::IO, | 
|  215       FROM_HERE, |  217       FROM_HERE, | 
|  216       base::Bind(&AudioMirroringManager::StartMirroring, |  218       base::Bind(&AudioMirroringManager::StartMirroring, | 
|  217                  base::Unretained(mirroring_manager_), |  219                  base::Unretained(mirroring_manager_), | 
|  218                  target_render_process_id_, target_render_view_id_, |  220                  target_render_process_id_, target_render_view_id_, | 
|  219                  make_scoped_refptr(this))); |  221                  make_scoped_refptr(this))); | 
|  220 } |  222 } | 
|  221  |  223  | 
|  222 void WebContentsAudioInputStream::Impl::StopMirroring() { |  224 void WebContentsAudioInputStream::Impl::StopMirroring() { | 
|  223   DCHECK(message_loop_->BelongsToCurrentThread()); |  225   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  224  |  226  | 
|  225   BrowserThread::PostTask( |  227   BrowserThread::PostTask( | 
|  226       BrowserThread::IO, |  228       BrowserThread::IO, | 
|  227       FROM_HERE, |  229       FROM_HERE, | 
|  228       base::Bind(&AudioMirroringManager::StopMirroring, |  230       base::Bind(&AudioMirroringManager::StopMirroring, | 
|  229                  base::Unretained(mirroring_manager_), |  231                  base::Unretained(mirroring_manager_), | 
|  230                  target_render_process_id_, target_render_view_id_, |  232                  target_render_process_id_, target_render_view_id_, | 
|  231                  make_scoped_refptr(this))); |  233                  make_scoped_refptr(this))); | 
|  232 } |  234 } | 
|  233  |  235  | 
|  234 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput( |  236 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput( | 
|  235     const media::AudioParameters& params) { |  237     const media::AudioParameters& params) { | 
|  236   // Note: The closure created here holds a reference to "this," which will |  238   // Note: The closure created here holds a reference to "this," which will | 
|  237   // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the |  239   // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the | 
|  238   // VirtualAudioOutputStream. |  240   // VirtualAudioOutputStream. | 
|  239   return new media::VirtualAudioOutputStream( |  241   return new media::VirtualAudioOutputStream( | 
|  240       params, |  242       params, | 
|  241       message_loop_.get(), |  | 
|  242       mixer_stream_.get(), |  243       mixer_stream_.get(), | 
|  243       base::Bind(&Impl::ReleaseInput, this)); |  244       base::Bind(&Impl::ReleaseInput, this)); | 
|  244 } |  245 } | 
|  245  |  246  | 
|  246 void WebContentsAudioInputStream::Impl::ReleaseInput( |  247 void WebContentsAudioInputStream::Impl::ReleaseInput( | 
|  247     media::VirtualAudioOutputStream* stream) { |  248     media::VirtualAudioOutputStream* stream) { | 
|  248   delete stream; |  249   delete stream; | 
|  249 } |  250 } | 
|  250  |  251  | 
|  251 void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, |  252 void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, | 
|  252                                                         int render_view_id) { |  253                                                         int render_view_id) { | 
|  253   DCHECK(message_loop_->BelongsToCurrentThread()); |  254   DCHECK(thread_checker_.CalledOnValidThread()); | 
|  254  |  255  | 
|  255   if (target_render_process_id_ == render_process_id && |  256   if (target_render_process_id_ == render_process_id && | 
|  256       target_render_view_id_ == render_view_id) { |  257       target_render_view_id_ == render_view_id) { | 
|  257     return; |  258     return; | 
|  258   } |  259   } | 
|  259  |  260  | 
|  260   DVLOG(1) << "Target RenderView has changed from " |  261   DVLOG(1) << "Target RenderView has changed from " | 
|  261            << target_render_process_id_ << ':' << target_render_view_id_ |  262            << target_render_process_id_ << ':' << target_render_view_id_ | 
|  262            << " to " << render_process_id << ':' << render_view_id; |  263            << " to " << render_process_id << ':' << render_view_id; | 
|  263  |  264  | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  274     } else { |  275     } else { | 
|  275       StartMirroring(); |  276       StartMirroring(); | 
|  276     } |  277     } | 
|  277   } |  278   } | 
|  278 } |  279 } | 
|  279  |  280  | 
|  280 // static |  281 // static | 
|  281 WebContentsAudioInputStream* WebContentsAudioInputStream::Create( |  282 WebContentsAudioInputStream* WebContentsAudioInputStream::Create( | 
|  282     const std::string& device_id, |  283     const std::string& device_id, | 
|  283     const media::AudioParameters& params, |  284     const media::AudioParameters& params, | 
|  284     const scoped_refptr<base::MessageLoopProxy>& message_loop) { |  285     const scoped_refptr<base::MessageLoopProxy>& worker_loop) { | 
|  285   int render_process_id; |  286   int render_process_id; | 
|  286   int render_view_id; |  287   int render_view_id; | 
|  287   if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( |  288   if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( | 
|  288           device_id, &render_process_id, &render_view_id)) { |  289           device_id, &render_process_id, &render_view_id)) { | 
|  289     return NULL; |  290     return NULL; | 
|  290   } |  291   } | 
|  291  |  292  | 
|  292   return new WebContentsAudioInputStream( |  293   return new WebContentsAudioInputStream( | 
|  293       render_process_id, render_view_id, message_loop, |  294       render_process_id, render_view_id, | 
|  294       BrowserMainLoop::GetAudioMirroringManager(), |  295       BrowserMainLoop::GetAudioMirroringManager(), | 
|  295       new WebContentsTracker(), |  296       new WebContentsTracker(), | 
|  296       new media::VirtualAudioInputStream( |  297       new media::VirtualAudioInputStream( | 
|  297           params, message_loop, |  298           params, worker_loop, | 
|  298           media::VirtualAudioInputStream::AfterCloseCallback())); |  299           media::VirtualAudioInputStream::AfterCloseCallback())); | 
|  299 } |  300 } | 
|  300  |  301  | 
|  301 WebContentsAudioInputStream::WebContentsAudioInputStream( |  302 WebContentsAudioInputStream::WebContentsAudioInputStream( | 
|  302     int render_process_id, int render_view_id, |  303     int render_process_id, int render_view_id, | 
|  303     const scoped_refptr<base::MessageLoopProxy>& message_loop, |  | 
|  304     AudioMirroringManager* mirroring_manager, |  304     AudioMirroringManager* mirroring_manager, | 
|  305     const scoped_refptr<WebContentsTracker>& tracker, |  305     const scoped_refptr<WebContentsTracker>& tracker, | 
|  306     media::VirtualAudioInputStream* mixer_stream) |  306     media::VirtualAudioInputStream* mixer_stream) | 
|  307     : impl_(new Impl(render_process_id, render_view_id, message_loop, |  307     : impl_(new Impl(render_process_id, render_view_id, | 
|  308                      mirroring_manager, tracker, mixer_stream)) {} |  308                      mirroring_manager, tracker, mixer_stream)) {} | 
|  309  |  309  | 
|  310 WebContentsAudioInputStream::~WebContentsAudioInputStream() {} |  310 WebContentsAudioInputStream::~WebContentsAudioInputStream() {} | 
|  311  |  311  | 
|  312 bool WebContentsAudioInputStream::Open() { |  312 bool WebContentsAudioInputStream::Open() { | 
|  313   return impl_->Open(); |  313   return impl_->Open(); | 
|  314 } |  314 } | 
|  315  |  315  | 
|  316 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { |  316 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { | 
|  317   impl_->Start(callback); |  317   impl_->Start(callback); | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  340  |  340  | 
|  341 void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) { |  341 void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) { | 
|  342   impl_->mixer_stream()->SetAutomaticGainControl(enabled); |  342   impl_->mixer_stream()->SetAutomaticGainControl(enabled); | 
|  343 } |  343 } | 
|  344  |  344  | 
|  345 bool WebContentsAudioInputStream::GetAutomaticGainControl() { |  345 bool WebContentsAudioInputStream::GetAutomaticGainControl() { | 
|  346   return impl_->mixer_stream()->GetAutomaticGainControl(); |  346   return impl_->mixer_stream()->GetAutomaticGainControl(); | 
|  347 } |  347 } | 
|  348  |  348  | 
|  349 }  // namespace content |  349 }  // namespace content | 
| OLD | NEW |