您的位置:首页 > 其它

Directshow 如何获取摄像头音视频设备,并判断摄像头是否占用。

2015-01-24 17:58 811 查看
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();
}

}
}


(2) 判断摄像头是否占用。

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;i<InputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);

if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}

}

for(int i =0;i<OutputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);

if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}

for (int i=0;i<InputPinCount;i++)
{
for (int j=0;j<OutputPinCount;j++)
{
if(S_OK==pXBar1->CanRoute(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;i<InputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);

if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}

}

for(int i =0;i<OutputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);

if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}

for (int i=0;i<InputPinCount;i++)
{
for (int j=0;j<OutputPinCount;j++)
{
if(S_OK==pXBar1->CanRoute(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;
}


(3)头文件

#include "windows.h"
#include "stdio.h"
#include "string.h"
#include <string>
#include "Dshow.h"
#include "atlconv.h"

#pragma   comment(lib,"Strmiids.lib")
#pragma   comment(lib,"Quartz.lib")
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: