OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/browser/renderer_host/media/video_capture_manager.h" | 5 #include "content/browser/renderer_host/media/video_capture_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
20 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
21 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
22 #include "base/threading/sequenced_worker_pool.h" | 22 #include "base/threading/sequenced_worker_pool.h" |
23 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
25 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" | 25 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" |
26 #include "content/browser/media/capture/web_contents_video_capture_device.h" | 26 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
27 #include "content/browser/media/media_internals.h" | 27 #include "content/browser/media/media_internals.h" |
| 28 #include "content/browser/renderer_host/media/in_process_buildable_video_capture
_device.h" |
28 #include "content/browser/renderer_host/media/video_capture_controller.h" | 29 #include "content/browser/renderer_host/media/video_capture_controller.h" |
29 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" | 30 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" |
30 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" | |
31 #include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.
h" | |
32 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
33 #include "content/public/browser/desktop_media_id.h" | 32 #include "content/public/browser/desktop_media_id.h" |
34 #include "content/public/common/media_stream_request.h" | 33 #include "content/public/common/media_stream_request.h" |
35 #include "media/base/bind_to_current_loop.h" | 34 #include "media/base/bind_to_current_loop.h" |
36 #include "media/base/media_switches.h" | 35 #include "media/base/media_switches.h" |
37 #include "media/base/video_facing.h" | 36 #include "media/base/video_facing.h" |
38 #include "media/capture/video/video_capture_buffer_pool_impl.h" | 37 #include "media/capture/video/video_capture_buffer_pool_impl.h" |
39 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" | 38 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" |
40 #include "media/capture/video/video_capture_device.h" | 39 #include "media/capture/video/video_capture_device.h" |
41 #include "media/capture/video/video_capture_device_client.h" | 40 #include "media/capture/video/video_capture_device_client.h" |
(...skipping 10 matching lines...) Expand all Loading... |
52 #endif | 51 #endif |
53 | 52 |
54 #if defined(OS_ANDROID) | 53 #if defined(OS_ANDROID) |
55 #include "content/browser/media/capture/screen_capture_device_android.h" | 54 #include "content/browser/media/capture/screen_capture_device_android.h" |
56 #endif | 55 #endif |
57 | 56 |
58 #endif // defined(ENABLE_SCREEN_CAPTURE) | 57 #endif // defined(ENABLE_SCREEN_CAPTURE) |
59 | 58 |
60 namespace { | 59 namespace { |
61 | 60 |
62 class VideoFrameConsumerFeedbackObserverOnTaskRunner | |
63 : public media::VideoFrameConsumerFeedbackObserver { | |
64 public: | |
65 VideoFrameConsumerFeedbackObserverOnTaskRunner( | |
66 media::VideoFrameConsumerFeedbackObserver* observer, | |
67 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | |
68 : observer_(observer), task_runner_(std::move(task_runner)) {} | |
69 | |
70 void OnUtilizationReport(int frame_feedback_id, double utilization) override { | |
71 task_runner_->PostTask( | |
72 FROM_HERE, | |
73 base::Bind( | |
74 &media::VideoFrameConsumerFeedbackObserver::OnUtilizationReport, | |
75 base::Unretained(observer_), frame_feedback_id, utilization)); | |
76 } | |
77 | |
78 private: | |
79 media::VideoFrameConsumerFeedbackObserver* const observer_; | |
80 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
81 }; | |
82 | |
83 // Compares two VideoCaptureFormat by checking smallest frame_size area, then | 61 // Compares two VideoCaptureFormat by checking smallest frame_size area, then |
84 // by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that | 62 // by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that |
85 // the first entry for a given resolution has the largest frame rate, as needed | 63 // the first entry for a given resolution has the largest frame rate, as needed |
86 // by the ConsolidateCaptureFormats() method. | 64 // by the ConsolidateCaptureFormats() method. |
87 bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1, | 65 bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1, |
88 const media::VideoCaptureFormat& format2) { | 66 const media::VideoCaptureFormat& format2) { |
89 DCHECK(format1.frame_size.GetCheckedArea().IsValid()); | 67 DCHECK(format1.frame_size.GetCheckedArea().IsValid()); |
90 DCHECK(format2.frame_size.GetCheckedArea().IsValid()); | 68 DCHECK(format2.frame_size.GetCheckedArea().IsValid()); |
91 if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) == | 69 if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) == |
92 format2.frame_size.GetCheckedArea().ValueOrDefault(0)) { | 70 format2.frame_size.GetCheckedArea().ValueOrDefault(0)) { |
(...skipping 25 matching lines...) Expand all Loading... |
118 formats->erase(last, formats->end()); | 96 formats->erase(last, formats->end()); |
119 // Mark all formats as I420, since this is what the renderer side will get | 97 // Mark all formats as I420, since this is what the renderer side will get |
120 // anyhow: the actual pixel format is decided at the device level. | 98 // anyhow: the actual pixel format is decided at the device level. |
121 // Don't do this for Y16 format as it is handled separatelly. | 99 // Don't do this for Y16 format as it is handled separatelly. |
122 for (auto& format : *formats) { | 100 for (auto& format : *formats) { |
123 if (format.pixel_format != media::PIXEL_FORMAT_Y16) | 101 if (format.pixel_format != media::PIXEL_FORMAT_Y16) |
124 format.pixel_format = media::PIXEL_FORMAT_I420; | 102 format.pixel_format = media::PIXEL_FORMAT_I420; |
125 } | 103 } |
126 } | 104 } |
127 | 105 |
128 // The maximum number of video frame buffers in-flight at any one time. This | |
129 // value should be based on the logical capacity of the capture pipeline, and | |
130 // not on hardware performance. For example, tab capture requires more buffers | |
131 // than webcam capture because the pipeline is longer (it includes read-backs | |
132 // pending in the GPU pipeline). | |
133 const int kMaxNumberOfBuffers = 3; | |
134 // TODO(miu): The value for tab capture should be determined programmatically. | |
135 // http://crbug.com/460318 | |
136 const int kMaxNumberOfBuffersForTabCapture = 10; | |
137 | |
138 // Used for logging capture events. | 106 // Used for logging capture events. |
139 // Elements in this enum should not be deleted or rearranged; the only | 107 // Elements in this enum should not be deleted or rearranged; the only |
140 // permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT. | 108 // permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT. |
141 enum VideoCaptureEvent { | 109 enum VideoCaptureEvent { |
142 VIDEO_CAPTURE_START_CAPTURE = 0, | 110 VIDEO_CAPTURE_START_CAPTURE = 0, |
143 VIDEO_CAPTURE_STOP_CAPTURE_OK = 1, | 111 VIDEO_CAPTURE_STOP_CAPTURE_OK = 1, |
144 VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2, | 112 VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2, |
145 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3, | 113 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3, |
146 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4, | 114 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4, |
147 NUM_VIDEO_CAPTURE_EVENT | 115 NUM_VIDEO_CAPTURE_EVENT |
148 }; | 116 }; |
149 | 117 |
150 void LogVideoCaptureEvent(VideoCaptureEvent event) { | 118 void LogVideoCaptureEvent(VideoCaptureEvent event) { |
151 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", | 119 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", event, |
152 event, | |
153 NUM_VIDEO_CAPTURE_EVENT); | 120 NUM_VIDEO_CAPTURE_EVENT); |
154 } | 121 } |
155 | 122 |
156 // Counter used for identifying a DeviceRequest to start a capture device. | |
157 static int g_device_start_id = 0; | |
158 | |
159 const media::VideoCaptureSessionId kFakeSessionId = -1; | 123 const media::VideoCaptureSessionId kFakeSessionId = -1; |
160 | 124 |
161 std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( | |
162 const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) { | |
163 return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb); | |
164 } | |
165 | |
166 } // namespace | 125 } // namespace |
167 | 126 |
168 namespace content { | 127 namespace content { |
169 | 128 |
170 // Instances of this struct go through several different phases during their | |
171 // lifetime. | |
172 // Phase 1: When first created (in GetOrCreateDeviceEntry()), this consists of | |
173 // only the |video_capture_controller|. Clients can already connect to the | |
174 // controller, but there is no |video_capture_device| present. | |
175 // Phase 2: When a request to "start" the entry comes in (via | |
176 // HandleQueuedStartRequest()), creation of |video_capture_device| is scheduled | |
177 // to run asynchronously on the Device Thread. | |
178 // Phase 3: As soon as the creation of the VideoCaptureDevice is complete, this | |
179 // newly created VideoCaptureDevice instance is connected to the | |
180 // VideoCaptureController via SetConsumerFeedbackObserver(). | |
181 // Phase 4: This phase can only be reached on Android. When the application goes | |
182 // to the background, the |video_capture_device| is asynchronously stopped and | |
183 // released on the Device Thread. When the application is resumed, we | |
184 // transition to Phase 2. | |
185 struct VideoCaptureManager::DeviceEntry { | |
186 public: | |
187 DeviceEntry(MediaStreamType stream_type, | |
188 const std::string& id, | |
189 const media::VideoCaptureParams& params); | |
190 ~DeviceEntry(); | |
191 std::unique_ptr<media::VideoCaptureDevice::Client> CreateDeviceClient(); | |
192 | |
193 const int serial_id; | |
194 const MediaStreamType stream_type; | |
195 const std::string id; | |
196 const media::VideoCaptureParams parameters; | |
197 VideoCaptureController video_capture_controller; | |
198 std::unique_ptr<media::VideoCaptureDevice> video_capture_device; | |
199 }; | |
200 | |
201 // Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported | 129 // Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported |
202 // video formats. | 130 // video formats. |
203 struct VideoCaptureManager::DeviceInfo { | 131 struct VideoCaptureManager::DeviceInfo { |
204 DeviceInfo(); | 132 DeviceInfo(); |
205 DeviceInfo(media::VideoCaptureDeviceDescriptor descriptor); | 133 DeviceInfo(media::VideoCaptureDeviceDescriptor descriptor); |
206 DeviceInfo(const DeviceInfo& other); | 134 DeviceInfo(const DeviceInfo& other); |
207 ~DeviceInfo(); | 135 ~DeviceInfo(); |
208 DeviceInfo& operator=(const DeviceInfo& other); | 136 DeviceInfo& operator=(const DeviceInfo& other); |
209 | 137 |
210 media::VideoCaptureDeviceDescriptor descriptor; | 138 media::VideoCaptureDeviceDescriptor descriptor; |
(...skipping 17 matching lines...) Expand all Loading... |
228 | 156 |
229 private: | 157 private: |
230 const int serial_id_; | 158 const int serial_id_; |
231 const media::VideoCaptureSessionId session_id_; | 159 const media::VideoCaptureSessionId session_id_; |
232 const media::VideoCaptureParams params_; | 160 const media::VideoCaptureParams params_; |
233 // Set to true if the device should be stopped before it has successfully | 161 // Set to true if the device should be stopped before it has successfully |
234 // been started. | 162 // been started. |
235 bool abort_start_; | 163 bool abort_start_; |
236 }; | 164 }; |
237 | 165 |
238 VideoCaptureManager::DeviceEntry::DeviceEntry( | |
239 MediaStreamType stream_type, | |
240 const std::string& id, | |
241 const media::VideoCaptureParams& params) | |
242 : serial_id(g_device_start_id++), | |
243 stream_type(stream_type), | |
244 id(id), | |
245 parameters(params) {} | |
246 | |
247 VideoCaptureManager::DeviceEntry::~DeviceEntry() { | |
248 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
249 // DCHECK that this DeviceEntry does not still own a | |
250 // media::VideoCaptureDevice. media::VideoCaptureDevice must be deleted on | |
251 // the device thread. | |
252 DCHECK(video_capture_device == nullptr); | |
253 } | |
254 | |
255 std::unique_ptr<media::VideoCaptureDevice::Client> | |
256 VideoCaptureManager::DeviceEntry::CreateDeviceClient() { | |
257 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
258 | |
259 const int max_buffers = stream_type == MEDIA_TAB_VIDEO_CAPTURE | |
260 ? kMaxNumberOfBuffersForTabCapture | |
261 : kMaxNumberOfBuffers; | |
262 scoped_refptr<media::VideoCaptureBufferPool> buffer_pool = | |
263 new media::VideoCaptureBufferPoolImpl( | |
264 base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), | |
265 max_buffers); | |
266 | |
267 return base::MakeUnique<media::VideoCaptureDeviceClient>( | |
268 base::MakeUnique<VideoFrameReceiverOnIOThread>( | |
269 video_capture_controller.GetWeakPtrForIOThread()), | |
270 std::move(buffer_pool), | |
271 base::Bind(&CreateGpuJpegDecoder, | |
272 base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer, | |
273 video_capture_controller.GetWeakPtrForIOThread()))); | |
274 } | |
275 | |
276 VideoCaptureManager::DeviceInfo::DeviceInfo() = default; | 166 VideoCaptureManager::DeviceInfo::DeviceInfo() = default; |
277 | 167 |
278 VideoCaptureManager::DeviceInfo::DeviceInfo( | 168 VideoCaptureManager::DeviceInfo::DeviceInfo( |
279 media::VideoCaptureDeviceDescriptor descriptor) | 169 media::VideoCaptureDeviceDescriptor descriptor) |
280 : descriptor(descriptor) {} | 170 : descriptor(descriptor) {} |
281 | 171 |
282 VideoCaptureManager::DeviceInfo::DeviceInfo( | 172 VideoCaptureManager::DeviceInfo::DeviceInfo( |
283 const VideoCaptureManager::DeviceInfo& other) = default; | 173 const VideoCaptureManager::DeviceInfo& other) = default; |
284 | 174 |
285 VideoCaptureManager::DeviceInfo::~DeviceInfo() = default; | 175 VideoCaptureManager::DeviceInfo::~DeviceInfo() = default; |
286 | 176 |
287 VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=( | 177 VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=( |
288 const VideoCaptureManager::DeviceInfo& other) = default; | 178 const VideoCaptureManager::DeviceInfo& other) = default; |
289 | 179 |
290 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest( | 180 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest( |
291 int serial_id, | 181 int serial_id, |
292 media::VideoCaptureSessionId session_id, | 182 media::VideoCaptureSessionId session_id, |
293 const media::VideoCaptureParams& params) | 183 const media::VideoCaptureParams& params) |
294 : serial_id_(serial_id), | 184 : serial_id_(serial_id), |
295 session_id_(session_id), | 185 session_id_(session_id), |
296 params_(params), | 186 params_(params), |
297 abort_start_(false) { | 187 abort_start_(false) {} |
298 } | |
299 | 188 |
300 VideoCaptureManager::VideoCaptureManager( | 189 VideoCaptureManager::VideoCaptureManager( |
301 std::unique_ptr<media::VideoCaptureDeviceFactory> factory, | 190 std::unique_ptr<media::VideoCaptureDeviceFactory> factory, |
302 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner) | 191 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner) |
303 : device_task_runner_(std::move(device_task_runner)), | 192 : device_task_runner_(std::move(device_task_runner)), |
304 new_capture_session_id_(1), | 193 new_capture_session_id_(1), |
305 video_capture_device_factory_(std::move(factory)) {} | 194 video_capture_device_factory_(std::move(factory)) {} |
306 | 195 |
307 VideoCaptureManager::~VideoCaptureManager() { | 196 VideoCaptureManager::~VideoCaptureManager() { |
308 DCHECK(devices_.empty()); | 197 DCHECK(controllers_.empty()); |
309 DCHECK(device_start_queue_.empty()); | 198 DCHECK(device_start_queue_.empty()); |
310 } | 199 } |
311 | 200 |
312 void VideoCaptureManager::AddVideoCaptureObserver( | 201 void VideoCaptureManager::AddVideoCaptureObserver( |
313 media::VideoCaptureObserver* observer) { | 202 media::VideoCaptureObserver* observer) { |
314 DCHECK(observer); | 203 DCHECK(observer); |
315 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 204 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
316 capture_observers_.AddObserver(observer); | 205 capture_observers_.AddObserver(observer); |
317 } | 206 } |
318 | 207 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 devices_info_cache_); | 247 devices_info_cache_); |
359 // OK to use base::Unretained() since we own the VCDFactory and |this| is | 248 // OK to use base::Unretained() since we own the VCDFactory and |this| is |
360 // bound in |devices_enumerated_callback|. | 249 // bound in |devices_enumerated_callback|. |
361 device_task_runner_->PostTask( | 250 device_task_runner_->PostTask( |
362 FROM_HERE, | 251 FROM_HERE, |
363 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors, | 252 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors, |
364 base::Unretained(video_capture_device_factory_.get()), | 253 base::Unretained(video_capture_device_factory_.get()), |
365 devices_enumerated_callback)); | 254 devices_enumerated_callback)); |
366 } | 255 } |
367 | 256 |
| 257 const media::VideoCaptureDeviceDescriptor* |
| 258 VideoCaptureManager::LookupDeviceDescriptor(const std::string& id) { |
| 259 const DeviceInfo* info = GetDeviceInfoById(id); |
| 260 return info ? (&info->descriptor) : nullptr; |
| 261 } |
| 262 |
368 int VideoCaptureManager::Open(const MediaStreamDevice& device) { | 263 int VideoCaptureManager::Open(const MediaStreamDevice& device) { |
369 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 264 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
370 | 265 |
371 // Generate a new id for the session being opened. | 266 // Generate a new id for the session being opened. |
372 const media::VideoCaptureSessionId capture_session_id = | 267 const media::VideoCaptureSessionId capture_session_id = |
373 new_capture_session_id_++; | 268 new_capture_session_id_++; |
374 | 269 |
375 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); | 270 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); |
376 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; | 271 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; |
377 | 272 |
(...skipping 12 matching lines...) Expand all Loading... |
390 void VideoCaptureManager::Close(int capture_session_id) { | 285 void VideoCaptureManager::Close(int capture_session_id) { |
391 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 286 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
392 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; | 287 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; |
393 | 288 |
394 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 289 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
395 if (session_it == sessions_.end()) { | 290 if (session_it == sessions_.end()) { |
396 NOTREACHED(); | 291 NOTREACHED(); |
397 return; | 292 return; |
398 } | 293 } |
399 | 294 |
400 DeviceEntry* const existing_device = | 295 VideoCaptureController* const existing_device = LookupControllerByTypeAndId( |
401 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); | 296 session_it->second.type, session_it->second.id); |
402 if (existing_device) { | 297 if (existing_device) { |
403 // Remove any client that is still using the session. This is safe to call | 298 // Remove any client that is still using the session. This is safe to call |
404 // even if there are no clients using the session. | 299 // even if there are no clients using the session. |
405 existing_device->video_capture_controller.StopSession(capture_session_id); | 300 existing_device->StopSession(capture_session_id); |
406 | 301 |
407 // StopSession() may have removed the last client, so we might need to | 302 // StopSession() may have removed the last client, so we might need to |
408 // close the device. | 303 // close the device. |
409 DestroyDeviceEntryIfNoClients(existing_device); | 304 DestroyControllerIfNoClients(existing_device); |
410 } | 305 } |
411 | 306 |
412 // Notify listeners asynchronously, and forget the session. | 307 // Notify listeners asynchronously, and forget the session. |
413 base::ThreadTaskRunnerHandle::Get()->PostTask( | 308 base::ThreadTaskRunnerHandle::Get()->PostTask( |
414 FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this, | 309 FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this, |
415 session_it->second.type, capture_session_id)); | 310 session_it->second.type, capture_session_id)); |
416 sessions_.erase(session_it); | 311 sessions_.erase(session_it); |
417 } | 312 } |
418 | 313 |
419 void VideoCaptureManager::QueueStartDevice( | 314 void VideoCaptureManager::QueueStartDevice( |
420 media::VideoCaptureSessionId session_id, | 315 media::VideoCaptureSessionId session_id, |
421 DeviceEntry* entry, | 316 VideoCaptureController* controller, |
422 const media::VideoCaptureParams& params) { | 317 const media::VideoCaptureParams& params) { |
423 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 318 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
424 device_start_queue_.push_back( | 319 device_start_queue_.push_back( |
425 CaptureDeviceStartRequest(entry->serial_id, session_id, params)); | 320 CaptureDeviceStartRequest(controller->serial_id(), session_id, params)); |
426 if (device_start_queue_.size() == 1) | 321 if (device_start_queue_.size() == 1) |
427 HandleQueuedStartRequest(); | 322 HandleQueuedStartRequest(); |
428 } | 323 } |
429 | 324 |
430 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) { | 325 void VideoCaptureManager::DoStopDevice(VideoCaptureController* controller) { |
431 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 326 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
432 // TODO(mcasas): use a helper function https://crbug.com/624854. | 327 // TODO(mcasas): use a helper function https://crbug.com/624854. |
433 DCHECK( | 328 DCHECK(std::find_if( |
434 std::find_if(devices_.begin(), devices_.end(), | 329 controllers_.begin(), controllers_.end(), |
435 [entry](const std::unique_ptr<DeviceEntry>& device_entry) { | 330 [controller]( |
436 return device_entry.get() == entry; | 331 const scoped_refptr<VideoCaptureController>& device_entry) { |
437 }) != devices_.end()); | 332 return device_entry.get() == controller; |
| 333 }) != controllers_.end()); |
438 | 334 |
439 // Find the matching start request. | 335 // Find the matching start request. |
440 for (DeviceStartQueue::reverse_iterator request = | 336 for (DeviceStartQueue::reverse_iterator request = |
441 device_start_queue_.rbegin(); | 337 device_start_queue_.rbegin(); |
442 request != device_start_queue_.rend(); ++request) { | 338 request != device_start_queue_.rend(); ++request) { |
443 if (request->serial_id() == entry->serial_id) { | 339 if (request->serial_id() == controller->serial_id()) { |
444 request->set_abort_start(); | 340 request->set_abort_start(); |
445 DVLOG(3) << "DoStopDevice, aborting start request for device " | 341 DVLOG(3) << "DoStopDevice, aborting start request for device " |
446 << entry->id << " serial_id = " << entry->serial_id; | 342 << controller->device_id() |
| 343 << " serial_id = " << controller->serial_id(); |
447 return; | 344 return; |
448 } | 345 } |
449 } | 346 } |
450 | 347 |
451 const DeviceInfo* device_info = GetDeviceInfoById(entry->id); | 348 const DeviceInfo* device_info = GetDeviceInfoById(controller->device_id()); |
452 if (device_info != nullptr) { | 349 if (device_info != nullptr) { |
453 for (auto& observer : capture_observers_) | 350 for (auto& observer : capture_observers_) |
454 observer.OnVideoCaptureStopped(device_info->descriptor.facing); | 351 observer.OnVideoCaptureStopped(device_info->descriptor.facing); |
455 } | 352 } |
456 | 353 |
457 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id | 354 DVLOG(3) << "DoStopDevice. Send stop request for device = " |
458 << " serial_id = " << entry->serial_id << "."; | 355 << controller->device_id() |
459 entry->video_capture_controller.OnLog( | 356 << " serial_id = " << controller->serial_id() << "."; |
460 base::StringPrintf("Stopping device: id: %s", entry->id.c_str())); | 357 controller->OnLog(base::StringPrintf("Stopping device: id: %s", |
461 entry->video_capture_controller.SetConsumerFeedbackObserver(nullptr); | 358 controller->device_id().c_str())); |
462 | 359 |
463 // |entry->video_capture_device| can be null if creating the device has | 360 if (controller->IsDeviceAlive()) { |
464 // failed. | 361 // Since we may be removing |controller| from |controllers_| while |
465 if (entry->video_capture_device) { | 362 // ReleaseDeviceAsnyc() is executing, we pass it shared ownership to |
466 device_task_runner_->PostTask( | 363 // |controller|. |
467 FROM_HERE, | 364 controller->ReleaseDeviceAsync(base::Bind( |
468 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 365 [](scoped_refptr<VideoCaptureController>) {}, |
469 base::Passed(&entry->video_capture_device))); | 366 GetControllerSharedRefFromSerialId(controller->serial_id()))); |
470 } | 367 } |
471 } | 368 } |
472 | 369 |
473 void VideoCaptureManager::HandleQueuedStartRequest() { | 370 void VideoCaptureManager::HandleQueuedStartRequest() { |
474 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 371 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
475 // Remove all start requests that have been aborted. | 372 // Remove all start requests that have been aborted. |
476 while (device_start_queue_.begin() != device_start_queue_.end() && | 373 while (device_start_queue_.begin() != device_start_queue_.end() && |
477 device_start_queue_.begin()->abort_start()) { | 374 device_start_queue_.begin()->abort_start()) { |
478 device_start_queue_.pop_front(); | 375 device_start_queue_.pop_front(); |
479 } | 376 } |
480 DeviceStartQueue::iterator request = device_start_queue_.begin(); | 377 DeviceStartQueue::iterator request = device_start_queue_.begin(); |
481 if (request == device_start_queue_.end()) | 378 if (request == device_start_queue_.end()) |
482 return; | 379 return; |
483 | 380 |
484 const int serial_id = request->serial_id(); | 381 const int serial_id = request->serial_id(); |
485 DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id); | 382 VideoCaptureController* const controller = |
486 DCHECK(entry); | 383 LookupControllerBySerialId(serial_id); |
| 384 DCHECK(controller); |
487 | 385 |
488 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " | 386 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " |
489 << entry->id << " start id = " << entry->serial_id; | 387 << controller->device_id() |
| 388 << " start id = " << controller->serial_id(); |
490 | 389 |
491 std::unique_ptr<media::VideoCaptureDevice::Client> device_client = | 390 // The method CreateAndStartDeviceAsync() is going to run asynchronously. |
492 entry->CreateDeviceClient(); | 391 // Since we may be removing the controller while it is executing, we need to |
493 | 392 // pass it shared ownership to itself so that it stays alive while executing. |
494 base::Callback<std::unique_ptr<VideoCaptureDevice>(void)> | 393 // And since the execution may make callbacks into |this|, we also need |
495 start_capture_function; | 394 // to pass it shared ownership to |this|. |
496 | 395 // TODO(chfremer): Check if request->params() can actually be different from |
497 switch (entry->stream_type) { | 396 // controller->parameters, and simplify if this is not the case. |
498 case MEDIA_DEVICE_VIDEO_CAPTURE: { | 397 controller->CreateAndStartDeviceAsync( |
499 // We look up the device id from the renderer in our local enumeration | 398 request->params(), |
500 // since the renderer does not have all the information that might be | 399 static_cast<BuildableVideoCaptureDevice::Callbacks*>(this), |
501 // held in the browser-side VideoCaptureDevice::Name structure. | 400 base::Bind([](scoped_refptr<VideoCaptureManager>, |
502 const DeviceInfo* found = GetDeviceInfoById(entry->id); | 401 scoped_refptr<VideoCaptureController>) {}, |
503 if (found) { | 402 scoped_refptr<VideoCaptureManager>(this), |
504 entry->video_capture_controller.OnLog( | 403 GetControllerSharedRefFromSerialId(serial_id))); |
505 base::StringPrintf("Starting device: id: %s, name: %s, api: %s", | |
506 found->descriptor.device_id.c_str(), | |
507 found->descriptor.GetNameAndModel().c_str(), | |
508 found->descriptor.GetCaptureApiTypeString())); | |
509 | |
510 for (auto& observer : capture_observers_) | |
511 observer.OnVideoCaptureStarted(found->descriptor.facing); | |
512 | |
513 start_capture_function = | |
514 base::Bind(&VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread, | |
515 this, found->descriptor, request->params(), | |
516 base::Passed(std::move(device_client))); | |
517 } else { | |
518 // Errors from DoStartDeviceCaptureOnDeviceThread go via | |
519 // VideoCaptureDeviceClient::OnError, which needs some thread | |
520 // dancing to get errors processed on the IO thread. But since | |
521 // we're on that thread, we call VideoCaptureController | |
522 // methods directly. | |
523 const std::string log_message = base::StringPrintf( | |
524 "Error on %s:%d: device %s unknown. Maybe recently disconnected?", | |
525 __FILE__, __LINE__, entry->id.c_str()); | |
526 DLOG(ERROR) << log_message; | |
527 entry->video_capture_controller.OnLog(log_message); | |
528 entry->video_capture_controller.OnError(); | |
529 // Drop the failed start request. | |
530 device_start_queue_.pop_front(); | |
531 | |
532 return; | |
533 } | |
534 break; | |
535 } | |
536 case MEDIA_TAB_VIDEO_CAPTURE: | |
537 start_capture_function = base::Bind( | |
538 &VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this, | |
539 entry->id, request->params(), base::Passed(std::move(device_client))); | |
540 break; | |
541 | |
542 case MEDIA_DESKTOP_VIDEO_CAPTURE: | |
543 start_capture_function = base::Bind( | |
544 &VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread, this, | |
545 entry->id, request->params(), base::Passed(std::move(device_client))); | |
546 break; | |
547 | |
548 default: { | |
549 NOTIMPLEMENTED(); | |
550 return; | |
551 } | |
552 } | |
553 base::PostTaskAndReplyWithResult( | |
554 device_task_runner_.get(), FROM_HERE, start_capture_function, | |
555 base::Bind(&VideoCaptureManager::OnDeviceStarted, this, | |
556 request->serial_id())); | |
557 } | 404 } |
558 | 405 |
559 void VideoCaptureManager::OnDeviceStarted( | 406 void VideoCaptureManager::WillStartDevice(media::VideoFacingMode facing_mode) { |
560 int serial_id, | 407 for (auto& observer : capture_observers_) |
561 std::unique_ptr<VideoCaptureDevice> device) { | 408 observer.OnVideoCaptureStarted(facing_mode); |
| 409 } |
| 410 |
| 411 void VideoCaptureManager::DidStartDevice(VideoCaptureController* controller) { |
562 DVLOG(3) << __func__; | 412 DVLOG(3) << __func__; |
563 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 413 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
564 DCHECK_EQ(serial_id, device_start_queue_.begin()->serial_id()); | 414 DCHECK(controller); |
565 // |device| can be null if creation failed in | 415 DCHECK_EQ(controller->serial_id(), device_start_queue_.begin()->serial_id()); |
566 // DoStartDeviceCaptureOnDeviceThread. | |
567 if (device_start_queue_.front().abort_start()) { | 416 if (device_start_queue_.front().abort_start()) { |
568 // The device is no longer wanted. Stop the device again. | 417 // A request to release the device may have arrived during the asynchronous |
569 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; | 418 // device startup. |
570 media::VideoCaptureDevice* device_ptr = device.get(); | 419 DVLOG(3) << "Device release request has been issued while device was " |
571 base::Closure closure = | 420 << "starting up asynchronously."; |
572 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 421 controller->ReleaseDeviceAsync(base::Bind( |
573 base::Passed(&device)); | 422 [](scoped_refptr<VideoCaptureController>) {}, |
574 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) { | 423 GetControllerSharedRefFromSerialId(controller->serial_id()))); |
575 // PostTask failed. The device must be stopped anyway. | |
576 device_ptr->StopAndDeAllocate(); | |
577 } | |
578 } else { | 424 } else { |
579 DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id); | 425 if (controller->stream_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
580 DCHECK(entry); | |
581 DCHECK(!entry->video_capture_device); | |
582 if (device) { | |
583 // Passing raw pointer |device.get()| to the controller is safe, | |
584 // because we transfer ownership of it to |entry|. We are calling | |
585 // SetConsumerFeedbackObserver(nullptr) before releasing | |
586 // |entry->video_capture_device_| on the |device_task_runner_|. | |
587 entry->video_capture_controller.SetConsumerFeedbackObserver( | |
588 base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>( | |
589 device.get(), device_task_runner_)); | |
590 } | |
591 entry->video_capture_device = std::move(device); | |
592 | |
593 if (entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) { | |
594 const media::VideoCaptureSessionId session_id = | 426 const media::VideoCaptureSessionId session_id = |
595 device_start_queue_.front().session_id(); | 427 device_start_queue_.front().session_id(); |
596 DCHECK(session_id != kFakeSessionId); | 428 DCHECK(session_id != kFakeSessionId); |
597 MaybePostDesktopCaptureWindowId(session_id); | 429 MaybePostDesktopCaptureWindowId(session_id); |
598 } | 430 } |
599 | 431 |
600 auto it = photo_request_queue_.begin(); | 432 auto it = photo_request_queue_.begin(); |
601 while (it != photo_request_queue_.end()) { | 433 while (it != photo_request_queue_.end()) { |
602 auto request = it++; | 434 auto request = it++; |
603 DeviceEntry* maybe_entry = GetDeviceEntryBySessionId(request->first); | 435 VideoCaptureController* maybe_entry = |
604 if (maybe_entry && maybe_entry->video_capture_device) { | 436 LookupControllerBySessionId(request->first); |
605 request->second.Run(maybe_entry->video_capture_device.get()); | 437 if (maybe_entry && maybe_entry->IsDeviceAlive()) { |
| 438 request->second.Run(); |
606 photo_request_queue_.erase(request); | 439 photo_request_queue_.erase(request); |
607 } | 440 } |
608 } | 441 } |
609 } | 442 } |
610 | 443 |
611 device_start_queue_.pop_front(); | 444 device_start_queue_.pop_front(); |
612 HandleQueuedStartRequest(); | 445 HandleQueuedStartRequest(); |
613 } | 446 } |
614 | 447 |
615 std::unique_ptr<media::VideoCaptureDevice> | 448 void VideoCaptureManager::OnDeviceStartFailed( |
616 VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread( | 449 VideoCaptureController* controller) { |
617 const VideoCaptureDeviceDescriptor& descriptor, | 450 const std::string log_message = base::StringPrintf( |
618 const media::VideoCaptureParams& params, | 451 "Starting device %s has failed. Maybe recently disconnected?", |
619 std::unique_ptr<VideoCaptureDevice::Client> device_client) { | 452 controller->device_id().c_str()); |
620 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 453 DLOG(ERROR) << log_message; |
621 DCHECK(IsOnDeviceThread()); | 454 controller->OnLog(log_message); |
| 455 controller->OnError(); |
622 | 456 |
623 std::unique_ptr<VideoCaptureDevice> video_capture_device; | 457 device_start_queue_.pop_front(); |
624 video_capture_device = | 458 HandleQueuedStartRequest(); |
625 video_capture_device_factory_->CreateDevice(descriptor); | |
626 | |
627 if (!video_capture_device) { | |
628 device_client->OnError(FROM_HERE, "Could not create capture device"); | |
629 return nullptr; | |
630 } | |
631 | |
632 video_capture_device->AllocateAndStart(params, std::move(device_client)); | |
633 return video_capture_device; | |
634 } | |
635 | |
636 std::unique_ptr<media::VideoCaptureDevice> | |
637 VideoCaptureManager::DoStartTabCaptureOnDeviceThread( | |
638 const std::string& id, | |
639 const media::VideoCaptureParams& params, | |
640 std::unique_ptr<VideoCaptureDevice::Client> device_client) { | |
641 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | |
642 DCHECK(IsOnDeviceThread()); | |
643 | |
644 std::unique_ptr<VideoCaptureDevice> video_capture_device; | |
645 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN) | |
646 video_capture_device = WebContentsVideoCaptureDevice::Create(id); | |
647 #endif | |
648 | |
649 if (!video_capture_device) { | |
650 device_client->OnError(FROM_HERE, "Could not create capture device"); | |
651 return nullptr; | |
652 } | |
653 | |
654 video_capture_device->AllocateAndStart(params, std::move(device_client)); | |
655 return video_capture_device; | |
656 } | |
657 | |
658 std::unique_ptr<media::VideoCaptureDevice> | |
659 VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread( | |
660 const std::string& id, | |
661 const media::VideoCaptureParams& params, | |
662 std::unique_ptr<VideoCaptureDevice::Client> device_client) { | |
663 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | |
664 DCHECK(IsOnDeviceThread()); | |
665 | |
666 std::unique_ptr<VideoCaptureDevice> video_capture_device; | |
667 #if defined(ENABLE_SCREEN_CAPTURE) | |
668 DesktopMediaID desktop_id = DesktopMediaID::Parse(id); | |
669 if (desktop_id.is_null()) { | |
670 device_client->OnError(FROM_HERE, "Desktop media ID is null"); | |
671 return nullptr; | |
672 } | |
673 | |
674 if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) { | |
675 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN) | |
676 video_capture_device = WebContentsVideoCaptureDevice::Create(id); | |
677 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED); | |
678 if (desktop_id.audio_share) { | |
679 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO); | |
680 } else { | |
681 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITHOUT_AUDIO); | |
682 } | |
683 #endif | |
684 } else { | |
685 #if defined(OS_ANDROID) | |
686 video_capture_device = base::MakeUnique<ScreenCaptureDeviceAndroid>(); | |
687 #else | |
688 #if defined(USE_AURA) | |
689 video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id); | |
690 #endif // defined(USE_AURA) | |
691 #if BUILDFLAG(ENABLE_WEBRTC) | |
692 if (!video_capture_device) | |
693 video_capture_device = DesktopCaptureDevice::Create(desktop_id); | |
694 #endif // BUILDFLAG(ENABLE_WEBRTC) | |
695 #endif // defined (OS_ANDROID) | |
696 } | |
697 #endif // defined(ENABLE_SCREEN_CAPTURE) | |
698 | |
699 if (!video_capture_device) { | |
700 device_client->OnError(FROM_HERE, "Could not create capture device"); | |
701 return nullptr; | |
702 } | |
703 | |
704 video_capture_device->AllocateAndStart(params, std::move(device_client)); | |
705 return video_capture_device; | |
706 } | 459 } |
707 | 460 |
708 void VideoCaptureManager::StartCaptureForClient( | 461 void VideoCaptureManager::StartCaptureForClient( |
709 media::VideoCaptureSessionId session_id, | 462 media::VideoCaptureSessionId session_id, |
710 const media::VideoCaptureParams& params, | 463 const media::VideoCaptureParams& params, |
711 VideoCaptureControllerID client_id, | 464 VideoCaptureControllerID client_id, |
712 VideoCaptureControllerEventHandler* client_handler, | 465 VideoCaptureControllerEventHandler* client_handler, |
713 const DoneCB& done_cb) { | 466 const DoneCB& done_cb) { |
714 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 467 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
715 DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: " | 468 DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: " |
716 << media::VideoCaptureFormat::ToString(params.requested_format); | 469 << media::VideoCaptureFormat::ToString(params.requested_format); |
717 | 470 |
718 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id, params); | 471 VideoCaptureController* controller = |
719 if (!entry) { | 472 GetOrCreateController(session_id, params); |
| 473 if (!controller) { |
720 done_cb.Run(base::WeakPtr<VideoCaptureController>()); | 474 done_cb.Run(base::WeakPtr<VideoCaptureController>()); |
721 return; | 475 return; |
722 } | 476 } |
723 | 477 |
724 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); | 478 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); |
725 | 479 |
726 // First client starts the device. | 480 // First client starts the device. |
727 if (!entry->video_capture_controller.HasActiveClient() && | 481 if (!controller->HasActiveClient() && !controller->HasPausedClient()) { |
728 !entry->video_capture_controller.HasPausedClient()) { | 482 DVLOG(1) << "VideoCaptureManager starting device (id = " |
729 DVLOG(1) << "VideoCaptureManager starting device (type = " | 483 << controller->device_id() << ")"; |
730 << entry->stream_type << ", id = " << entry->id << ")"; | 484 QueueStartDevice(session_id, controller, params); |
731 QueueStartDevice(session_id, entry, params); | |
732 } | 485 } |
733 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 486 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
734 done_cb.Run(entry->video_capture_controller.GetWeakPtrForIOThread()); | 487 done_cb.Run(controller->GetWeakPtrForIOThread()); |
735 entry->video_capture_controller.AddClient(client_id, client_handler, | 488 controller->AddClient(client_id, client_handler, session_id, params); |
736 session_id, params); | |
737 } | 489 } |
738 | 490 |
739 void VideoCaptureManager::StopCaptureForClient( | 491 void VideoCaptureManager::StopCaptureForClient( |
740 VideoCaptureController* controller, | 492 VideoCaptureController* controller, |
741 VideoCaptureControllerID client_id, | 493 VideoCaptureControllerID client_id, |
742 VideoCaptureControllerEventHandler* client_handler, | 494 VideoCaptureControllerEventHandler* client_handler, |
743 bool aborted_due_to_error) { | 495 bool aborted_due_to_error) { |
744 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 496 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
745 DCHECK(controller); | 497 DCHECK(controller); |
746 DCHECK(client_handler); | 498 DCHECK(client_handler); |
747 | 499 |
748 DeviceEntry* entry = GetDeviceEntryByController(controller); | 500 if (!IsControllerPointerValid(controller)) { |
749 if (!entry) { | |
750 NOTREACHED(); | 501 NOTREACHED(); |
751 return; | 502 return; |
752 } | 503 } |
753 if (!aborted_due_to_error) { | 504 if (!aborted_due_to_error) { |
754 if (controller->has_received_frames()) { | 505 if (controller->has_received_frames()) { |
755 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK); | 506 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK); |
756 } else if (entry->stream_type == MEDIA_DEVICE_VIDEO_CAPTURE) { | 507 } else if (controller->stream_type() == MEDIA_DEVICE_VIDEO_CAPTURE) { |
757 LogVideoCaptureEvent( | 508 LogVideoCaptureEvent( |
758 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE); | 509 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE); |
759 } else { | 510 } else { |
760 LogVideoCaptureEvent( | 511 LogVideoCaptureEvent( |
761 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB); | 512 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB); |
762 } | 513 } |
763 } else { | 514 } else { |
764 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); | 515 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); |
765 for (auto it : sessions_) { | 516 for (auto it : sessions_) { |
766 if (it.second.type == entry->stream_type && it.second.id == entry->id) { | 517 if (it.second.type == controller->stream_type() && |
| 518 it.second.id == controller->device_id()) { |
767 for (auto& listener : listeners_) | 519 for (auto& listener : listeners_) |
768 listener.Aborted(it.second.type, it.first); | 520 listener.Aborted(it.second.type, it.first); |
769 // Aborted() call might synchronously destroy |entry|, recheck. | 521 // Aborted() call might synchronously destroy |controller|, recheck. |
770 entry = GetDeviceEntryByController(controller); | 522 if (!IsControllerPointerValid(controller)) |
771 if (!entry) | |
772 return; | 523 return; |
773 break; | 524 break; |
774 } | 525 } |
775 } | 526 } |
776 } | 527 } |
777 | 528 |
778 // Detach client from controller. | 529 // Detach client from controller. |
779 const media::VideoCaptureSessionId session_id = | 530 const media::VideoCaptureSessionId session_id = |
780 controller->RemoveClient(client_id, client_handler); | 531 controller->RemoveClient(client_id, client_handler); |
781 DVLOG(1) << __func__ << ", session_id = " << session_id; | 532 DVLOG(1) << __func__ << ", session_id = " << session_id; |
782 | 533 |
783 // If controller has no more clients, delete controller and device. | 534 // If controller has no more clients, delete controller and device. |
784 DestroyDeviceEntryIfNoClients(entry); | 535 DestroyControllerIfNoClients(controller); |
785 } | 536 } |
786 | 537 |
787 void VideoCaptureManager::PauseCaptureForClient( | 538 void VideoCaptureManager::PauseCaptureForClient( |
788 VideoCaptureController* controller, | 539 VideoCaptureController* controller, |
789 VideoCaptureControllerID client_id, | 540 VideoCaptureControllerID client_id, |
790 VideoCaptureControllerEventHandler* client_handler) { | 541 VideoCaptureControllerEventHandler* client_handler) { |
791 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 542 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
792 DCHECK(controller); | 543 DCHECK(controller); |
793 DCHECK(client_handler); | 544 DCHECK(client_handler); |
794 DeviceEntry* entry = GetDeviceEntryByController(controller); | 545 if (!IsControllerPointerValid(controller)) |
795 if (!entry) | 546 NOTREACHED() << "Got Null controller while pausing capture"; |
796 NOTREACHED() << "Got Null entry while pausing capture"; | |
797 | 547 |
798 const bool had_active_client = controller->HasActiveClient(); | 548 const bool had_active_client = controller->HasActiveClient(); |
799 controller->PauseClient(client_id, client_handler); | 549 controller->PauseClient(client_id, client_handler); |
800 if (!had_active_client || controller->HasActiveClient()) | 550 if (!had_active_client || controller->HasActiveClient()) |
801 return; | 551 return; |
802 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { | 552 if (!controller->IsDeviceAlive()) |
803 device_task_runner_->PostTask( | 553 return; |
804 FROM_HERE, | 554 controller->MaybeSuspend(); |
805 base::Bind(&VideoCaptureDevice::MaybeSuspend, | |
806 // Unretained is safe to use here because |device| would be | |
807 // null if it was scheduled for shutdown and destruction, and | |
808 // because this task is guaranteed to run before the task | |
809 // that destroys the |device|. | |
810 base::Unretained(device))); | |
811 } | |
812 } | 555 } |
813 | 556 |
814 void VideoCaptureManager::ResumeCaptureForClient( | 557 void VideoCaptureManager::ResumeCaptureForClient( |
815 media::VideoCaptureSessionId session_id, | 558 media::VideoCaptureSessionId session_id, |
816 const media::VideoCaptureParams& params, | 559 const media::VideoCaptureParams& params, |
817 VideoCaptureController* controller, | 560 VideoCaptureController* controller, |
818 VideoCaptureControllerID client_id, | 561 VideoCaptureControllerID client_id, |
819 VideoCaptureControllerEventHandler* client_handler) { | 562 VideoCaptureControllerEventHandler* client_handler) { |
820 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 563 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
821 DCHECK(controller); | 564 DCHECK(controller); |
822 DCHECK(client_handler); | 565 DCHECK(client_handler); |
823 | 566 |
824 DeviceEntry* entry = GetDeviceEntryByController(controller); | 567 if (!IsControllerPointerValid(controller)) |
825 if (!entry) | 568 NOTREACHED() << "Got Null controller while resuming capture"; |
826 NOTREACHED() << "Got Null entry while resuming capture"; | |
827 | 569 |
828 const bool had_active_client = controller->HasActiveClient(); | 570 const bool had_active_client = controller->HasActiveClient(); |
829 controller->ResumeClient(client_id, client_handler); | 571 controller->ResumeClient(client_id, client_handler); |
830 if (had_active_client || !controller->HasActiveClient()) | 572 if (had_active_client || !controller->HasActiveClient()) |
831 return; | 573 return; |
832 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { | 574 if (!controller->IsDeviceAlive()) |
833 device_task_runner_->PostTask( | 575 return; |
834 FROM_HERE, | 576 controller->Resume(); |
835 base::Bind(&VideoCaptureDevice::Resume, | |
836 // Unretained is safe to use here because |device| would be | |
837 // null if it was scheduled for shutdown and destruction, and | |
838 // because this task is guaranteed to run before the task | |
839 // that destroys the |device|. | |
840 base::Unretained(device))); | |
841 } | |
842 } | 577 } |
843 | 578 |
844 void VideoCaptureManager::RequestRefreshFrameForClient( | 579 void VideoCaptureManager::RequestRefreshFrameForClient( |
845 VideoCaptureController* controller) { | 580 VideoCaptureController* controller) { |
846 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 581 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
847 | 582 |
848 if (DeviceEntry* entry = GetDeviceEntryByController(controller)) { | 583 if (IsControllerPointerValid(controller)) { |
849 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { | 584 if (!controller->IsDeviceAlive()) |
850 device_task_runner_->PostTask( | 585 return; |
851 FROM_HERE, | 586 controller->RequestRefreshFrame(); |
852 base::Bind(&VideoCaptureDevice::RequestRefreshFrame, | |
853 // Unretained is safe to use here because |device| would be | |
854 // null if it was scheduled for shutdown and destruction, | |
855 // and because this task is guaranteed to run before the | |
856 // task that destroys the |device|. | |
857 base::Unretained(device))); | |
858 } | |
859 } | 587 } |
860 } | 588 } |
861 | 589 |
862 bool VideoCaptureManager::GetDeviceSupportedFormats( | 590 bool VideoCaptureManager::GetDeviceSupportedFormats( |
863 media::VideoCaptureSessionId capture_session_id, | 591 media::VideoCaptureSessionId capture_session_id, |
864 media::VideoCaptureFormats* supported_formats) { | 592 media::VideoCaptureFormats* supported_formats) { |
865 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 593 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
866 DCHECK(supported_formats->empty()); | 594 DCHECK(supported_formats->empty()); |
867 | 595 |
868 SessionMap::iterator it = sessions_.find(capture_session_id); | 596 SessionMap::iterator it = sessions_.find(capture_session_id); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 return GetDeviceFormatsInUse(it->second.type, it->second.id, formats_in_use); | 628 return GetDeviceFormatsInUse(it->second.type, it->second.id, formats_in_use); |
901 } | 629 } |
902 | 630 |
903 bool VideoCaptureManager::GetDeviceFormatsInUse( | 631 bool VideoCaptureManager::GetDeviceFormatsInUse( |
904 MediaStreamType stream_type, | 632 MediaStreamType stream_type, |
905 const std::string& device_id, | 633 const std::string& device_id, |
906 media::VideoCaptureFormats* formats_in_use) { | 634 media::VideoCaptureFormats* formats_in_use) { |
907 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 635 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
908 DCHECK(formats_in_use->empty()); | 636 DCHECK(formats_in_use->empty()); |
909 // Return the currently in-use format(s) of the device, if it's started. | 637 // Return the currently in-use format(s) of the device, if it's started. |
910 DeviceEntry* device_in_use = | 638 VideoCaptureController* device_in_use = |
911 GetDeviceEntryByTypeAndId(stream_type, device_id); | 639 LookupControllerByTypeAndId(stream_type, device_id); |
912 if (device_in_use) { | 640 if (device_in_use) { |
913 // Currently only one format-in-use is supported at the VCC level. | 641 // Currently only one format-in-use is supported at the VCC level. |
914 formats_in_use->push_back( | 642 formats_in_use->push_back(device_in_use->GetVideoCaptureFormat()); |
915 device_in_use->video_capture_controller.GetVideoCaptureFormat()); | |
916 } | 643 } |
917 return true; | 644 return true; |
918 } | 645 } |
919 | 646 |
920 void VideoCaptureManager::SetDesktopCaptureWindowId( | 647 void VideoCaptureManager::SetDesktopCaptureWindowId( |
921 media::VideoCaptureSessionId session_id, | 648 media::VideoCaptureSessionId session_id, |
922 gfx::NativeViewId window_id) { | 649 gfx::NativeViewId window_id) { |
923 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 650 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
924 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; | 651 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; |
925 | 652 |
926 notification_window_ids_[session_id] = window_id; | 653 notification_window_ids_[session_id] = window_id; |
927 MaybePostDesktopCaptureWindowId(session_id); | 654 MaybePostDesktopCaptureWindowId(session_id); |
928 } | 655 } |
929 | 656 |
930 void VideoCaptureManager::MaybePostDesktopCaptureWindowId( | 657 void VideoCaptureManager::MaybePostDesktopCaptureWindowId( |
931 media::VideoCaptureSessionId session_id) { | 658 media::VideoCaptureSessionId session_id) { |
932 SessionMap::iterator session_it = sessions_.find(session_id); | 659 SessionMap::iterator session_it = sessions_.find(session_id); |
933 if (session_it == sessions_.end()) | 660 if (session_it == sessions_.end()) |
934 return; | 661 return; |
935 | 662 |
936 DeviceEntry* const existing_device = | 663 VideoCaptureController* const existing_device = LookupControllerByTypeAndId( |
937 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); | 664 session_it->second.type, session_it->second.id); |
938 if (!existing_device) { | 665 if (!existing_device) { |
939 DVLOG(2) << "Failed to find an existing screen capture device."; | 666 DVLOG(2) << "Failed to find an existing screen capture device."; |
940 return; | 667 return; |
941 } | 668 } |
942 | 669 |
943 if (!existing_device->video_capture_device) { | 670 if (!existing_device->IsDeviceAlive()) { |
944 DVLOG(2) << "Screen capture device not yet started."; | 671 DVLOG(2) << "Screen capture device not yet started."; |
945 return; | 672 return; |
946 } | 673 } |
947 | 674 |
948 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type); | 675 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type()); |
949 DesktopMediaID id = DesktopMediaID::Parse(existing_device->id); | 676 DesktopMediaID id = DesktopMediaID::Parse(existing_device->device_id()); |
950 if (id.is_null()) | 677 if (id.is_null()) |
951 return; | 678 return; |
952 | 679 |
953 auto window_id_it = notification_window_ids_.find(session_id); | 680 auto window_id_it = notification_window_ids_.find(session_id); |
954 if (window_id_it == notification_window_ids_.end()) { | 681 if (window_id_it == notification_window_ids_.end()) { |
955 DVLOG(2) << "Notification window id not set for screen capture."; | 682 DVLOG(2) << "Notification window id not set for screen capture."; |
956 return; | 683 return; |
957 } | 684 } |
958 | 685 |
959 // Post |existing_device->video_capture_device| to the VideoCaptureDevice to | 686 existing_device->SetDesktopCaptureWindowIdAsync( |
960 // the device_task_runner_. This is safe since the device is destroyed on the | 687 window_id_it->second, |
961 // device_task_runner_. | 688 base::Bind([](scoped_refptr<VideoCaptureManager>) {}, |
962 device_task_runner_->PostTask( | 689 scoped_refptr<VideoCaptureManager>(this))); |
963 FROM_HERE, | |
964 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, | |
965 this, existing_device->video_capture_device.get(), | |
966 window_id_it->second)); | |
967 | |
968 notification_window_ids_.erase(window_id_it); | 690 notification_window_ids_.erase(window_id_it); |
969 } | 691 } |
970 | 692 |
971 void VideoCaptureManager::GetPhotoCapabilities( | 693 void VideoCaptureManager::GetPhotoCapabilities( |
972 int session_id, | 694 int session_id, |
973 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) { | 695 media::VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) { |
974 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 696 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
975 | 697 |
976 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); | 698 const VideoCaptureController* controller = |
977 if (!entry) | 699 LookupControllerBySessionId(session_id); |
| 700 if (!controller) |
978 return; | 701 return; |
979 VideoCaptureDevice* device = entry->video_capture_device.get(); | 702 if (controller->IsDeviceAlive()) { |
980 if (device) { | 703 controller->GetPhotoCapabilities(std::move(callback)); |
981 VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device); | |
982 return; | 704 return; |
983 } | 705 } |
984 // |entry| is known but |device| is nullptr, queue up a request for later. | 706 // Queue up a request for later. |
985 photo_request_queue_.emplace_back( | 707 photo_request_queue_.emplace_back( |
986 session_id, base::Bind(&VideoCaptureManager::DoGetPhotoCapabilities, this, | 708 session_id, |
987 base::Passed(&callback))); | 709 base::Bind(&VideoCaptureController::GetPhotoCapabilities, |
| 710 base::Unretained(controller), base::Passed(&callback))); |
988 } | 711 } |
989 | 712 |
990 void VideoCaptureManager::SetPhotoOptions( | 713 void VideoCaptureManager::SetPhotoOptions( |
991 int session_id, | 714 int session_id, |
992 media::mojom::PhotoSettingsPtr settings, | 715 media::mojom::PhotoSettingsPtr settings, |
993 VideoCaptureDevice::SetPhotoOptionsCallback callback) { | 716 media::VideoCaptureDevice::SetPhotoOptionsCallback callback) { |
994 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 717 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
995 | 718 |
996 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); | 719 VideoCaptureController* controller = LookupControllerBySessionId(session_id); |
997 if (!entry) | 720 if (!controller) |
998 return; | 721 return; |
999 VideoCaptureDevice* device = entry->video_capture_device.get(); | 722 if (controller->IsDeviceAlive()) { |
1000 if (device) { | 723 controller->SetPhotoOptions(std::move(settings), std::move(callback)); |
1001 VideoCaptureManager::DoSetPhotoOptions(std::move(callback), | |
1002 std::move(settings), device); | |
1003 return; | 724 return; |
1004 } | 725 } |
1005 // |entry| is known but |device| is nullptr, queue up a request for later. | 726 // Queue up a request for later. |
1006 photo_request_queue_.emplace_back( | 727 photo_request_queue_.emplace_back( |
1007 session_id, base::Bind(&VideoCaptureManager::DoSetPhotoOptions, this, | 728 session_id, base::Bind(&VideoCaptureController::SetPhotoOptions, |
1008 base::Passed(&callback), base::Passed(&settings))); | 729 base::Unretained(controller), |
| 730 base::Passed(&settings), base::Passed(&callback))); |
1009 } | 731 } |
1010 | 732 |
1011 void VideoCaptureManager::TakePhoto( | 733 void VideoCaptureManager::TakePhoto( |
1012 int session_id, | 734 int session_id, |
1013 VideoCaptureDevice::TakePhotoCallback callback) { | 735 media::VideoCaptureDevice::TakePhotoCallback callback) { |
1014 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 736 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1015 | 737 |
1016 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); | 738 VideoCaptureController* controller = LookupControllerBySessionId(session_id); |
1017 if (!entry) | 739 if (!controller) |
1018 return; | 740 return; |
1019 VideoCaptureDevice* device = entry->video_capture_device.get(); | 741 if (controller->IsDeviceAlive()) { |
1020 if (device) { | 742 controller->TakePhoto(std::move(callback)); |
1021 VideoCaptureManager::DoTakePhoto(std::move(callback), device); | |
1022 return; | 743 return; |
1023 } | 744 } |
1024 // |entry| is known but |device| is nullptr, queue up a request for later. | 745 // Queue up a request for later. |
1025 photo_request_queue_.emplace_back( | 746 photo_request_queue_.emplace_back( |
1026 session_id, base::Bind(&VideoCaptureManager::DoTakePhoto, this, | 747 session_id, |
1027 base::Passed(&callback))); | 748 base::Bind(&VideoCaptureController::TakePhoto, |
1028 } | 749 base::Unretained(controller), base::Passed(&callback))); |
1029 | |
1030 void VideoCaptureManager::DoStopDeviceOnDeviceThread( | |
1031 std::unique_ptr<VideoCaptureDevice> device) { | |
1032 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); | |
1033 DCHECK(IsOnDeviceThread()); | |
1034 device->StopAndDeAllocate(); | |
1035 DVLOG(3) << "DoStopDeviceOnDeviceThread"; | |
1036 } | 750 } |
1037 | 751 |
1038 void VideoCaptureManager::OnOpened( | 752 void VideoCaptureManager::OnOpened( |
1039 MediaStreamType stream_type, | 753 MediaStreamType stream_type, |
1040 media::VideoCaptureSessionId capture_session_id) { | 754 media::VideoCaptureSessionId capture_session_id) { |
1041 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 755 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1042 for (auto& listener : listeners_) | 756 for (auto& listener : listeners_) |
1043 listener.Opened(stream_type, capture_session_id); | 757 listener.Opened(stream_type, capture_session_id); |
1044 } | 758 } |
1045 | 759 |
(...skipping 17 matching lines...) Expand all Loading... |
1063 | 777 |
1064 // Walk the |devices_info_cache_| and produce a | 778 // Walk the |devices_info_cache_| and produce a |
1065 // media::VideoCaptureDeviceDescriptors for return purposes. | 779 // media::VideoCaptureDeviceDescriptors for return purposes. |
1066 media::VideoCaptureDeviceDescriptors devices; | 780 media::VideoCaptureDeviceDescriptors devices; |
1067 std::vector<std::tuple<media::VideoCaptureDeviceDescriptor, | 781 std::vector<std::tuple<media::VideoCaptureDeviceDescriptor, |
1068 media::VideoCaptureFormats>> | 782 media::VideoCaptureFormats>> |
1069 descriptors_and_formats; | 783 descriptors_and_formats; |
1070 for (const auto& it : devices_info_cache_) { | 784 for (const auto& it : devices_info_cache_) { |
1071 devices.emplace_back(it.descriptor); | 785 devices.emplace_back(it.descriptor); |
1072 descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats); | 786 descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats); |
1073 } | |
1074 | |
1075 if (!descriptors_and_formats.empty()) { | |
1076 MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities( | 787 MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities( |
1077 descriptors_and_formats); | 788 descriptors_and_formats); |
1078 } | 789 } |
1079 | 790 |
1080 client_callback.Run(devices); | 791 client_callback.Run(devices); |
1081 } | 792 } |
1082 | 793 |
1083 bool VideoCaptureManager::IsOnDeviceThread() const { | |
1084 return device_task_runner_->BelongsToCurrentThread(); | |
1085 } | |
1086 | |
1087 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( | 794 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( |
1088 base::Callback<void(const VideoCaptureManager::DeviceInfos&)> | 795 base::Callback<void(const VideoCaptureManager::DeviceInfos&)> |
1089 on_devices_enumerated_callback, | 796 on_devices_enumerated_callback, |
1090 const VideoCaptureManager::DeviceInfos& old_device_info_cache, | 797 const VideoCaptureManager::DeviceInfos& old_device_info_cache, |
1091 std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) { | 798 std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) { |
1092 DCHECK(IsOnDeviceThread()); | 799 DCHECK(device_task_runner_->BelongsToCurrentThread()); |
1093 // Construct |new_devices_info_cache| with the cached devices that are still | 800 // Construct |new_devices_info_cache| with the cached devices that are still |
1094 // present in the system, and remove their names from |names_snapshot|, so we | 801 // present in the system, and remove their names from |names_snapshot|, so we |
1095 // keep there the truly new devices. | 802 // keep there the truly new devices. |
1096 VideoCaptureManager::DeviceInfos new_devices_info_cache; | 803 VideoCaptureManager::DeviceInfos new_devices_info_cache; |
1097 for (const auto& device_info : old_device_info_cache) { | 804 for (const auto& device_info : old_device_info_cache) { |
1098 for (VideoCaptureDeviceDescriptors::iterator it = | 805 for (VideoCaptureDeviceDescriptors::iterator it = |
1099 descriptors_snapshot->begin(); | 806 descriptors_snapshot->begin(); |
1100 it != descriptors_snapshot->end(); ++it) { | 807 it != descriptors_snapshot->end(); ++it) { |
1101 if (device_info.descriptor.device_id == it->device_id) { | 808 if (device_info.descriptor.device_id == it->device_id) { |
1102 new_devices_info_cache.push_back(device_info); | 809 new_devices_info_cache.push_back(device_info); |
1103 descriptors_snapshot->erase(it); | 810 descriptors_snapshot->erase(it); |
1104 break; | 811 break; |
1105 } | 812 } |
1106 } | 813 } |
1107 } | 814 } |
1108 | 815 |
1109 // Get the device info for the new devices in |names_snapshot|. | 816 // Get the device info for the new devices in |names_snapshot|. |
1110 for (const auto& it : *descriptors_snapshot) { | 817 for (const auto& it : *descriptors_snapshot) { |
1111 DeviceInfo device_info(it); | 818 DeviceInfo device_info(it); |
1112 video_capture_device_factory_->GetSupportedFormats( | 819 video_capture_device_factory_->GetSupportedFormats( |
1113 it, &device_info.supported_formats); | 820 it, &device_info.supported_formats); |
1114 ConsolidateCaptureFormats(&device_info.supported_formats); | 821 ConsolidateCaptureFormats(&device_info.supported_formats); |
1115 new_devices_info_cache.push_back(device_info); | 822 new_devices_info_cache.push_back(device_info); |
1116 } | 823 } |
1117 | 824 |
1118 on_devices_enumerated_callback.Run(new_devices_info_cache); | 825 on_devices_enumerated_callback.Run(new_devices_info_cache); |
1119 } | 826 } |
1120 | 827 |
1121 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { | 828 void VideoCaptureManager::DestroyControllerIfNoClients( |
| 829 VideoCaptureController* controller) { |
1122 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 830 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1123 // Removal of the last client stops the device. | 831 // Removal of the last client stops the device. |
1124 if (!entry->video_capture_controller.HasActiveClient() && | 832 if (!controller->HasActiveClient() && !controller->HasPausedClient()) { |
1125 !entry->video_capture_controller.HasPausedClient()) { | |
1126 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 833 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
1127 << entry->stream_type << ", id = " << entry->id << ")"; | 834 << controller->stream_type() |
| 835 << ", id = " << controller->device_id() << ")"; |
1128 | 836 |
1129 // The DeviceEntry is removed from |devices_| immediately. The controller is | 837 // The VideoCaptureController is removed from |controllers_| immediately. |
1130 // deleted immediately, and the device is freed asynchronously. After this | 838 // The controller is deleted immediately, and the device is freed |
1131 // point, subsequent requests to open this same device ID will create a new | 839 // asynchronously. After this point, subsequent requests to open this same |
1132 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. | 840 // device ID will create a new VideoCaptureController, |
1133 DoStopDevice(entry); | 841 // VideoCaptureController, and VideoCaptureDevice. |
| 842 DoStopDevice(controller); |
1134 // TODO(mcasas): use a helper function https://crbug.com/624854. | 843 // TODO(mcasas): use a helper function https://crbug.com/624854. |
1135 DeviceEntries::iterator device_it = | 844 auto controller_iter = std::find_if( |
1136 std::find_if(devices_.begin(), devices_.end(), | 845 controllers_.begin(), controllers_.end(), |
1137 [entry](const std::unique_ptr<DeviceEntry>& device_entry) { | 846 [controller]( |
1138 return device_entry.get() == entry; | 847 const scoped_refptr<VideoCaptureController>& device_entry) { |
1139 }); | 848 return device_entry.get() == controller; |
1140 devices_.erase(device_it); | 849 }); |
| 850 controllers_.erase(controller_iter); |
1141 } | 851 } |
1142 } | 852 } |
1143 | 853 |
1144 VideoCaptureManager::DeviceEntry* | 854 VideoCaptureController* VideoCaptureManager::LookupControllerBySessionId( |
1145 VideoCaptureManager::GetDeviceEntryBySessionId(int session_id) { | 855 int session_id) { |
1146 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 856 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1147 SessionMap::const_iterator session_it = sessions_.find(session_id); | 857 SessionMap::const_iterator session_it = sessions_.find(session_id); |
1148 if (session_it == sessions_.end()) | 858 if (session_it == sessions_.end()) |
1149 return nullptr; | 859 return nullptr; |
1150 | 860 |
1151 return GetDeviceEntryByTypeAndId(session_it->second.type, | 861 return LookupControllerByTypeAndId(session_it->second.type, |
1152 session_it->second.id); | 862 session_it->second.id); |
1153 } | 863 } |
1154 | 864 |
1155 VideoCaptureManager::DeviceEntry* | 865 VideoCaptureController* VideoCaptureManager::LookupControllerByTypeAndId( |
1156 VideoCaptureManager::GetDeviceEntryByTypeAndId( | |
1157 MediaStreamType type, | 866 MediaStreamType type, |
1158 const std::string& device_id) const { | 867 const std::string& device_id) const { |
1159 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 868 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1160 | 869 |
1161 for (const std::unique_ptr<DeviceEntry>& device : devices_) { | 870 for (const auto& entry : controllers_) { |
1162 if (type == device->stream_type && device_id == device->id) | 871 if (type == entry->stream_type() && device_id == entry->device_id()) |
1163 return device.get(); | 872 return entry.get(); |
1164 } | 873 } |
1165 return nullptr; | 874 return nullptr; |
1166 } | 875 } |
1167 | 876 |
1168 VideoCaptureManager::DeviceEntry* | 877 bool VideoCaptureManager::IsControllerPointerValid( |
1169 VideoCaptureManager::GetDeviceEntryByController( | |
1170 const VideoCaptureController* controller) const { | 878 const VideoCaptureController* controller) const { |
1171 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 879 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 880 return base::ContainsValue(controllers_, controller); |
| 881 } |
1172 | 882 |
1173 // Look up |controller| in |devices_|. | 883 VideoCaptureController* VideoCaptureManager::LookupControllerBySerialId( |
1174 for (const std::unique_ptr<DeviceEntry>& device : devices_) { | 884 int serial_id) const { |
1175 if (&device->video_capture_controller == controller) | 885 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1176 return device.get(); | 886 |
| 887 for (const auto& entry : controllers_) { |
| 888 if (entry->serial_id() == serial_id) |
| 889 return entry.get(); |
1177 } | 890 } |
1178 return nullptr; | 891 return nullptr; |
1179 } | 892 } |
1180 | 893 |
1181 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetDeviceEntryBySerialId( | 894 scoped_refptr<VideoCaptureController> |
1182 int serial_id) const { | 895 VideoCaptureManager::GetControllerSharedRefFromSerialId(int serial_id) const { |
1183 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 896 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1184 | 897 |
1185 for (const std::unique_ptr<DeviceEntry>& device : devices_) { | 898 for (const auto& entry : controllers_) { |
1186 if (device->serial_id == serial_id) | 899 if (entry->serial_id() == serial_id) |
1187 return device.get(); | 900 return entry; |
1188 } | 901 } |
1189 return nullptr; | 902 return nullptr; |
1190 } | 903 } |
1191 | 904 |
1192 VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById( | 905 VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById( |
1193 const std::string& id) { | 906 const std::string& id) { |
1194 for (auto& it : devices_info_cache_) { | 907 for (auto& it : devices_info_cache_) { |
1195 if (it.descriptor.device_id == id) | 908 if (it.descriptor.device_id == id) |
1196 return ⁢ | 909 return ⁢ |
1197 } | 910 } |
1198 return nullptr; | 911 return nullptr; |
1199 } | 912 } |
1200 | 913 |
1201 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 914 VideoCaptureController* VideoCaptureManager::GetOrCreateController( |
1202 media::VideoCaptureSessionId capture_session_id, | 915 media::VideoCaptureSessionId capture_session_id, |
1203 const media::VideoCaptureParams& params) { | 916 const media::VideoCaptureParams& params) { |
1204 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 917 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1205 | 918 |
1206 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 919 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
1207 if (session_it == sessions_.end()) | 920 if (session_it == sessions_.end()) |
1208 return nullptr; | 921 return nullptr; |
1209 const MediaStreamDevice& device_info = session_it->second; | 922 const MediaStreamDevice& device_info = session_it->second; |
1210 | 923 |
1211 // Check if another session has already opened this device. If so, just | 924 // Check if another session has already opened this device. If so, just |
1212 // use that opened device. | 925 // use that opened device. |
1213 DeviceEntry* const existing_device = | 926 VideoCaptureController* const existing_device = |
1214 GetDeviceEntryByTypeAndId(device_info.type, device_info.id); | 927 LookupControllerByTypeAndId(device_info.type, device_info.id); |
1215 if (existing_device) { | 928 if (existing_device) { |
1216 DCHECK_EQ(device_info.type, existing_device->stream_type); | 929 DCHECK_EQ(device_info.type, existing_device->stream_type()); |
1217 return existing_device; | 930 return existing_device; |
1218 } | 931 } |
1219 | 932 |
1220 devices_.emplace_back( | 933 VideoCaptureController* new_device_entry = new VideoCaptureController( |
1221 new DeviceEntry(device_info.type, device_info.id, params)); | 934 device_info.id, device_info.type, params, |
1222 return devices_.back().get(); | 935 base::MakeUnique<InProcessBuildableVideoCaptureDevice>( |
1223 } | 936 device_task_runner_, video_capture_device_factory_.get())); |
1224 | 937 controllers_.emplace_back(new_device_entry); |
1225 void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( | 938 return new_device_entry; |
1226 media::VideoCaptureDevice* device, | |
1227 gfx::NativeViewId window_id) { | |
1228 DCHECK(IsOnDeviceThread()); | |
1229 #if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_AN
DROID) | |
1230 DesktopCaptureDevice* desktop_device = | |
1231 static_cast<DesktopCaptureDevice*>(device); | |
1232 desktop_device->SetNotificationWindowId(window_id); | |
1233 VLOG(2) << "Screen capture notification window passed on device thread."; | |
1234 #endif | |
1235 } | |
1236 | |
1237 void VideoCaptureManager::DoGetPhotoCapabilities( | |
1238 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback, | |
1239 VideoCaptureDevice* device) { | |
1240 // Unretained() is safe to use here because |device| would be null if it | |
1241 // was scheduled for shutdown and destruction, and because this task is | |
1242 // guaranteed to run before the task that destroys the |device|. | |
1243 device_task_runner_->PostTask( | |
1244 FROM_HERE, base::Bind(&VideoCaptureDevice::GetPhotoCapabilities, | |
1245 base::Unretained(device), base::Passed(&callback))); | |
1246 } | |
1247 | |
1248 void VideoCaptureManager::DoSetPhotoOptions( | |
1249 VideoCaptureDevice::SetPhotoOptionsCallback callback, | |
1250 media::mojom::PhotoSettingsPtr settings, | |
1251 VideoCaptureDevice* device) { | |
1252 // Unretained() is safe to use here because |device| would be null if it | |
1253 // was scheduled for shutdown and destruction, and because this task is | |
1254 // guaranteed to run before the task that destroys the |device|. | |
1255 device_task_runner_->PostTask( | |
1256 FROM_HERE, | |
1257 base::Bind(&VideoCaptureDevice::SetPhotoOptions, base::Unretained(device), | |
1258 base::Passed(&settings), base::Passed(&callback))); | |
1259 } | |
1260 | |
1261 void VideoCaptureManager::DoTakePhoto( | |
1262 VideoCaptureDevice::TakePhotoCallback callback, | |
1263 VideoCaptureDevice* device) { | |
1264 // Unretained() is safe to use here because |device| would be null if it | |
1265 // was scheduled for shutdown and destruction, and because this task is | |
1266 // guaranteed to run before the task that destroys the |device|. | |
1267 device_task_runner_->PostTask( | |
1268 FROM_HERE, base::Bind(&VideoCaptureDevice::TakePhoto, | |
1269 base::Unretained(device), base::Passed(&callback))); | |
1270 } | 939 } |
1271 | 940 |
1272 base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration( | 941 base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration( |
1273 const std::string& device_id) { | 942 const std::string& device_id) { |
1274 VideoCaptureManager::DeviceInfo* info = GetDeviceInfoById(device_id); | 943 VideoCaptureManager::DeviceInfo* info = GetDeviceInfoById(device_id); |
1275 if (!info) | 944 if (!info) |
1276 return base::Optional<CameraCalibration>(); | 945 return base::Optional<CameraCalibration>(); |
1277 return info->descriptor.camera_calibration; | 946 return info->descriptor.camera_calibration; |
1278 } | 947 } |
1279 | 948 |
(...skipping 10 matching lines...) Expand all Loading... |
1290 application_state_has_running_activities_ = true; | 959 application_state_has_running_activities_ = true; |
1291 } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { | 960 } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { |
1292 ReleaseDevices(); | 961 ReleaseDevices(); |
1293 application_state_has_running_activities_ = false; | 962 application_state_has_running_activities_ = false; |
1294 } | 963 } |
1295 } | 964 } |
1296 | 965 |
1297 void VideoCaptureManager::ReleaseDevices() { | 966 void VideoCaptureManager::ReleaseDevices() { |
1298 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 967 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1299 | 968 |
1300 for (auto& entry : devices_) { | 969 for (auto& controller : controllers_) { |
1301 // Do not stop Content Video Capture devices, e.g. Tab or Screen capture. | 970 // Do not stop Content Video Capture devices, e.g. Tab or Screen capture. |
1302 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 971 if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE) |
1303 continue; | 972 continue; |
1304 | 973 |
1305 DoStopDevice(entry.get()); | 974 DoStopDevice(controller.get()); |
1306 } | 975 } |
1307 } | 976 } |
1308 | 977 |
1309 void VideoCaptureManager::ResumeDevices() { | 978 void VideoCaptureManager::ResumeDevices() { |
1310 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 979 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1311 | 980 |
1312 for (auto& entry : devices_) { | 981 for (auto& controller : controllers_) { |
1313 // Do not resume Content Video Capture devices, e.g. Tab or Screen capture. | 982 // Do not resume Content Video Capture devices, e.g. Tab or Screen capture. |
1314 // Do not try to restart already running devices. | 983 // Do not try to restart already running devices. |
1315 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE || | 984 if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE || |
1316 entry->video_capture_device) | 985 controller->IsDeviceAlive()) |
1317 continue; | 986 continue; |
1318 | 987 |
1319 // Check if the device is already in the start queue. | 988 // Check if the device is already in the start queue. |
1320 bool device_in_queue = false; | 989 bool device_in_queue = false; |
1321 for (auto& request : device_start_queue_) { | 990 for (auto& request : device_start_queue_) { |
1322 if (request.serial_id() == entry->serial_id) { | 991 if (request.serial_id() == controller->serial_id()) { |
1323 device_in_queue = true; | 992 device_in_queue = true; |
1324 break; | 993 break; |
1325 } | 994 } |
1326 } | 995 } |
1327 | 996 |
1328 if (!device_in_queue) { | 997 if (!device_in_queue) { |
1329 // Session ID is only valid for Screen capture. So we can fake it to | 998 // Session ID is only valid for Screen capture. So we can fake it to |
1330 // resume video capture devices here. | 999 // resume video capture devices here. |
1331 QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters); | 1000 QueueStartDevice(kFakeSessionId, controller.get(), |
| 1001 controller->parameters()); |
1332 } | 1002 } |
1333 } | 1003 } |
1334 } | 1004 } |
1335 #endif // defined(OS_ANDROID) | 1005 #endif // defined(OS_ANDROID) |
1336 | 1006 |
1337 } // namespace content | 1007 } // namespace content |
OLD | NEW |