Enable right clicking on the applist doodle web contents and log the data.
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_capturer_source.cc
blobb414f7a6eeb7cf9dd736a09cb54b99a8e61bed78
1 // Copyright 2014 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 "content/renderer/media/media_stream_video_capturer_source.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "content/renderer/media/video_capture_impl_manager.h"
11 #include "content/renderer/render_thread_impl.h"
12 #include "media/base/bind_to_current_loop.h"
13 #include "media/base/video_frame.h"
15 namespace {
17 struct SourceVideoResolution {
18 int width;
19 int height;
22 // Resolutions used if the source doesn't support capability enumeration.
23 const SourceVideoResolution kVideoResolutions[] = {{1920, 1080},
24 {1280, 720},
25 {960, 720},
26 {640, 480},
27 {640, 360},
28 {320, 240},
29 {320, 180}};
30 // Frame rates for sources with no support for capability enumeration.
31 const int kVideoFrameRates[] = {30, 60};
33 // Hard upper-bound frame rate for tab/desktop capture.
34 const double kMaxScreenCastFrameRate = 120.0;
36 } // namespace
38 namespace content {
40 VideoCapturerDelegate::VideoCapturerDelegate(
41 const StreamDeviceInfo& device_info)
42 : session_id_(device_info.session_id),
43 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE ||
44 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE),
45 weak_factory_(this) {
46 DVLOG(3) << "VideoCapturerDelegate::ctor";
48 // NULL in unit test.
49 if (RenderThreadImpl::current()) {
50 VideoCaptureImplManager* manager =
51 RenderThreadImpl::current()->video_capture_impl_manager();
52 if (manager)
53 release_device_cb_ = manager->UseDevice(session_id_);
57 VideoCapturerDelegate::~VideoCapturerDelegate() {
58 DCHECK(thread_checker_.CalledOnValidThread());
59 DVLOG(3) << "VideoCapturerDelegate::dtor";
60 if (!release_device_cb_.is_null())
61 release_device_cb_.Run();
64 void VideoCapturerDelegate::GetCurrentSupportedFormats(
65 int max_requested_width,
66 int max_requested_height,
67 double max_requested_frame_rate,
68 const VideoCaptureDeviceFormatsCB& callback) {
69 DVLOG(3)
70 << "GetCurrentSupportedFormats("
71 << " { max_requested_height = " << max_requested_height << "})"
72 << " { max_requested_width = " << max_requested_width << "})"
73 << " { max_requested_frame_rate = " << max_requested_frame_rate << "})";
75 if (is_screen_cast_) {
76 const int width = max_requested_width ?
77 max_requested_width : MediaStreamVideoSource::kDefaultWidth;
78 const int height = max_requested_height ?
79 max_requested_height : MediaStreamVideoSource::kDefaultHeight;
80 callback.Run(media::VideoCaptureFormats(1, media::VideoCaptureFormat(
81 gfx::Size(width, height),
82 static_cast<float>(std::min(kMaxScreenCastFrameRate,
83 max_requested_frame_rate)),
84 media::PIXEL_FORMAT_I420)));
85 return;
88 // NULL in unit test.
89 if (!RenderThreadImpl::current())
90 return;
91 VideoCaptureImplManager* manager =
92 RenderThreadImpl::current()->video_capture_impl_manager();
93 if (!manager)
94 return;
95 DCHECK(source_formats_callback_.is_null());
96 source_formats_callback_ = callback;
97 manager->GetDeviceFormatsInUse(
98 session_id_,
99 media::BindToCurrentLoop(
100 base::Bind(
101 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived,
102 weak_factory_.GetWeakPtr())));
105 void VideoCapturerDelegate::StartCapture(
106 const media::VideoCaptureParams& params,
107 const VideoCaptureDeliverFrameCB& new_frame_callback,
108 scoped_refptr<base::SingleThreadTaskRunner> frame_callback_task_runner,
109 const RunningCallback& running_callback) {
110 DCHECK(params.requested_format.IsValid());
111 DCHECK(thread_checker_.CalledOnValidThread());
112 running_callback_ = running_callback;
114 // NULL in unit test.
115 if (!RenderThreadImpl::current())
116 return;
117 VideoCaptureImplManager* manager =
118 RenderThreadImpl::current()->video_capture_impl_manager();
119 if (!manager)
120 return;
121 if (frame_callback_task_runner !=
122 RenderThreadImpl::current()->GetIOMessageLoopProxy()) {
123 DCHECK(false) << "Only IO thread supported right now.";
124 running_callback.Run(false);
125 return;
128 stop_capture_cb_ =
129 manager->StartCapture(
130 session_id_,
131 params,
132 media::BindToCurrentLoop(base::Bind(
133 &VideoCapturerDelegate::OnStateUpdateOnRenderThread,
134 weak_factory_.GetWeakPtr())),
135 new_frame_callback);
138 void VideoCapturerDelegate::StopCapture() {
139 // Immediately make sure we don't provide more frames.
140 DVLOG(3) << "VideoCapturerDelegate::StopCapture()";
141 DCHECK(thread_checker_.CalledOnValidThread());
142 if (!stop_capture_cb_.is_null()) {
143 base::ResetAndReturn(&stop_capture_cb_).Run();
145 running_callback_.Reset();
146 source_formats_callback_.Reset();
149 void VideoCapturerDelegate::OnStateUpdateOnRenderThread(
150 VideoCaptureState state) {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 DVLOG(3) << "OnStateUpdateOnRenderThread state = " << state;
153 if (state == VIDEO_CAPTURE_STATE_STARTED && !running_callback_.is_null()) {
154 running_callback_.Run(true);
155 return;
157 if (state > VIDEO_CAPTURE_STATE_STARTED && !running_callback_.is_null()) {
158 base::ResetAndReturn(&running_callback_).Run(false);
162 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived(
163 const media::VideoCaptureFormats& formats_in_use) {
164 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size();
165 DCHECK(thread_checker_.CalledOnValidThread());
166 // StopCapture() might have destroyed |source_formats_callback_| before
167 // arriving here.
168 if (source_formats_callback_.is_null())
169 return;
170 // If there are no formats in use, try to retrieve the whole list of
171 // supported form.
172 if (!formats_in_use.empty()) {
173 source_formats_callback_.Run(formats_in_use);
174 source_formats_callback_.Reset();
175 return;
178 // NULL in unit test.
179 if (!RenderThreadImpl::current())
180 return;
181 VideoCaptureImplManager* manager =
182 RenderThreadImpl::current()->video_capture_impl_manager();
183 if (!manager)
184 return;
186 manager->GetDeviceSupportedFormats(
187 session_id_,
188 media::BindToCurrentLoop(
189 base::Bind(
190 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated,
191 weak_factory_.GetWeakPtr())));
194 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated(
195 const media::VideoCaptureFormats& formats) {
196 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size()
197 << " received";
198 DCHECK(thread_checker_.CalledOnValidThread());
199 // StopCapture() might have destroyed |source_formats_callback_| before
200 // arriving here.
201 if (source_formats_callback_.is_null())
202 return;
203 if (formats.size()) {
204 base::ResetAndReturn(&source_formats_callback_).Run(formats);
205 } else {
206 // The capture device doesn't seem to support capability enumeration,
207 // compose a fallback list of capabilities.
208 media::VideoCaptureFormats default_formats;
209 for (size_t i = 0; i < arraysize(kVideoResolutions); ++i) {
210 for (size_t j = 0; j < arraysize(kVideoFrameRates); ++j) {
211 default_formats.push_back(media::VideoCaptureFormat(
212 gfx::Size(kVideoResolutions[i].width, kVideoResolutions[i].height),
213 kVideoFrameRates[j], media::PIXEL_FORMAT_I420));
216 base::ResetAndReturn(&source_formats_callback_).Run(default_formats);
220 MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
221 const SourceStoppedCallback& stop_callback,
222 scoped_ptr<media::VideoCapturerSource> delegate)
223 : delegate_(delegate.Pass()) {
224 SetStopCallback(stop_callback);
227 void MediaStreamVideoCapturerSource::SetDeviceInfo(
228 const StreamDeviceInfo& device_info) {
229 MediaStreamVideoSource::SetDeviceInfo(device_info);
232 MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
235 void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
236 int max_requested_width,
237 int max_requested_height,
238 double max_requested_frame_rate,
239 const VideoCaptureDeviceFormatsCB& callback) {
240 delegate_->GetCurrentSupportedFormats(
241 max_requested_width,
242 max_requested_height,
243 max_requested_frame_rate,
244 callback);
247 void MediaStreamVideoCapturerSource::StartSourceImpl(
248 const media::VideoCaptureFormat& format,
249 const VideoCaptureDeliverFrameCB& frame_callback) {
250 media::VideoCaptureParams new_params;
251 new_params.requested_format = format;
252 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE ||
253 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
254 new_params.resolution_change_policy =
255 media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT;
257 delegate_->StartCapture(
258 new_params,
259 frame_callback,
260 RenderThreadImpl::current() ?
261 RenderThreadImpl::current()->GetIOMessageLoopProxy() :
262 nullptr,
263 base::Bind(&MediaStreamVideoCapturerSource::OnStarted,
264 base::Unretained(this)));
267 void MediaStreamVideoCapturerSource::OnStarted(bool result) {
268 OnStartDone(result ? MEDIA_DEVICE_OK : MEDIA_DEVICE_TRACK_START_FAILURE);
271 void MediaStreamVideoCapturerSource::StopSourceImpl() {
272 delegate_->StopCapture();
275 } // namespace content