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