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" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 UINT32* count) { | 85 UINT32* count) { |
86 ScopedComPtr<IMFAttributes> attributes; | 86 ScopedComPtr<IMFAttributes> attributes; |
87 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) | 87 if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) |
88 return false; | 88 return false; |
89 | 89 |
90 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); | 90 return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count)); |
91 } | 91 } |
92 | 92 |
93 static void GetDeviceNamesDirectShow(Names* device_names) { | 93 static void GetDeviceNamesDirectShow(Names* device_names) { |
94 DCHECK(device_names); | 94 DCHECK(device_names); |
95 DCHECK(device_names->empty()); | |
95 DVLOG(1) << " GetDeviceNamesDirectShow"; | 96 DVLOG(1) << " GetDeviceNamesDirectShow"; |
96 | 97 |
97 ScopedComPtr<ICreateDevEnum> dev_enum; | 98 ScopedComPtr<ICreateDevEnum> dev_enum; |
98 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, | 99 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
99 CLSCTX_INPROC); | 100 CLSCTX_INPROC); |
100 if (FAILED(hr)) | 101 if (FAILED(hr)) |
101 return; | 102 return; |
102 | 103 |
103 static const struct{ | 104 static const struct{ |
104 CLSID class_id; | 105 CLSID class_id; |
105 Name::CaptureApiType capture_api_type; | 106 Name::CaptureApiType capture_api_type; |
106 } kDirectShowFilterClasses[] = { | 107 } kDirectShowFilterClasses[] = { |
107 { CLSID_VideoInputDeviceCategory, Name::DIRECT_SHOW }, | 108 { CLSID_VideoInputDeviceCategory, Name::DIRECT_SHOW }, |
108 { AM_KSCATEGORY_CROSSBAR, Name::DIRECT_SHOW_WDM} | 109 { AM_KSCATEGORY_CROSSBAR, Name::DIRECT_SHOW_WDM} // Must be the last entry. |
perkj_chrome
2014/09/02 09:22:03
http://msdn.microsoft.com/en-us/library/windows/de
mcasas
2014/09/02 15:13:41
Done.
| |
109 }; | 110 }; |
110 | 111 |
111 | |
112 device_names->clear(); | |
113 for (int class_index = 0; class_index < arraysize(kDirectShowFilterClasses); | 112 for (int class_index = 0; class_index < arraysize(kDirectShowFilterClasses); |
perkj_chrome
2014/09/02 09:22:03
instead of a for loop- would it make sence to put
mcasas
2014/09/02 15:13:41
Done.
| |
114 ++class_index) { | 113 ++class_index) { |
115 ScopedComPtr<IEnumMoniker> enum_moniker; | 114 ScopedComPtr<IEnumMoniker> enum_moniker; |
116 hr = dev_enum->CreateClassEnumerator( | 115 hr = dev_enum->CreateClassEnumerator( |
117 kDirectShowFilterClasses[class_index].class_id, | 116 kDirectShowFilterClasses[class_index].class_id, |
118 enum_moniker.Receive(), | 117 enum_moniker.Receive(), |
119 0); | 118 0); |
120 // CreateClassEnumerator returns S_FALSE on some Windows OS | 119 // CreateClassEnumerator returns S_FALSE on some Windows OS |
121 // when no camera exist. Therefore the FAILED macro can't be used. | 120 // when no camera exist. Therefore the FAILED macro can't be used. |
122 if (hr != S_OK) | 121 if (hr != S_OK) |
123 continue; | 122 continue; |
(...skipping 20 matching lines...) Expand all Loading... | |
144 if (FAILED(hr)) | 143 if (FAILED(hr)) |
145 hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0); | 144 hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0); |
146 | 145 |
147 if (SUCCEEDED(hr) && name.type() == VT_BSTR) { | 146 if (SUCCEEDED(hr) && name.type() == VT_BSTR) { |
148 // Ignore all VFW drivers and the special Google Camera Adapter. | 147 // Ignore all VFW drivers and the special Google Camera Adapter. |
149 // Google Camera Adapter is not a real DirectShow camera device. | 148 // Google Camera Adapter is not a real DirectShow camera device. |
150 // VFW are very old Video for Windows drivers that can not be used. | 149 // VFW are very old Video for Windows drivers that can not be used. |
151 const wchar_t* str_ptr = V_BSTR(&name); | 150 const wchar_t* str_ptr = V_BSTR(&name); |
152 const int name_length = arraysize(kGoogleCameraAdapter) - 1; | 151 const int name_length = arraysize(kGoogleCameraAdapter) - 1; |
153 | 152 |
154 if ((wcsstr(str_ptr, L"(VFW)") == NULL) && | 153 if ((wcsstr(str_ptr, L"(VFW)") == NULL) && |
magjed_chromium
2014/09/02 15:14:41
These parentheses are wrong. && has higher precede
| |
155 lstrlenW(str_ptr) < name_length || | 154 lstrlenW(str_ptr) < name_length || |
156 (!(LowerCaseEqualsASCII(str_ptr, str_ptr + name_length, | 155 (!(LowerCaseEqualsASCII(str_ptr, str_ptr + name_length, |
157 kGoogleCameraAdapter)))) { | 156 kGoogleCameraAdapter)))) { |
158 std::string id; | 157 std::string id; |
159 std::string device_name(base::SysWideToUTF8(str_ptr)); | 158 std::string device_name(base::SysWideToUTF8(str_ptr)); |
magjed_chromium
2014/09/02 15:14:41
device_name can be made const
| |
160 name.Reset(); | 159 name.Reset(); |
161 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); | 160 hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); |
162 if (FAILED(hr) || name.type() != VT_BSTR) { | 161 if (FAILED(hr) || name.type() != VT_BSTR) { |
163 id = device_name; | 162 id = device_name; |
164 } else { | 163 } else { |
165 DCHECK_EQ(name.type(), VT_BSTR); | 164 DCHECK_EQ(name.type(), VT_BSTR); |
166 id = base::SysWideToUTF8(V_BSTR(&name)); | 165 id = base::SysWideToUTF8(V_BSTR(&name)); |
167 } | 166 } |
168 device_names->push_back(Name(device_name, id, | 167 Name device(device_name, id, |
magjed_chromium
2014/09/02 15:14:41
device can be made const
| |
169 kDirectShowFilterClasses[class_index].capture_api_type)); | 168 kDirectShowFilterClasses[class_index].capture_api_type); |
169 // For WDM devices, we need to search in the listed |device_names| to | |
170 // find a device with matching USB ID. | |
perkj_chrome
2014/09/02 09:22:03
you are comparing GetModel() to find the USB id o
mcasas
2014/09/02 15:13:41
Clarified.
| |
171 if (device.capture_api_type() == Name::DIRECT_SHOW_WDM) { | |
172 const std::string& device_model = device.GetModel(); | |
173 Names::const_iterator iter = device_names->begin(); | |
174 for (; iter != device_names->end(); ++iter) { | |
175 if (device_model.compare(iter->GetModel()) == 0) { | |
perkj_chrome
2014/09/02 09:22:03
prefer ==
mcasas
2014/09/02 15:13:41
Not sure I understand. Can you please clarify?
| |
176 device.set_capabilities_unique_id(iter->id()); | |
perkj_chrome
2014/09/02 09:22:03
Do you know what happens if you have two capture c
mcasas
2014/09/02 15:13:41
Yes.
| |
177 break; | |
178 } | |
179 } | |
180 } | |
181 device_names->push_back(device); | |
170 } | 182 } |
171 } | 183 } |
172 moniker.Release(); | 184 moniker.Release(); |
173 } | 185 } |
174 } | 186 } |
175 } | 187 } |
176 | 188 |
177 static void GetDeviceNamesMediaFoundation(Names* device_names) { | 189 static void GetDeviceNamesMediaFoundation(Names* device_names) { |
178 DVLOG(1) << " GetDeviceNamesMediaFoundation"; | 190 DVLOG(1) << " GetDeviceNamesMediaFoundation"; |
179 ScopedCoMem<IMFActivate*> devices; | 191 ScopedCoMem<IMFActivate*> devices; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 return; | 227 return; |
216 | 228 |
217 ScopedComPtr<IEnumMoniker> enum_moniker; | 229 ScopedComPtr<IEnumMoniker> enum_moniker; |
218 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, | 230 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, |
219 enum_moniker.Receive(), 0); | 231 enum_moniker.Receive(), 0); |
220 // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera | 232 // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera |
221 // exists. Therefore the FAILED macro can't be used. | 233 // exists. Therefore the FAILED macro can't be used. |
222 if (hr != S_OK) | 234 if (hr != S_OK) |
223 return; | 235 return; |
224 | 236 |
225 // Walk the capture devices. No need to check for device presence again, that | 237 // Walk the capture devices. No need to check for device presence again since |
226 // is caught in GetDeviceFilter(). "google camera adapter" and old VFW devices | 238 // that is anyway needed in GetDeviceFilter(). "google camera adapter" and old |
227 // are already skipped in the previous GetDeviceNames() enumeration. | 239 // VFW devices are already skipped previously in GetDeviceNames() enumeration. |
228 base::win::ScopedComPtr<IBaseFilter> capture_filter; | 240 base::win::ScopedComPtr<IBaseFilter> capture_filter; |
229 hr = VideoCaptureDeviceWin::GetDeviceFilter(device, | 241 hr = VideoCaptureDeviceWin::GetDeviceFilter(device.capabilities_unique_id(), |
230 capture_filter.Receive()); | 242 capture_filter.Receive()); |
231 if (!capture_filter) { | 243 if (!capture_filter) { |
232 DVLOG(2) << "Failed to create capture filter."; | 244 DVLOG(2) << "Failed to create capture filter." ; |
magjed_chromium
2014/09/02 15:14:41
Unnecessary space after string :)
| |
233 return; | 245 return; |
234 } | 246 } |
235 | 247 |
236 base::win::ScopedComPtr<IPin> output_capture_pin( | 248 base::win::ScopedComPtr<IPin> output_capture_pin( |
237 VideoCaptureDeviceWin::GetPin(capture_filter, | 249 VideoCaptureDeviceWin::GetPin(capture_filter, |
238 PINDIR_OUTPUT, | 250 PINDIR_OUTPUT, |
239 PIN_CATEGORY_CAPTURE)); | 251 PIN_CATEGORY_CAPTURE)); |
240 if (!output_capture_pin) { | 252 if (!output_capture_pin) { |
241 DVLOG(2) << "Failed to get capture output pin"; | 253 DVLOG(2) << "Failed to get capture output pin"; |
242 return; | 254 return; |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 const Name& device, | 430 const Name& device, |
419 VideoCaptureFormats* formats) { | 431 VideoCaptureFormats* formats) { |
420 DCHECK(thread_checker_.CalledOnValidThread()); | 432 DCHECK(thread_checker_.CalledOnValidThread()); |
421 if (use_media_foundation_) | 433 if (use_media_foundation_) |
422 GetDeviceSupportedFormatsMediaFoundation(device, formats); | 434 GetDeviceSupportedFormatsMediaFoundation(device, formats); |
423 else | 435 else |
424 GetDeviceSupportedFormatsDirectShow(device, formats); | 436 GetDeviceSupportedFormatsDirectShow(device, formats); |
425 } | 437 } |
426 | 438 |
427 } // namespace media | 439 } // namespace media |
OLD | NEW |