Index: media/capture/video/win/video_capture_device_factory_win.cc |
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc |
index 3c3bf3155fa1df27c944557ca181468d34901295..7f4c7a0225e968cabef934a3948afec1c47769f0 100644 |
--- a/media/capture/video/win/video_capture_device_factory_win.cc |
+++ b/media/capture/video/win/video_capture_device_factory_win.cc |
@@ -24,11 +24,17 @@ |
using base::win::ScopedCoMem; |
using base::win::ScopedComPtr; |
using base::win::ScopedVariant; |
-using Name = media::VideoCaptureDevice::Name; |
-using Names = media::VideoCaptureDevice::Names; |
+using Descriptor = media::VideoCaptureDeviceDescriptor; |
+using Descriptors = media::VideoCaptureDeviceDescriptors; |
namespace media { |
+// In Windows device identifiers, the USB VID and PID are preceded by the string |
+// "vid_" or "pid_". The identifiers are each 4 bytes long. |
+const char kVidPrefix[] = "vid_"; // Also contains '\0'. |
+const char kPidPrefix[] = "pid_"; // Also contains '\0'. |
+const size_t kVidPidSize = 4; |
+ |
// Avoid enumerating and/or using certain devices due to they provoking crashes |
// or any other reason (http://crbug.com/378494). This enum is defined for the |
// purposes of UMA collection. Existing entries cannot be removed. |
@@ -48,9 +54,7 @@ static const char* const kBlacklistedCameraNames[] = { |
// Name of a fake DirectShow filter on computers with GTalk installed. |
"Google Camera Adapter", |
// The following software WebCams cause crashes. |
- "IP Camera [JPEG/MJPEG]", |
- "CyberLink Webcam Splitter", |
- "EpocCam", |
+ "IP Camera [JPEG/MJPEG]", "CyberLink Webcam Splitter", "EpocCam", |
}; |
static_assert(arraysize(kBlacklistedCameraNames) == BLACKLISTED_CAMERA_MAX + 1, |
"kBlacklistedCameraNames should be same size as " |
@@ -122,9 +126,29 @@ static bool IsDeviceBlackListed(const std::string& name) { |
return false; |
} |
-static void GetDeviceNamesDirectShow(Names* device_names) { |
- DCHECK(device_names); |
- DVLOG(1) << " GetDeviceNamesDirectShow"; |
+static std::string GetDeviceModelId(const std::string& device_id) { |
+ const size_t vid_prefix_size = sizeof(kVidPrefix) - 1; |
+ const size_t pid_prefix_size = sizeof(kPidPrefix) - 1; |
+ const size_t vid_location = device_id.find(kVidPrefix); |
+ if (vid_location == std::string::npos || |
+ vid_location + vid_prefix_size + kVidPidSize > device_id.size()) { |
+ return std::string(); |
+ } |
+ const size_t pid_location = device_id.find(kPidPrefix); |
+ if (pid_location == std::string::npos || |
+ pid_location + pid_prefix_size + kVidPidSize > device_id.size()) { |
+ return std::string(); |
+ } |
+ const std::string id_vendor = |
+ device_id.substr(vid_location + vid_prefix_size, kVidPidSize); |
+ const std::string id_product = |
+ device_id.substr(pid_location + pid_prefix_size, kVidPidSize); |
+ return id_vendor + ":" + id_product; |
+} |
+ |
+static void GetDeviceDescriptorsDirectShow(Descriptors* device_descriptors) { |
+ DCHECK(device_descriptors); |
+ DVLOG(1) << __FUNCTION__; |
ScopedComPtr<ICreateDevEnum> dev_enum; |
HRESULT hr = |
@@ -171,12 +195,17 @@ static void GetDeviceNamesDirectShow(Names* device_names) { |
DCHECK_EQ(name.type(), VT_BSTR); |
id = base::SysWideToUTF8(V_BSTR(name.ptr())); |
} |
- device_names->push_back(Name(device_name, id, Name::DIRECT_SHOW)); |
+ |
+ const std::string model_id = GetDeviceModelId(id); |
+ |
+ device_descriptors->emplace_back(device_name, id, model_id, |
+ VideoCaptureApi::WIN_DIRECT_SHOW); |
} |
} |
-static void GetDeviceNamesMediaFoundation(Names* device_names) { |
- DVLOG(1) << " GetDeviceNamesMediaFoundation"; |
+static void GetDeviceDescriptorsMediaFoundation( |
+ Descriptors* device_descriptors) { |
+ DVLOG(1) << " GetDeviceDescriptorsMediaFoundation"; |
ScopedCoMem<IMFActivate*> devices; |
UINT32 count; |
if (!EnumerateVideoDevicesMediaFoundation(&devices, &count)) |
@@ -194,10 +223,12 @@ static void GetDeviceNamesMediaFoundation(Names* device_names) { |
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &id, |
&id_size); |
if (SUCCEEDED(hr)) { |
- device_names->push_back( |
- Name(base::SysWideToUTF8(std::wstring(name, name_size)), |
- base::SysWideToUTF8(std::wstring(id, id_size)), |
- Name::MEDIA_FOUNDATION)); |
+ const std::string device_id = |
+ base::SysWideToUTF8(std::wstring(id, id_size)); |
+ const std::string model_id = GetDeviceModelId(device_id); |
+ device_descriptors->emplace_back( |
+ base::SysWideToUTF8(std::wstring(name, name_size)), device_id, |
+ model_id, VideoCaptureApi::WIN_MEDIA_FOUNDATION); |
} |
} |
DLOG_IF(ERROR, FAILED(hr)) << "GetAllocatedString failed: " |
@@ -206,9 +237,10 @@ static void GetDeviceNamesMediaFoundation(Names* device_names) { |
} |
} |
-static void GetDeviceSupportedFormatsDirectShow(const Name& device, |
+static void GetDeviceSupportedFormatsDirectShow(const Descriptor& descriptor, |
VideoCaptureFormats* formats) { |
- DVLOG(1) << "GetDeviceSupportedFormatsDirectShow for " << device.name(); |
+ DVLOG(1) << "GetDeviceSupportedFormatsDirectShow for " |
+ << descriptor.display_name; |
ScopedComPtr<ICreateDevEnum> dev_enum; |
HRESULT hr = |
dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC); |
@@ -227,7 +259,7 @@ static void GetDeviceSupportedFormatsDirectShow(const Name& device, |
// that is anyway needed in GetDeviceFilter(). "google camera adapter" and old |
// VFW devices are already skipped previously in GetDeviceNames() enumeration. |
base::win::ScopedComPtr<IBaseFilter> capture_filter; |
- hr = VideoCaptureDeviceWin::GetDeviceFilter(device.capabilities_id(), |
+ hr = VideoCaptureDeviceWin::GetDeviceFilter(descriptor.device_id, |
capture_filter.Receive()); |
if (!capture_filter.get()) { |
DLOG(ERROR) << "Failed to create capture filter: " |
@@ -288,17 +320,19 @@ static void GetDeviceSupportedFormatsDirectShow(const Name& device, |
? kSecondsToReferenceTime / static_cast<float>(h->AvgTimePerFrame) |
: 0.0f; |
formats->push_back(format); |
- DVLOG(1) << device.name() << " " << VideoCaptureFormat::ToString(format); |
+ DVLOG(1) << descriptor.display_name << " " |
+ << VideoCaptureFormat::ToString(format); |
} |
} |
} |
static void GetDeviceSupportedFormatsMediaFoundation( |
- const Name& device, |
+ const Descriptor& descriptor, |
VideoCaptureFormats* formats) { |
- DVLOG(1) << "GetDeviceSupportedFormatsMediaFoundation for " << device.name(); |
+ DVLOG(1) << "GetDeviceSupportedFormatsMediaFoundation for " |
+ << descriptor.display_name; |
ScopedComPtr<IMFMediaSource> source; |
- if (!CreateVideoCaptureDeviceMediaFoundation(device.id().c_str(), |
+ if (!CreateVideoCaptureDeviceMediaFoundation(descriptor.device_id.c_str(), |
source.Receive())) { |
return; |
} |
@@ -349,7 +383,7 @@ static void GetDeviceSupportedFormatsMediaFoundation( |
formats->push_back(capture_format); |
++stream_index; |
- DVLOG(1) << device.name() << " " |
+ DVLOG(1) << descriptor.display_name << " " |
<< VideoCaptureFormat::ToString(capture_format); |
} |
} |
@@ -376,41 +410,44 @@ VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin() |
base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kForceMediaFoundationVideoCapture)) {} |
-std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create( |
- const Name& device_name) { |
+std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::CreateDevice( |
+ const Descriptor& device_descriptor) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
std::unique_ptr<VideoCaptureDevice> device; |
- if (device_name.capture_api_type() == Name::MEDIA_FOUNDATION) { |
+ if (device_descriptor.capture_api == VideoCaptureApi::WIN_MEDIA_FOUNDATION) { |
DCHECK(PlatformSupportsMediaFoundation()); |
- device.reset(new VideoCaptureDeviceMFWin(device_name)); |
- DVLOG(1) << " MediaFoundation Device: " << device_name.name(); |
+ device.reset(new VideoCaptureDeviceMFWin(device_descriptor)); |
+ DVLOG(1) << " MediaFoundation Device: " << device_descriptor.display_name; |
ScopedComPtr<IMFMediaSource> source; |
- if (!CreateVideoCaptureDeviceMediaFoundation(device_name.id().c_str(), |
- source.Receive())) { |
+ if (!CreateVideoCaptureDeviceMediaFoundation( |
+ device_descriptor.device_id.c_str(), source.Receive())) { |
return std::unique_ptr<VideoCaptureDevice>(); |
} |
if (!static_cast<VideoCaptureDeviceMFWin*>(device.get())->Init(source)) |
device.reset(); |
- } else { |
- DCHECK(device_name.capture_api_type() == Name::DIRECT_SHOW); |
- device.reset(new VideoCaptureDeviceWin(device_name)); |
- DVLOG(1) << " DirectShow Device: " << device_name.name(); |
+ } else if (device_descriptor.capture_api == |
+ VideoCaptureApi::WIN_DIRECT_SHOW) { |
+ device.reset(new VideoCaptureDeviceWin(device_descriptor)); |
+ DVLOG(1) << " DirectShow Device: " << device_descriptor.display_name; |
if (!static_cast<VideoCaptureDeviceWin*>(device.get())->Init()) |
device.reset(); |
+ } else { |
+ NOTREACHED(); |
} |
return device; |
} |
-void VideoCaptureDeviceFactoryWin::GetDeviceNames(Names* device_names) { |
+void VideoCaptureDeviceFactoryWin::GetDeviceDescriptors( |
+ VideoCaptureDeviceDescriptors* device_descriptors) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (use_media_foundation_) |
- GetDeviceNamesMediaFoundation(device_names); |
+ GetDeviceDescriptorsMediaFoundation(device_descriptors); |
else |
- GetDeviceNamesDirectShow(device_names); |
+ GetDeviceDescriptorsDirectShow(device_descriptors); |
} |
-void VideoCaptureDeviceFactoryWin::GetDeviceSupportedFormats( |
- const Name& device, |
+void VideoCaptureDeviceFactoryWin::GetSupportedFormats( |
+ const Descriptor& device, |
VideoCaptureFormats* formats) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (use_media_foundation_) |