Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: media/video/capture/win/video_capture_device_factory_win.cc

Issue 517273004: Win Video Capture: add DirectShow WDM devices capabilities enumeration. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added an entry to VCD to hold unique_id to be used for caps retrieval, rest of the code modified to… Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698