Chromium Code Reviews| 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" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 | 116 |
| 116 void VideoCaptureManager::Unregister() { | 117 void VideoCaptureManager::Unregister() { |
| 117 DCHECK(listener_); | 118 DCHECK(listener_); |
| 118 listener_ = NULL; | 119 listener_ = NULL; |
| 119 } | 120 } |
| 120 | 121 |
| 121 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { | 122 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { |
| 122 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 123 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 123 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; | 124 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; |
| 124 DCHECK(listener_); | 125 DCHECK(listener_); |
| 125 base::PostTaskAndReplyWithResult( | 126 if (stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
|
perkj_chrome
2014/05/26 11:49:42
THis looks weird. Why return devices_info_cache_
mcasas
2014/05/26 13:00:18
This was a cleanup of previous code, where
GetAva
| |
| 126 device_task_runner_, FROM_HERE, | 127 OnDevicesInfoEnumerated(stream_type, devices_info_cache_); |
| 127 base::Bind(&VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread, | 128 return; |
| 128 this, stream_type, devices_info_cache_), | 129 } |
| 129 base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this, | 130 DCHECK_EQ(stream_type, MEDIA_DEVICE_VIDEO_CAPTURE); |
| 130 stream_type)); | 131 |
| 132 // TODO(mcasas): replace previous SCOPED_UMA_HISTOGRAM_TIMER( | |
| 133 // "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime"); | |
|
perkj_chrome
2014/05/26 11:49:42
this does not seem to have anything to do with wha
mcasas
2014/05/26 13:00:18
Yes, this is an open question.
Before this CL, th
perkj_chrome
2014/05/27 12:15:08
Was that something you added because you wanted it
| |
| 134 // with a base/timer/elapsed_timer.h ElapsedTime, constructed here and | |
| 135 // measured in OnDevicesInfoEnumerated() | |
| 136 | |
| 137 base::Callback<void(media::VideoCaptureDevice::Names&)> | |
| 138 devices_enumerated_callback = | |
| 139 base::Bind(&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, | |
|
perkj_chrome
2014/05/26 11:49:42
To avoid the raw message loop pointer - how about
mcasas
2014/05/26 13:00:18
Done.
| |
| 140 this, | |
| 141 base::MessageLoop::current(), | |
| 142 stream_type, | |
| 143 devices_info_cache_); | |
| 144 // OK to use base::Unretained() since we own the VCDFactory. | |
|
perkj_chrome
2014/05/26 11:49:42
What guarantee that the video capture manager is n
mcasas
2014/05/26 13:00:18
VCM outlives the VCDF, plus is reference counted v
| |
| 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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, |
| 435 const DeviceInfos& new_devices_info_cache) { | 451 const DeviceInfos& new_devices_info_cache) { |
| 436 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 452 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 437 | |
| 438 if (!listener_) { | 453 if (!listener_) { |
| 439 // Listener has been removed. | 454 // Listener has been removed. |
| 440 return; | 455 return; |
| 441 } | 456 } |
| 442 devices_info_cache_ = new_devices_info_cache; | 457 devices_info_cache_ = new_devices_info_cache; |
| 443 | 458 |
| 444 // Walk the |devices_info_cache_| and transform from VCD::Name to | 459 // Walk the |devices_info_cache_| and transform from VCD::Name to |
| 445 // StreamDeviceInfo for return purposes. | 460 // StreamDeviceInfo for return purposes. |
| 446 StreamDeviceInfoArray devices; | 461 StreamDeviceInfoArray devices; |
| 447 for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); | 462 for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); |
| 448 it != devices_info_cache_.end(); ++it) { | 463 it != devices_info_cache_.end(); ++it) { |
| 449 devices.push_back(StreamDeviceInfo( | 464 devices.push_back(StreamDeviceInfo( |
| 450 stream_type, it->name.GetNameAndModel(), it->name.id())); | 465 stream_type, it->name.GetNameAndModel(), it->name.id())); |
| 451 } | 466 } |
| 452 listener_->DevicesEnumerated(stream_type, devices); | 467 listener_->DevicesEnumerated(stream_type, devices); |
| 453 } | 468 } |
| 454 | 469 |
| 455 bool VideoCaptureManager::IsOnDeviceThread() const { | 470 bool VideoCaptureManager::IsOnDeviceThread() const { |
| 456 return device_task_runner_->BelongsToCurrentThread(); | 471 return device_task_runner_->BelongsToCurrentThread(); |
| 457 } | 472 } |
| 458 | 473 |
| 459 VideoCaptureManager::DeviceInfos | 474 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( |
| 460 VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread( | 475 base::MessageLoop* io_loop, |
| 461 MediaStreamType stream_type, | 476 MediaStreamType stream_type, |
| 462 const DeviceInfos& old_device_info_cache) { | 477 const DeviceInfos& old_device_info_cache, |
| 463 SCOPED_UMA_HISTOGRAM_TIMER( | 478 media::VideoCaptureDevice::Names& names_snapshot) { |
| 464 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime"); | |
| 465 DCHECK(IsOnDeviceThread()); | 479 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 | 480 // 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 | 481 // present in the system, and remove their names from |names_snapshot|, so we |
| 484 // keep there the truly new devices. | 482 // keep there the truly new devices. |
| 485 DeviceInfos new_devices_info_cache; | 483 DeviceInfos new_devices_info_cache; |
| 486 for (DeviceInfos::const_iterator it_device_info = | 484 for (DeviceInfos::const_iterator it_device_info = |
| 487 old_device_info_cache.begin(); | 485 old_device_info_cache.begin(); |
| 488 it_device_info != old_device_info_cache.end(); ++it_device_info) { | 486 it_device_info != old_device_info_cache.end(); ++it_device_info) { |
| 489 for (media::VideoCaptureDevice::Names::iterator it = | 487 for (media::VideoCaptureDevice::Names::iterator it = |
| 490 names_snapshot.begin(); | 488 names_snapshot.begin(); |
| 491 it != names_snapshot.end(); ++it) { | 489 it != names_snapshot.end(); ++it) { |
| 492 if (it_device_info->name.id() == it->id()) { | 490 if (it_device_info->name.id() == it->id()) { |
| 493 new_devices_info_cache.push_back(*it_device_info); | 491 new_devices_info_cache.push_back(*it_device_info); |
| 494 names_snapshot.erase(it); | 492 names_snapshot.erase(it); |
| 495 break; | 493 break; |
| 496 } | 494 } |
| 497 } | 495 } |
| 498 } | 496 } |
| 499 | 497 |
| 500 // Get the supported capture formats for the new devices in |names_snapshot|. | 498 // Get the supported capture formats for the new devices in |names_snapshot|. |
| 501 for (media::VideoCaptureDevice::Names::const_iterator it = | 499 for (media::VideoCaptureDevice::Names::const_iterator it = |
| 502 names_snapshot.begin(); | 500 names_snapshot.begin(); |
| 503 it != names_snapshot.end(); ++it) { | 501 it != names_snapshot.end(); ++it) { |
| 504 media::VideoCaptureFormats supported_formats; | 502 media::VideoCaptureFormats supported_formats; |
| 505 DeviceInfo device_info(*it, media::VideoCaptureFormats()); | 503 DeviceInfo device_info(*it, media::VideoCaptureFormats()); |
| 506 video_capture_device_factory_->GetDeviceSupportedFormats( | 504 video_capture_device_factory_->GetDeviceSupportedFormats( |
| 507 *it, &(device_info.supported_formats)); | 505 *it, &(device_info.supported_formats)); |
| 508 ConsolidateCaptureFormats(&device_info.supported_formats); | 506 ConsolidateCaptureFormats(&device_info.supported_formats); |
| 509 new_devices_info_cache.push_back(device_info); | 507 new_devices_info_cache.push_back(device_info); |
| 510 } | 508 } |
| 511 return new_devices_info_cache; | 509 |
| 510 io_loop->PostTask(FROM_HERE, | |
|
perkj_chrome
2014/05/26 11:49:42
Use a callback as input parameter instead and just
mcasas
2014/05/26 13:00:18
Done.
| |
| 511 base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, | |
| 512 this, stream_type, new_devices_info_cache)); | |
| 512 } | 513 } |
| 513 | 514 |
| 514 VideoCaptureManager::DeviceEntry* | 515 VideoCaptureManager::DeviceEntry* |
| 515 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( | 516 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( |
| 516 const MediaStreamDevice& device_info) { | 517 const MediaStreamDevice& device_info) { |
| 517 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 518 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 518 | 519 |
| 519 for (DeviceEntries::iterator it = devices_.begin(); | 520 for (DeviceEntries::iterator it = devices_.begin(); |
| 520 it != devices_.end(); ++it) { | 521 it != devices_.end(); ++it) { |
| 521 DeviceEntry* device = *it; | 522 DeviceEntry* device = *it; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( | 615 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( |
| 615 media::VideoCaptureSessionId session_id, | 616 media::VideoCaptureSessionId session_id, |
| 616 gfx::NativeViewId window_id) { | 617 gfx::NativeViewId window_id) { |
| 617 DCHECK(IsOnDeviceThread()); | 618 DCHECK(IsOnDeviceThread()); |
| 618 DCHECK(notification_window_ids_.find(session_id) == | 619 DCHECK(notification_window_ids_.find(session_id) == |
| 619 notification_window_ids_.end()); | 620 notification_window_ids_.end()); |
| 620 notification_window_ids_[session_id] = window_id; | 621 notification_window_ids_[session_id] = window_id; |
| 621 } | 622 } |
| 622 | 623 |
| 623 } // namespace content | 624 } // namespace content |
| OLD | NEW |