摘要:本文主要講述用Directshow進行視頻捕捉(捕捉靜態圖像)的編程思路,並提供針對攝像頭編程的一個視頻捕捉類CcaptureVideo和一個示例。
前言
DirectShow是微軟公司提供的一套在Windows平臺上進行流媒體處理的開發包,與DirectX開發包一起發佈。DirectShow爲多媒體流的捕捉和回放提供了強有力的支持。用DirectShow開發應用程序,我們可以很方便地從支持WDM驅動模型的採集卡上捕獲數據,並且進行相應的後期處理乃至存儲到文件中。
DirectShow是基於COM的,爲了編寫DirectShow應用程序,需要了解COM客戶程序編寫的基礎知識。DirectShow提供了大量的接口,但在編程中發現還是不夠方便,如果能構建一個視頻捕捉類把常用的一些動作封裝起來,那麼就更方便了。
編程思路
爲了更加容易建立視頻捕捉應用程序,DirectShow提供了一個叫做Capture Graph Builder的對象,Capture Graph Builder提供IcaptureGraphBuilder2接口,該接口可以建立和控制Capture Graph。
建立視頻捕捉程序,必須首先獲取並初始化IcaptureGraphBuilder2接口,然後選擇一個適當的視頻捕捉設備。選擇好設備後,爲該設備創建Capture filter,然後調用AddFilter把Capture filter添加到Filter Graph。
如果僅僅希望用攝像頭來進行實時監控的話,只需要在上面的基礎上調用ICaptureGraphBuilder2::RenderStream就可以了:
ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
//省略初始化部分代碼
IBaseFilter *pCap; // Video capture filter.
//省略初始化和添加到Filter Graph部分代碼
pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
DirectShow提供了一個捕捉靜態圖像的方法:使用Sample Grabber filter。依次按照以下三個步驟就可以了:
第一步, 定義一個類實現Sample Grabber的回調接口IsampleGrabberCB:
class CSampleGrabberCB : public ISampleGrabberCB
{
//在後面提供的類中具體完成
}
CSampleGrabberCB mCB;
第二步、調用RenderStream依次把Still pin、Sample Grabber和系統默認Renderer Filter連接起來。
第三步、配置Sample Grabber以捕獲數據。
視頻捕捉類CCaptureVideo的具體實現
如何使用視頻捕捉類CCaptureVideo
構建CCaptureVideo類以後,使用就方便多了,我們在編程中只需要是要下面三個類成員函數就可以實現用攝像頭進行視頻捕捉:
①int EnumDevices(HWND hList); //hList是下拉列表框的句柄,本函數用於枚舉當前系統安裝的所有視頻捕捉設備
②HRESULT Init(int iDeviceID,HWND hWnd);//iDeviceID是視頻捕捉設備序號,hWnd是視頻捕捉窗口的句柄
③void GrabOneFrame(BOOL bGrab);//調用GrabOneFrame(true)就可以捕獲當前的靜態圖像並保存到硬盤上
具體示例:用MFC AppWizard(exe)創建一個對話框應用程序,取名爲ds,給對話框添加一個下拉列表框(IDC_COMBO1)、兩個按鈕(IDC_PHOTO、IDC_HAVEALOOK)和一個Picture控件(ID:IDC_STATIC_SCREEN,Type: Rectangle,Color:Gray)。
1、使用嚮導添加成員變量
CStatic m_staticScreen; // IDC_STATIC_SCREEN
CComboBox m_ListCtrl; // IDC_COMBO1
CCaptureVideo m_cap;
2、爲BOOL CDsDlg::OnInitDialog()添加如下代碼:
// TODO: Add extra initialization here
m_cap.EnumDevices (m_ListCtrl);
m_ListCtrl.SetCurSel (0);
3、爲確定按鈕添加代碼如下:
void CDsDlg::OnOK()
{
//只需要四行代碼就可以進行視頻捕捉了
UpdateData();
HWND hWnd = m_staticScreen.GetSafeHwnd() ;
HRESULT hr = m_cap.Init(m_ListCtrl.GetCurSel (),hWnd);
GetDlgItem(IDOK)->EnableWindow(FALSE);
}
4、如果希望捕捉靜態圖像,爲照相按鈕添加如下代碼:
void CDsDlg::OnPhoto()
{
m_cap.GrabOneFrame(true);
}
運行程序時,選定攝像頭後只需要按確定就可以了。
結束語
本文提供的視頻捕捉類CcaptureVideo和示例,在Win2K + DirectX9 SDK + VC6 環境下調試通過。注意:編譯時需要Strmiids.lib Quartz.lib兩個庫文件(DirectX9 SDK自帶)。