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/logging.h" | 11 #include "base/logging.h" |
11 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/task_runner_util.h" | 14 #include "base/task_runner_util.h" |
14 #include "base/threading/sequenced_worker_pool.h" | 15 #include "base/threading/sequenced_worker_pool.h" |
15 #include "content/browser/media/capture/web_contents_video_capture_device.h" | 16 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
16 #include "content/browser/renderer_host/media/video_capture_controller.h" | 17 #include "content/browser/renderer_host/media/video_capture_controller.h" |
17 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" | 18 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" |
18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/desktop_media_id.h" | 20 #include "content/public/browser/desktop_media_id.h" |
20 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
21 #include "content/public/common/media_stream_request.h" | 22 #include "content/public/common/media_stream_request.h" |
| 23 #include "media/base/bind_to_current_loop.h" |
22 #include "media/base/scoped_histogram_timer.h" | 24 #include "media/base/scoped_histogram_timer.h" |
23 #include "media/video/capture/video_capture_device.h" | 25 #include "media/video/capture/video_capture_device.h" |
24 #include "media/video/capture/video_capture_device_factory.h" | 26 #include "media/video/capture/video_capture_device_factory.h" |
25 | 27 |
26 #if defined(ENABLE_SCREEN_CAPTURE) | 28 #if defined(ENABLE_SCREEN_CAPTURE) |
27 #include "content/browser/media/capture/desktop_capture_device.h" | 29 #include "content/browser/media/capture/desktop_capture_device.h" |
28 #if defined(USE_AURA) | 30 #if defined(USE_AURA) |
29 #include "content/browser/media/capture/desktop_capture_device_aura.h" | 31 #include "content/browser/media/capture/desktop_capture_device_aura.h" |
30 #endif | 32 #endif |
31 #endif | 33 #endif |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 | 117 |
116 void VideoCaptureManager::Unregister() { | 118 void VideoCaptureManager::Unregister() { |
117 DCHECK(listener_); | 119 DCHECK(listener_); |
118 listener_ = NULL; | 120 listener_ = NULL; |
119 } | 121 } |
120 | 122 |
121 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { | 123 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { |
122 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 124 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
123 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; | 125 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; |
124 DCHECK(listener_); | 126 DCHECK(listener_); |
125 base::PostTaskAndReplyWithResult( | 127 DCHECK_EQ(stream_type, MEDIA_DEVICE_VIDEO_CAPTURE); |
126 device_task_runner_, FROM_HERE, | 128 |
127 base::Bind(&VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread, | 129 // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument |
128 this, stream_type, devices_info_cache_), | 130 // for another callback to OnDevicesInfoEnumerated() to be run in the current |
129 base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this, | 131 // loop, i.e. IO loop. Pass a timer for UMA histogram collection. |
130 stream_type)); | 132 base::Callback<void(scoped_ptr<media::VideoCaptureDevice::Names>)> |
| 133 devices_enumerated_callback = |
| 134 base::Bind(&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, |
| 135 this, |
| 136 media::BindToCurrentLoop(base::Bind( |
| 137 &VideoCaptureManager::OnDevicesInfoEnumerated, |
| 138 this, |
| 139 stream_type, |
| 140 base::Owned(new base::ElapsedTimer()))), |
| 141 stream_type, |
| 142 devices_info_cache_); |
| 143 // OK to use base::Unretained() since we own the VCDFactory and |this| is |
| 144 // bound in |devices_enumerated_callback|. |
| 145 device_task_runner_->PostTask(FROM_HERE, |
| 146 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceNames, |
| 147 base::Unretained(video_capture_device_factory_.get()), |
| 148 devices_enumerated_callback)); |
131 } | 149 } |
132 | 150 |
133 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { | 151 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { |
134 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 152 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
135 DCHECK(listener_); | 153 DCHECK(listener_); |
136 | 154 |
137 // Generate a new id for the session being opened. | 155 // Generate a new id for the session being opened. |
138 const media::VideoCaptureSessionId capture_session_id = | 156 const media::VideoCaptureSessionId capture_session_id = |
139 new_capture_session_id_++; | 157 new_capture_session_id_++; |
140 | 158 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 | 211 |
194 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 212 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
195 switch (entry->stream_type) { | 213 switch (entry->stream_type) { |
196 case MEDIA_DEVICE_VIDEO_CAPTURE: { | 214 case MEDIA_DEVICE_VIDEO_CAPTURE: { |
197 // We look up the device id from the renderer in our local enumeration | 215 // We look up the device id from the renderer in our local enumeration |
198 // since the renderer does not have all the information that might be | 216 // since the renderer does not have all the information that might be |
199 // held in the browser-side VideoCaptureDevice::Name structure. | 217 // held in the browser-side VideoCaptureDevice::Name structure. |
200 DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_); | 218 DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_); |
201 if (found) { | 219 if (found) { |
202 video_capture_device = | 220 video_capture_device = |
203 video_capture_device_factory_->Create( | 221 video_capture_device_factory_->Create(found->name); |
204 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), | |
205 found->name); | |
206 } | 222 } |
207 break; | 223 break; |
208 } | 224 } |
209 case MEDIA_TAB_VIDEO_CAPTURE: { | 225 case MEDIA_TAB_VIDEO_CAPTURE: { |
210 video_capture_device.reset( | 226 video_capture_device.reset( |
211 WebContentsVideoCaptureDevice::Create(entry->id)); | 227 WebContentsVideoCaptureDevice::Create(entry->id)); |
212 break; | 228 break; |
213 } | 229 } |
214 case MEDIA_DESKTOP_VIDEO_CAPTURE: { | 230 case MEDIA_DESKTOP_VIDEO_CAPTURE: { |
215 #if defined(ENABLE_SCREEN_CAPTURE) | 231 #if defined(ENABLE_SCREEN_CAPTURE) |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 441 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
426 if (!listener_) { | 442 if (!listener_) { |
427 // Listener has been removed. | 443 // Listener has been removed. |
428 return; | 444 return; |
429 } | 445 } |
430 listener_->Closed(stream_type, capture_session_id); | 446 listener_->Closed(stream_type, capture_session_id); |
431 } | 447 } |
432 | 448 |
433 void VideoCaptureManager::OnDevicesInfoEnumerated( | 449 void VideoCaptureManager::OnDevicesInfoEnumerated( |
434 MediaStreamType stream_type, | 450 MediaStreamType stream_type, |
| 451 base::ElapsedTimer* timer, |
435 const DeviceInfos& new_devices_info_cache) { | 452 const DeviceInfos& new_devices_info_cache) { |
436 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 453 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
437 | 454 UMA_HISTOGRAM_TIMES( |
| 455 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime", |
| 456 timer->Elapsed()); |
438 if (!listener_) { | 457 if (!listener_) { |
439 // Listener has been removed. | 458 // Listener has been removed. |
440 return; | 459 return; |
441 } | 460 } |
442 devices_info_cache_ = new_devices_info_cache; | 461 devices_info_cache_ = new_devices_info_cache; |
443 | 462 |
444 // Walk the |devices_info_cache_| and transform from VCD::Name to | 463 // Walk the |devices_info_cache_| and transform from VCD::Name to |
445 // StreamDeviceInfo for return purposes. | 464 // StreamDeviceInfo for return purposes. |
446 StreamDeviceInfoArray devices; | 465 StreamDeviceInfoArray devices; |
447 for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); | 466 for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); |
448 it != devices_info_cache_.end(); ++it) { | 467 it != devices_info_cache_.end(); ++it) { |
449 devices.push_back(StreamDeviceInfo( | 468 devices.push_back(StreamDeviceInfo( |
450 stream_type, it->name.GetNameAndModel(), it->name.id())); | 469 stream_type, it->name.GetNameAndModel(), it->name.id())); |
451 } | 470 } |
452 listener_->DevicesEnumerated(stream_type, devices); | 471 listener_->DevicesEnumerated(stream_type, devices); |
453 } | 472 } |
454 | 473 |
455 bool VideoCaptureManager::IsOnDeviceThread() const { | 474 bool VideoCaptureManager::IsOnDeviceThread() const { |
456 return device_task_runner_->BelongsToCurrentThread(); | 475 return device_task_runner_->BelongsToCurrentThread(); |
457 } | 476 } |
458 | 477 |
459 VideoCaptureManager::DeviceInfos | 478 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( |
460 VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread( | 479 base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback, |
461 MediaStreamType stream_type, | 480 MediaStreamType stream_type, |
462 const DeviceInfos& old_device_info_cache) { | 481 const DeviceInfos& old_device_info_cache, |
463 SCOPED_UMA_HISTOGRAM_TIMER( | 482 scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot) { |
464 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime"); | |
465 DCHECK(IsOnDeviceThread()); | 483 DCHECK(IsOnDeviceThread()); |
466 media::VideoCaptureDevice::Names names_snapshot; | |
467 switch (stream_type) { | |
468 case MEDIA_DEVICE_VIDEO_CAPTURE: | |
469 // Cache the latest enumeration of video capture devices. | |
470 // We'll refer to this list again in OnOpen to avoid having to | |
471 // enumerate the devices again. | |
472 video_capture_device_factory_->GetDeviceNames(&names_snapshot); | |
473 break; | |
474 case MEDIA_DESKTOP_VIDEO_CAPTURE: | |
475 // Do nothing. | |
476 break; | |
477 default: | |
478 NOTREACHED(); | |
479 break; | |
480 } | |
481 | |
482 // Construct |new_devices_info_cache| with the cached devices that are still | 484 // Construct |new_devices_info_cache| with the cached devices that are still |
483 // present in the system, and remove their names from |names_snapshot|, so we | 485 // present in the system, and remove their names from |names_snapshot|, so we |
484 // keep there the truly new devices. | 486 // keep there the truly new devices. |
485 DeviceInfos new_devices_info_cache; | 487 DeviceInfos new_devices_info_cache; |
486 for (DeviceInfos::const_iterator it_device_info = | 488 for (DeviceInfos::const_iterator it_device_info = |
487 old_device_info_cache.begin(); | 489 old_device_info_cache.begin(); |
488 it_device_info != old_device_info_cache.end(); ++it_device_info) { | 490 it_device_info != old_device_info_cache.end(); ++it_device_info) { |
489 for (media::VideoCaptureDevice::Names::iterator it = | 491 for (media::VideoCaptureDevice::Names::iterator it = |
490 names_snapshot.begin(); | 492 names_snapshot->begin(); |
491 it != names_snapshot.end(); ++it) { | 493 it != names_snapshot->end(); ++it) { |
492 if (it_device_info->name.id() == it->id()) { | 494 if (it_device_info->name.id() == it->id()) { |
493 new_devices_info_cache.push_back(*it_device_info); | 495 new_devices_info_cache.push_back(*it_device_info); |
494 names_snapshot.erase(it); | 496 names_snapshot->erase(it); |
495 break; | 497 break; |
496 } | 498 } |
497 } | 499 } |
498 } | 500 } |
499 | 501 |
500 // Get the supported capture formats for the new devices in |names_snapshot|. | 502 // Get the supported capture formats for the new devices in |names_snapshot|. |
501 for (media::VideoCaptureDevice::Names::const_iterator it = | 503 for (media::VideoCaptureDevice::Names::const_iterator it = |
502 names_snapshot.begin(); | 504 names_snapshot->begin(); |
503 it != names_snapshot.end(); ++it) { | 505 it != names_snapshot->end(); ++it) { |
504 media::VideoCaptureFormats supported_formats; | 506 media::VideoCaptureFormats supported_formats; |
505 DeviceInfo device_info(*it, media::VideoCaptureFormats()); | 507 DeviceInfo device_info(*it, media::VideoCaptureFormats()); |
506 video_capture_device_factory_->GetDeviceSupportedFormats( | 508 video_capture_device_factory_->GetDeviceSupportedFormats( |
507 *it, &(device_info.supported_formats)); | 509 *it, &(device_info.supported_formats)); |
508 ConsolidateCaptureFormats(&device_info.supported_formats); | 510 ConsolidateCaptureFormats(&device_info.supported_formats); |
509 new_devices_info_cache.push_back(device_info); | 511 new_devices_info_cache.push_back(device_info); |
510 } | 512 } |
511 return new_devices_info_cache; | 513 |
| 514 on_devices_enumerated_callback.Run(new_devices_info_cache); |
512 } | 515 } |
513 | 516 |
514 VideoCaptureManager::DeviceEntry* | 517 VideoCaptureManager::DeviceEntry* |
515 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( | 518 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( |
516 const MediaStreamDevice& device_info) { | 519 const MediaStreamDevice& device_info) { |
517 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 520 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
518 | 521 |
519 for (DeviceEntries::iterator it = devices_.begin(); | 522 for (DeviceEntries::iterator it = devices_.begin(); |
520 it != devices_.end(); ++it) { | 523 it != devices_.end(); ++it) { |
521 DeviceEntry* device = *it; | 524 DeviceEntry* device = *it; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( | 617 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( |
615 media::VideoCaptureSessionId session_id, | 618 media::VideoCaptureSessionId session_id, |
616 gfx::NativeViewId window_id) { | 619 gfx::NativeViewId window_id) { |
617 DCHECK(IsOnDeviceThread()); | 620 DCHECK(IsOnDeviceThread()); |
618 DCHECK(notification_window_ids_.find(session_id) == | 621 DCHECK(notification_window_ids_.find(session_id) == |
619 notification_window_ids_.end()); | 622 notification_window_ids_.end()); |
620 notification_window_ids_[session_id] = window_id; | 623 notification_window_ids_[session_id] = window_id; |
621 } | 624 } |
622 | 625 |
623 } // namespace content | 626 } // namespace content |
OLD | NEW |