使用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;
}