This source file includes following definitions.
- mixer_stream
- Open
- Start
- Stop
- Close
- IsTargetLost
- ReportError
- StartMirroring
- StopMirroring
- AddInput
- ReleaseInput
- OnTargetChanged
- Create
- Open
- Start
- Stop
- Close
- GetMaxVolume
- SetVolume
- GetVolume
- SetAutomaticGainControl
- GetAutomaticGainControl
#include "content/browser/media/capture/web_contents_audio_input_stream.h"
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/capture/web_contents_capture_util.h"
#include "content/browser/media/capture/web_contents_tracker.h"
#include "content/public/browser/browser_thread.h"
#include "media/audio/virtual_audio_input_stream.h"
#include "media/audio/virtual_audio_output_stream.h"
namespace content {
class WebContentsAudioInputStream::Impl
: public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>,
public AudioMirroringManager::MirroringDestination {
public:
Impl(int render_process_id, int render_view_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream);
bool Open();
void Start(AudioInputCallback* callback);
void Stop();
void Close();
media::VirtualAudioInputStream* mixer_stream() const {
return mixer_stream_.get();
}
private:
friend class base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>;
enum State {
CONSTRUCTED,
OPENED,
MIRRORING,
CLOSED
};
virtual ~Impl();
bool IsTargetLost() const;
void ReportError();
void StartMirroring();
void StopMirroring();
virtual media::AudioOutputStream* AddInput(
const media::AudioParameters& params) OVERRIDE;
void ReleaseInput(media::VirtualAudioOutputStream* stream);
void OnTargetChanged(int render_process_id, int render_view_id);
AudioMirroringManager* const mirroring_manager_;
const scoped_refptr<WebContentsTracker> tracker_;
const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_;
State state_;
int target_render_process_id_;
int target_render_view_id_;
AudioInputCallback* callback_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(Impl);
};
WebContentsAudioInputStream::Impl::Impl(
int render_process_id, int render_view_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream)
: mirroring_manager_(mirroring_manager),
tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED),
target_render_process_id_(render_process_id),
target_render_view_id_(render_view_id),
callback_(NULL) {
DCHECK(mirroring_manager_);
DCHECK(tracker_.get());
DCHECK(mixer_stream_.get());
thread_checker_.DetachFromThread();
}
WebContentsAudioInputStream::Impl::~Impl() {
DCHECK(state_ == CONSTRUCTED || state_ == CLOSED);
}
bool WebContentsAudioInputStream::Impl::Open() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(CONSTRUCTED, state_) << "Illegal to Open more than once.";
if (!mixer_stream_->Open())
return false;
state_ = OPENED;
tracker_->Start(
target_render_process_id_, target_render_view_id_,
base::Bind(&Impl::OnTargetChanged, this));
return true;
}
void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(callback);
if (state_ != OPENED)
return;
callback_ = callback;
if (IsTargetLost()) {
ReportError();
callback_ = NULL;
return;
}
state_ = MIRRORING;
mixer_stream_->Start(callback);
StartMirroring();
}
void WebContentsAudioInputStream::Impl::Stop() {
DCHECK(thread_checker_.CalledOnValidThread());
if (state_ != MIRRORING)
return;
state_ = OPENED;
mixer_stream_->Stop();
callback_ = NULL;
if (!IsTargetLost())
StopMirroring();
}
void WebContentsAudioInputStream::Impl::Close() {
DCHECK(thread_checker_.CalledOnValidThread());
Stop();
if (state_ == OPENED) {
state_ = CONSTRUCTED;
tracker_->Stop();
mixer_stream_->Close();
}
DCHECK_EQ(CONSTRUCTED, state_);
state_ = CLOSED;
}
bool WebContentsAudioInputStream::Impl::IsTargetLost() const {
DCHECK(thread_checker_.CalledOnValidThread());
return target_render_process_id_ <= 0 || target_render_view_id_ <= 0;
}
void WebContentsAudioInputStream::Impl::ReportError() {
DCHECK(thread_checker_.CalledOnValidThread());
callback_->OnError(NULL);
}
void WebContentsAudioInputStream::Impl::StartMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioMirroringManager::StartMirroring,
base::Unretained(mirroring_manager_),
target_render_process_id_, target_render_view_id_,
make_scoped_refptr(this)));
}
void WebContentsAudioInputStream::Impl::StopMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioMirroringManager::StopMirroring,
base::Unretained(mirroring_manager_),
target_render_process_id_, target_render_view_id_,
make_scoped_refptr(this)));
}
media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput(
const media::AudioParameters& params) {
return new media::VirtualAudioOutputStream(
params,
mixer_stream_.get(),
base::Bind(&Impl::ReleaseInput, this));
}
void WebContentsAudioInputStream::Impl::ReleaseInput(
media::VirtualAudioOutputStream* stream) {
delete stream;
}
void WebContentsAudioInputStream::Impl::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;
}
DVLOG(1) << "Target RenderView has changed from "
<< target_render_process_id_ << ':' << target_render_view_id_
<< " to " << render_process_id << ':' << render_view_id;
if (state_ == MIRRORING)
StopMirroring();
target_render_process_id_ = render_process_id;
target_render_view_id_ = render_view_id;
if (state_ == MIRRORING) {
if (IsTargetLost()) {
ReportError();
Stop();
} else {
StartMirroring();
}
}
}
WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
const std::string& device_id,
const media::AudioParameters& params,
const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
AudioMirroringManager* audio_mirroring_manager) {
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,
audio_mirroring_manager,
new WebContentsTracker(),
new media::VirtualAudioInputStream(
params, worker_task_runner,
media::VirtualAudioInputStream::AfterCloseCallback()));
}
WebContentsAudioInputStream::WebContentsAudioInputStream(
int render_process_id, int render_view_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream)
: impl_(new Impl(render_process_id, render_view_id,
mirroring_manager, tracker, mixer_stream)) {}
WebContentsAudioInputStream::~WebContentsAudioInputStream() {}
bool WebContentsAudioInputStream::Open() {
return impl_->Open();
}
void WebContentsAudioInputStream::Start(AudioInputCallback* callback) {
impl_->Start(callback);
}
void WebContentsAudioInputStream::Stop() {
impl_->Stop();
}
void WebContentsAudioInputStream::Close() {
impl_->Close();
delete this;
}
double WebContentsAudioInputStream::GetMaxVolume() {
return impl_->mixer_stream()->GetMaxVolume();
}
void WebContentsAudioInputStream::SetVolume(double volume) {
impl_->mixer_stream()->SetVolume(volume);
}
double WebContentsAudioInputStream::GetVolume() {
return impl_->mixer_stream()->GetVolume();
}
void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) {
impl_->mixer_stream()->SetAutomaticGainControl(enabled);
}
bool WebContentsAudioInputStream::GetAutomaticGainControl() {
return impl_->mixer_stream()->GetAutomaticGainControl();
}
}