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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章