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" |
| (...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 |