Directshow 能很方便的获取连接的 视频和音频设备的名称。本篇文章同时介绍如何判断获取的摄像头是否正在占用。
代码如下:
(1) 获取摄像头音视频设备名称
void CDeviceTree::EnumDevices()
{
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
//将CLSID_VideoInputDeviceCategory 改成 CLSID_AudioInputDeviceCategory 即能获取音频设备
if (FAILED(hr))
{
return;
}
if(hr == S_OK)
{
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag* pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(SUCCEEDED(hr))
{
VARIANT varName;
varName.vt=VT_BSTR;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
USES_CONVERSION;
LPTSTR lpstrMsg = W2T(varName.bstrVal);
if(SUCCEEDED(hr))
{
//videoDev[videoIndex]=lpstrMsg;
//videoIndex++;
//此处即得到获得的视频设备名称 你可以将它打印出来 或者存入队列
}
pPropBag->Release();
}
pMoniker->Release();
}
}
}
int DeviceIsBusy(char *videoName,char *audioName)
{
//输入设备的音视频名称
HRESULT hr;
HRESULT hhr;
int ret=0;
int videoBusy=1;
int audioBusy=1;
CoInitialize(NULL);
ICreateDevEnum* pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);
IEnumMoniker* pEnumCat ;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
if(hr == S_OK)
{
IMoniker* pMoniker = NULL;
IMoniker* pm1=NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag* pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(SUCCEEDED(hr))
{
VARIANT varName;
varName.vt=VT_BSTR;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
USES_CONVERSION;
LPTSTR lpstrMsg = W2T(varName.bstrVal);
if(SUCCEEDED(hr))
{
if (!strcmp(videoName,lpstrMsg))//存在设备
{
LPBC *pbc=NULL;
IBaseFilter *P_VCamTrans=NULL;
IBaseFilter *pCap=NULL;
CreateBindCtx(0,pbc);
hr=pMoniker->BindToObject((IBindCtx *)pbc,0,IID_IBaseFilter,(void **)&pCap);
ICaptureGraphBuilder2 *m_pCapGB;
IGraphBuilder *m_pGB;
IMediaControl *m_pMC;
IVideoWindow *m_pVW;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
if (FAILED(hr)) return hr;
m_pGB->AddFilter(pCap,NULL);
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
if (FAILED(hr)) return hr;
m_pCapGB->SetFiltergraph(m_pGB);
IAMCrossbar *pXBar1 = NULL;
hr=m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY,NULL,pCap,IID_IAMCrossbar,(void **)&pXBar1);
if (SUCCEEDED(hr))
{
long OutputPinCount;
long InputPinCount;
long PinIndexRelated;
long PhysicalType;
long inPort = 0;
long outPort = 0;
pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
//对于存在输入输出引脚的摄像头。此处采用轮询所有的引脚
for(int i =0;iget_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}
}
for(int i =0;iget_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}
for (int i=0;iCanRoute(j,i))
{
pXBar1->Route(j,i);
m_pGB->AddFilter(pCap, L"Capture Filter");
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
hr = m_pVW->put_Owner((OAHWND)NULL);
hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
hr = m_pVW->put_Visible(OAFALSE);
hr=m_pVW->put_AutoShow(OAFALSE);
hhr=m_pMC->StopWhenReady();
if (SUCCEEDED(hhr))
{
videoBusy=0;
}
}
}
}
if (videoBusy == 1)
{
ret=-1; //视频设备占用
}
}
else
{
m_pGB->AddFilter(pCap, L"Capture Filter");
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
hr = m_pVW->put_Owner((OAHWND)NULL);
hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
hr = m_pVW->put_Visible(OAFALSE);
hr=m_pVW->put_AutoShow(OAFALSE);
hhr=m_pMC->StopWhenReady();
if (FAILED(hhr))
{
ret=-1; //视频设备占用
}
}
}
}
pPropBag->Release();
}
pMoniker->Release();
}
}
//判断音频的方法和上面的一样 重复。
hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);
if(hr == S_OK)
{
IMoniker* pMoniker = NULL;
IMoniker* pm1=NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag* pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(SUCCEEDED(hr))
{
VARIANT varName;
varName.vt=VT_BSTR;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
USES_CONVERSION;
LPTSTR lpstrMsg = W2T(varName.bstrVal);
if(SUCCEEDED(hr))
{
if (!strcmp(videoName,lpstrMsg))//存在设备
{
LPBC *pbc=NULL;
IBaseFilter *P_VCamTrans=NULL;
IBaseFilter *pCap=NULL;
CreateBindCtx(0,pbc);
hr=pMoniker->BindToObject((IBindCtx *)pbc,0,IID_IBaseFilter,(void **)&pCap);
ICaptureGraphBuilder2 *m_pCapGB;
IGraphBuilder *m_pGB;
IMediaControl *m_pMC;
IVideoWindow *m_pVW;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
if (FAILED(hr)) return hr;
m_pGB->AddFilter(pCap,NULL);
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
if (FAILED(hr)) return hr;
m_pCapGB->SetFiltergraph(m_pGB);
IAMCrossbar *pXBar1 = NULL;
hr=m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY,NULL,pCap,IID_IAMCrossbar,(void **)&pXBar1);
if (SUCCEEDED(hr))
{
long OutputPinCount;
long InputPinCount;
long PinIndexRelated;
long PhysicalType;
long inPort = 0;
long outPort = 0;
pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
for(int i =0;iget_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}
}
for(int i =0;iget_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}
for (int i=0;iCanRoute(j,i))
{
pXBar1->Route(j,i);
m_pGB->AddFilter(pCap, L"Capture Filter");
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
hr = m_pVW->put_Owner((OAHWND)NULL);
hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
hr = m_pVW->put_Visible(OAFALSE);
hr=m_pVW->put_AutoShow(OAFALSE);
hhr=m_pMC->StopWhenReady();
if (SUCCEEDED(hhr))
{
audioBusy=0;
}
}
}
}
if (audioBusy == 1)
{
ret=-1; //音频设备占用
}
}
else
{
m_pGB->AddFilter(pCap, L"Capture Filter");
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
hr = m_pVW->put_Owner((OAHWND)NULL);
hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
hr = m_pVW->put_Visible(OAFALSE);
hr=m_pVW->put_AutoShow(OAFALSE);
hhr=m_pMC->StopWhenReady();
if (FAILED(hhr))
{
ret=-1; //音频设备占用
}
}
}
}
pPropBag->Release();
}
pMoniker->Release();
}
}
pSysDevEnum->Release();
CoUninitialize();
return ret;
}
#include "windows.h"
#include "stdio.h"
#include "string.h"
#include
#include "Dshow.h"
#include "atlconv.h"
#pragma comment(lib,"Strmiids.lib")
#pragma comment(lib,"Quartz.lib")