| Index: media/video/capture/win/video_capture_device_factory_win.cc
|
| diff --git a/media/video/capture/win/video_capture_device_factory_win.cc b/media/video/capture/win/video_capture_device_factory_win.cc
|
| index fd044b9a4e0eafc579bc99f194c3438531bc2e49..f36f4e6a3aec4a6de6e3b66cd64ee53811d5ee8e 100644
|
| --- a/media/video/capture/win/video_capture_device_factory_win.cc
|
| +++ b/media/video/capture/win/video_capture_device_factory_win.cc
|
| @@ -90,7 +90,10 @@ static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices,
|
| return SUCCEEDED(MFEnumDeviceSources(attributes, devices, count));
|
| }
|
|
|
| -static void GetDeviceNamesDirectShow(Names* device_names) {
|
| +static void GetDeviceNamesDirectShow(
|
| + const CLSID class_id,
|
| + const Name::CaptureApiType capture_api_type,
|
| + Names* device_names) {
|
| DCHECK(device_names);
|
| DVLOG(1) << " GetDeviceNamesDirectShow";
|
|
|
| @@ -100,77 +103,59 @@ static void GetDeviceNamesDirectShow(Names* device_names) {
|
| if (FAILED(hr))
|
| return;
|
|
|
| - static const struct{
|
| - CLSID class_id;
|
| - Name::CaptureApiType capture_api_type;
|
| - } kDirectShowFilterClasses[] = {
|
| - { CLSID_VideoInputDeviceCategory, Name::DIRECT_SHOW },
|
| - { AM_KSCATEGORY_CROSSBAR, Name::DIRECT_SHOW_WDM}
|
| - };
|
| + ScopedComPtr<IEnumMoniker> enum_moniker;
|
| + hr = dev_enum->CreateClassEnumerator(class_id, enum_moniker.Receive(), 0);
|
| + // CreateClassEnumerator returns S_FALSE on some Windows OS
|
| + // when no camera exist. Therefore the FAILED macro can't be used.
|
| + if (hr != S_OK)
|
| + return;
|
|
|
| + // Name of a fake DirectShow filter that exist on computers with
|
| + // GTalk installed.
|
| + static const char kGoogleCameraAdapter[] = "google camera adapter";
|
|
|
| - device_names->clear();
|
| - for (int class_index = 0; class_index < arraysize(kDirectShowFilterClasses);
|
| - ++class_index) {
|
| - ScopedComPtr<IEnumMoniker> enum_moniker;
|
| - hr = dev_enum->CreateClassEnumerator(
|
| - kDirectShowFilterClasses[class_index].class_id,
|
| - enum_moniker.Receive(),
|
| - 0);
|
| - // CreateClassEnumerator returns S_FALSE on some Windows OS
|
| - // when no camera exist. Therefore the FAILED macro can't be used.
|
| - if (hr != S_OK)
|
| - continue;
|
| -
|
| - // Name of a fake DirectShow filter that exist on computers with
|
| - // GTalk installed.
|
| - static const char kGoogleCameraAdapter[] = "google camera adapter";
|
| -
|
| - // Enumerate all video capture devices.
|
| - ScopedComPtr<IMoniker> moniker;
|
| - int index = 0;
|
| - while (enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK) {
|
| - ScopedComPtr<IPropertyBag> prop_bag;
|
| - hr = moniker->BindToStorage(0, 0, IID_IPropertyBag,
|
| - prop_bag.ReceiveVoid());
|
| - if (FAILED(hr)) {
|
| - moniker.Release();
|
| - continue;
|
| - }
|
| + // Enumerate all video capture devices.
|
| + ScopedComPtr<IMoniker> moniker;
|
| + int index = 0;
|
| + while (enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK) {
|
| + ScopedComPtr<IPropertyBag> prop_bag;
|
| + hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid());
|
| + if (FAILED(hr)) {
|
| + moniker.Release();
|
| + return;
|
| + }
|
|
|
| - // Find the description or friendly name.
|
| - ScopedVariant name;
|
| - hr = prop_bag->Read(L"Description", name.Receive(), 0);
|
| - if (FAILED(hr))
|
| - hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0);
|
| -
|
| - if (SUCCEEDED(hr) && name.type() == VT_BSTR) {
|
| - // Ignore all VFW drivers and the special Google Camera Adapter.
|
| - // Google Camera Adapter is not a real DirectShow camera device.
|
| - // VFW are very old Video for Windows drivers that can not be used.
|
| - const wchar_t* str_ptr = V_BSTR(&name);
|
| - const int name_length = arraysize(kGoogleCameraAdapter) - 1;
|
| -
|
| - if ((wcsstr(str_ptr, L"(VFW)") == NULL) &&
|
| - lstrlenW(str_ptr) < name_length ||
|
| - (!(LowerCaseEqualsASCII(str_ptr, str_ptr + name_length,
|
| - kGoogleCameraAdapter)))) {
|
| - std::string id;
|
| - std::string device_name(base::SysWideToUTF8(str_ptr));
|
| - name.Reset();
|
| - hr = prop_bag->Read(L"DevicePath", name.Receive(), 0);
|
| - if (FAILED(hr) || name.type() != VT_BSTR) {
|
| - id = device_name;
|
| - } else {
|
| - DCHECK_EQ(name.type(), VT_BSTR);
|
| - id = base::SysWideToUTF8(V_BSTR(&name));
|
| - }
|
| - device_names->push_back(Name(device_name, id,
|
| - kDirectShowFilterClasses[class_index].capture_api_type));
|
| + // Find the description or friendly name.
|
| + ScopedVariant name;
|
| + hr = prop_bag->Read(L"Description", name.Receive(), 0);
|
| + if (FAILED(hr))
|
| + hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0);
|
| +
|
| + if (SUCCEEDED(hr) && name.type() == VT_BSTR) {
|
| + // Ignore all VFW drivers and the special Google Camera Adapter.
|
| + // Google Camera Adapter is not a real DirectShow camera device.
|
| + // VFW are very old Video for Windows drivers that can not be used.
|
| + const wchar_t* str_ptr = V_BSTR(&name);
|
| + const int name_length = arraysize(kGoogleCameraAdapter) - 1;
|
| +
|
| + if ((wcsstr(str_ptr, L"(VFW)") == NULL) &&
|
| + lstrlenW(str_ptr) < name_length ||
|
| + (!(LowerCaseEqualsASCII(str_ptr, str_ptr + name_length,
|
| + kGoogleCameraAdapter)))) {
|
| + std::string id;
|
| + std::string device_name(base::SysWideToUTF8(str_ptr));
|
| + name.Reset();
|
| + hr = prop_bag->Read(L"DevicePath", name.Receive(), 0);
|
| + if (FAILED(hr) || name.type() != VT_BSTR) {
|
| + id = device_name;
|
| + } else {
|
| + DCHECK_EQ(name.type(), VT_BSTR);
|
| + id = base::SysWideToUTF8(V_BSTR(&name));
|
| }
|
| + device_names->push_back(Name(device_name, id, capture_api_type));
|
| }
|
| - moniker.Release();
|
| }
|
| + moniker.Release();
|
| }
|
| }
|
|
|
| @@ -222,11 +207,11 @@ static void GetDeviceSupportedFormatsDirectShow(const Name& device,
|
| if (hr != S_OK)
|
| return;
|
|
|
| - // Walk the capture devices. No need to check for device presence again, that
|
| - // is caught in GetDeviceFilter(). "google camera adapter" and old VFW devices
|
| - // are already skipped in the previous GetDeviceNames() enumeration.
|
| + // Walk the capture devices. No need to check for device presence again since
|
| + // that is anyway needed in GetDeviceFilter(). "google camera adapter" and old
|
| + // VFW devices are already skipped previously in GetDeviceNames() enumeration.
|
| base::win::ScopedComPtr<IBaseFilter> capture_filter;
|
| - hr = VideoCaptureDeviceWin::GetDeviceFilter(device,
|
| + hr = VideoCaptureDeviceWin::GetDeviceFilter(device.capabilities_id(),
|
| capture_filter.Receive());
|
| if (!capture_filter) {
|
| DLOG(ERROR) << "Failed to create capture filter: "
|
| @@ -404,7 +389,7 @@ scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create(
|
| device.reset();
|
| } else {
|
| DCHECK(device_name.capture_api_type() == Name::DIRECT_SHOW ||
|
| - device_name.capture_api_type() == Name::DIRECT_SHOW_WDM);
|
| + device_name.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR);
|
| device.reset(new VideoCaptureDeviceWin(device_name));
|
| DVLOG(1) << " DirectShow Device: " << device_name.name();
|
| if (!static_cast<VideoCaptureDeviceWin*>(device.get())->Init())
|
| @@ -415,10 +400,33 @@ scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create(
|
|
|
| void VideoCaptureDeviceFactoryWin::GetDeviceNames(Names* device_names) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (use_media_foundation_)
|
| + if (use_media_foundation_) {
|
| GetDeviceNamesMediaFoundation(device_names);
|
| - else
|
| - GetDeviceNamesDirectShow(device_names);
|
| + } else {
|
| + GetDeviceNamesDirectShow(CLSID_VideoInputDeviceCategory,
|
| + Name::DIRECT_SHOW,
|
| + device_names);
|
| +
|
| + Names crossbar_device_names;
|
| + GetDeviceNamesDirectShow(AM_KSCATEGORY_CROSSBAR,
|
| + Name::DIRECT_SHOW_WDM_CROSSBAR,
|
| + &crossbar_device_names);
|
| + // Search in the listed |device_names| to find a device with matching USB ID
|
| + // to each device in |crossbar_device_names|.
|
| + for (Names::iterator crossbar_device_it = crossbar_device_names.begin();
|
| + crossbar_device_it != crossbar_device_names.end();
|
| + ++crossbar_device_it) {
|
| + const std::string& crossbar_device_model = crossbar_device_it->GetModel();
|
| + for (Names::const_iterator device_it = device_names->begin();
|
| + device_it != device_names->end(); ++device_it) {
|
| + if (crossbar_device_model == device_it->GetModel()) {
|
| + crossbar_device_it->set_capabilities_id(device_it->id());
|
| + device_names->push_back(*crossbar_device_it);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
| void VideoCaptureDeviceFactoryWin::GetDeviceSupportedFormats(
|
|
|