VC利用VFW進(jìn)行視頻采集_第1頁(yè)
VC利用VFW進(jìn)行視頻采集_第2頁(yè)
VC利用VFW進(jìn)行視頻采集_第3頁(yè)
VC利用VFW進(jìn)行視頻采集_第4頁(yè)
VC利用VFW進(jìn)行視頻采集_第5頁(yè)
已閱讀5頁(yè),還剩145頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、2.2  VFW視頻采集方案VFW是Microsoft于1992年推出的數(shù)字視頻軟件包,它不依賴(lài)于專(zhuān)用的硬件設(shè)備,提供了通用的數(shù)字視頻開(kāi)發(fā)方案。VFW主要由AVICap.dll、MSVideo.dll、MCIAvi.drv、AVIFile.dll、vfw32.lib等庫(kù)文件組成,這些庫(kù)提供了相關(guān)視頻、音頻、AVI文件的函數(shù),本節(jié)將介紹如何利用這些函數(shù)進(jìn)行視頻采集。2.2.1  開(kāi)發(fā)流程分析VFW使用的視頻函數(shù)被封裝在vfw32.lib庫(kù)文件中,該庫(kù)文件默認(rèn)情況下沒(méi)有被連接到MFC工程中,因此使用VFW進(jìn)行視頻開(kāi)發(fā)的第一步是導(dǎo)入vfw32.lib庫(kù)文件。方法如下:(1)引用v

2、fw.h頭文件。#include "vfw.h"(2)導(dǎo)入vfw32.lib庫(kù)文件。#pragma comment (lib,"vfw32")步驟2也可以在通過(guò)工程選項(xiàng)窗口的連接選項(xiàng)卡進(jìn)行設(shè)置。如圖2.1所示。連接vfw32.lib庫(kù)文件 圖2.1  工程選項(xiàng)窗口在導(dǎo)入vfw32.lib庫(kù)文件后便可以使用視頻函數(shù)了。首先調(diào)用capCreateCaptureWindow函數(shù)創(chuàng)建具有WS_POPUP風(fēng)格的視頻捕捉窗口。然后調(diào)用capDriverConnect函數(shù)連接驅(qū)動(dòng)程序,設(shè)置視頻捕捉窗口的大小、顯示位置。最后調(diào)用capPreviewR

3、ate函數(shù)設(shè)置預(yù)覽速率,調(diào)用capPreview函數(shù)進(jìn)行視頻預(yù)覽??偨Y(jié)上述流程分析,VFW視頻捕捉開(kāi)發(fā)流程具體步驟如下:(1)引用“vfw.h”頭文件并導(dǎo)入vfw32.lib庫(kù)。(2)創(chuàng)建一個(gè)線(xiàn)程,在線(xiàn)程函數(shù)中調(diào)用capCreateCaptureWindow創(chuàng)建視頻捕捉窗口。(3)調(diào)用capDriverConnect連接驅(qū)動(dòng)程序,設(shè)置視頻捕捉窗口風(fēng)格、大小及父窗口。(4)調(diào)用capPreviewRate函數(shù)設(shè)置預(yù)覽速度,調(diào)用capPreview函數(shù)開(kāi)始預(yù)覽。2.2.2  視頻窗口創(chuàng)建在進(jìn)行視頻程序開(kāi)發(fā)時(shí),第一步需要?jiǎng)?chuàng)建一個(gè)視頻預(yù)覽窗口。在程序中可以使用capCreateCapture

4、Window函數(shù)來(lái)創(chuàng)建視頻預(yù)覽窗口,該函數(shù)語(yǔ)法如下:HWND VFWAPI capCreateCaptureWindow(LPCSTR lpszWindowName, DWORD dwStyle, int x,                  int y, int nWidth, int nHeight, HWND hWnd, int nID);參數(shù)說(shuō)明:lpszWindowName:表示視頻捕捉窗口的名稱(chēng)。dwStyle:

5、表示視頻捕獲窗口的風(fēng)格,一般包含有WS_CHILD 和 WS_VISIBLE風(fēng)格。x、y:表示視頻捕捉窗口的左上角坐標(biāo)。nWidth、nHeight:表示視頻捕捉窗口的寬度和高度。hWnd:表示視頻捕捉窗口父窗口的句柄。nID:表示視頻捕捉窗口標(biāo)識(shí)。在創(chuàng)建視頻捕捉窗口之后,需要將其顯示在對(duì)話(huà)框中的適當(dāng)位置。可以在對(duì)話(huà)框中預(yù)先放置一個(gè)靜態(tài)文本控件,調(diào)整其大小和位置,然后將視頻捕捉窗口放置在該控件的位置處就可以了。例如:m_Captured = FALSE;m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);

6、:SetParent(m_hWndVideo,*this);:SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);CRect wndRC;m_Panel.GetClientRect(wndRC);m_Panel.MapWindowPoints(this,wndRC);wndRC.DeflateRect(1,1,1,1);:SetWindowPos(m_hWndVideo,NULL,wndRC.left,wndRC.top,wndRC.Width(),wndRC.Height(),SWP_NOZORDER);:ShowWindow(m_hWndVideo,

7、SW_SHOW);2.2.3  視頻預(yù)覽實(shí)現(xiàn)在開(kāi)發(fā)視頻應(yīng)用程序時(shí),第一步需要實(shí)現(xiàn)的功能便是視頻預(yù)覽。在2.2.1節(jié)中筆者曾分析了視頻預(yù)覽的實(shí)現(xiàn)過(guò)程,下面以一個(gè)具體實(shí)例來(lái)說(shuō)明VFW視頻預(yù)覽的實(shí)現(xiàn)過(guò)程。效果如圖2.2所示。圖2.2  視頻預(yù)覽實(shí)現(xiàn)程序設(shè)計(jì)步驟如下:  實(shí)例位置:光盤(pán)mr22.22.2.301(1)創(chuàng)建一個(gè)基于對(duì)話(huà)框的工程,在對(duì)話(huà)框中添加Picture控件,如圖2.3所示。圖2.3  視頻預(yù)覽設(shè)計(jì)窗口(2)在類(lèi)向?qū)У摹癕ember Variables”選項(xiàng)卡中為Picture控件命名,如圖2.4所示。圖2.4  類(lèi)向?qū)Т翱冢?)在對(duì)話(huà)

8、框的頭文件中引用“vfw.h”頭文件,然后鏈接“vfw32.lib”庫(kù)文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)在對(duì)話(huà)框中定義一個(gè)視頻預(yù)覽窗口的句柄。HWND   m_hWndVideo; /視頻顯示窗口(5)在對(duì)話(huà)框初始化時(shí)創(chuàng)建視頻預(yù)覽窗口,連接視頻驅(qū)動(dòng)程序,設(shè)置預(yù)覽幀率,開(kāi)始視頻預(yù)覽。BOOL CVideoPreviewDlg:OnInitDialog()   CDialog:OnInitDialog();   ASSERT(IDM

9、_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX);   ASSERT(IDM_ABOUTBOX < 0xF000);   CMenu* pSysMenu = GetSystemMenu(FALSE);   if (pSysMenu != NULL)          CString strAboutMenu;       strAboutMenu.LoadStr

10、ing(IDS_ABOUTBOX);       if (!strAboutMenu.IsEmpty()                     pSysMenu->AppendMenu(MF_SEPARATOR);          

11、0;   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);             SetIcon(m_hIcon, TRUE);       SetIcon(m_hIcon, FALSE);   /創(chuàng)建預(yù)覽窗口   m_hWndVideo = capCreateCaptureWindow(NULL,WS_PO

12、PUP,1,1,10,10,m_hWnd,0);   /連接驅(qū)動(dòng)程序   if (capDriverConnect(m_hWndVideo,0)            :SetParent(m_hWndVideo,*this);       :SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);      

13、CRect wndRC;       m_Panel.GetClientRect(wndRC);       m_Panel.MapWindowPoints(this,wndRC);       wndRC.DeflateRect(1,1,1,1);       :SetWindowPos(m_hWndVideo,NULL,wndRC.left,wndRC.

14、top,wndRC.Width(),wndRC.Height(),SWP_NOZORDER);       :ShowWindow(m_hWndVideo,SW_SHOW);       capPreviewRate(m_hWndVideo,30);       capPreview(m_hWndVideo,TRUE);        return TRUE; (6)

15、在對(duì)話(huà)框關(guān)閉時(shí)斷開(kāi)視頻驅(qū)動(dòng)程序。void CVideoPreviewDlg:OnCancel()   /斷開(kāi)驅(qū)動(dòng)程序連接   capDriverDisconnect(m_hWndVideo);   CDialog:OnCancel();2.2.4  捕捉參數(shù)設(shè)置在進(jìn)行視頻捕捉時(shí),通常需要設(shè)置視頻捕捉參數(shù)。VFW提供了capCaptureSetSetup函數(shù)用于設(shè)置視頻捕捉參數(shù),該函數(shù)語(yǔ)法如下:BOOL capCaptureSetSetup(HWND hwnd, LPCAPTUREPARMS  psCapParms,

16、UINT wSize );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。psCapParms:表示視頻捕捉參數(shù),該參數(shù)是CAPTUREPARMS結(jié)構(gòu)指針。CAPTUREPARMS結(jié)構(gòu)成員描述如表2.1所示。表2.1  CAPTUREPARMS結(jié)構(gòu)成員描述成員名稱(chēng)成員類(lèi)型描述dwRequestMicroSecPerFrameDWORD以毫秒為單位設(shè)置捕捉幀率,默認(rèn)值為66667,即每秒15幀fMakeUserHitOKToCaptureBOOL如果為T(mén)RUE,將顯示一個(gè)對(duì)話(huà)框幫助用戶(hù)快速地進(jìn)行捕捉設(shè)置wPerentDropForErrorUINT在捕捉過(guò)程中允許棄幀的最大百分比f(wàn)Yield

17、BOOL如果為T(mén)RUE,將產(chǎn)生一個(gè)后臺(tái)線(xiàn)程來(lái)進(jìn)行視頻捕捉dwIndexSizeDWORD表示AVI文件最大的索引入口數(shù)wChunkGranularityUINT以字節(jié)為單位表示AVI文件的大小fUsingDOSMemoryBOOL未使用wNumVideoRequestedUINT分配視頻緩沖區(qū)的最大數(shù)量fCaptureAudioBOOL為T(mén)RUE,表示音頻被捕捉,默認(rèn)值依賴(lài)于安裝的音頻設(shè)備wNumAudioRequestedUINT表示分配的音頻緩沖區(qū)的最大數(shù)量vKeyAbortUINT表示終止捕捉的虛擬鍵fAbortLeftMouseBOOL為T(mén)RUE,表示單擊鼠標(biāo)左鍵停止捕捉fAbortR

18、ightMouseBOOL為T(mén)RUE,表示單擊鼠標(biāo)右鍵停止捕捉fLimitEnabledBOOL為T(mén)RUE,表示設(shè)置捕捉時(shí)間限制wTimeLimitUINT以秒為單位設(shè)置捕捉的超時(shí)時(shí)間fMCIControlBOOL為T(mén)RUE,控制MCI(媒體設(shè)備接口)兼容的視頻源fStepMCIDeviceBOOL為T(mén)RUE,使用MCI設(shè)備使用步進(jìn)幀進(jìn)行捕捉,為FALSE,使用MCI設(shè)備進(jìn)行時(shí)時(shí)捕捉,如果fMCIControl成員為FALSE,該成員被忽略dwMCIStartTimeDWORD以毫秒為單位標(biāo)識(shí)MCI設(shè)備視頻捕捉序列的起始位置,如果fMCIControl成員為FALSE,該成員被忽略dwMCIS

19、topTimeDWORD以毫秒為單位標(biāo)識(shí)MCI設(shè)備視頻捕捉序列的停止位置,如果fMCIControl成員為FALSE,該成員被忽略fStepCaptureAt2xBOOL為T(mén)RUE,捕捉的視頻幀使用兩個(gè)分辨率,它可以使用軟件在某個(gè)分辨率的基礎(chǔ)上改寫(xiě)像素,將其該為高清晰度的圖像wStepCaptureAverageFramesUINT在捕捉時(shí)每幀圖像使用的時(shí)間大小dwAudioBufferSizeDWORD音頻緩沖區(qū)大小fDisableWriteCacheBOOL未使用AVStreamMasterUINT確定在寫(xiě)入AVI文件時(shí),音頻流是否控制時(shí)鐘wSize:表示psCapParms參數(shù)的大小。在

20、進(jìn)行視頻捕捉時(shí),通常會(huì)根據(jù)實(shí)際需要設(shè)置捕捉參數(shù)。例如,在視頻錄像時(shí),通常會(huì)將fYield成員設(shè)置為T(mén)RUE,啟動(dòng)后臺(tái)線(xiàn)程來(lái)進(jìn)行視頻錄像,這樣,前臺(tái)用戶(hù)依然可以進(jìn)行其他界面有關(guān)操作。2.2.5  回調(diào)函數(shù)設(shè)計(jì)在開(kāi)發(fā)視頻應(yīng)用程序時(shí),可以為視頻捕捉窗口設(shè)計(jì)一些回調(diào)函數(shù),這樣,當(dāng)視頻應(yīng)用程序的某些狀態(tài)改變時(shí),可以在回調(diào)函數(shù)中進(jìn)行處理。VFW提供了如下的函數(shù)進(jìn)行回調(diào)函數(shù)注冊(cè)。(1)capSetCallbackOnCapControl該函數(shù)提供了視頻捕捉時(shí)精確地控制捕捉開(kāi)始和結(jié)束的時(shí)間。語(yǔ)法如下:BOOL capSetCallbackOnCapControl(HWND hwnd,  C

21、APCONTROLCALLBACK fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示視頻捕捉回調(diào)函數(shù)指針,其定義如下:typedef LRESULT (CALLBACK* CAPCONTROLCALLBACK)(HWND hWnd, int nState);其中,hWnd表示視頻捕捉窗口句柄,nState參數(shù)如果設(shè)置為CONTROLCALLBACK_PREROLL,表示將要開(kāi)啟視頻源,為CONTROLCALLBACK_CAPTURING,表示應(yīng)用程序允許通過(guò)返回FALSE去結(jié)束視頻捕捉。(2)capSetCallbackOnError該函數(shù)用于為客戶(hù)端應(yīng)用程序設(shè)置

22、錯(cuò)誤處理的回調(diào)函數(shù)。語(yǔ)法如下:BOOL capSetCallbackOnError(HWND hwnd, CAPERRORCALLBACKA  fpProc);參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示錯(cuò)誤處理的回調(diào)函數(shù)指針,其定義如下:typedef LRESULT (CALLBACK* CAPERRORCALLBACKA)  (HWND hWnd, int nID, LPCSTR lpsz);其中,hWnd表示視頻捕捉窗口句柄,nID表示消息ID,lpsz表示消息文本描述。(3)capSetCallbackOnFrame該函數(shù)用于設(shè)置預(yù)覽回調(diào)函數(shù),回調(diào)

23、函數(shù)在預(yù)覽幀之前調(diào)用。語(yǔ)法如下:BOOL capSetCallbackOnFrame(HWND hwnd, CAPVIDEOCALLBACK  fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示預(yù)覽回調(diào)函數(shù)指針,其定義如下:typedef LRESULT (CALLBACK* CAPVIDEOCALLBACK)  (HWND hWnd, LPVIDEOHDR lpVHdr);其中, hWnd表示視頻捕捉窗口句柄,lpVHdr是一個(gè)VIDEOHDR結(jié)構(gòu)指針,表示視頻數(shù)據(jù)頭。(4)capSetCallbackOnStatus該函數(shù)用于在程序中設(shè)置一個(gè)

24、狀態(tài)回調(diào)函數(shù)。語(yǔ)法如下:BOOL capSetCallbackOnStatus(HWND hwnd,  CAPSTATUSCALLBACKA fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)應(yīng)用程序的狀態(tài)改變時(shí)將調(diào)用該函數(shù)。其定義如下:typedef LRESULT (CALLBACK* CAPSTATUSCALLBACKA) (HWND hWnd, int nID, LPCSTR lpsz);其中, hWnd表示視頻捕捉窗口句柄,nID表示狀態(tài)碼,lpsz表示狀態(tài)文本描述。(5)capSetCallbackOnVideoStream該函

25、數(shù)用于注冊(cè)一個(gè)回調(diào)函數(shù),使得視頻緩沖區(qū)被填充時(shí)調(diào)用回調(diào)函數(shù)。語(yǔ)法如下:BOOL capSetCallbackOnVideoStream(HWND hwnd, CAPVIDEOCALLBACK fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)視頻緩沖區(qū)被填充時(shí)調(diào)用回調(diào)函數(shù),其定義與capSetCallbackOnFrame函數(shù)的fpProc參數(shù)相同。(6)capSetCallbackOnWaveStream該函數(shù)用于注冊(cè)一個(gè)回調(diào)函數(shù),使得音頻緩沖區(qū)被填充時(shí)調(diào)用回調(diào)函數(shù)。語(yǔ)法如下:BOOL capSetCallbackOnWaveStream (HWN

26、D hwnd, CAPWAVECALLBACK fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)音頻緩沖區(qū)被填充時(shí)調(diào)用回調(diào)函數(shù)。其定義如下:typedef LRESULT (CALLBACK* CAPWAVECALLBACK)   (HWND hWnd, LPWAVEHDR lpWHdr);其中, hWnd表示視頻捕捉窗口句柄,lpWHdr是一個(gè)WAVEHDR結(jié)構(gòu)指針,表示音頻數(shù)據(jù)頭。(7)capSetCallbackOnYield該函數(shù)用于注冊(cè)一個(gè)回調(diào)函數(shù),使得在每一次捕捉視頻幀時(shí)調(diào)用一次回調(diào)函數(shù)。語(yǔ)法如下:BOOL capS

27、etCallbackOnYield(HWND hwnd,  fpProc );參數(shù)說(shuō)明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,其定義如下:typedef LRESULT (CALLBACK* CAPYIELDCALLBACK)  (HWND hWnd);其中, hWnd表示視頻捕捉窗口句柄。通常,該函數(shù)由消息循環(huán)構(gòu)成。VFW的回調(diào)函數(shù)在視頻預(yù)覽、視頻錄像、視頻壓縮等多個(gè)地方被廣泛使用。下面以統(tǒng)計(jì)預(yù)覽幀數(shù)為例介紹VFW回調(diào)函數(shù)的使用。效果如圖2.5所示。統(tǒng)計(jì)預(yù)覽幀數(shù) 圖2.5  回調(diào)函數(shù)設(shè)計(jì)程序設(shè)計(jì)步驟如下:  實(shí)例位置

28、:光盤(pán)mr22.22.2.501(1)創(chuàng)建一個(gè)基于對(duì)話(huà)框的工程,在對(duì)話(huà)框中添加靜態(tài)文本、圖像等控件,如圖2.6所示。圖2.6  回調(diào)函數(shù)設(shè)計(jì)窗口(2)利用類(lèi)向?qū)閳D像、靜態(tài)文本控件命令,如圖2.7所示。圖2.7  MFC類(lèi)向?qū)Т翱冢?)在對(duì)話(huà)框的頭文件中引用“vfw.h”頭文件,并導(dǎo)入“vfw32.lib”庫(kù)文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)向?qū)υ?huà)框中添加成員變量m_hWndVideo,作為預(yù)覽窗口的句柄。HWND   m_hWndVideo; /

29、視頻顯示窗口(5)定義一個(gè)全局變量,記錄當(dāng)前的預(yù)覽幀數(shù)。long num = 0;(6)定義一個(gè)全局函數(shù),作為視頻預(yù)覽的回調(diào)函數(shù)。LRESULT CALLBACK  PreviewCallback (HWND hWnd)   num+;   return 0;(7)處理對(duì)話(huà)框的WM_TIMER消息,將num數(shù)值顯示在界面中。void CCallbackDesigendDlg:OnTimer(UINT nIDEvent)    CString str;   str.Format("%i"

30、,num);   m_FrameNum.SetWindowText(str);   CDialog:OnTimer(nIDEvent);(8)在對(duì)話(huà)框初始化時(shí)創(chuàng)建視頻預(yù)覽窗口,設(shè)置預(yù)覽回調(diào)函數(shù),開(kāi)始視頻預(yù)覽。BOOL CCallbackDesigendDlg:OnInitDialog()   CDialog:OnInitDialog();   ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX);   ASSERT(IDM_ABOUTBOX <

31、 0xF000);   CMenu* pSysMenu = GetSystemMenu(FALSE);   if (pSysMenu != NULL)          CString strAboutMenu;       strAboutMenu.LoadString(IDS_ABOUTBOX);       if (!strAboutMenu.IsEm

32、pty()                     pSysMenu->AppendMenu(MF_SEPARATOR);              pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu)

33、;             SetIcon(m_hIcon, TRUE);       SetIcon(m_hIcon, FALSE);      /創(chuàng)建預(yù)覽窗口   m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);   /連接驅(qū)動(dòng)程序   if (cap

34、DriverConnect(m_hWndVideo,0)            :SetParent(m_hWndVideo,*this);       :SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);       CRect wndRC;       m_Panel.GetClie

35、ntRect(wndRC);       m_Panel.MapWindowPoints(this,wndRC);       wndRC.DeflateRect(1,1,1,1);       :SetWindowPos(m_hWndVideo,NULL,wndRC.left,       wndRC.top,wndRC.Width(),wndRC.Hei

36、ght(),SWP_NOZORDER);       :ShowWindow(m_hWndVideo,SW_SHOW);       capSetCallbackOnFrame(m_hWndVideo,PreviewCallback);       capPreviewRate(m_hWndVideo,30);       capPreview(m_hWnd

37、Video,TRUE);           SetTimer(1,800,NULL);   (9)在對(duì)話(huà)框關(guān)閉時(shí)斷開(kāi)視頻驅(qū)動(dòng)程序。void CCallbackDesigendDlg:OnCancel()    /斷開(kāi)驅(qū)動(dòng)程序連接   capDriverDisconnect(m_hWndVideo);   CDialog:OnCancel();2.2.6  視頻錄像設(shè)計(jì)方案在VFW中,可以有3種方式實(shí)現(xiàn)視頻錄像。其中,最簡(jiǎn)單的方式是調(diào)用

38、capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)。該種方式存在許多缺點(diǎn),例如,在錄像時(shí)無(wú)法響應(yīng)用戶(hù)界面,無(wú)法實(shí)現(xiàn)視頻壓縮等。第二種方式是調(diào)用capCaptureSetSetup函數(shù),將CAPTUREPARMS結(jié)構(gòu)的fYield成員設(shè)置為T(mén)RUE,啟動(dòng)后臺(tái)線(xiàn)程來(lái)實(shí)現(xiàn)錄像,然后調(diào)用capDlgVideoCompression函數(shù)讓用戶(hù)選擇壓縮器進(jìn)行壓縮,最后調(diào)用capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)開(kāi)始錄像。第二種方式的缺點(diǎn)是每次錄像時(shí)都需要彈出一個(gè)對(duì)話(huà)框,讓用戶(hù)選擇一種壓縮器。第三種方式是注冊(cè)回調(diào)函數(shù)cap

39、SetCallbackOnVideoStream,在回調(diào)函數(shù)中壓縮數(shù)據(jù)并寫(xiě)入AVI文件。相對(duì)于前兩種方式,第三種方式更為靈活和實(shí)用,因此在進(jìn)行視頻錄像時(shí),通常采用該種方式實(shí)現(xiàn)。具體實(shí)現(xiàn)過(guò)程如下:(1)定義一個(gè)回調(diào)函數(shù),該回調(diào)函數(shù)實(shí)現(xiàn)數(shù)據(jù)壓縮,并將壓縮的數(shù)據(jù)寫(xiě)入文件流中。(2)調(diào)用capSetCallbackOnVideoStream注冊(cè)回調(diào)函數(shù)。(3)調(diào)用ICOpen函數(shù)打開(kāi)一個(gè)壓縮器,并調(diào)用ICCompressBegin函數(shù)開(kāi)始?jí)嚎s。(4)調(diào)用AVIFileOpen函數(shù)打開(kāi)一個(gè)AVI文件,并調(diào)用AVIFileCreateStream函數(shù)創(chuàng)建文件流。(5)調(diào)用capCaptureSequenc

40、eNoFile函數(shù)開(kāi)始錄像。下面以一個(gè)具體實(shí)例介紹如何采用第三種方式實(shí)現(xiàn)視頻錄像。效果如圖2.8所示。圖2.8  視頻錄像設(shè)計(jì)方案  實(shí)例位置:光盤(pán)mr22.22.2.601(1)創(chuàng)建一個(gè)基于對(duì)話(huà)框的工程,在對(duì)話(huà)框中添加按鈕、圖像控件,如圖2.9所示。圖2.9  對(duì)話(huà)框資源設(shè)計(jì)(2)在對(duì)話(huà)框的頭文件中引用“vfw.h”頭文件,并導(dǎo)入“vfw32.lib”庫(kù)文件。#include "vfw.h"#pragma comment (lib,"vfw32")(3)向?qū)υ?huà)框類(lèi)中添加成員變量。DWORD   

41、;        m_Frame;              /記錄幀數(shù)COMPVARS        m_Com;                /壓縮參數(shù)BITMAPINFO&

42、#160;    m_InInfo,m_OutInfo; /位圖格式PAVIFILE        m_pFile;              /AVI文件AVISTREAMINFO  strhdr;             &#

43、160; /AVI流信息PAVISTREAM      ps;                   /AVI流指針BOOL             m_Captured;      

44、0;   /是否開(kāi)始捕捉(4)定義一個(gè)回調(diào)函數(shù),在流捕捉時(shí)執(zhí)行。LRESULT WINAPI EncodeCallback(HWND hWnd, LPVIDEOHDR lpVHdr)   CVideoEncodeDlg* pDlg = (CVideoEncodeDlg*)AfxGetMainWnd();   if (pDlg->m_Captured) && (lpVHdr->dwFlags&VHDR_DONE)        &#

45、160; char* buffer = new char lpVHdr->dwBytesUsed+1;       memset(buffer,0,lpVHdr->dwBytesUsed+1);       DWORD dwCkID         ;        DWORD dwCompFlags  &

46、#160; ;        DWORD dwQuality = 100;               /視頻壓縮       if (ICCompress(pDlg->m_Com.hic, 0, &pDlg->m_OutInfo.bmiHeader, buffer, &pDlg->m_InInfo.bmiHead

47、er,               (unsigned char *)lpVHdr->lpData, &dwCkID, &dwCompFlags, pDlg->m_Frame+,0, dwQuality, NULL, NULL) = ICERR_OK)                

48、;     AVIStreamSetFormat(pDlg->ps,pDlg->m_Frame,&pDlg->m_OutInfo,sizeof(pDlg->m_OutInfo);              AVIStreamWrite(pDlg->ps,pDlg->m_Frame ,1, (LPBYTE)  buffer,pDlg->m_OutInfo.bmiHead

49、er.biSizeImage ,AVIIF_KEYFRAME,NULL,NULL);              delete buffer;       return 1;(5)在對(duì)話(huà)框初始化時(shí)開(kāi)始視頻預(yù)覽,設(shè)置視頻參數(shù)。m_Captured = FALSE;m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);/連接驅(qū)動(dòng)程序if (cap

50、DriverConnect(m_hWndVideo,0)     :SetParent(m_hWndVideo,*this);   :SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);   CRect wndRC;   m_Panel.GetClientRect(wndRC);   m_Panel.MapWindowPoints(this,wndRC);   wndRC.DeflateRect(1,1,1,1); 

51、  :SetWindowPos(m_hWndVideo,NULL,wndRC.left,wndRC.top,wndRC.Width(),wndRC.Height(),SWP_NOZORDER);   :ShowWindow(m_hWndVideo,SW_SHOW);   CAPDRIVERCAPS caps;   capDriverGetCaps(m_hWndVideo,sizeof(caps),&caps);   if (caps.fHasOverlay)   &#

52、160;   capOverlay(m_hWndVideo,TRUE);   CAPTUREPARMS params;   capCaptureGetSetup(m_hWndVideo,&params,sizeof(params);   params.fYield           = TRUE;   params.fAbortLeftMouse  = FALSE; 

53、  params.fAbortRightMouse = FALSE;   params.fLimitEnabled    = FALSE;   params.vKeyAbort        = FALSE;   params.fCaptureAudio    = FALSE;      capCaptureSetSetup(m_hWndVideo,&

54、;params,sizeof(params);   capSetCallbackOnVideoStream(m_hWndVideo,EncodeCallback);   capPreviewRate(m_hWndVideo,30);   capPreview(m_hWndVideo,TRUE);(6)向?qū)υ?huà)框中添加InitCompress方法,設(shè)置壓縮參數(shù)信息。void CVideoEncodeDlg:InitCompress()   capGetVideoFormat(m_hWndVideo,&m_InI

55、nfo ,sizeof(BITMAPINFO);   capGetVideoFormat(m_hWndVideo,&m_OutInfo,sizeof(BITMAPINFO);   memset(&m_Com,0,sizeof(COMPVARS);     m_Com.cbSize=sizeof(m_Com);    /利用代碼選擇壓縮器   m_Com.dwFlags=ICMF_COMPVARS_VALID;     m_Com.fccHa

56、ndler=mmioFOURCC('x','v','i','d');   m_Com.fccType=ICTYPE_VIDEO;      m_Com.lFrame=0;      m_Com.lKey=15;      m_Com.lKeyCount=0;     m_Com.lDataRate = 780;   m_Com.lpbiOut=

57、(BITMAPINFO*)&m_OutInfo;      m_Com.hic= ICOpen(ICTYPE_VIDEO,mmioFOURCC('x','v','i','d'),ICMODE_COMPRESS);   m_Com.cbState = 1180;   /利用對(duì)話(huà)框選擇壓縮器   / ICCompressorChoose(NULL,ICMF_CHOOSE_ALLCOMPRESSORS ,(LPVOID)&m_InI

58、nfo,NULL,&m_Com,"選擇壓縮類(lèi)型");   ICCompressGetFormat(m_Com.hic,&m_InInfo.bmiHeader,&m_OutInfo.bmiHeader);   /開(kāi)始?jí)嚎s   int ret = ICCompressBegin(m_Com.hic,(BITMAPINFO*)&m_InInfo,(BITMAPINFO*)&m_OutInfo);   if (ret!=ICERR_OK )  

59、     MessageBox("壓縮失敗");(7)處理“錄像”按鈕的單擊事件,開(kāi)始視頻錄像。void CVideoEncodeDlg:OnOK()    CString filename;   CFileDialog FileDlg(FALSE,"avi");   if (FileDlg.DoModal()=IDOK)          filename = FileDlg

60、.GetPathName();       capGetVideoFormat(m_hWndVideo,&m_InInfo,sizeof(m_InInfo);       m_Frame = 0 ;       /AVI文件初始化       AVIFileInit() ;       /設(shè)

61、置壓縮參數(shù)       InitCompress();       /打開(kāi)文件       AVIFileOpen(&m_pFile,filename,OF_WRITE | OF_CREATE,NULL);       memset(&strhdr, 0, sizeof(strhdr) ;    

62、60;  strhdr.fccType    = streamtypeVIDEO;        strhdr.fccHandler = 0  ;       strhdr.dwScale    = 1  ;       strhdr.dwRate     = 15 ;  

63、60;     strhdr.dwSuggestedBufferSize = m_InInfo.bmiHeader.biSizeImage;       SetRect(&strhdr.rcFrame, 0, 0, m_InInfo.bmiHeader.biWidth, m_InInfo.bmiHeader.biHeight);       ps = NULL;     

64、;  /文件文件流       AVIFileCreateStream(m_pFile,&ps,&strhdr);        m_Captured = TRUE;       /開(kāi)始捕捉       capCaptureSequenceNoFile(m_hWndVideo);   (8)在對(duì)話(huà)框關(guān)閉時(shí)停止視頻

65、錄像。void CVideoEncodeDlg:OnCancel()    /終止回調(diào)函數(shù)   capSetCallbackOnVideoStream(m_hWndVideo,NULL);   /結(jié)束數(shù)據(jù)壓縮   ICCompressEnd(m_Com.hic);   /關(guān)閉壓縮句柄   ICClose(m_Com.hic);   if (m_Captured)         

66、; /關(guān)閉AVI文件流       AVIStreamClose(ps);       if(m_pFile != NULL)              AVIFileRelease(m_pFile);       AVIFileExit();    

67、0;    /停止捕捉   capCaptureStop(m_hWndVideo);   /斷開(kāi)驅(qū)動(dòng)程序連接   capDriverDisconnect(m_hWndVideo);   CDialog:OnCancel();2.3  DirectShow視頻采集方案流媒體處理技術(shù)以其復(fù)雜性和技術(shù)性一直受到人們的關(guān)注。隨著網(wǎng)絡(luò)技術(shù)的不斷發(fā)展,流媒體在網(wǎng)絡(luò)上得到了廣泛地應(yīng)用。如何能夠簡(jiǎn)單、有效地進(jìn)行流媒體處理,已成為一個(gè)焦點(diǎn)問(wèn)題。為此,Microsoft推出了DirectShow,Dire

68、ctShow是Microsoft推出的基于Windows平臺(tái)的流媒體處理開(kāi)發(fā)包,它與DirectX一起發(fā)布。DirectShow對(duì)流媒體的捕捉、回放提供了強(qiáng)大的支持,使用它還可以在基于WDM驅(qū)動(dòng)的采集卡上進(jìn)行數(shù)據(jù)捕捉。本節(jié)將介紹有關(guān)DirectShow的相關(guān)知識(shí)。2.3.1  DirectShow系統(tǒng)結(jié)構(gòu)分析DirectShow主要由過(guò)濾器(Filter Graph)圖表構(gòu)成。過(guò)濾圖表中包含了各種Filter,這些Filter能夠按一定順序連接在一起,構(gòu)成一條流水線(xiàn)。從功能的角度劃分,F(xiàn)ilter大體可以分為3類(lèi),Source Filters、Transform Filters和Re

69、ndering Filters。Source Filters主要負(fù)責(zé)獲取數(shù)據(jù),可以是一個(gè)文件、一個(gè)采集卡、聲卡或數(shù)碼相機(jī)等。Transform Filters負(fù)責(zé)數(shù)據(jù)的轉(zhuǎn)換、傳輸。例如各種編碼器、解碼器等。Rendering Filters負(fù)責(zé)數(shù)據(jù)的最終去向,例如將數(shù)據(jù)傳送到聲卡、顯卡或存儲(chǔ)為文件。在開(kāi)發(fā)DirectShow應(yīng)用程序時(shí),通常需要設(shè)計(jì)一個(gè)過(guò)濾圖表(Filter Graph),向過(guò)濾圖表中添加相應(yīng)的過(guò)濾器,最后連接過(guò)濾器的引腳就完成了功能的設(shè)計(jì)。例如,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的視頻預(yù)覽功能,需要向過(guò)濾圖表中添加一個(gè)視頻捕捉源過(guò)濾器和一個(gè)Video Renderer過(guò)濾  器,將視頻捕

70、捉源過(guò)濾器的輸出引腳與Video Renderer過(guò)濾器的輸入引腳相連就可以了。而在程序中只需要按照設(shè)計(jì)過(guò)濾圖表的捕捉添加過(guò)濾器并連接過(guò)濾器引腳就可以了。在連接過(guò)濾器引腳時(shí)需要注意:只能是輸出過(guò)濾器引腳與輸入過(guò)濾器引腳相連,兩個(gè)輸出過(guò)濾器或兩個(gè)輸入過(guò)濾器引腳是不能相連的。為了在程序中使用DirectShow,需要單獨(dú)安裝DirectX,當(dāng)前DirectX的最新版本為9.0,即DirectX9.0,用戶(hù)可以從Microsoft的官方網(wǎng)站上免費(fèi)下載。在安裝DirectX之后,程序中需要引用“dshow.h”頭文件,并導(dǎo)入“Strmiids.lib”庫(kù)文件和“quartz.lib”庫(kù)文件才可以使用D

71、irectShow。代碼如下:#pragma comment (lib,"Strmiids")#pragma comment (lib,"quartz")#include <dshow.h>2.3.2  Filter圖表設(shè)計(jì)為了方便用戶(hù)設(shè)計(jì)過(guò)濾圖表,DirectX提供了一個(gè)Graph Edit工具。用戶(hù)可以單擊“開(kāi)始”菜單下的“Microsoft DirectX 9 SDKDirectX UtilitiesGraph Edit”菜單項(xiàng)打開(kāi)Graph Edit工具,如圖2.10所示。圖2.10  Graph Edit工具下面

72、筆者介紹如何使用Graph Edit工具設(shè)計(jì)過(guò)濾圖表,過(guò)濾圖表的功能是實(shí)現(xiàn)視頻的預(yù)覽功能。具體步驟如下:(1)在圖2.4中單擊“Graph/Insert Filters”菜單項(xiàng)打開(kāi)“添加過(guò)濾器”窗口,如圖2.11所示。圖2.11  添加過(guò)濾器窗口(2)在“Video Capture Sources”節(jié)點(diǎn)下選擇一個(gè)視頻捕捉源過(guò)濾器,單擊“Insert Filter”按鈕將其添加到過(guò)濾圖表中,如圖2.12所示圖2.12  添加視頻捕捉源過(guò)濾器窗口提示:如果系統(tǒng)中沒(méi)有安裝攝像頭及其驅(qū)動(dòng)程序,該節(jié)點(diǎn)下將不會(huì)有視頻捕捉源過(guò)濾器。(3)在“DirectShow Filters”節(jié)點(diǎn)下選

73、擇“Video Renderer”過(guò)濾器,將其添加到圖表中,如圖2.13所示。圖2.13  添加“Video Renderer”過(guò)濾器窗口(4)利用鼠標(biāo)將視頻捕捉源過(guò)濾器的“Capture”引腳與“Video Renderer”過(guò)濾器的“VMR Input0”引腳相連,如圖2.14所示。圖2.14  連接過(guò)濾器引腳窗口(5)單擊工具欄中的“”按鈕運(yùn)行過(guò)濾圖表,將顯示一個(gè)視頻預(yù)覽窗口,如圖2.15所示。圖2.15  視頻預(yù)覽窗口2.3.3  枚舉系統(tǒng)設(shè)備使用Graph Edit工具,用戶(hù)可以非常方便地獲得與某一系統(tǒng)設(shè)備相關(guān)的過(guò)濾器。但是,在程序中該如何獲得

74、這些過(guò)濾器呢?用戶(hù)可以采用枚舉的方式列舉系統(tǒng)中安裝的設(shè)備。以列舉系統(tǒng)中的視頻捕捉設(shè)備為例,首先定義一個(gè)設(shè)備列舉接口ICreateDevEnum的一個(gè)指針,調(diào)用CoCreateInstance方法創(chuàng)建ICreateDevEnum實(shí)例,然后定義一個(gè)列舉監(jiān)視器IEnumMoniker的一個(gè)指針,調(diào)用ICreateDevEnum實(shí)例的CreateClassEnumerator方法創(chuàng)建IEnumMoniker實(shí)例,最后以循環(huán)的方式調(diào)用IEnumMoniker實(shí)例的Next方法遍歷系統(tǒng)設(shè)備,調(diào)用IEnumMoniker實(shí)例的BindToObject方法將系統(tǒng)設(shè)備綁定到過(guò)濾器上。在上面的描述中,ICreateDevEnum實(shí)例的CreateClassEnumerator方法的第一個(gè)參數(shù)確定枚舉的系統(tǒng)設(shè)備。例如,第一個(gè)參數(shù)為CLSID_VideoInputDeviceCategory,表示將要枚舉系統(tǒng)中的視頻捕捉卡,為CLSID_VideoCompressorCategory,表示枚舉系統(tǒng)中的視頻

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論