blob: 659bf04ca4d655ad13f1e52ea0ec77badfb9a19f [file] [log] [blame]
// Copyright 2015 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 "chrome/renderer/media/cast_receiver_session.h"
#include <memory>
#include "base/bind.h"
#include "base/location.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/renderer/media/cast_receiver_audio_valve.h"
#include "content/public/renderer/render_thread.h"
#include "media/base/audio_capturer_source.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video_capturer_source.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
// This is a render thread object.
class CastReceiverSession::AudioCapturerSource :
public media::AudioCapturerSource {
public:
AudioCapturerSource(
const scoped_refptr<CastReceiverSession> cast_receiver_session);
void Initialize(const media::AudioParameters& params,
CaptureCallback* callback) override;
void Start() override;
void Stop() override;
void SetVolume(double volume) override;
void SetAutomaticGainControl(bool enable) override;
void SetOutputDeviceForAec(const std::string& output_device_id) override;
private:
~AudioCapturerSource() override;
const scoped_refptr<CastReceiverSession> cast_receiver_session_;
scoped_refptr<CastReceiverAudioValve> audio_valve_;
};
// This is a render thread object.
class CastReceiverSession::VideoCapturerSource
: public media::VideoCapturerSource {
public:
explicit VideoCapturerSource(
const scoped_refptr<CastReceiverSession> cast_receiver_session);
protected:
media::VideoCaptureFormats GetPreferredFormats() override;
void StartCapture(const media::VideoCaptureParams& params,
const VideoCaptureDeliverFrameCB& frame_callback,
const RunningCallback& running_callback) override;
void StopCapture() override;
private:
const scoped_refptr<CastReceiverSession> cast_receiver_session_;
};
CastReceiverSession::CastReceiverSession()
: delegate_(new CastReceiverSessionDelegate()),
io_task_runner_(content::RenderThread::Get()->GetIOTaskRunner()) {}
CastReceiverSession::~CastReceiverSession() {
// We should always be able to delete the object on the IO thread.
CHECK(io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release()));
}
void CastReceiverSession::Start(
const media::cast::FrameReceiverConfig& audio_config,
const media::cast::FrameReceiverConfig& video_config,
const net::IPEndPoint& local_endpoint,
const net::IPEndPoint& remote_endpoint,
std::unique_ptr<base::DictionaryValue> options,
const media::VideoCaptureFormat& capture_format,
const StartCB& start_callback,
const CastReceiverSessionDelegate::ErrorCallback& error_callback) {
audio_config_ = audio_config;
video_config_ = video_config;
format_ = capture_format;
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&CastReceiverSessionDelegate::Start,
base::Unretained(delegate_.get()), audio_config,
video_config, local_endpoint, remote_endpoint,
std::move(options), format_,
media::BindToCurrentLoop(error_callback)));
scoped_refptr<media::AudioCapturerSource> audio(
new CastReceiverSession::AudioCapturerSource(this));
std::unique_ptr<media::VideoCapturerSource> video(
new CastReceiverSession::VideoCapturerSource(this));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(start_callback, audio, std::move(video)));
}
void CastReceiverSession::StartAudio(
scoped_refptr<CastReceiverAudioValve> audio_valve) {
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CastReceiverSessionDelegate::StartAudio,
base::Unretained(delegate_.get()), audio_valve));
}
void CastReceiverSession::StartVideo(
blink::VideoCaptureDeliverFrameCB frame_callback) {
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CastReceiverSessionDelegate::StartVideo,
base::Unretained(delegate_.get()), frame_callback));
}
void CastReceiverSession::StopVideo() {
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&CastReceiverSessionDelegate::StopVideo,
base::Unretained(delegate_.get())));
}
CastReceiverSession::VideoCapturerSource::VideoCapturerSource(
const scoped_refptr<CastReceiverSession> cast_receiver_session)
: cast_receiver_session_(cast_receiver_session) {
}
media::VideoCaptureFormats
CastReceiverSession::VideoCapturerSource::GetPreferredFormats() {
media::VideoCaptureFormats formats;
if (cast_receiver_session_->format_.IsValid())
formats.push_back(cast_receiver_session_->format_);
return formats;
}
void CastReceiverSession::VideoCapturerSource::StartCapture(
const media::VideoCaptureParams& params,
const VideoCaptureDeliverFrameCB& frame_callback,
const RunningCallback& running_callback) {
cast_receiver_session_->StartVideo(frame_callback);
running_callback.Run(true);
}
void CastReceiverSession::VideoCapturerSource::StopCapture() {
cast_receiver_session_->StopVideo();
}
CastReceiverSession::AudioCapturerSource::AudioCapturerSource(
const scoped_refptr<CastReceiverSession> cast_receiver_session)
: cast_receiver_session_(cast_receiver_session) {
}
CastReceiverSession::AudioCapturerSource::~AudioCapturerSource() {
DCHECK(!audio_valve_);
}
void CastReceiverSession::AudioCapturerSource::Initialize(
const media::AudioParameters& params,
CaptureCallback* callback) {
// TODO(hubbe): Consider converting the audio to whatever the caller wants.
if (params.sample_rate() !=
cast_receiver_session_->audio_config_.rtp_timebase ||
params.channels() != cast_receiver_session_->audio_config_.channels) {
callback->OnCaptureError(std::string());
return;
}
audio_valve_ = new CastReceiverAudioValve(params, callback);
}
void CastReceiverSession::AudioCapturerSource::Start() {
DCHECK(audio_valve_);
cast_receiver_session_->StartAudio(audio_valve_);
}
void CastReceiverSession::AudioCapturerSource::Stop() {
audio_valve_->Stop();
audio_valve_ = nullptr;
}
void CastReceiverSession::AudioCapturerSource::SetVolume(double volume) {
// not supported
}
void CastReceiverSession::AudioCapturerSource::SetAutomaticGainControl(
bool enable) {
// not supported
}
void CastReceiverSession::AudioCapturerSource::SetOutputDeviceForAec(
const std::string& output_device_id) {
// not supported
}