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



(3)头文件

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

你可能感兴趣的:(Directshow)