使用dshow如何打开指定摄像头

使用dshow如何打开指定摄像头

  • 通过设备VID/PID找到指定摄像头设备
  • 通过设备名打开指定摄像头设备
  • 绑定设备过滤器

最近做了一个关于摄像头的项目,需要适配WindowsXP及以上系统,需要兼容XP系统就打算用dshow技术,顺便把相关技术学了一遍,这里给大家分享一下如何打开指定摄像头设备。

通过设备VID/PID找到指定摄像头设备

HRESULT GetCameraId()
{
	ICreateDevEnum *pDevEnum = NULL;
	IEnumMoniker *pEnum = NULL;
	HRESULT hr = NULL;
	CoInitialize(NULL);
	int index = -1;
	int iCapCount = 0;
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum));
	if (SUCCEEDED(hr))
	{

		hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
		if (hr == S_OK)
		{
			//枚举捕获设备
			IMoniker *pMoniker = NULL;
			ULONG cFetched;
			while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK)
			{
				IPropertyBag* pPropBag;
				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<void**>(&pPropBag));
				if (SUCCEEDED(hr))
				{
					index++;
					//获取PID VID
					BSTR devicePath = NULL;
					hr = pMoniker->GetDisplayName(NULL, NULL, &devicePath);
					if (!SUCCEEDED(hr))
					{
						pMoniker->Release();
						continue;
					}
					wchar_t* lpszDevicePath = _bstr_t(devicePath);
					CString strDevice;
					strDevice.Format(L"%s", lpszDevicePath);
					if (strDevice.Find(L"vid_0000") >= 0 && strDevice.Find(L"pid_0000") >= 0)
					{
						cameraID = index;
					}
					pPropBag->Release();
				}
				pMoniker->Release();
			}
		}
	}
	CoUninitialize();

	return hr;
}

通过设备名打开指定摄像头设备

HRESULT GetCameraId()
{
	ICreateDevEnum *pDevEnum = NULL;
	IEnumMoniker *pEnum = NULL;
	HRESULT hr = NULL;
	CoInitialize(NULL);
	int index = -1;
	int iCapCount = 0;
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum));
	if (SUCCEEDED(hr))
	{

		hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
		if (hr == S_OK)
		{
			//枚举捕获设备
			IMoniker *pMoniker = NULL;
			ULONG cFetched;
			while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK)
			{
				IPropertyBag* pPropBag;
				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<void**>(&pPropBag));
				if (SUCCEEDED(hr))
				{
					index++;
					//获取设备名称
					VARIANT varName;
					varName.vt = VT_BSTR;
					VariantInit(&varName);
					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
					wchar_t* lpszBSTR = L"";
					if (SUCCEEDED(hr))
					{
						lpszBSTR = _bstr_t(varName.bstrVal);
					}
					int iSize;
					char* pszMultiByte;
					//返回接受字符串所需缓冲区的大小,已经包含字符结尾符'\0'
					iSize = WideCharToMultiByte(CP_ACP, 0, lpszBSTR, -1, NULL, 0, NULL, NULL); //iSize =wcslen(pwsUnicode)+1=6
					pszMultiByte = (char*)malloc(iSize * sizeof(char)); //不需要 pszMultiByte = (char*)malloc(iSize*sizeof(char)+1);
					WideCharToMultiByte(CP_ACP, 0, lpszBSTR, -1, pszMultiByte, iSize, NULL, NULL);
					if (0 == strcmp(szDeviceName, pszMultiByte))
					{
						cameraID = index;
					}
					free(pszMultiByte);
					pPropBag->Release();
				}
				pMoniker->Release();
			}
		}
	}
	CoUninitialize();

	return hr;
}

在WindowsXP下由于设备名都是USB Camera,此方法不适用

绑定设备过滤器

绑定设备过滤器, 我们知道了设备因为传入了id

IBaseFilter* m_pBF;
if (!BindFilter(cameraID, &m_pBF))
{
	return S_FALSE;
}

你可能感兴趣的:(摄像头,dshow,打开摄像头)