出處:http://blog.csdn.net/chenice9999/article/details/6968957
枚舉網路攝影機裝置(不論裝置能否被使用都會被枚舉出來):
int EnumDevices()
{
int id = 0;
//枚舉視頻撲捉裝置
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
return -1;
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
if (hr != NOERROR)
return -1;
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL); //you can get other info by first parame
if (hr == NOERROR)
{
id++;
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
}
return id;
}
啟動網路攝影機:
HWND m_hWnd;
IGraphBuilder *m_pGB;
ICaptureGraphBuilder2* m_pCapture;
IBaseFilter* m_pBF;
IMediaControl* m_pMC;
IVideoWindow* m_pVW;
CComPtr<ISampleGrabber> m_pGrabber;
1.初始化GraphBuilder
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
m_pCapture->SetFiltergraph(m_pGB);
m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW);
2.綁定一個裝置到InputFilter
CComPtr<ICreateDevEnum> pCreateDevEnum;
CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
CComPtr<IEnumMoniker> pEm;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
IPropertyBag *pBag; hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
}
3.建立一個OutputFilter
m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
4.設定SampleGrabber的視頻格式
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24; //這裡只是設定輸出的映像資料類型(24bit,32bit,...),directshow會對自動的對採集到的映像資料做轉換
m_pGrabber->SetMediaType(&mt);
5.將2個Filter添加到GraphBuilder
m_pGB->AddFilter(m_pBF, L"Capture Filter");
m_pGB->AddFilter( pGrabBase, L"Grabber" );
6.嘗試去RenderStream,失敗則表示該裝置無法使用(比如被其他應用程式所佔用)
hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
if( FAILED( hr ) )
{
AfxMessageBox(L"Can’t build the graph");
return hr;
}
7.配置SampleGrabber
m_pGrabber->SetBufferSamples( FALSE ); //如果設定true,SampleGrabber會建立一個內部的buffer,可以通過GetCurrentBuffer獲得當前幀資料
m_pGrabber->SetOneShot( FALSE ); //如果設定成true,表示只會進入callback函數一次
m_pGrabber->SetCallback( &mCB, 1 );//設定callback,第2個參數如果設定成0,則第一個參數必須是IMediaSample指標
8.開始視頻捕獲
m_pMC->Run();
枚舉,設定InputFilter的資料格式:
CComPtr<IAMStreamConfig> pam;
m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pBF, IID_IAMStreamConfig, reinterpret_cast<void**>(&pam));
int nCount = 0;
int nSize = 0;
pam->GetNumberOfCapabilities(&nCount, &nSize);
AM_MEDIA_TYPE* pmmt = NULL;
VIDEO_STREAM_CONFIG_CAPS scc;
if (sizeof(VIDEO_STREAM_CONFIG_CAPS) == nSize) {
for (int i=0; i<nCount; i++) {
pmmt = NULL;
hr = pam->GetStreamCaps(i, &pmmt, reinterpret_cast<BYTE*>(&scc));
if (FAILED(hr))
{
continue;
}
if ( pmmt->majortype == MEDIATYPE_Video && pmmt->formattype == FORMAT_VideoInfo )
{
pam->SetFormat(pmmt);
break;
}
}
}
釋放AM_MEDIA_TYPE類型資源:
void FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
// Strictly unnecessary but tidier
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
綁定視頻輸出視窗:
建立一個picture空間,設定其屬性(Type: Rectangle,Color:Gray)
m_pVW->put_Owner((OAHWND)m_hWnd);
m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
Rect rc;
::GetClientRect(m_hWnd,&rc);
float fk = (float)mCB.lWidth / (float)mCB.lHeight;
long rw = fk * rc.bottom;
int off_x = (rc.right - rw)/2;
m_pVW->SetWindowPosition(off_x, 0, rw, rc.bottom);//讓捕獲到的視頻置中顯示
m_pVW->put_Visible(OATRUE);
解除綁定視頻輸出視窗:
m_pVW->put_Visible(OAFALSE);
m_pVW->put_Owner(NULL);