Chromium Code Reviews| Index: content/browser/renderer_host/media/video_capture_manager.cc |
| diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc |
| index 00fa52e43eb0e366848c675ecf7bd44a6559dfe9..4061ba68e2c9f1652f888435c4f93cf2bf1c7a95 100644 |
| --- a/content/browser/renderer_host/media/video_capture_manager.cc |
| +++ b/content/browser/renderer_host/media/video_capture_manager.cc |
| @@ -11,6 +11,7 @@ |
| #include "base/logging.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/stl_util.h" |
| +#include "base/task_runner_util.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| #include "content/browser/renderer_host/media/video_capture_controller.h" |
| #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" |
| @@ -42,6 +43,16 @@ VideoCaptureManager::DeviceEntry::DeviceEntry( |
| VideoCaptureManager::DeviceEntry::~DeviceEntry() {} |
| +VideoCaptureManager::DeviceInfo::DeviceInfo() {} |
| + |
| +VideoCaptureManager::DeviceInfo::DeviceInfo( |
| + const media::VideoCaptureDevice::Name& name, |
| + const media::VideoCaptureFormats& supported_formats) |
| + : name(name), |
| + supported_formats(supported_formats) {} |
| + |
| +VideoCaptureManager::DeviceInfo::~DeviceInfo() {} |
| + |
| VideoCaptureManager::VideoCaptureManager() |
| : listener_(NULL), |
| new_capture_session_id_(1), |
| @@ -70,11 +81,17 @@ void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; |
| DCHECK(listener_); |
| + |
| base::PostTaskAndReplyWithResult( |
| - device_loop_, FROM_HERE, |
| - base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, this, |
| - stream_type), |
| - base::Bind(&VideoCaptureManager::OnDevicesEnumerated, this, stream_type)); |
| + device_loop_, |
| + FROM_HERE, |
| + base::Bind(&VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread, |
| + this, |
| + stream_type, |
| + devices_info_cache_), |
| + base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, |
| + this, |
| + stream_type)); |
| } |
| int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { |
| @@ -147,12 +164,11 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread( |
| // We look up the device id from the renderer in our local enumeration |
| // since the renderer does not have all the information that might be |
| // held in the browser-side VideoCaptureDevice::Name structure. |
| - media::VideoCaptureDevice::Name* found = |
| - video_capture_devices_.FindById(entry->id); |
| + DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_); |
| if (found) { |
| video_capture_device.reset(use_fake_device_ ? |
| - media::FakeVideoCaptureDevice::Create(*found) : |
| - media::VideoCaptureDevice::Create(*found)); |
| + media::FakeVideoCaptureDevice::Create(found->name) : |
| + media::VideoCaptureDevice::Create(found->name)); |
| } |
| break; |
| } |
| @@ -214,7 +230,6 @@ void VideoCaptureManager::StartCaptureForClient( |
| if (entry->video_capture_controller->GetClientCount() == 0) { |
| DVLOG(1) << "VideoCaptureManager starting device (type = " |
| << entry->stream_type << ", id = " << entry->id << ")"; |
| - |
| device_loop_->PostTask( |
| FROM_HERE, |
| base::Bind( |
| @@ -253,6 +268,35 @@ void VideoCaptureManager::StopCaptureForClient( |
| DestroyDeviceEntryIfNoClients(entry); |
| } |
| +void VideoCaptureManager::GetDeviceSupportedFormats( |
| + int capture_session_id, |
| + media::VideoCaptureFormats* supported_formats) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + supported_formats->clear(); |
| + |
| + std::map<int, MediaStreamDevice>::iterator it = |
| + sessions_.find(capture_session_id); |
| + DCHECK(it != sessions_.end()); |
| + DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name; |
| + |
| + DeviceInfo* device_in_use = |
| + FindDeviceInfoById(it->second.id, devices_info_cache_); |
| + DCHECK(device_in_use); |
|
scherkus (not reviewing)
2013/12/03 22:04:48
if you're DCHECK'ing this is non-null ... but then
mcasas
2013/12/04 15:23:32
Done.
|
| + if (device_in_use) { |
| + DeviceEntry* const existing_device = |
| + GetDeviceEntryForMediaStreamDevice(it->second); |
| + if (!existing_device) { |
| + // If the device is not in use, return all its cached supported formats. |
| + *supported_formats = device_in_use->supported_formats; |
| + return; |
| + } |
| + // Otherwise, get the video capture parameters in use from the controller |
| + // associated to the device. |
| + supported_formats->push_back( |
| + existing_device->video_capture_controller->GetVideoCaptureFormat()); |
| + } |
| +} |
| + |
| void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); |
| DCHECK(IsOnDeviceThread()); |
| @@ -282,24 +326,26 @@ void VideoCaptureManager::OnClosed(MediaStreamType stream_type, |
| listener_->Closed(stream_type, capture_session_id); |
| } |
| -void VideoCaptureManager::OnDevicesEnumerated( |
| +void VideoCaptureManager::OnDevicesInfoEnumerated( |
| MediaStreamType stream_type, |
| - const media::VideoCaptureDevice::Names& device_names) { |
| + const DeviceInfos& new_devices_info_cache) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - |
| - if (!listener_) { |
| - // Listener has been removed. |
| + DVLOG(1) << "OnDevicesInfoEnumerated, #new devices: " |
| + << new_devices_info_cache.size(); |
| + if (!listener_) { // Listener has been removed. |
| return; |
| } |
| + devices_info_cache_ = new_devices_info_cache; |
| - // Transform from VCD::Name to StreamDeviceInfo. |
| + // Walk the |devices_info_cache_| and transform from VCD::Name to |
| + // StreamDeviceInfo for return purposes. |
| StreamDeviceInfoArray devices; |
| - for (media::VideoCaptureDevice::Names::const_iterator it = |
| - device_names.begin(); it != device_names.end(); ++it) { |
| + for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); |
| + it != devices_info_cache_.end(); |
| + ++it) { |
| devices.push_back(StreamDeviceInfo( |
| - stream_type, it->GetNameAndModel(), it->id())); |
| + stream_type, it->name.GetNameAndModel(), it->name.id())); |
| } |
| - |
| listener_->DevicesEnumerated(stream_type, devices); |
| } |
| @@ -307,40 +353,64 @@ bool VideoCaptureManager::IsOnDeviceThread() const { |
| return device_loop_->BelongsToCurrentThread(); |
| } |
| -media::VideoCaptureDevice::Names |
| -VideoCaptureManager::GetAvailableDevicesOnDeviceThread( |
| - MediaStreamType stream_type) { |
| - SCOPED_UMA_HISTOGRAM_TIMER( |
| - "Media.VideoCaptureManager.GetAvailableDevicesTime"); |
| +VideoCaptureManager::DeviceInfos |
| +VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread( |
| + MediaStreamType stream_type, |
| + const DeviceInfos& old_device_info_cache) { |
| + SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager." |
| + "GetAvailableDevicesInfoOnDeviceThreadTime"); |
| DCHECK(IsOnDeviceThread()); |
| - media::VideoCaptureDevice::Names result; |
| - |
| + media::VideoCaptureDevice::Names names_snapshot; |
| switch (stream_type) { |
| case MEDIA_DEVICE_VIDEO_CAPTURE: |
| - // Cache the latest enumeration of video capture devices. |
| - // We'll refer to this list again in OnOpen to avoid having to |
| - // enumerate the devices again. |
| - if (!use_fake_device_) { |
| - media::VideoCaptureDevice::GetDeviceNames(&result); |
| - } else { |
| - media::FakeVideoCaptureDevice::GetDeviceNames(&result); |
| - } |
| - |
| - // TODO(nick): The correctness of device start depends on this cache being |
| - // maintained, but it seems a little odd to keep a cache here. Can we |
| - // eliminate it? |
| - video_capture_devices_ = result; |
| + if (!use_fake_device_) |
| + media::VideoCaptureDevice::GetDeviceNames(&names_snapshot); |
| + else |
| + media::FakeVideoCaptureDevice::GetDeviceNames(&names_snapshot); |
| break; |
| - |
| case MEDIA_DESKTOP_VIDEO_CAPTURE: |
| // Do nothing. |
| break; |
| - |
| default: |
| NOTREACHED(); |
| break; |
| } |
| - return result; |
| + |
| + // Construct |new_devices_info_cache| with the cached devices that are still |
| + // present in the system, and remove their names from |names_snapshot|, so we |
| + // keep there the truly new devices. |
| + DeviceInfos new_devices_info_cache; |
| + for (DeviceInfos::const_iterator it_device_info = |
| + old_device_info_cache.begin(); |
| + it_device_info != old_device_info_cache.end(); |
| + ++it_device_info) { |
| + media::VideoCaptureDevice::Names::iterator it; |
| + for (it = names_snapshot.begin(); it != names_snapshot.end(); ++it) { |
| + if (it_device_info->name.id() == it->id()) { |
| + new_devices_info_cache.push_back(*it_device_info); |
| + names_snapshot.erase(it); |
| + break; |
| + } |
| + } |
| + } |
| + |
| + // Get the supported capture formats for the new devices in |names_snapshot|. |
| + for (media::VideoCaptureDevice::Names::const_iterator it = |
| + names_snapshot.begin(); |
| + it != names_snapshot.end(); |
| + ++it) { |
| + media::VideoCaptureFormats supported_formats; |
| + DeviceInfo device_info(*it, media::VideoCaptureFormats()); |
| + if (!use_fake_device_) { |
| + media::VideoCaptureDevice::GetDeviceSupportedFormats( |
| + *it, &(device_info.supported_formats)); |
| + } else { |
| + media::FakeVideoCaptureDevice::GetDeviceSupportedFormats( |
| + *it, &(device_info.supported_formats)); |
| + } |
| + new_devices_info_cache.push_back(device_info); |
| + } |
| + return new_devices_info_cache; |
| } |
| VideoCaptureManager::DeviceEntry* |
| @@ -387,7 +457,8 @@ void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { |
| entry->video_capture_controller.reset(); |
| device_loop_->PostTask( |
| FROM_HERE, |
| - base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
| + base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, |
| + this, |
| base::Owned(entry))); |
| } |
| } |
| @@ -421,4 +492,15 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
| return new_device; |
| } |
| +VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById( |
| + const std::string& id, |
| + DeviceInfos& device_vector) { |
| + for (DeviceInfos::iterator it = device_vector.begin(); |
| + it != device_vector.end(); ++it) { |
| + if (it->name.id() == id) |
| + return &(*it); |
| + } |
| + return NULL; |
| +} |
| + |
| } // namespace content |