




版權(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,¶ms,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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 工地供應(yīng)合同范本
- 房屋裝修解約合同范本
- 2025-2030年中國(guó)甲醇制芳烴行業(yè)發(fā)展?fàn)顩r及營(yíng)銷(xiāo)戰(zhàn)略研究報(bào)告
- 2025-2030年中國(guó)橋式起重機(jī)市場(chǎng)十三五規(guī)劃與投資戰(zhàn)略研究報(bào)告
- 2025-2030年中國(guó)枳殼行業(yè)前景展望規(guī)劃研究報(bào)告
- 2025-2030年中國(guó)開(kāi)關(guān)穩(wěn)壓電源供應(yīng)器市場(chǎng)規(guī)模分析及發(fā)展建議研究報(bào)告
- 2025-2030年中國(guó)參茸滋補(bǔ)品行業(yè)運(yùn)行態(tài)勢(shì)規(guī)劃研究報(bào)告
- 2025-2030年中國(guó)動(dòng)物膽汁提取脫氧膽酸市場(chǎng)發(fā)展?fàn)顩r及營(yíng)銷(xiāo)戰(zhàn)略研究報(bào)告
- 2025-2030年中國(guó)冷凍冷藏產(chǎn)業(yè)市場(chǎng)運(yùn)營(yíng)現(xiàn)狀及投資戰(zhàn)略研究報(bào)告
- 2025-2030年中國(guó)獸用生物制品市場(chǎng)發(fā)展?fàn)顩r及營(yíng)銷(xiāo)戰(zhàn)略研究報(bào)告
- 轉(zhuǎn)基因調(diào)查分析報(bào)告
- 英語(yǔ)-時(shí)文閱讀-7年級(jí)(8篇)
- 數(shù)據(jù)挖掘(第2版)全套教學(xué)課件
- 產(chǎn)學(xué)研融合創(chuàng)新合作機(jī)制
- 胃早癌-經(jīng)典課件
- 幕墻工安全技術(shù)交底
- 集裝箱七點(diǎn)檢查表
- 7S管理標(biāo)準(zhǔn)目視化管理標(biāo)準(zhǔn)
- 籃球場(chǎng)改造工程投標(biāo)方案(技術(shù)方案)
- 茉莉花的生長(zhǎng)習(xí)性及栽培管理辦法
- 蛤蟆先生去看心理醫(yī)生
評(píng)論
0/150
提交評(píng)論