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 // Some devices cause crashes when trying to be enumerated. This enum is defined | |
32 // for the purposes of UMA collection. Existing entries cannot be removed. | |
33 enum BlacklistedCameraNames{ | |
34 BLACKLISTED_CAMERA_IP_CAMERA, | |
35 BLACKLISTED_CAMERA_CYBERLINK_WEBCAM_SPLITTER, | |
36 BLACKLISTED_CAMERA_MAX // This one must be last. | |
37 }; | |
38 | |
30 // Lazy Instance to initialize the MediaFoundation Library. | 39 // Lazy Instance to initialize the MediaFoundation Library. |
31 class MFInitializerSingleton { | 40 class MFInitializerSingleton { |
32 public: | 41 public: |
33 MFInitializerSingleton() { MFStartup(MF_VERSION, MFSTARTUP_LITE); } | 42 MFInitializerSingleton() { MFStartup(MF_VERSION, MFSTARTUP_LITE); } |
34 ~MFInitializerSingleton() { MFShutdown(); } | 43 ~MFInitializerSingleton() { MFShutdown(); } |
35 }; | 44 }; |
36 | 45 |
37 static base::LazyInstance<MFInitializerSingleton> g_mf_initialize = | 46 static base::LazyInstance<MFInitializerSingleton> g_mf_initialize = |
38 LAZY_INSTANCE_INITIALIZER; | 47 LAZY_INSTANCE_INITIALIZER; |
39 | 48 |
49 // Blacklisted devices are identified by a characteristic substring of the name. | |
50 static const char* kBlacklistedCameraNames[] = { | |
51 {"IP Camera [JPEG/MJPEG]" }, | |
tommi (sloooow) - chröme
2014/10/12 09:46:03
nit: no space before } (for consistency)
mcasas
2014/10/12 14:45:39
Done.
| |
52 {"CyberLink Webcam Splitter"} | |
tommi (sloooow) - chröme
2014/10/12 09:46:03
Can you point me to a report where we encountered
mcasas
2014/10/12 14:45:39
Sure, there are a few in the other bug linked to t
| |
53 }; | |
54 | |
40 static void EnsureMediaFoundationInit() { | 55 static void EnsureMediaFoundationInit() { |
41 g_mf_initialize.Get(); | 56 g_mf_initialize.Get(); |
42 } | 57 } |
43 | 58 |
44 static bool LoadMediaFoundationDlls() { | 59 static bool LoadMediaFoundationDlls() { |
45 static const wchar_t* const kMfDLLs[] = { | 60 static const wchar_t* const kMfDLLs[] = { |
46 L"%WINDIR%\\system32\\mf.dll", | 61 L"%WINDIR%\\system32\\mf.dll", |
47 L"%WINDIR%\\system32\\mfplat.dll", | 62 L"%WINDIR%\\system32\\mfplat.dll", |
48 L"%WINDIR%\\system32\\mfreadwrite.dll", | 63 L"%WINDIR%\\system32\\mfreadwrite.dll", |
49 }; | 64 }; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 | 98 |
84 static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, | 99 static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, |
85 UINT32* count) { | 100 UINT32* count) { |
86 ScopedComPtr<IMFAttributes> attributes; | 101 ScopedComPtr<IMFAttributes> attributes; |
87 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) | 102 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) |
88 return false; | 103 return false; |
89 | 104 |
90 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); | 105 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); |
91 } | 106 } |
92 | 107 |
108 static bool IsDeviceBlackListed(const std::string& name) { | |
109 DCHECK_EQ(static_cast<int>(arraysize(kBlacklistedCameraNames)), | |
110 BLACKLISTED_CAMERA_MAX); | |
111 for (size_t i = 0; i < arraysize(kBlacklistedCameraNames); ++i) { | |
112 if (name.find (kBlacklistedCameraNames[i]) != std::string::npos) { | |
tommi (sloooow) - chröme
2014/10/12 09:46:03
no space before (
What about StartsWith? (string_
mcasas
2014/10/12 14:45:39
Done.
| |
113 DVLOG(1) << "Enumerated blacklisted device: " << name; | |
114 UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.BlacklistedDevice", | |
115 i, BLACKLISTED_CAMERA_MAX + 1); | |
116 return true; | |
117 } | |
118 } | |
119 return false; | |
120 } | |
121 | |
93 static void GetDeviceNamesDirectShow( | 122 static void GetDeviceNamesDirectShow( |
94 const CLSID& class_id, | 123 const CLSID& class_id, |
95 const Name::CaptureApiType capture_api_type, | 124 const Name::CaptureApiType capture_api_type, |
96 Names* device_names) { | 125 Names* device_names) { |
97 DCHECK(device_names); | 126 DCHECK(device_names); |
98 DVLOG(1) << " GetDeviceNamesDirectShow"; | 127 DVLOG(1) << " GetDeviceNamesDirectShow"; |
99 | 128 |
100 ScopedComPtr<ICreateDevEnum> dev_enum; | 129 ScopedComPtr<ICreateDevEnum> dev_enum; |
101 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, | 130 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
102 CLSCTX_INPROC); | 131 CLSCTX_INPROC); |
(...skipping 24 matching lines...) Expand all Loading... | |
127 | 156 |
128 if (FAILED(hr) || name.type() != VT_BSTR) | 157 if (FAILED(hr) || name.type() != VT_BSTR) |
129 continue; | 158 continue; |
130 | 159 |
131 // Ignore all VFW drivers and the special Google Camera Adapter. | 160 // Ignore all VFW drivers and the special Google Camera Adapter. |
132 // Google Camera Adapter is not a real DirectShow camera device. | 161 // Google Camera Adapter is not a real DirectShow camera device. |
133 // VFW are very old Video for Windows drivers that can not be used. | 162 // VFW are very old Video for Windows drivers that can not be used. |
134 const wchar_t* str_ptr = V_BSTR(&name); | 163 const wchar_t* str_ptr = V_BSTR(&name); |
135 // Name of a fake DirectShow filter that exist on computers with | 164 // Name of a fake DirectShow filter that exist on computers with |
136 // GTalk installed. | 165 // GTalk installed. |
137 static const char kGoogleCameraAdapter[] = "google camera adapter"; | 166 static const char kGoogleCameraAdapter[] = "google camera adapter"; |
tommi (sloooow) - chröme
2014/10/12 09:46:03
What about moving this into the blacklist now that
mcasas
2014/10/12 14:45:39
Done, moved "google camera adapter" to the blackli
| |
138 if (wcsstr(str_ptr, L"(VFW)") != NULL || | 167 if (wcsstr(str_ptr, L"(VFW)") != NULL || |
139 LowerCaseEqualsASCII(str_ptr, | 168 LowerCaseEqualsASCII(str_ptr, |
140 str_ptr + arraysize(kGoogleCameraAdapter) - 1, | 169 str_ptr + arraysize(kGoogleCameraAdapter) - 1, |
141 kGoogleCameraAdapter)) { | 170 kGoogleCameraAdapter)) { |
142 continue; | 171 continue; |
143 } | 172 } |
144 | 173 |
145 const std::string device_name(base::SysWideToUTF8(str_ptr)); | 174 const std::string device_name(base::SysWideToUTF8(str_ptr)); |
175 if (IsDeviceBlackListed(device_name)) | |
176 continue; | |
146 name.Reset(); | 177 name.Reset(); |
147 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); | 178 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); |
148 std::string id; | 179 std::string id; |
149 if (FAILED(hr) || name.type() != VT_BSTR) { | 180 if (FAILED(hr) || name.type() != VT_BSTR) { |
150 id = device_name; | 181 id = device_name; |
151 } else { | 182 } else { |
152 DCHECK_EQ(name.type(), VT_BSTR); | 183 DCHECK_EQ(name.type(), VT_BSTR); |
153 id = base::SysWideToUTF8(V_BSTR(&name)); | 184 id = base::SysWideToUTF8(V_BSTR(&name)); |
154 } | 185 } |
155 device_names->push_back(Name(device_name, id, capture_api_type)); | 186 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, | 458 const Name& device, |
428 VideoCaptureFormats* formats) { | 459 VideoCaptureFormats* formats) { |
429 DCHECK(thread_checker_.CalledOnValidThread()); | 460 DCHECK(thread_checker_.CalledOnValidThread()); |
430 if (use_media_foundation_) | 461 if (use_media_foundation_) |
431 GetDeviceSupportedFormatsMediaFoundation(device, formats); | 462 GetDeviceSupportedFormatsMediaFoundation(device, formats); |
432 else | 463 else |
433 GetDeviceSupportedFormatsDirectShow(device, formats); | 464 GetDeviceSupportedFormatsDirectShow(device, formats); |
434 } | 465 } |
435 | 466 |
436 } // namespace media | 467 } // namespace media |
OLD | NEW |