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 <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 | 111 |
112 VideoCaptureManager::VideoCaptureManager( | 112 VideoCaptureManager::VideoCaptureManager( |
113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) | 113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) |
114 : listener_(NULL), | 114 : listener_(NULL), |
115 new_capture_session_id_(1), | 115 new_capture_session_id_(1), |
116 video_capture_device_factory_(factory.Pass()) { | 116 video_capture_device_factory_(factory.Pass()) { |
117 } | 117 } |
118 | 118 |
119 VideoCaptureManager::~VideoCaptureManager() { | 119 VideoCaptureManager::~VideoCaptureManager() { |
120 DCHECK(devices_.empty()); | 120 DCHECK(devices_.empty()); |
121 DCHECK(device_start_queue_.empty()); | |
121 } | 122 } |
122 | 123 |
123 void VideoCaptureManager::Register( | 124 void VideoCaptureManager::Register( |
124 MediaStreamProviderListener* listener, | 125 MediaStreamProviderListener* listener, |
125 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { | 126 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { |
126 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 127 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
127 DCHECK(!listener_); | 128 DCHECK(!listener_); |
128 DCHECK(!device_task_runner_.get()); | 129 DCHECK(!device_task_runner_.get()); |
129 listener_ = listener; | 130 listener_ = listener; |
130 device_task_runner_ = device_task_runner; | 131 device_task_runner_ = device_task_runner; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 DestroyDeviceEntryIfNoClients(existing_device); | 210 DestroyDeviceEntryIfNoClients(existing_device); |
210 } | 211 } |
211 | 212 |
212 // Notify listeners asynchronously, and forget the session. | 213 // Notify listeners asynchronously, and forget the session. |
213 base::MessageLoop::current()->PostTask(FROM_HERE, | 214 base::MessageLoop::current()->PostTask(FROM_HERE, |
214 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, | 215 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, |
215 capture_session_id)); | 216 capture_session_id)); |
216 sessions_.erase(session_it); | 217 sessions_.erase(session_it); |
217 } | 218 } |
218 | 219 |
220 // Creates a start request. | |
221 VideoCaptureManager:: | |
222 CaptureDeviceStartRequest::CaptureDeviceStartRequest( | |
tommi (sloooow) - chröme
2014/12/15 16:25:05
no need to wrap?
perkj_chrome
2014/12/16 20:15:05
media::VideoCaptureSessionId session_id, does not
tommi (sloooow) - chröme
2014/12/16 22:31:25
I meant the function:
VideoCaptureManager::Captur
| |
223 DeviceEntry* device_entry, | |
224 media::VideoCaptureSessionId session_id, | |
225 const media::VideoCaptureParams& params) | |
226 : device_entry(device_entry), | |
227 session_id(session_id), | |
228 params(params) { | |
229 } | |
230 | |
231 void VideoCaptureManager::QueueStartDevice( | |
232 media::VideoCaptureSessionId session_id, | |
233 DeviceEntry* entry, | |
234 const media::VideoCaptureParams& params) { | |
235 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
236 DCHECK(entry->video_capture_controller.get()); | |
237 DVLOG(3) << "QueueStartDevice, device = " << entry->id; | |
238 | |
239 device_start_queue_.push_back( | |
240 CaptureDeviceStartRequest(entry, session_id, params)); | |
241 if (device_start_queue_.size() == 1) { | |
242 HandleQueuedStartRequest(); | |
243 } | |
244 } | |
245 | |
246 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry, bool delete_entry) { | |
247 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
248 // Check if the start request has not yet been sent to the device thread. | |
249 // If so, delete the request. | |
250 if (device_start_queue_.size() > 1) { | |
251 for (DeviceStartQueue::iterator request = ++device_start_queue_.begin(); | |
252 request != device_start_queue_.end(); ++request) { | |
253 if (request->device_entry->id == entry->id && | |
254 request->device_entry->stream_type == entry->stream_type) { | |
255 device_start_queue_.erase(request); | |
256 DVLOG(3) << "DoStopDevice, erasing start request for device " | |
257 << entry->id << "."; | |
258 if (delete_entry) { | |
259 delete entry; | |
tommi (sloooow) - chröme
2014/12/15 16:25:05
can we use a scoped_ptr<> for this instead?
| |
260 } | |
261 return; | |
262 } | |
263 } | |
264 } | |
265 | |
266 DVLOG(3) << "DoStopDevice. Send stop request for device " << entry->id << "."; | |
267 if (delete_entry) { | |
tommi (sloooow) - chröme
2014/12/15 16:25:05
FYI - here there are two call sites + bindings for
| |
268 device_task_runner_->PostTask( | |
269 FROM_HERE, | |
270 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
271 base::Owned(entry))); | |
272 } else { | |
273 device_task_runner_->PostTask( | |
274 FROM_HERE, | |
275 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
276 base::Unretained(entry))); | |
277 } | |
278 } | |
279 | |
280 void VideoCaptureManager::HandleQueuedStartRequest() { | |
281 auto request = device_start_queue_.begin(); | |
282 if (request == device_start_queue_.end()) | |
283 return; | |
284 | |
285 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " | |
286 << request->device_entry->id; | |
287 | |
288 device_task_runner_->PostTaskAndReply( | |
289 FROM_HERE, | |
290 base::Bind( | |
291 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
292 this, | |
293 request->session_id, | |
294 request->device_entry, | |
295 request->params, | |
296 base::Passed(request->device_entry->video_capture_controller-> | |
297 NewDeviceClient())), | |
298 base::Bind(&VideoCaptureManager::OnDeviceStarted, this)); | |
299 } | |
300 | |
301 void VideoCaptureManager::OnDeviceStarted() { | |
302 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
303 DVLOG(3) << "OnDeviceStarted"; | |
304 device_start_queue_.pop_front(); | |
305 HandleQueuedStartRequest(); | |
306 } | |
307 | |
219 void VideoCaptureManager::DoStartDeviceOnDeviceThread( | 308 void VideoCaptureManager::DoStartDeviceOnDeviceThread( |
220 media::VideoCaptureSessionId session_id, | 309 media::VideoCaptureSessionId session_id, |
221 DeviceEntry* entry, | 310 DeviceEntry* entry, |
222 const media::VideoCaptureParams& params, | 311 const media::VideoCaptureParams& params, |
223 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { | 312 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
224 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 313 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
225 DCHECK(IsOnDeviceThread()); | 314 DCHECK(IsOnDeviceThread()); |
226 | 315 |
227 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 316 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
228 switch (entry->stream_type) { | 317 switch (entry->stream_type) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 } | 388 } |
300 | 389 |
301 DCHECK(entry->video_capture_controller); | 390 DCHECK(entry->video_capture_controller); |
302 | 391 |
303 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); | 392 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); |
304 | 393 |
305 // First client starts the device. | 394 // First client starts the device. |
306 if (entry->video_capture_controller->GetActiveClientCount() == 0) { | 395 if (entry->video_capture_controller->GetActiveClientCount() == 0) { |
307 DVLOG(1) << "VideoCaptureManager starting device (type = " | 396 DVLOG(1) << "VideoCaptureManager starting device (type = " |
308 << entry->stream_type << ", id = " << entry->id << ")"; | 397 << entry->stream_type << ", id = " << entry->id << ")"; |
309 | 398 QueueStartDevice(session_id, entry, params); |
310 device_task_runner_->PostTask( | |
311 FROM_HERE, | |
312 base::Bind( | |
313 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
314 this, | |
315 session_id, | |
316 entry, | |
317 params, | |
318 base::Passed(entry->video_capture_controller->NewDeviceClient()))); | |
319 } | 399 } |
320 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 400 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
321 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); | 401 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); |
322 entry->video_capture_controller->AddClient( | 402 entry->video_capture_controller->AddClient( |
323 client_id, client_handler, client_render_process, session_id, params); | 403 client_id, client_handler, client_render_process, session_id, params); |
324 } | 404 } |
325 | 405 |
326 void VideoCaptureManager::StopCaptureForClient( | 406 void VideoCaptureManager::StopCaptureForClient( |
327 VideoCaptureController* controller, | 407 VideoCaptureController* controller, |
328 VideoCaptureControllerID client_id, | 408 VideoCaptureControllerID client_id, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to | 465 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to |
386 // system. | 466 // system. |
387 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 467 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
388 return; | 468 return; |
389 | 469 |
390 controller->PauseOrResumeClient(client_id, client_handler, true); | 470 controller->PauseOrResumeClient(client_id, client_handler, true); |
391 if (controller->GetActiveClientCount() != 0) | 471 if (controller->GetActiveClientCount() != 0) |
392 return; | 472 return; |
393 | 473 |
394 // There is no more client, release the camera. | 474 // There is no more client, release the camera. |
395 device_task_runner_->PostTask( | 475 DoStopDevice(entry, false); |
396 FROM_HERE, | |
397 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
398 base::Unretained(entry))); | |
399 } | 476 } |
400 | 477 |
401 void VideoCaptureManager::ResumeCaptureForClient( | 478 void VideoCaptureManager::ResumeCaptureForClient( |
402 media::VideoCaptureSessionId session_id, | 479 media::VideoCaptureSessionId session_id, |
403 const media::VideoCaptureParams& params, | 480 const media::VideoCaptureParams& params, |
404 VideoCaptureController* controller, | 481 VideoCaptureController* controller, |
405 VideoCaptureControllerID client_id, | 482 VideoCaptureControllerID client_id, |
406 VideoCaptureControllerEventHandler* client_handler) { | 483 VideoCaptureControllerEventHandler* client_handler) { |
407 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 484 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
408 DCHECK(controller); | 485 DCHECK(controller); |
409 DCHECK(client_handler); | 486 DCHECK(client_handler); |
410 | 487 |
411 DeviceEntry* entry = GetDeviceEntryForController(controller); | 488 DeviceEntry* entry = GetDeviceEntryForController(controller); |
412 if (!entry) { | 489 if (!entry) { |
413 NOTREACHED(); | 490 NOTREACHED(); |
414 return; | 491 return; |
415 } | 492 } |
416 | 493 |
417 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. | 494 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. |
418 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 495 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
419 return; | 496 return; |
420 | 497 |
421 controller->PauseOrResumeClient(client_id, client_handler, false); | 498 controller->PauseOrResumeClient(client_id, client_handler, false); |
422 if (controller->GetActiveClientCount() != 1) | 499 if (controller->GetActiveClientCount() != 1) |
423 return; | 500 return; |
424 | 501 |
425 // This is first active client, allocate the camera. | 502 // This is first active client, allocate the camera. |
426 device_task_runner_->PostTask( | 503 QueueStartDevice(session_id, entry, params); |
427 FROM_HERE, | |
428 base::Bind( | |
429 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
430 this, | |
431 session_id, | |
432 entry, | |
433 params, | |
434 base::Passed(entry->video_capture_controller->NewDeviceClient()))); | |
435 } | 504 } |
436 | 505 |
437 bool VideoCaptureManager::GetDeviceSupportedFormats( | 506 bool VideoCaptureManager::GetDeviceSupportedFormats( |
438 media::VideoCaptureSessionId capture_session_id, | 507 media::VideoCaptureSessionId capture_session_id, |
439 media::VideoCaptureFormats* supported_formats) { | 508 media::VideoCaptureFormats* supported_formats) { |
440 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 509 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
441 DCHECK(supported_formats->empty()); | 510 DCHECK(supported_formats->empty()); |
442 | 511 |
443 SessionMap::iterator it = sessions_.find(capture_session_id); | 512 SessionMap::iterator it = sessions_.find(capture_session_id); |
444 if (it == sessions_.end()) | 513 if (it == sessions_.end()) |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
648 if (entry->video_capture_controller->GetClientCount() == 0) { | 717 if (entry->video_capture_controller->GetClientCount() == 0) { |
649 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 718 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
650 << entry->stream_type << ", id = " << entry->id << ")"; | 719 << entry->stream_type << ", id = " << entry->id << ")"; |
651 | 720 |
652 // The DeviceEntry is removed from |devices_| immediately. The controller is | 721 // The DeviceEntry is removed from |devices_| immediately. The controller is |
653 // deleted immediately, and the device is freed asynchronously. After this | 722 // deleted immediately, and the device is freed asynchronously. After this |
654 // point, subsequent requests to open this same device ID will create a new | 723 // point, subsequent requests to open this same device ID will create a new |
655 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. | 724 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. |
656 devices_.erase(entry); | 725 devices_.erase(entry); |
657 entry->video_capture_controller.reset(); | 726 entry->video_capture_controller.reset(); |
658 device_task_runner_->PostTask( | 727 DoStopDevice(entry, true); |
659 FROM_HERE, | |
660 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
661 base::Owned(entry))); | |
662 } | 728 } |
663 } | 729 } |
664 | 730 |
665 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 731 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
666 media::VideoCaptureSessionId capture_session_id) { | 732 media::VideoCaptureSessionId capture_session_id) { |
667 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 733 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
668 | 734 |
669 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 735 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
670 if (session_it == sessions_.end()) { | 736 if (session_it == sessions_.end()) { |
671 return NULL; | 737 return NULL; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
720 gfx::NativeViewId window_id) { | 786 gfx::NativeViewId window_id) { |
721 DCHECK(IsOnDeviceThread()); | 787 DCHECK(IsOnDeviceThread()); |
722 DCHECK(notification_window_ids_.find(session_id) == | 788 DCHECK(notification_window_ids_.find(session_id) == |
723 notification_window_ids_.end()); | 789 notification_window_ids_.end()); |
724 notification_window_ids_[session_id] = window_id; | 790 notification_window_ids_[session_id] = window_id; |
725 VLOG(2) << "Screen capture notification window saved for session " | 791 VLOG(2) << "Screen capture notification window saved for session " |
726 << session_id << " on device thread."; | 792 << session_id << " on device thread."; |
727 } | 793 } |
728 | 794 |
729 } // namespace content | 795 } // namespace content |
OLD | NEW |