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

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")

//指定视频采集设备的友好名字,为它创建一个Filter IBaseFilter * CTestPreviewDlg::CreateVideoDevice(const char * inFriendlyName) { return CreateHardwareFilter(CLSID_VideoInputDeviceCategory,inFriendlyName); } //根据设备的友好名字,创建一个代表该设备的Filter IBaseFilter * CTestPreviewDlg::CreateHardwareFilter(GUID inCategory,const char * inFriendlyName) { //创建一个系统枚举组件对象 ICreateDevEnum * enumHardware = NULL; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL, IID_ICreateDevEnum,(void**)&enumHardware); if(FAILED(hr)) { return NULL; } IBaseFilter * hardwareFilter = NULL; IEnumMoniker * enumMoniker = NULL; //为指定的目录创建枚举器 hr = enumHardware->CreateClassEnumerator(inCategory,&enumMoniker,0); if(enumMoniker) { enumMoniker->Reset(); ULONG fetched = 0; IMoniker * moniker = NULL; char friendlyName[256]; //枚举得到该目录下所有的设备,逐个进行名字匹配 while(!hardwareFilter && SUCCEEDED(enumMoniker->Next(1,&moniker, &fetched)) && fetched) { if(moniker) { IPropertyBag * propertyBag = NULL; VARIANT name; friendlyName[0] = 0; hr = moniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&propertyBag); //读取设备的友好名字 if(SUCCEEDED(hr)) { name.vt = VT_BSTR; hr = propertyBag->Read(L"Friendlyname",&name,NULL); } if(SUCCEEDED(hr)) { WideCharToMultiByte(CP_ACP,0,name.bstrVal,-1, friendlyName,256,NULL,NULL); //如果当前设备的友好名字与用户指定的设备名字相同, //则将当前设备标识绑定为Filter形式 if(strcmp(friendlyName,inFriendlyName) == 0) { moniker->BindToObject(0,0,IID_IBaseFilter, (void**)&hardwareFilter); } } //释放使用过的接口 if(propertyBag) { propertyBag->Release(); propertyBag = NULL; } moniker->Release(); } } enumMoniker->Release(); } enumHardware->Release(); return hardwareFilter; }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零凌灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值