Chromium Code Reviews| Index: content/browser/renderer_host/media/web_contents_audio_input_stream.cc |
| diff --git a/content/browser/renderer_host/media/web_contents_audio_input_stream.cc b/content/browser/renderer_host/media/web_contents_audio_input_stream.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..64ebf47484d5bc10afe8b7333cc2a097e7c138d5 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/media/web_contents_audio_input_stream.cc |
| @@ -0,0 +1,166 @@ |
| +// 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 "content/browser/renderer_host/media/web_contents_audio_input_stream.h" |
| + |
| +#include <string> |
| + |
| +#include "base/bind.h" |
| +#include "base/logging.h" |
| +#include "content/browser/renderer_host/media/audio_renderer_host.h" |
| +#include "media/base/bind_to_loop.h" |
| + |
| +namespace content { |
| + |
| +//static |
| +WebContentsAudioInputStream* WebContentsAudioInputStream::Create( |
| + const std::string& device_id) { |
| + int render_process_id; |
| + int render_view_id; |
| + if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( |
| + device_id, &render_process_id, &render_view_id)) { |
| + return NULL; |
| + } |
| + |
| + return new WebContentsAudioInputStream(render_process_id, render_view_id); |
| +} |
| + |
| +WebContentsAudioInputStream::WebContentsAudioInputStream(int render_process_id, |
| + int render_view_id) |
| + : state_(kConstructed), |
| + target_render_process_id_(render_process_id), |
| + target_render_view_id_(render_view_id) { |
| +} |
| + |
| +WebContentsAudioInputStream::~WebContentsAudioInputStream() { |
| + DCHECK(!tracker_) << "BUG: Close() not called after Open()."; |
| +} |
| + |
| +bool WebContentsAudioInputStream::Open() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (state_ != kConstructed) { |
| + return false; |
| + } |
| + |
| + state_ = kOpened; |
| + |
| + DCHECK(!tracker_); |
| + tracker_ = new WebContentsCaptureUtil::RenderViewTracker(); |
| + tracker_->Start( |
| + target_render_process_id_, target_render_view_id_, |
| + media::BindToLoop( |
| + base::MessageLoopProxy::current(), |
| + base::Bind(&WebContentsAudioInputStream::OnTargetChanged, this))); |
| + |
| + return true; |
| +} |
| + |
| +void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (state_ != kOpened) { |
| + return; |
| + } |
| + |
| + state_ = kRecording; |
| + |
| + if (target_host_) { |
| + target_host_->StartMirroring(target_render_view_id_, this); |
|
Alpha Left Google
2012/11/26 22:59:59
Does it work if WCAIS doesn't own or reference ARH
miu
2012/11/28 05:05:01
Done.
|
| + } |
| +} |
| + |
| +void WebContentsAudioInputStream::Stop() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (state_ != kRecording) { |
| + return; |
| + } |
| + |
| + if (target_host_) { |
| + target_host_->StopMirroring(target_render_view_id_, this); |
|
Alpha Left Google
2012/11/26 22:59:59
What if this becomes AudioRendererHost::StopMirror
miu
2012/11/28 05:05:01
Done.
|
| + } |
| + |
| + state_ = kOpened; |
| +} |
| + |
| +void WebContentsAudioInputStream::Close() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + Stop(); |
| + |
| + target_host_ = NULL; |
| + tracker_->Stop(); |
| + tracker_ = NULL; |
| + |
| + state_ = kClosed; |
| +} |
| + |
| +void WebContentsAudioInputStream::OnTargetChanged(int render_process_id, |
| + int render_view_id) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (target_render_process_id_ == render_process_id && |
| + target_render_view_id_ == render_view_id) { |
| + return; |
| + } |
| + |
| + if (state_ == kRecording) { |
| + if (target_host_) { |
| + target_host_->StopMirroring(target_render_view_id_, this); |
| + } |
| + } |
| + |
| + target_render_process_id_ = render_process_id; |
| + target_render_view_id_ = render_view_id; |
| + target_host_ = AudioRendererHost::FromRenderProcessID(render_process_id); |
| + |
| + if (state_ == kRecording) { |
| + if (target_host_) { |
| + target_host_->StartMirroring(target_render_view_id_, this); |
| + } |
| + } |
| +} |
| + |
| +double WebContentsAudioInputStream::GetMaxVolume() { |
| + return 1.0; |
| +} |
| + |
| +void WebContentsAudioInputStream::SetVolume(double volume) { |
| + // no-op |
| +} |
| + |
| +double WebContentsAudioInputStream::GetVolume() { |
| + return 1.0; |
| +} |
| + |
| +void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) { |
| + // no-op |
| +} |
| + |
| +bool WebContentsAudioInputStream::GetAutomaticGainControl() { |
| + return false; |
| +} |
| + |
| +void WebContentsAudioInputStream::AddAudioOutputStream( |
| + media::DivertedAudioOutputStream* aos) { |
| + base::AutoLock guard(streams_lock_); |
|
Alpha Left Google
2012/11/26 22:59:59
Is a lock necessary here? I see these two methods
miu
2012/11/28 05:05:01
Removed the locking for now. I agree that it'll p
|
| + DCHECK(!streams_.count(aos)) << "BUG: Adding same stream twice."; |
| + streams_.insert(aos); |
| + |
| + DVLOG(1) << "STUB: WebContentsAudioInputStream@" << this |
| + << "->AddAudioOutputStream(" << aos << ')'; |
| +} |
| + |
| +void WebContentsAudioInputStream::RemoveAudioOutputStream( |
| + media::DivertedAudioOutputStream* aos) { |
| + base::AutoLock guard(streams_lock_); |
| + DCHECK(streams_.count(aos)) << "BUG: Removing unknown stream."; |
| + streams_.erase(aos); |
| + |
| + DVLOG(1) << "STUB: WebContentsAudioInputStream@" << this |
| + << "->RemoveAudioOutputStream(" << aos << ')'; |
| +} |
| + |
| +} // namespace content |