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"
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"
17 struct SourceVideoFormat {
23 // List of formats used if the source doesn't support capability enumeration.
24 const SourceVideoFormat kVideoFormats[] = {{1920, 1080, 30},
36 VideoCapturerDelegate::VideoCapturerDelegate(
37 const StreamDeviceInfo& device_info)
38 : session_id_(device_info.session_id),
39 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE ||
40 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE),
41 got_first_frame_(false) {
42 DVLOG(3) << "VideoCapturerDelegate::ctor";
45 if (RenderThreadImpl::current()) {
46 VideoCaptureImplManager* manager =
47 RenderThreadImpl::current()->video_capture_impl_manager();
49 release_device_cb_ = manager->UseDevice(session_id_);
53 VideoCapturerDelegate::~VideoCapturerDelegate() {
54 DVLOG(3) << "VideoCapturerDelegate::dtor";
55 if (!release_device_cb_.is_null())
56 release_device_cb_.Run();
59 void VideoCapturerDelegate::GetCurrentSupportedFormats(
60 int max_requested_width,
61 int max_requested_height,
62 const VideoCaptureDeviceFormatsCB& callback) {
63 DVLOG(3) << "GetCurrentSupportedFormats("
64 << " { max_requested_height = " << max_requested_height << "})"
65 << " { max_requested_width = " << max_requested_width << "})";
67 if (is_screen_cast_) {
68 media::VideoCaptureFormats formats;
69 const int width = max_requested_width ?
70 max_requested_width : MediaStreamVideoSource::kDefaultWidth;
71 const int height = max_requested_height ?
72 max_requested_height : MediaStreamVideoSource::kDefaultHeight;
74 media::VideoCaptureFormat(
75 gfx::Size(width, height),
76 MediaStreamVideoSource::kDefaultFrameRate,
77 media::PIXEL_FORMAT_I420));
78 callback.Run(formats);
83 if (!RenderThreadImpl::current())
85 VideoCaptureImplManager* manager =
86 RenderThreadImpl::current()->video_capture_impl_manager();
89 DCHECK(source_formats_callback_.is_null());
90 source_formats_callback_ = callback;
91 manager->GetDeviceFormatsInUse(
93 media::BindToCurrentLoop(
95 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this)));
98 void VideoCapturerDelegate::StartCapture(
99 const media::VideoCaptureParams& params,
100 const VideoCaptureDeliverFrameCB& new_frame_callback,
101 const StartedCallback& started_callback) {
102 DCHECK(params.requested_format.IsValid());
103 DCHECK(thread_checker_.CalledOnValidThread());
104 started_callback_ = started_callback;
105 got_first_frame_ = false;
107 // NULL in unit test.
108 if (!RenderThreadImpl::current())
110 VideoCaptureImplManager* manager =
111 RenderThreadImpl::current()->video_capture_impl_manager();
115 manager->StartCapture(
118 media::BindToCurrentLoop(base::Bind(
119 &VideoCapturerDelegate::OnStateUpdateOnRenderThread, this)),
123 void VideoCapturerDelegate::StopCapture() {
124 // Immediately make sure we don't provide more frames.
125 DVLOG(3) << "VideoCapturerDelegate::StopCapture()";
126 DCHECK(thread_checker_.CalledOnValidThread());
127 if (!stop_capture_cb_.is_null()) {
128 base::ResetAndReturn(&stop_capture_cb_).Run();
130 started_callback_.Reset();
131 source_formats_callback_.Reset();
134 void VideoCapturerDelegate::OnStateUpdateOnRenderThread(
135 VideoCaptureState state) {
136 DCHECK(thread_checker_.CalledOnValidThread());
137 DVLOG(3) << "OnStateUpdateOnRenderThread state = " << state;
138 if (state > VIDEO_CAPTURE_STATE_STARTING && !started_callback_.is_null()) {
139 base::ResetAndReturn(&started_callback_).Run(
140 state == VIDEO_CAPTURE_STATE_STARTED);
144 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived(
145 const media::VideoCaptureFormats& formats_in_use) {
146 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size();
147 DCHECK(thread_checker_.CalledOnValidThread());
148 // StopCapture() might have destroyed |source_formats_callback_| before
150 if (source_formats_callback_.is_null())
152 // If there are no formats in use, try to retrieve the whole list of
154 if (!formats_in_use.empty()) {
155 source_formats_callback_.Run(formats_in_use);
156 source_formats_callback_.Reset();
160 // NULL in unit test.
161 if (!RenderThreadImpl::current())
163 VideoCaptureImplManager* manager =
164 RenderThreadImpl::current()->video_capture_impl_manager();
167 manager->GetDeviceSupportedFormats(
169 media::BindToCurrentLoop(
171 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated,
175 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated(
176 const media::VideoCaptureFormats& formats) {
177 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size()
179 DCHECK(thread_checker_.CalledOnValidThread());
180 // StopCapture() might have destroyed |source_formats_callback_| before
182 if (source_formats_callback_.is_null())
184 if (formats.size()) {
185 source_formats_callback_.Run(formats);
187 // The capture device doesn't seem to support capability enumeration,
188 // compose a fallback list of capabilities.
189 media::VideoCaptureFormats default_formats;
190 for (size_t i = 0; i < arraysize(kVideoFormats); ++i) {
191 default_formats.push_back(media::VideoCaptureFormat(
192 gfx::Size(kVideoFormats[i].width, kVideoFormats[i].height),
193 kVideoFormats[i].frame_rate,
194 media::PIXEL_FORMAT_I420));
196 source_formats_callback_.Run(default_formats);
198 source_formats_callback_.Reset();
201 MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
202 const StreamDeviceInfo& device_info,
203 const SourceStoppedCallback& stop_callback,
204 const scoped_refptr<VideoCapturerDelegate>& delegate)
205 : delegate_(delegate) {
206 SetDeviceInfo(device_info);
207 SetStopCallback(stop_callback);
210 MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
213 void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
214 int max_requested_width,
215 int max_requested_height,
216 const VideoCaptureDeviceFormatsCB& callback) {
217 delegate_->GetCurrentSupportedFormats(
219 max_requested_height,
223 void MediaStreamVideoCapturerSource::StartSourceImpl(
224 const media::VideoCaptureParams& params,
225 const VideoCaptureDeliverFrameCB& frame_callback) {
226 media::VideoCaptureParams new_params(params);
227 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE ||
228 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
229 new_params.allow_resolution_change = true;
231 delegate_->StartCapture(
234 base::Bind(&MediaStreamVideoCapturerSource::OnStartDone,
235 base::Unretained(this)));
238 void MediaStreamVideoCapturerSource::StopSourceImpl() {
239 delegate_->StopCapture();
242 } // namespace content