Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_capturer_source.cc
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.
4
5 #include "content/renderer/media/media_stream_video_capturer_source.h"
6
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"
14
15 namespace {
16
17 struct SourceVideoFormat {
18   int width;
19   int height;
20   int frame_rate;
21 };
22
23 // List of formats used if the source doesn't support capability enumeration.
24 const SourceVideoFormat kVideoFormats[] = {{1920, 1080, 30},
25                                            {1280, 720, 30},
26                                            {960, 720, 30},
27                                            {640, 480, 30},
28                                            {640, 360, 30},
29                                            {320, 240, 30},
30                                            {320, 180, 30}};
31
32 }  // namespace
33
34 namespace content {
35
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";
43
44   // NULL in unit test.
45   if (RenderThreadImpl::current()) {
46     VideoCaptureImplManager* manager =
47         RenderThreadImpl::current()->video_capture_impl_manager();
48     if (manager)
49       release_device_cb_ = manager->UseDevice(session_id_);
50   }
51 }
52
53 VideoCapturerDelegate::~VideoCapturerDelegate() {
54   DVLOG(3) << "VideoCapturerDelegate::dtor";
55   if (!release_device_cb_.is_null())
56     release_device_cb_.Run();
57 }
58
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 << "})";
66
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;
73     formats.push_back(
74           media::VideoCaptureFormat(
75               gfx::Size(width, height),
76               MediaStreamVideoSource::kDefaultFrameRate,
77               media::PIXEL_FORMAT_I420));
78     callback.Run(formats);
79     return;
80   }
81
82   // NULL in unit test.
83   if (!RenderThreadImpl::current())
84     return;
85   VideoCaptureImplManager* manager =
86       RenderThreadImpl::current()->video_capture_impl_manager();
87   if (!manager)
88     return;
89   DCHECK(source_formats_callback_.is_null());
90   source_formats_callback_ = callback;
91   manager->GetDeviceFormatsInUse(
92       session_id_,
93       media::BindToCurrentLoop(
94           base::Bind(
95               &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this)));
96 }
97
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;
106
107   // NULL in unit test.
108   if (!RenderThreadImpl::current())
109     return;
110   VideoCaptureImplManager* manager =
111       RenderThreadImpl::current()->video_capture_impl_manager();
112   if (!manager)
113     return;
114   stop_capture_cb_ =
115       manager->StartCapture(
116           session_id_,
117           params,
118           media::BindToCurrentLoop(base::Bind(
119               &VideoCapturerDelegate::OnStateUpdateOnRenderThread, this)),
120           new_frame_callback);
121 }
122
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();
129   }
130   started_callback_.Reset();
131   source_formats_callback_.Reset();
132 }
133
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);
141   }
142 }
143
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
149   // arriving here.
150   if (source_formats_callback_.is_null())
151     return;
152   // If there are no formats in use, try to retrieve the whole list of
153   // supported form.
154   if (!formats_in_use.empty()) {
155     source_formats_callback_.Run(formats_in_use);
156     source_formats_callback_.Reset();
157     return;
158   }
159
160   // NULL in unit test.
161   if (!RenderThreadImpl::current())
162     return;
163   VideoCaptureImplManager* manager =
164       RenderThreadImpl::current()->video_capture_impl_manager();
165   if (!manager)
166     return;
167   manager->GetDeviceSupportedFormats(
168       session_id_,
169       media::BindToCurrentLoop(
170           base::Bind(
171               &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated,
172               this)));
173 }
174
175 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated(
176     const media::VideoCaptureFormats& formats) {
177   DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size()
178            << " received";
179   DCHECK(thread_checker_.CalledOnValidThread());
180   // StopCapture() might have destroyed |source_formats_callback_| before
181   // arriving here.
182   if (source_formats_callback_.is_null())
183     return;
184   if (formats.size()) {
185     source_formats_callback_.Run(formats);
186   } else {
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));
195     }
196     source_formats_callback_.Run(default_formats);
197   }
198   source_formats_callback_.Reset();
199 }
200
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);
208 }
209
210 MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
211 }
212
213 void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
214     int max_requested_width,
215     int max_requested_height,
216     const VideoCaptureDeviceFormatsCB& callback) {
217   delegate_->GetCurrentSupportedFormats(
218       max_requested_width,
219       max_requested_height,
220       callback);
221 }
222
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;
230   }
231   delegate_->StartCapture(
232       new_params,
233       frame_callback,
234       base::Bind(&MediaStreamVideoCapturerSource::OnStartDone,
235                  base::Unretained(this)));
236 }
237
238 void MediaStreamVideoCapturerSource::StopSourceImpl() {
239   delegate_->StopCapture();
240 }
241
242 }  // namespace content