1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/renderer/media/cast_receiver_session.h"
7 #include "base/location.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/renderer/media/cast_receiver_audio_valve.h"
11 #include "content/public/renderer/render_thread.h"
12 #include "media/base/audio_capturer_source.h"
13 #include "media/base/bind_to_current_loop.h"
14 #include "media/base/video_capturer_source.h"
15 #include "third_party/WebKit/public/platform/WebMediaStream.h"
16 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
17 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
19 // This is a render thread object.
20 class CastReceiverSession::AudioCapturerSource
:
21 public media::AudioCapturerSource
{
24 const scoped_refptr
<CastReceiverSession
> cast_receiver_session
);
25 void Initialize(const media::AudioParameters
& params
,
26 CaptureCallback
* callback
,
27 int session_id
) override
;
28 void Start() override
;
30 void SetVolume(double volume
) override
;
31 void SetAutomaticGainControl(bool enable
) override
;
33 ~AudioCapturerSource() override
;
34 const scoped_refptr
<CastReceiverSession
> cast_receiver_session_
;
35 scoped_refptr
<CastReceiverAudioValve
> audio_valve_
;
38 // This is a render thread object.
39 class CastReceiverSession::VideoCapturerSource
:
40 public media::VideoCapturerSource
{
42 explicit VideoCapturerSource(
43 const scoped_refptr
<CastReceiverSession
> cast_receiver_session
);
45 void GetCurrentSupportedFormats(
46 int max_requested_width
,
47 int max_requested_height
,
48 double max_requested_frame_rate
,
49 const VideoCaptureDeviceFormatsCB
& callback
) override
;
51 const media::VideoCaptureParams
& params
,
52 const content::VideoCaptureDeliverFrameCB
& frame_callback
,
53 scoped_refptr
<base::SingleThreadTaskRunner
> frame_callback_task_runner
,
54 const RunningCallback
& running_callback
) override
;
55 void StopCapture() override
;
57 const scoped_refptr
<CastReceiverSession
> cast_receiver_session_
;
60 CastReceiverSession::CastReceiverSession()
61 : delegate_(new CastReceiverSessionDelegate()),
63 content::RenderThread::Get()->GetIOMessageLoopProxy()) {}
65 CastReceiverSession::~CastReceiverSession() {
66 // We should always be able to delete the object on the IO thread.
67 CHECK(io_task_runner_
->DeleteSoon(FROM_HERE
, delegate_
.release()));
70 void CastReceiverSession::Start(
71 const media::cast::FrameReceiverConfig
& audio_config
,
72 const media::cast::FrameReceiverConfig
& video_config
,
73 const net::IPEndPoint
& local_endpoint
,
74 const net::IPEndPoint
& remote_endpoint
,
75 scoped_ptr
<base::DictionaryValue
> options
,
76 const media::VideoCaptureFormat
& capture_format
,
77 const StartCB
& start_callback
,
78 const CastReceiverSessionDelegate::ErrorCallback
& error_callback
) {
79 audio_config_
= audio_config
;
80 video_config_
= video_config
;
81 format_
= capture_format
;
82 io_task_runner_
->PostTask(
84 base::Bind(&CastReceiverSessionDelegate::Start
,
85 base::Unretained(delegate_
.get()),
90 base::Passed(&options
),
92 media::BindToCurrentLoop(error_callback
)));
93 scoped_refptr
<media::AudioCapturerSource
> audio(
94 new CastReceiverSession::AudioCapturerSource(this));
95 scoped_ptr
<media::VideoCapturerSource
> video(
96 new CastReceiverSession::VideoCapturerSource(this));
97 base::ThreadTaskRunnerHandle::Get()->PostTask(
98 FROM_HERE
, base::Bind(start_callback
, audio
, base::Passed(&video
)));
101 void CastReceiverSession::StartAudio(
102 scoped_refptr
<CastReceiverAudioValve
> audio_valve
) {
103 io_task_runner_
->PostTask(
105 base::Bind(&CastReceiverSessionDelegate::StartAudio
,
106 base::Unretained(delegate_
.get()),
110 void CastReceiverSession::StartVideo(
111 content::VideoCaptureDeliverFrameCB frame_callback
) {
112 io_task_runner_
->PostTask(
114 base::Bind(&CastReceiverSessionDelegate::StartVideo
,
115 base::Unretained(delegate_
.get()),
119 void CastReceiverSession::StopVideo() {
120 io_task_runner_
->PostTask(
122 base::Bind(&CastReceiverSessionDelegate::StopVideo
,
123 base::Unretained(delegate_
.get())));
126 CastReceiverSession::VideoCapturerSource::VideoCapturerSource(
127 const scoped_refptr
<CastReceiverSession
> cast_receiver_session
)
128 : cast_receiver_session_(cast_receiver_session
) {
131 void CastReceiverSession::VideoCapturerSource::GetCurrentSupportedFormats(
132 int max_requested_width
,
133 int max_requested_height
,
134 double max_requested_frame_rate
,
135 const VideoCaptureDeviceFormatsCB
& callback
) {
136 std::vector
<media::VideoCaptureFormat
> formats
;
137 if (cast_receiver_session_
->format_
.IsValid()) {
138 formats
.push_back(cast_receiver_session_
->format_
);
140 callback
.Run(formats
);
143 void CastReceiverSession::VideoCapturerSource::StartCapture(
144 const media::VideoCaptureParams
& params
,
145 const content::VideoCaptureDeliverFrameCB
& frame_callback
,
146 scoped_refptr
<base::SingleThreadTaskRunner
> frame_callback_task_runner
,
147 const RunningCallback
& running_callback
) {
148 if (frame_callback_task_runner
!=
149 content::RenderThread::Get()->GetIOMessageLoopProxy()) {
150 DCHECK(false) << "Only IO thread supported right now.";
151 running_callback
.Run(false);
154 cast_receiver_session_
->StartVideo(frame_callback
);
155 running_callback
.Run(true);
158 void CastReceiverSession::VideoCapturerSource::StopCapture() {
159 cast_receiver_session_
->StopVideo();
162 CastReceiverSession::AudioCapturerSource::AudioCapturerSource(
163 const scoped_refptr
<CastReceiverSession
> cast_receiver_session
)
164 : cast_receiver_session_(cast_receiver_session
) {
167 CastReceiverSession::AudioCapturerSource::~AudioCapturerSource() {
168 DCHECK(!audio_valve_
);
171 void CastReceiverSession::AudioCapturerSource::Initialize(
172 const media::AudioParameters
& params
,
173 CaptureCallback
* callback
,
175 // TODO(hubbe): Consider converting the audio to whatever the caller wants.
176 if (params
.sample_rate() !=
177 cast_receiver_session_
->audio_config_
.rtp_timebase
||
178 params
.channels() != cast_receiver_session_
->audio_config_
.channels
) {
179 callback
->OnCaptureError();
182 audio_valve_
= new CastReceiverAudioValve(callback
);
185 void CastReceiverSession::AudioCapturerSource::Start() {
186 DCHECK(audio_valve_
);
187 cast_receiver_session_
->StartAudio(audio_valve_
);
190 void CastReceiverSession::AudioCapturerSource::Stop() {
191 audio_valve_
->Stop();
192 audio_valve_
= nullptr;
195 void CastReceiverSession::AudioCapturerSource::SetVolume(double volume
) {
199 void CastReceiverSession::AudioCapturerSource::SetAutomaticGainControl(