Chromium Code Reviews| 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..0db7e65fa381bd8580669f920ae90887bf49dc19 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,9 @@ static bool IsDeviceBlackListed(const std::string& name) { |
| return false; |
| } |
| -static void GetDeviceNamesDirectShow(Names* device_names) { |
| - DCHECK(device_names); |
| - DVLOG(1) << " GetDeviceNamesDirectShow"; |
| +static void GetDeviceDescriptorsDirectShow(Descriptors* device_descriptors) { |
| + DCHECK(device_descriptors); |
| + DVLOG(1) << " GetDeviceDescriptorsDirectShow"; |
|
emircan
2016/07/25 22:56:40
Replace hard coded function names with __FUNCTION_
chfremer
2016/07/26 16:56:35
Done.
|
| ScopedComPtr<ICreateDevEnum> dev_enum; |
| HRESULT hr = |
| @@ -171,12 +175,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)); |
| + Descriptor descriptor; |
| + descriptor.device_id = id; |
| + descriptor.friendly_name = device_name; |
| + descriptor.capture_api = VideoCaptureApiType::WINDOWS_DIRECT_SHOW; |
| + device_descriptors->push_back(descriptor); |
|
emircan
2016/07/25 22:56:40
Use std::list::emplace_back to avoid extra copy.
chfremer
2016/07/26 16:56:35
Done.
|
| } |
| } |
| -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 +203,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)); |
| + Descriptor descriptor; |
| + descriptor.friendly_name = |
| + base::SysWideToUTF8(std::wstring(name, name_size)); |
| + descriptor.device_id = base::SysWideToUTF8(std::wstring(id, id_size)); |
| + descriptor.capture_api = VideoCaptureApiType::WINDOWS_MEDIA_FOUNDATION; |
| + device_descriptors->push_back(descriptor); |
| } |
| } |
| DLOG_IF(ERROR, FAILED(hr)) << "GetAllocatedString failed: " |
| @@ -206,9 +217,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.friendly_name; |
| ScopedComPtr<ICreateDevEnum> dev_enum; |
| HRESULT hr = |
| dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC); |
| @@ -227,7 +239,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 +300,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.friendly_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.friendly_name; |
| ScopedComPtr<IMFMediaSource> source; |
| - if (!CreateVideoCaptureDeviceMediaFoundation(device.id().c_str(), |
| + if (!CreateVideoCaptureDeviceMediaFoundation(descriptor.device_id.c_str(), |
| source.Receive())) { |
| return; |
| } |
| @@ -349,7 +363,7 @@ static void GetDeviceSupportedFormatsMediaFoundation( |
| formats->push_back(capture_format); |
| ++stream_index; |
| - DVLOG(1) << device.name() << " " |
| + DVLOG(1) << descriptor.friendly_name << " " |
| << VideoCaptureFormat::ToString(capture_format); |
| } |
| } |
| @@ -377,46 +391,84 @@ VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin() |
| switches::kForceMediaFoundationVideoCapture)) {} |
| std::unique_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create( |
| - const Name& device_name) { |
| + 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 == |
| + VideoCaptureApiType::WINDOWS_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.friendly_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 == |
| + VideoCaptureApiType::WINDOWS_DIRECT_SHOW) { |
| + device.reset(new VideoCaptureDeviceWin(device_descriptor)); |
| + DVLOG(1) << " DirectShow Device: " << device_descriptor.friendly_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::GetDeviceInfo( |
| + const VideoCaptureDeviceDescriptor& device_descriptor, |
| + VideoCaptureDeviceInfo* device_info) { |
| + DCHECK(device_info); |
| + device_info->descriptor = device_descriptor; |
| + GetDeviceSupportedFormats(device_descriptor, |
| + &(device_info->supported_formats)); |
| + device_info->model_id = GetDeviceModelId(device_descriptor); |
| } |
| void VideoCaptureDeviceFactoryWin::GetDeviceSupportedFormats( |
| - const Name& device, |
| + const Descriptor& device, |
| VideoCaptureFormats* formats) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - if (use_media_foundation_) |
| + if (use_media_foundation_) { |
| GetDeviceSupportedFormatsMediaFoundation(device, formats); |
| - else |
| + } else { |
| GetDeviceSupportedFormatsDirectShow(device, formats); |
| + } |
| +} |
| + |
| +std::string VideoCaptureDeviceFactoryWin::GetDeviceModelId( |
| + const Descriptor& device_descriptor) { |
| + const size_t vid_prefix_size = sizeof(kVidPrefix) - 1; |
| + const size_t pid_prefix_size = sizeof(kPidPrefix) - 1; |
| + const size_t vid_location = device_descriptor.device_id.find(kVidPrefix); |
| + if (vid_location == std::string::npos || |
| + vid_location + vid_prefix_size + kVidPidSize > |
| + device_descriptor.device_id.size()) { |
| + return std::string(); |
| + } |
| + const size_t pid_location = device_descriptor.device_id.find(kPidPrefix); |
| + if (pid_location == std::string::npos || |
| + pid_location + pid_prefix_size + kVidPidSize > |
| + device_descriptor.device_id.size()) { |
| + return std::string(); |
| + } |
| + std::string id_vendor = device_descriptor.device_id.substr( |
|
emircan
2016/07/25 22:56:40
const
chfremer
2016/07/26 16:56:35
Done.
|
| + vid_location + vid_prefix_size, kVidPidSize); |
| + std::string id_product = device_descriptor.device_id.substr( |
|
emircan
2016/07/25 22:56:40
const
chfremer
2016/07/26 16:56:35
Done.
|
| + pid_location + pid_prefix_size, kVidPidSize); |
| + return id_vendor + ":" + id_product; |
| } |
| // static |