| 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 18a7f2b679b5d0bb899fbe573867c74d39460d7d..f85155f96787f1baee51cca2698f6971c565a321 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"
|
| @@ -39,6 +40,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),
|
| @@ -67,11 +78,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) {
|
| @@ -144,12 +161,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;
|
| }
|
| @@ -206,7 +222,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(
|
| @@ -245,6 +260,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);
|
| + 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());
|
| @@ -274,24 +318,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);
|
| }
|
|
|
| @@ -299,40 +345,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*
|
| @@ -379,7 +449,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)));
|
| }
|
| }
|
| @@ -413,4 +484,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
|
|
|