Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "media/video/capture/win/video_capture_device_factory_win.h" | 5 #include "media/video/capture/win/video_capture_device_factory_win.h" |
| 6 | 6 |
| 7 #include <mfapi.h> | 7 #include <mfapi.h> |
| 8 #include <mferror.h> | 8 #include <mferror.h> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/metrics/histogram.h" | |
| 12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 13 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 14 #include "base/win/metro.h" | 15 #include "base/win/metro.h" |
| 15 #include "base/win/scoped_co_mem.h" | 16 #include "base/win/scoped_co_mem.h" |
| 16 #include "base/win/scoped_variant.h" | 17 #include "base/win/scoped_variant.h" |
| 17 #include "base/win/windows_version.h" | 18 #include "base/win/windows_version.h" |
| 18 #include "media/base/media_switches.h" | 19 #include "media/base/media_switches.h" |
| 19 #include "media/video/capture/win/video_capture_device_mf_win.h" | 20 #include "media/video/capture/win/video_capture_device_mf_win.h" |
| 20 #include "media/video/capture/win/video_capture_device_win.h" | 21 #include "media/video/capture/win/video_capture_device_win.h" |
| 21 | 22 |
| 22 using base::win::ScopedCoMem; | 23 using base::win::ScopedCoMem; |
| 23 using base::win::ScopedComPtr; | 24 using base::win::ScopedComPtr; |
| 24 using base::win::ScopedVariant; | 25 using base::win::ScopedVariant; |
| 25 using Name = media::VideoCaptureDevice::Name; | 26 using Name = media::VideoCaptureDevice::Name; |
| 26 using Names = media::VideoCaptureDevice::Names; | 27 using Names = media::VideoCaptureDevice::Names; |
| 27 | 28 |
| 28 namespace media { | 29 namespace media { |
| 29 | 30 |
| 31 // We would like to avoid enumerating and/or using certain devices due to they | |
| 32 // provoking crashes or any other reason. This enum is defined for the purposes | |
| 33 // of UMA collection. Existing entries cannot be removed. | |
| 34 enum BlacklistedCameraNames{ | |
|
Alexei Svitkine (slow)
2014/10/14 15:18:45
Nit: Space before {.
mcasas
2014/10/15 07:25:09
Done.
| |
| 35 BLACKLISTED_CAMERA_GOOGLE_CAMERA_ADAPTER, | |
| 36 BLACKLISTED_CAMERA_IP_CAMERA, | |
| 37 BLACKLISTED_CAMERA_CYBERLINK_WEBCAM_SPLITTER, | |
| 38 BLACKLISTED_CAMERA_MAX // This one must be last. | |
| 39 }; | |
| 40 | |
| 30 // Lazy Instance to initialize the MediaFoundation Library. | 41 // Lazy Instance to initialize the MediaFoundation Library. |
| 31 class MFInitializerSingleton { | 42 class MFInitializerSingleton { |
| 32 public: | 43 public: |
| 33 MFInitializerSingleton() { MFStartup(MF_VERSION, MFSTARTUP_LITE); } | 44 MFInitializerSingleton() { MFStartup(MF_VERSION, MFSTARTUP_LITE); } |
| 34 ~MFInitializerSingleton() { MFShutdown(); } | 45 ~MFInitializerSingleton() { MFShutdown(); } |
| 35 }; | 46 }; |
| 36 | 47 |
| 37 static base::LazyInstance<MFInitializerSingleton> g_mf_initialize = | 48 static base::LazyInstance<MFInitializerSingleton> g_mf_initialize = |
| 38 LAZY_INSTANCE_INITIALIZER; | 49 LAZY_INSTANCE_INITIALIZER; |
| 39 | 50 |
| 51 // Blacklisted devices are identified by a characteristic prefix of the name. | |
| 52 // This prefix is used case-insensitively. | |
|
Alexei Svitkine (slow)
2014/10/14 15:18:45
Mention that this should be updated in sync with |
mcasas
2014/10/15 07:25:09
Done.
| |
| 53 static const char* kBlacklistedCameraNames[] = { | |
| 54 // Name of a fake DirectShow filter on computers with GTalk installed. | |
| 55 {"Google Camera Adapter"}, | |
| 56 // The following two software WebCams cause crashes. | |
| 57 {"IP Camera [JPEG/MJPEG]"}, | |
| 58 {"CyberLink Webcam Splitter"} | |
| 59 }; | |
| 60 | |
| 40 static void EnsureMediaFoundationInit() { | 61 static void EnsureMediaFoundationInit() { |
| 41 g_mf_initialize.Get(); | 62 g_mf_initialize.Get(); |
| 42 } | 63 } |
| 43 | 64 |
| 44 static bool LoadMediaFoundationDlls() { | 65 static bool LoadMediaFoundationDlls() { |
| 45 static const wchar_t* const kMfDLLs[] = { | 66 static const wchar_t* const kMfDLLs[] = { |
| 46 L"%WINDIR%\\system32\\mf.dll", | 67 L"%WINDIR%\\system32\\mf.dll", |
| 47 L"%WINDIR%\\system32\\mfplat.dll", | 68 L"%WINDIR%\\system32\\mfplat.dll", |
| 48 L"%WINDIR%\\system32\\mfreadwrite.dll", | 69 L"%WINDIR%\\system32\\mfreadwrite.dll", |
| 49 }; | 70 }; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 | 104 |
| 84 static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, | 105 static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, |
| 85 UINT32* count) { | 106 UINT32* count) { |
| 86 ScopedComPtr<IMFAttributes> attributes; | 107 ScopedComPtr<IMFAttributes> attributes; |
| 87 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) | 108 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) |
| 88 return false; | 109 return false; |
| 89 | 110 |
| 90 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); | 111 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); |
| 91 } | 112 } |
| 92 | 113 |
| 114 static bool IsDeviceBlackListed(const std::string& name) { | |
| 115 DCHECK_EQ(static_cast<int>(arraysize(kBlacklistedCameraNames)), | |
| 116 BLACKLISTED_CAMERA_MAX); | |
|
Alexei Svitkine (slow)
2014/10/14 15:18:45
Nit: Expected value should be the first arg, so sw
mcasas
2014/10/15 07:25:09
Done.
| |
| 117 for (size_t i = 0; i < arraysize(kBlacklistedCameraNames); ++i) { | |
| 118 if (StartsWithASCII(name, kBlacklistedCameraNames[i], false)) { | |
| 119 DVLOG(1) << "Enumerated blacklisted device: " << name; | |
| 120 UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.BlacklistedDevice", | |
| 121 i, BLACKLISTED_CAMERA_MAX + 1); | |
|
Alexei Svitkine (slow)
2014/10/14 15:18:45
Remove "+ 1" from the last param, since it's alrea
mcasas
2014/10/15 07:25:09
Presubmit.py complained:
** Presubmit ERRORS **
U
Alexei Svitkine (slow)
2014/10/15 14:00:50
Sigh, it's because media code expects the MAX valu
| |
| 122 return true; | |
| 123 } | |
| 124 } | |
| 125 return false; | |
| 126 } | |
| 127 | |
| 93 static void GetDeviceNamesDirectShow( | 128 static void GetDeviceNamesDirectShow( |
| 94 const CLSID& class_id, | 129 const CLSID& class_id, |
| 95 const Name::CaptureApiType capture_api_type, | 130 const Name::CaptureApiType capture_api_type, |
| 96 Names* device_names) { | 131 Names* device_names) { |
| 97 DCHECK(device_names); | 132 DCHECK(device_names); |
| 98 DVLOG(1) << " GetDeviceNamesDirectShow"; | 133 DVLOG(1) << " GetDeviceNamesDirectShow"; |
| 99 | 134 |
| 100 ScopedComPtr<ICreateDevEnum> dev_enum; | 135 ScopedComPtr<ICreateDevEnum> dev_enum; |
| 101 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, | 136 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
| 102 CLSCTX_INPROC); | 137 CLSCTX_INPROC); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 121 | 156 |
| 122 // Find the description or friendly name. | 157 // Find the description or friendly name. |
| 123 ScopedVariant name; | 158 ScopedVariant name; |
| 124 hr = prop_bag->Read(L"Description", name.Receive(), 0); | 159 hr = prop_bag->Read(L"Description", name.Receive(), 0); |
| 125 if (FAILED(hr)) | 160 if (FAILED(hr)) |
| 126 hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0); | 161 hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0); |
| 127 | 162 |
| 128 if (FAILED(hr) || name.type() != VT_BSTR) | 163 if (FAILED(hr) || name.type() != VT_BSTR) |
| 129 continue; | 164 continue; |
| 130 | 165 |
| 131 // Ignore all VFW drivers and the special Google Camera Adapter. | 166 const std::string device_name(base::SysWideToUTF8(V_BSTR(&name))); |
| 132 // Google Camera Adapter is not a real DirectShow camera device. | 167 if (IsDeviceBlackListed(device_name)) |
| 133 // VFW are very old Video for Windows drivers that can not be used. | |
| 134 const wchar_t* str_ptr = V_BSTR(&name); | |
| 135 // Name of a fake DirectShow filter that exist on computers with | |
| 136 // GTalk installed. | |
| 137 static const char kGoogleCameraAdapter[] = "google camera adapter"; | |
| 138 if (wcsstr(str_ptr, L"(VFW)") != NULL || | |
| 139 LowerCaseEqualsASCII(str_ptr, | |
| 140 str_ptr + arraysize(kGoogleCameraAdapter) - 1, | |
| 141 kGoogleCameraAdapter)) { | |
| 142 continue; | 168 continue; |
| 143 } | |
| 144 | 169 |
| 145 const std::string device_name(base::SysWideToUTF8(str_ptr)); | |
| 146 name.Reset(); | 170 name.Reset(); |
| 147 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); | 171 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); |
| 148 std::string id; | 172 std::string id; |
| 149 if (FAILED(hr) || name.type() != VT_BSTR) { | 173 if (FAILED(hr) || name.type() != VT_BSTR) { |
| 150 id = device_name; | 174 id = device_name; |
| 151 } else { | 175 } else { |
| 152 DCHECK_EQ(name.type(), VT_BSTR); | 176 DCHECK_EQ(name.type(), VT_BSTR); |
| 153 id = base::SysWideToUTF8(V_BSTR(&name)); | 177 id = base::SysWideToUTF8(V_BSTR(&name)); |
| 154 } | 178 } |
| 155 device_names->push_back(Name(device_name, id, capture_api_type)); | 179 device_names->push_back(Name(device_name, id, capture_api_type)); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 const Name& device, | 451 const Name& device, |
| 428 VideoCaptureFormats* formats) { | 452 VideoCaptureFormats* formats) { |
| 429 DCHECK(thread_checker_.CalledOnValidThread()); | 453 DCHECK(thread_checker_.CalledOnValidThread()); |
| 430 if (use_media_foundation_) | 454 if (use_media_foundation_) |
| 431 GetDeviceSupportedFormatsMediaFoundation(device, formats); | 455 GetDeviceSupportedFormatsMediaFoundation(device, formats); |
| 432 else | 456 else |
| 433 GetDeviceSupportedFormatsDirectShow(device, formats); | 457 GetDeviceSupportedFormatsDirectShow(device, formats); |
| 434 } | 458 } |
| 435 | 459 |
| 436 } // namespace media | 460 } // namespace media |
| OLD | NEW |