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..b64a8fd34e1b734427c4105b7fa4c9e080f38d0e |
| --- /dev/null |
| +++ b/content/browser/renderer_host/media/web_contents_audio_input_stream.cc |
| @@ -0,0 +1,169 @@ |
| +// 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 "content/public/browser/browser_thread.h" |
| +#include "media/base/bind_to_loop.h" |
| + |
| +namespace content { |
| + |
| +//static |
| +WebContentsAudioInputStream* WebContentsAudioInputStream::Create( |
| + const std::string& device_id, |
| + const media::AudioParameters& params) { |
| + 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, params); |
| +} |
| + |
| +WebContentsAudioInputStream::WebContentsAudioInputStream( |
| + int render_process_id, int render_view_id, |
| + const media::AudioParameters& params) |
| + : params_(params), |
| + thread_checker_(), |
| + 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; |
| + |
| + AudioRendererHost::StartMirroring( |
| + target_render_process_id_, target_render_view_id_, this); |
| +} |
| + |
| +void WebContentsAudioInputStream::Stop() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (state_ != kRecording) { |
| + return; |
| + } |
| + |
| + AudioRendererHost::StopMirroring( |
| + target_render_process_id_, target_render_view_id_, this); |
| + |
| + state_ = kOpened; |
| +} |
| + |
| +void WebContentsAudioInputStream::Close() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + Stop(); |
| + |
| + 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) { |
| + AudioRendererHost::StopMirroring( |
|
Alpha Left Google
2012/11/28 20:02:25
This is on IO thread right?
miu
2012/11/28 22:05:50
Nope. Audio thread. See my other comments for ex
|
| + target_render_process_id_, target_render_view_id_, this); |
| + } |
| + |
| + target_render_process_id_ = render_process_id; |
| + target_render_view_id_ = render_view_id; |
| + |
| + if (state_ == kRecording) { |
| + AudioRendererHost::StartMirroring( |
| + target_render_process_id_, 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::AddInput( |
| + media::AudioOutputStream::AudioSourceCallback* callback, |
| + const media::AudioParameters& params){ |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + DCHECK(!source_params_.count(callback)) << "BUG: Adding same callback twice."; |
| + source_params_.insert(std::make_pair(callback, params)); |
| + |
| + DVLOG(1) << "STUB: WebContentsAudioInputStream@" << this |
| + << "->AddInput(" << callback << ')'; |
| +} |
| + |
| +void WebContentsAudioInputStream::RemoveInput( |
| + media::AudioOutputStream::AudioSourceCallback* callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + DCHECK(source_params_.count(callback)) << "BUG: Removing unknown callback."; |
| + source_params_.erase(callback); |
| + |
| + DVLOG(1) << "STUB: WebContentsAudioInputStream@" << this |
| + << "->RemoveInput(" << callback << ')'; |
| +} |
| + |
| +} // namespace content |