OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/media_stream_video_capturer_source.h" | 5 #include "content/renderer/media/media_stream_video_capturer_source.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | |
9 #include "base/location.h" | 8 #include "base/location.h" |
10 #include "content/renderer/media/video_capture_impl_manager.h" | 9 #include "content/renderer/media/video_capture_impl_manager.h" |
11 #include "content/renderer/render_thread_impl.h" | 10 #include "content/renderer/render_thread_impl.h" |
12 #include "media/base/bind_to_current_loop.h" | |
13 #include "media/base/video_frame.h" | 11 #include "media/base/video_frame.h" |
14 | 12 |
15 namespace { | 13 namespace { |
16 | 14 |
17 struct SourceVideoFormat { | 15 struct SourceVideoFormat { |
18 int width; | 16 int width; |
19 int height; | 17 int height; |
20 int frame_rate; | 18 int frame_rate; |
21 }; | 19 }; |
22 | 20 |
(...skipping 10 matching lines...) Expand all Loading... |
33 | 31 |
34 namespace content { | 32 namespace content { |
35 | 33 |
36 VideoCapturerDelegate::VideoCapturerDelegate( | 34 VideoCapturerDelegate::VideoCapturerDelegate( |
37 const StreamDeviceInfo& device_info) | 35 const StreamDeviceInfo& device_info) |
38 : session_id_(device_info.session_id), | 36 : session_id_(device_info.session_id), |
39 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || | 37 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || |
40 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), | 38 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), |
41 got_first_frame_(false) { | 39 got_first_frame_(false) { |
42 DVLOG(3) << "VideoCapturerDelegate::ctor"; | 40 DVLOG(3) << "VideoCapturerDelegate::ctor"; |
43 | 41 // RenderThreadImpl::current() may be NULL in testing. |
44 // NULL in unit test. | |
45 if (RenderThreadImpl::current()) { | 42 if (RenderThreadImpl::current()) { |
46 VideoCaptureImplManager* manager = | 43 capture_engine_ = RenderThreadImpl::current()->video_capture_impl_manager() |
47 RenderThreadImpl::current()->video_capture_impl_manager(); | 44 ->UseDevice(device_info.session_id); |
48 if (manager) | 45 DCHECK(capture_engine_); |
49 release_device_cb_ = manager->UseDevice(session_id_); | |
50 } | 46 } |
| 47 message_loop_proxy_ = base::MessageLoopProxy::current(); |
51 } | 48 } |
52 | 49 |
53 VideoCapturerDelegate::~VideoCapturerDelegate() { | 50 VideoCapturerDelegate::~VideoCapturerDelegate() { |
54 DVLOG(3) << "VideoCapturerDelegate::dtor"; | 51 DVLOG(3) << "VideoCapturerDelegate::dtor"; |
55 DCHECK(new_frame_callback_.is_null()); | 52 DCHECK(new_frame_callback_.is_null()); |
56 if (!release_device_cb_.is_null()) | |
57 release_device_cb_.Run(); | |
58 } | 53 } |
59 | 54 |
60 void VideoCapturerDelegate::GetCurrentSupportedFormats( | 55 void VideoCapturerDelegate::GetCurrentSupportedFormats( |
61 int max_requested_width, | 56 int max_requested_width, |
62 int max_requested_height, | 57 int max_requested_height, |
63 const VideoCaptureDeviceFormatsCB& callback) { | 58 const SupportedFormatsCallback& callback) { |
64 DVLOG(3) << "GetCurrentSupportedFormats(" | 59 DVLOG(3) << "GetCurrentSupportedFormats(" |
65 << " { max_requested_height = " << max_requested_height << "})" | 60 << " { max_requested_height = " << max_requested_height << "})" |
66 << " { max_requested_width = " << max_requested_width << "})"; | 61 << " { max_requested_width = " << max_requested_width << "})"; |
67 | 62 |
68 if (is_screen_cast_) { | 63 if (is_screen_cast_) { |
69 media::VideoCaptureFormats formats; | 64 media::VideoCaptureFormats formats; |
70 const int width = max_requested_width ? | 65 const int width = max_requested_width ? |
71 max_requested_width : MediaStreamVideoSource::kDefaultWidth; | 66 max_requested_width : MediaStreamVideoSource::kDefaultWidth; |
72 const int height = max_requested_height ? | 67 const int height = max_requested_height ? |
73 max_requested_height : MediaStreamVideoSource::kDefaultHeight; | 68 max_requested_height : MediaStreamVideoSource::kDefaultHeight; |
74 formats.push_back( | 69 formats.push_back( |
75 media::VideoCaptureFormat( | 70 media::VideoCaptureFormat( |
76 gfx::Size(width, height), | 71 gfx::Size(width, height), |
77 MediaStreamVideoSource::kDefaultFrameRate, | 72 MediaStreamVideoSource::kDefaultFrameRate, |
78 media::PIXEL_FORMAT_I420)); | 73 media::PIXEL_FORMAT_I420)); |
79 callback.Run(formats); | 74 callback.Run(formats); |
80 return; | 75 return; |
81 } | 76 } |
82 | 77 |
83 // NULL in unit test. | |
84 if (!RenderThreadImpl::current()) | |
85 return; | |
86 VideoCaptureImplManager* manager = | |
87 RenderThreadImpl::current()->video_capture_impl_manager(); | |
88 if (!manager) | |
89 return; | |
90 DCHECK(source_formats_callback_.is_null()); | 78 DCHECK(source_formats_callback_.is_null()); |
91 source_formats_callback_ = callback; | 79 source_formats_callback_ = callback; |
92 manager->GetDeviceFormatsInUse( | 80 capture_engine_->GetDeviceFormatsInUse(base::Bind( |
93 session_id_, | 81 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this)); |
94 media::BindToCurrentLoop( | |
95 base::Bind( | |
96 &VideoCapturerDelegate::OnDeviceFormatsInUseReceived, this))); | |
97 } | 82 } |
98 | 83 |
99 void VideoCapturerDelegate::StartCapture( | 84 void VideoCapturerDelegate::StartDeliver( |
100 const media::VideoCaptureParams& params, | 85 const media::VideoCaptureParams& params, |
101 const VideoCaptureDeliverFrameCB& new_frame_callback, | 86 const NewFrameCallback& new_frame_callback, |
102 const StartedCallback& started_callback) { | 87 const StartedCallback& started_callback) { |
103 DCHECK(params.requested_format.IsValid()); | 88 DCHECK(params.requested_format.IsValid()); |
104 DCHECK(thread_checker_.CalledOnValidThread()); | 89 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
105 new_frame_callback_ = new_frame_callback; | 90 new_frame_callback_ = new_frame_callback; |
106 started_callback_ = started_callback; | 91 started_callback_ = started_callback; |
107 got_first_frame_ = false; | 92 got_first_frame_ = false; |
108 | 93 |
109 // NULL in unit test. | 94 // Increase the reference count to ensure the object is not deleted until |
110 if (!RenderThreadImpl::current()) | 95 // it is unregistered in VideoCapturerDelegate::OnRemoved. |
111 return; | 96 AddRef(); |
112 VideoCaptureImplManager* manager = | 97 capture_engine_->StartCapture(this, params); |
113 RenderThreadImpl::current()->video_capture_impl_manager(); | |
114 if (!manager) | |
115 return; | |
116 stop_capture_cb_ = | |
117 manager->StartCapture( | |
118 session_id_, | |
119 params, | |
120 media::BindToCurrentLoop(base::Bind( | |
121 &VideoCapturerDelegate::OnStateUpdateOnRenderThread, this)), | |
122 media::BindToCurrentLoop(base::Bind( | |
123 &VideoCapturerDelegate::OnFrameReadyOnRenderThread, this))); | |
124 } | 98 } |
125 | 99 |
126 void VideoCapturerDelegate::StopCapture() { | 100 void VideoCapturerDelegate::StopDeliver() { |
127 // Immediately make sure we don't provide more frames. | 101 // Immediately make sure we don't provide more frames. |
128 DVLOG(3) << "VideoCapturerDelegate::StopCapture()"; | 102 DVLOG(3) << "VideoCapturerDelegate::StopDeliver()"; |
129 DCHECK(thread_checker_.CalledOnValidThread()); | 103 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
130 if (!stop_capture_cb_.is_null()) { | 104 capture_engine_->StopCapture(this); |
131 base::ResetAndReturn(&stop_capture_cb_).Run(); | |
132 } | |
133 new_frame_callback_.Reset(); | 105 new_frame_callback_.Reset(); |
134 started_callback_.Reset(); | 106 started_callback_.Reset(); |
135 source_formats_callback_.Reset(); | 107 source_formats_callback_.Reset(); |
136 } | 108 } |
137 | 109 |
| 110 void VideoCapturerDelegate::OnStarted(media::VideoCapture* capture) { |
| 111 DVLOG(3) << "VideoCapturerDelegate::OnStarted"; |
| 112 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 113 } |
| 114 |
| 115 void VideoCapturerDelegate::OnStopped(media::VideoCapture* capture) { |
| 116 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 117 } |
| 118 |
| 119 void VideoCapturerDelegate::OnPaused(media::VideoCapture* capture) { |
| 120 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 121 } |
| 122 |
| 123 void VideoCapturerDelegate::OnError(media::VideoCapture* capture, |
| 124 int error_code) { |
| 125 DVLOG(3) << "VideoCapturerDelegate::OnError"; |
| 126 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 127 message_loop_proxy_->PostTask( |
| 128 FROM_HERE, |
| 129 base::Bind(&VideoCapturerDelegate::OnErrorOnRenderThread, this, capture)); |
| 130 } |
| 131 |
| 132 void VideoCapturerDelegate::OnRemoved(media::VideoCapture* capture) { |
| 133 DVLOG(3) << " MediaStreamVideoCapturerSource::OnRemoved"; |
| 134 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 135 |
| 136 // Balance the AddRef in StartDeliver. |
| 137 // This means we are no longer registered as an event handler and can safely |
| 138 // be deleted. |
| 139 Release(); |
| 140 } |
| 141 |
| 142 void VideoCapturerDelegate::OnFrameReady( |
| 143 media::VideoCapture* capture, |
| 144 const scoped_refptr<media::VideoFrame>& frame) { |
| 145 DCHECK(!message_loop_proxy_->BelongsToCurrentThread()); |
| 146 message_loop_proxy_->PostTask( |
| 147 FROM_HERE, |
| 148 base::Bind(&VideoCapturerDelegate::OnFrameReadyOnRenderThread, |
| 149 this, |
| 150 capture, |
| 151 frame)); |
| 152 } |
| 153 |
138 void VideoCapturerDelegate::OnFrameReadyOnRenderThread( | 154 void VideoCapturerDelegate::OnFrameReadyOnRenderThread( |
139 const scoped_refptr<media::VideoFrame>& frame, | 155 media::VideoCapture* capture, |
140 const media::VideoCaptureFormat& format) { | 156 const scoped_refptr<media::VideoFrame>& frame) { |
141 if (!got_first_frame_) { | 157 if (!got_first_frame_) { |
142 got_first_frame_ = true; | 158 got_first_frame_ = true; |
143 if (!started_callback_.is_null()) | 159 if (!started_callback_.is_null()) |
144 started_callback_.Run(true); | 160 started_callback_.Run(true); |
145 } | 161 } |
146 | 162 |
147 if (!new_frame_callback_.is_null()) { | 163 if (!new_frame_callback_.is_null()) { |
148 new_frame_callback_.Run(frame, format); | 164 new_frame_callback_.Run(frame); |
149 } | 165 } |
150 } | 166 } |
151 | 167 |
152 void VideoCapturerDelegate::OnStateUpdateOnRenderThread( | 168 void VideoCapturerDelegate::OnErrorOnRenderThread( |
153 VideoCaptureState state) { | 169 media::VideoCapture* capture) { |
154 if (state == VIDEO_CAPTURE_STATE_ERROR && !started_callback_.is_null()) { | 170 if (!started_callback_.is_null()) |
155 started_callback_.Run(false); | 171 started_callback_.Run(false); |
156 } | |
157 } | 172 } |
158 | 173 |
159 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived( | 174 void VideoCapturerDelegate::OnDeviceFormatsInUseReceived( |
160 const media::VideoCaptureFormats& formats_in_use) { | 175 const media::VideoCaptureFormats& formats_in_use) { |
161 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size(); | 176 DVLOG(3) << "OnDeviceFormatsInUseReceived: " << formats_in_use.size(); |
162 DCHECK(thread_checker_.CalledOnValidThread()); | 177 DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current()); |
163 // StopCapture() might have destroyed |source_formats_callback_| before | 178 // StopDeliver() might have destroyed |source_formats_callback_| before |
164 // arriving here. | 179 // arriving here. |
165 if (source_formats_callback_.is_null()) | 180 if (source_formats_callback_.is_null()) |
166 return; | 181 return; |
167 // If there are no formats in use, try to retrieve the whole list of | |
168 // supported form. | |
169 if (!formats_in_use.empty()) { | 182 if (!formats_in_use.empty()) { |
170 source_formats_callback_.Run(formats_in_use); | 183 source_formats_callback_.Run(formats_in_use); |
171 source_formats_callback_.Reset(); | 184 source_formats_callback_.Reset(); |
172 return; | 185 } else { |
| 186 // If there are no formats in use, try to retrieve the whole list of |
| 187 // supported formats. |
| 188 capture_engine_->GetDeviceSupportedFormats(base::Bind( |
| 189 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated, this)); |
173 } | 190 } |
174 | |
175 // NULL in unit test. | |
176 if (!RenderThreadImpl::current()) | |
177 return; | |
178 VideoCaptureImplManager* manager = | |
179 RenderThreadImpl::current()->video_capture_impl_manager(); | |
180 if (!manager) | |
181 return; | |
182 manager->GetDeviceSupportedFormats( | |
183 session_id_, | |
184 media::BindToCurrentLoop( | |
185 base::Bind( | |
186 &VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated, | |
187 this))); | |
188 } | 191 } |
189 | 192 |
190 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated( | 193 void VideoCapturerDelegate::OnDeviceSupportedFormatsEnumerated( |
191 const media::VideoCaptureFormats& formats) { | 194 const media::VideoCaptureFormats& formats) { |
192 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size() | 195 DVLOG(3) << "OnDeviceSupportedFormatsEnumerated: " << formats.size() |
193 << " received"; | 196 << " received"; |
194 DCHECK(thread_checker_.CalledOnValidThread()); | 197 DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current()); |
195 // StopCapture() might have destroyed |source_formats_callback_| before | 198 // StopDeliver() might have destroyed |source_formats_callback_| before |
196 // arriving here. | 199 // arriving here. |
197 if (source_formats_callback_.is_null()) | 200 if (source_formats_callback_.is_null()) |
198 return; | 201 return; |
199 if (formats.size()) { | 202 if (formats.size()) { |
200 source_formats_callback_.Run(formats); | 203 source_formats_callback_.Run(formats); |
201 } else { | 204 } else { |
202 // The capture device doesn't seem to support capability enumeration, | 205 // The capture device doesn't seem to support capability enumeration, |
203 // compose a fallback list of capabilities. | 206 // compose a fallback list of capabilities. |
204 media::VideoCaptureFormats default_formats; | 207 media::VideoCaptureFormats default_formats; |
205 for (size_t i = 0; i < arraysize(kVideoFormats); ++i) { | 208 for (size_t i = 0; i < arraysize(kVideoFormats); ++i) { |
(...skipping 30 matching lines...) Expand all Loading... |
236 base::Unretained(this))); | 239 base::Unretained(this))); |
237 } | 240 } |
238 | 241 |
239 void MediaStreamVideoCapturerSource::StartSourceImpl( | 242 void MediaStreamVideoCapturerSource::StartSourceImpl( |
240 const media::VideoCaptureParams& params) { | 243 const media::VideoCaptureParams& params) { |
241 media::VideoCaptureParams new_params(params); | 244 media::VideoCaptureParams new_params(params); |
242 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || | 245 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || |
243 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { | 246 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
244 new_params.allow_resolution_change = true; | 247 new_params.allow_resolution_change = true; |
245 } | 248 } |
246 delegate_->StartCapture( | 249 delegate_->StartDeliver( |
247 new_params, | 250 new_params, |
248 base::Bind(&MediaStreamVideoCapturerSource::DeliverVideoFrame, | 251 base::Bind(&MediaStreamVideoCapturerSource::DeliverVideoFrame, |
249 base::Unretained(this)), | 252 base::Unretained(this)), |
250 base::Bind(&MediaStreamVideoCapturerSource::OnStartDone, | 253 base::Bind(&MediaStreamVideoCapturerSource::OnStartDone, |
251 base::Unretained(this))); | 254 base::Unretained(this))); |
252 } | 255 } |
253 | 256 |
254 void MediaStreamVideoCapturerSource::StopSourceImpl() { | 257 void MediaStreamVideoCapturerSource::StopSourceImpl() { |
255 delegate_->StopCapture(); | 258 delegate_->StopDeliver(); |
256 } | 259 } |
257 | 260 |
258 } // namespace content | 261 } // namespace content |
OLD | NEW |