使用dshow如何打開指定攝像頭


最近做了一個關於攝像頭的項目,需要適配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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章