| 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/media/capture/web_contents_audio_input_stream.h" | 5 #include "content/browser/media/capture/web_contents_audio_input_stream.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/threading/thread_checker.h" | 14 #include "base/threading/thread_checker.h" |
| 15 #include "content/browser/media/capture/audio_mirroring_manager.h" | 15 #include "content/browser/media/capture/audio_mirroring_manager.h" |
| 16 #include "content/browser/media/capture/web_contents_tracker.h" | 16 #include "content/browser/media/capture/web_contents_tracker.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
| 19 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" |
| 20 #include "content/public/browser/web_contents_media_capture_id.h" | 20 #include "content/public/browser/web_contents_media_capture_id.h" |
| 21 #include "media/audio/virtual_audio_input_stream.h" | 21 #include "media/audio/virtual_audio_input_stream.h" |
| 22 #include "media/audio/virtual_audio_output_stream.h" | 22 #include "media/audio/virtual_audio_output_stream.h" |
| 23 #include "media/audio/virtual_audio_sink.h" |
| 23 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
| 24 | 25 |
| 25 namespace content { | 26 namespace content { |
| 26 | 27 |
| 27 class WebContentsAudioInputStream::Impl | 28 class WebContentsAudioInputStream::Impl |
| 28 : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>, | 29 : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>, |
| 29 public AudioMirroringManager::MirroringDestination { | 30 public AudioMirroringManager::MirroringDestination { |
| 30 public: | 31 public: |
| 31 // Takes ownership of |mixer_stream|. The rest outlive this instance. | 32 // Takes ownership of |mixer_stream|. The rest outlive this instance. |
| 32 Impl(int render_process_id, int main_render_frame_id, | 33 Impl(int render_process_id, |
| 34 int main_render_frame_id, |
| 33 AudioMirroringManager* mirroring_manager, | 35 AudioMirroringManager* mirroring_manager, |
| 34 const scoped_refptr<WebContentsTracker>& tracker, | 36 const scoped_refptr<WebContentsTracker>& tracker, |
| 35 media::VirtualAudioInputStream* mixer_stream); | 37 media::VirtualAudioInputStream* mixer_stream, |
| 38 bool is_duplication); |
| 36 | 39 |
| 37 // Open underlying VirtualAudioInputStream and start tracker. | 40 // Open underlying VirtualAudioInputStream and start tracker. |
| 38 bool Open(); | 41 bool Open(); |
| 39 | 42 |
| 40 // Start the underlying VirtualAudioInputStream and instruct | 43 // Start the underlying VirtualAudioInputStream and instruct |
| 41 // AudioMirroringManager to begin a mirroring session. | 44 // AudioMirroringManager to begin a mirroring session. |
| 42 void Start(AudioInputCallback* callback); | 45 void Start(AudioInputCallback* callback); |
| 43 | 46 |
| 44 // Stop the underlying VirtualAudioInputStream and instruct | 47 // Stop the underlying VirtualAudioInputStream and instruct |
| 45 // AudioMirroringManager to shutdown a mirroring session. | 48 // AudioMirroringManager to shutdown a mirroring session. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 // successful audio capture. | 82 // successful audio capture. |
| 80 void UnmuteWebContentsAudio(); | 83 void UnmuteWebContentsAudio(); |
| 81 | 84 |
| 82 // AudioMirroringManager::MirroringDestination implementation | 85 // AudioMirroringManager::MirroringDestination implementation |
| 83 void QueryForMatches(const std::set<SourceFrameRef>& candidates, | 86 void QueryForMatches(const std::set<SourceFrameRef>& candidates, |
| 84 const MatchesCallback& results_callback) override; | 87 const MatchesCallback& results_callback) override; |
| 85 void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates, | 88 void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates, |
| 86 const MatchesCallback& results_callback); | 89 const MatchesCallback& results_callback); |
| 87 media::AudioOutputStream* AddInput( | 90 media::AudioOutputStream* AddInput( |
| 88 const media::AudioParameters& params) override; | 91 const media::AudioParameters& params) override; |
| 92 media::AudioPushSink* AddPushInput( |
| 93 const media::AudioParameters& params) override; |
| 89 | 94 |
| 90 // Callback which is run when |stream| is closed. Deletes |stream|. | 95 // Callback which is run when |stream| is closed. Deletes |stream|. |
| 91 void ReleaseInput(media::VirtualAudioOutputStream* stream); | 96 void ReleaseInput(media::VirtualAudioOutputStream* stream); |
| 97 void ReleasePushInput(media::VirtualAudioSink* sink); |
| 92 | 98 |
| 93 // Called by WebContentsTracker when the target of the audio mirroring has | 99 // Called by WebContentsTracker when the target of the audio mirroring has |
| 94 // changed. | 100 // changed. |
| 95 void OnTargetChanged(bool had_target); | 101 void OnTargetChanged(bool had_target); |
| 96 | 102 |
| 97 // Injected dependencies. | 103 // Injected dependencies. |
| 98 const int initial_render_process_id_; | 104 const int initial_render_process_id_; |
| 99 const int initial_main_render_frame_id_; | 105 const int initial_main_render_frame_id_; |
| 100 AudioMirroringManager* const mirroring_manager_; | 106 AudioMirroringManager* const mirroring_manager_; |
| 101 const scoped_refptr<WebContentsTracker> tracker_; | 107 const scoped_refptr<WebContentsTracker> tracker_; |
| 102 // The AudioInputStream implementation that handles the audio conversion and | 108 // The AudioInputStream implementation that handles the audio conversion and |
| 103 // mixing details. | 109 // mixing details. |
| 104 const std::unique_ptr<media::VirtualAudioInputStream> mixer_stream_; | 110 const std::unique_ptr<media::VirtualAudioInputStream> mixer_stream_; |
| 105 | 111 |
| 106 State state_; | 112 State state_; |
| 107 | 113 |
| 108 // Set to true if |tracker_| reports a NULL target, which indicates the target | 114 // Set to true if |tracker_| reports a NULL target, which indicates the target |
| 109 // is permanently lost. | 115 // is permanently lost. |
| 110 bool is_target_lost_; | 116 bool is_target_lost_; |
| 111 | 117 |
| 112 // Current callback used to consume the resulting mixed audio data. | 118 // Current callback used to consume the resulting mixed audio data. |
| 113 AudioInputCallback* callback_; | 119 AudioInputCallback* callback_; |
| 114 | 120 |
| 121 // If true, this WebContentsAudioInputStream will request a duplication of |
| 122 // audio data, instead of exclusive access to pull the audio data. |
| 123 bool is_duplication_; |
| 124 |
| 115 base::ThreadChecker thread_checker_; | 125 base::ThreadChecker thread_checker_; |
| 116 | 126 |
| 117 DISALLOW_COPY_AND_ASSIGN(Impl); | 127 DISALLOW_COPY_AND_ASSIGN(Impl); |
| 118 }; | 128 }; |
| 119 | 129 |
| 120 WebContentsAudioInputStream::Impl::Impl( | 130 WebContentsAudioInputStream::Impl::Impl( |
| 121 int render_process_id, int main_render_frame_id, | 131 int render_process_id, |
| 132 int main_render_frame_id, |
| 122 AudioMirroringManager* mirroring_manager, | 133 AudioMirroringManager* mirroring_manager, |
| 123 const scoped_refptr<WebContentsTracker>& tracker, | 134 const scoped_refptr<WebContentsTracker>& tracker, |
| 124 media::VirtualAudioInputStream* mixer_stream) | 135 media::VirtualAudioInputStream* mixer_stream, |
| 136 bool is_duplication) |
| 125 : initial_render_process_id_(render_process_id), | 137 : initial_render_process_id_(render_process_id), |
| 126 initial_main_render_frame_id_(main_render_frame_id), | 138 initial_main_render_frame_id_(main_render_frame_id), |
| 127 mirroring_manager_(mirroring_manager), | 139 mirroring_manager_(mirroring_manager), |
| 128 tracker_(tracker), | 140 tracker_(tracker), |
| 129 mixer_stream_(mixer_stream), | 141 mixer_stream_(mixer_stream), |
| 130 state_(CONSTRUCTED), | 142 state_(CONSTRUCTED), |
| 131 is_target_lost_(false), | 143 is_target_lost_(false), |
| 132 callback_(NULL) { | 144 callback_(NULL), |
| 145 is_duplication_(is_duplication) { |
| 133 DCHECK(mirroring_manager_); | 146 DCHECK(mirroring_manager_); |
| 134 DCHECK(tracker_); | 147 DCHECK(tracker_); |
| 135 DCHECK(mixer_stream_); | 148 DCHECK(mixer_stream_); |
| 136 | 149 |
| 137 // WAIS::Impl can be constructed on any thread, but will DCHECK that all | 150 // WAIS::Impl can be constructed on any thread, but will DCHECK that all |
| 138 // its methods from here on are called from the same thread. | 151 // its methods from here on are called from the same thread. |
| 139 thread_checker_.DetachFromThread(); | 152 thread_checker_.DetachFromThread(); |
| 140 } | 153 } |
| 141 | 154 |
| 142 WebContentsAudioInputStream::Impl::~Impl() { | 155 WebContentsAudioInputStream::Impl::~Impl() { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 for (std::set<SourceFrameRef>::const_iterator i = candidates.begin(); | 289 for (std::set<SourceFrameRef>::const_iterator i = candidates.begin(); |
| 277 i != candidates.end(); ++i) { | 290 i != candidates.end(); ++i) { |
| 278 WebContents* const contents_containing_frame = | 291 WebContents* const contents_containing_frame = |
| 279 WebContents::FromRenderFrameHost( | 292 WebContents::FromRenderFrameHost( |
| 280 RenderFrameHost::FromID(i->first, i->second)); | 293 RenderFrameHost::FromID(i->first, i->second)); |
| 281 if (contents_containing_frame == contents) | 294 if (contents_containing_frame == contents) |
| 282 matches.insert(*i); | 295 matches.insert(*i); |
| 283 } | 296 } |
| 284 } | 297 } |
| 285 | 298 |
| 286 results_callback.Run(matches); | 299 results_callback.Run(matches, is_duplication_); |
| 287 } | 300 } |
| 288 | 301 |
| 289 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput( | 302 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput( |
| 290 const media::AudioParameters& params) { | 303 const media::AudioParameters& params) { |
| 291 // Note: The closure created here holds a reference to "this," which will | 304 // Note: The closure created here holds a reference to "this," which will |
| 292 // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the | 305 // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the |
| 293 // VirtualAudioOutputStream. | 306 // VirtualAudioOutputStream. |
| 294 return new media::VirtualAudioOutputStream( | 307 return new media::VirtualAudioOutputStream( |
| 295 params, | 308 params, |
| 296 mixer_stream_.get(), | 309 mixer_stream_.get(), |
| 297 base::Bind(&Impl::ReleaseInput, this)); | 310 base::Bind(&Impl::ReleaseInput, this)); |
| 298 } | 311 } |
| 299 | 312 |
| 300 void WebContentsAudioInputStream::Impl::ReleaseInput( | 313 void WebContentsAudioInputStream::Impl::ReleaseInput( |
| 301 media::VirtualAudioOutputStream* stream) { | 314 media::VirtualAudioOutputStream* stream) { |
| 302 delete stream; | 315 delete stream; |
| 303 } | 316 } |
| 304 | 317 |
| 318 media::AudioPushSink* WebContentsAudioInputStream::Impl::AddPushInput( |
| 319 const media::AudioParameters& params) { |
| 320 // Note: The closure created here holds a reference to "this," which will |
| 321 // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the |
| 322 // VirtualAudioSink. |
| 323 return new media::VirtualAudioSink(params, mixer_stream_.get(), |
| 324 base::Bind(&Impl::ReleasePushInput, this)); |
| 325 } |
| 326 |
| 327 void WebContentsAudioInputStream::Impl::ReleasePushInput( |
| 328 media::VirtualAudioSink* stream) { |
| 329 delete stream; |
| 330 } |
| 331 |
| 305 void WebContentsAudioInputStream::Impl::OnTargetChanged(bool had_target) { | 332 void WebContentsAudioInputStream::Impl::OnTargetChanged(bool had_target) { |
| 306 DCHECK(thread_checker_.CalledOnValidThread()); | 333 DCHECK(thread_checker_.CalledOnValidThread()); |
| 307 | 334 |
| 308 is_target_lost_ = !had_target; | 335 is_target_lost_ = !had_target; |
| 309 | 336 |
| 310 if (state_ == MIRRORING) { | 337 if (state_ == MIRRORING) { |
| 311 if (is_target_lost_) { | 338 if (is_target_lost_) { |
| 312 ReportError(); | 339 ReportError(); |
| 313 Stop(); | 340 Stop(); |
| 314 } else { | 341 } else { |
| 315 StartMirroring(); | 342 StartMirroring(); |
| 316 } | 343 } |
| 317 } | 344 } |
| 318 } | 345 } |
| 319 | 346 |
| 320 // static | 347 // static |
| 321 WebContentsAudioInputStream* WebContentsAudioInputStream::Create( | 348 WebContentsAudioInputStream* WebContentsAudioInputStream::Create( |
| 322 const std::string& device_id, | 349 const std::string& device_id, |
| 323 const media::AudioParameters& params, | 350 const media::AudioParameters& params, |
| 324 const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, | 351 const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, |
| 325 AudioMirroringManager* audio_mirroring_manager) { | 352 AudioMirroringManager* audio_mirroring_manager) { |
| 326 int render_process_id; | 353 int render_process_id; |
| 327 int main_render_frame_id; | 354 int main_render_frame_id; |
| 328 if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget( | 355 if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget( |
| 329 device_id, &render_process_id, &main_render_frame_id)) { | 356 device_id, &render_process_id, &main_render_frame_id)) { |
| 330 return NULL; | 357 return NULL; |
| 331 } | 358 } |
| 332 | 359 |
| 360 // TODO(qiangchen): Plug in true for the case of Tab Typed Desktop Share. |
| 333 return new WebContentsAudioInputStream( | 361 return new WebContentsAudioInputStream( |
| 334 render_process_id, main_render_frame_id, | 362 render_process_id, main_render_frame_id, audio_mirroring_manager, |
| 335 audio_mirroring_manager, | |
| 336 new WebContentsTracker(false), | 363 new WebContentsTracker(false), |
| 337 new media::VirtualAudioInputStream( | 364 new media::VirtualAudioInputStream( |
| 338 params, worker_task_runner, | 365 params, worker_task_runner, |
| 339 media::VirtualAudioInputStream::AfterCloseCallback())); | 366 media::VirtualAudioInputStream::AfterCloseCallback()), |
| 367 false); |
| 340 } | 368 } |
| 341 | 369 |
| 342 WebContentsAudioInputStream::WebContentsAudioInputStream( | 370 WebContentsAudioInputStream::WebContentsAudioInputStream( |
| 343 int render_process_id, int main_render_frame_id, | 371 int render_process_id, |
| 372 int main_render_frame_id, |
| 344 AudioMirroringManager* mirroring_manager, | 373 AudioMirroringManager* mirroring_manager, |
| 345 const scoped_refptr<WebContentsTracker>& tracker, | 374 const scoped_refptr<WebContentsTracker>& tracker, |
| 346 media::VirtualAudioInputStream* mixer_stream) | 375 media::VirtualAudioInputStream* mixer_stream, |
| 347 : impl_(new Impl(render_process_id, main_render_frame_id, | 376 bool is_duplication) |
| 348 mirroring_manager, tracker, mixer_stream)) {} | 377 : impl_(new Impl(render_process_id, |
| 378 main_render_frame_id, |
| 379 mirroring_manager, |
| 380 tracker, |
| 381 mixer_stream, |
| 382 is_duplication)) {} |
| 349 | 383 |
| 350 WebContentsAudioInputStream::~WebContentsAudioInputStream() {} | 384 WebContentsAudioInputStream::~WebContentsAudioInputStream() {} |
| 351 | 385 |
| 352 bool WebContentsAudioInputStream::Open() { | 386 bool WebContentsAudioInputStream::Open() { |
| 353 return impl_->Open(); | 387 return impl_->Open(); |
| 354 } | 388 } |
| 355 | 389 |
| 356 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { | 390 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { |
| 357 impl_->Start(callback); | 391 impl_->Start(callback); |
| 358 } | 392 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 384 | 418 |
| 385 bool WebContentsAudioInputStream::GetAutomaticGainControl() { | 419 bool WebContentsAudioInputStream::GetAutomaticGainControl() { |
| 386 return impl_->mixer_stream()->GetAutomaticGainControl(); | 420 return impl_->mixer_stream()->GetAutomaticGainControl(); |
| 387 } | 421 } |
| 388 | 422 |
| 389 bool WebContentsAudioInputStream::IsMuted() { | 423 bool WebContentsAudioInputStream::IsMuted() { |
| 390 return false; | 424 return false; |
| 391 } | 425 } |
| 392 | 426 |
| 393 } // namespace content | 427 } // namespace content |
| OLD | NEW |