




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、2.2 VFW視頻采集方案VFW是Microsoft于1992年推出的數(shù)字視頻軟件包,它不依賴于專用的硬件設(shè)備,提供了通用的數(shù)字視頻開發(fā)方案。VFW主要由AVICap.dll、MSVideo.dll、MCIAvi.drv、AVIFile.dll、vfw32.lib等庫文件組成,這些庫提供了相關(guān)視頻、音頻、AVI文件的函數(shù),本節(jié)將介紹如何利用這些函數(shù)進(jìn)行視頻采集。2.2.1 開發(fā)流程分析VFW使用的視頻函數(shù)被封裝在vfw32.lib庫文件中,該庫文件默認(rèn)情況下沒有被連接到MFC工程中,因此使用VFW進(jìn)行視頻開發(fā)的第一步是導(dǎo)入vfw32.lib庫文件。方法如下:(1)引用v
2、fw.h頭文件。#include "vfw.h"(2)導(dǎo)入vfw32.lib庫文件。#pragma comment (lib,"vfw32")步驟2也可以在通過工程選項(xiàng)窗口的連接選項(xiàng)卡進(jìn)行設(shè)置。如圖2.1所示。連接vfw32.lib庫文件 圖2.1 工程選項(xiàng)窗口在導(dǎo)入vfw32.lib庫文件后便可以使用視頻函數(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視頻捕捉開發(fā)流程具體步驟如下:(1)引用“vfw.h”頭文件并導(dǎo)入vfw32.lib庫。(2)創(chuàng)建一個(gè)線程,在線程函數(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ù)開始預(yù)覽。2.2.2 視頻窗口創(chuàng)建在進(jìn)行視頻程序開發(fā)時(shí),第一步需要?jiǎng)?chuàng)建一個(gè)視頻預(yù)覽窗口。在程序中可以使用capCreateCapture
4、Window函數(shù)來創(chuàng)建視頻預(yù)覽窗口,該函數(shù)語法如下:HWND VFWAPI capCreateCaptureWindow(LPCSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWnd, int nID);參數(shù)說明:lpszWindowName:表示視頻捕捉窗口的名稱。dwStyle:
5、表示視頻捕獲窗口的風(fēng)格,一般包含有WS_CHILD 和 WS_VISIBLE風(fēng)格。x、y:表示視頻捕捉窗口的左上角坐標(biāo)。nWidth、nHeight:表示視頻捕捉窗口的寬度和高度。hWnd:表示視頻捕捉窗口父窗口的句柄。nID:表示視頻捕捉窗口標(biāo)識(shí)。在創(chuàng)建視頻捕捉窗口之后,需要將其顯示在對(duì)話框中的適當(dāng)位置??梢栽趯?duì)話框中預(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)在開發(fā)視頻應(yīng)用程序時(shí),第一步需要實(shí)現(xiàn)的功能便是視頻預(yù)覽。在2.2.1節(jié)中筆者曾分析了視頻預(yù)覽的實(shí)現(xiàn)過程,下面以一個(gè)具體實(shí)例來說明VFW視頻預(yù)覽的實(shí)現(xiàn)過程。效果如圖2.2所示。圖2.2 視頻預(yù)覽實(shí)現(xiàn)程序設(shè)計(jì)步驟如下: 實(shí)例位置:光盤mr22.22.2.301(1)創(chuàng)建一個(gè)基于對(duì)話框的工程,在對(duì)話框中添加Picture控件,如圖2.3所示。圖2.3 視頻預(yù)覽設(shè)計(jì)窗口(2)在類向?qū)У摹癕ember Variables”選項(xiàng)卡中為Picture控件命名,如圖2.4所示。圖2.4 類向?qū)Т翱冢?)在對(duì)話
8、框的頭文件中引用“vfw.h”頭文件,然后鏈接“vfw32.lib”庫文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)在對(duì)話框中定義一個(gè)視頻預(yù)覽窗口的句柄。HWND m_hWndVideo; /視頻顯示窗口(5)在對(duì)話框初始化時(shí)創(chuàng)建視頻預(yù)覽窗口,連接視頻驅(qū)動(dòng)程序,設(shè)置預(yù)覽幀率,開始視頻預(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ì)話框關(guān)閉時(shí)斷開視頻驅(qū)動(dòng)程序。void CVideoPreviewDlg:OnCancel() /斷開驅(qū)動(dòng)程序連接 capDriverDisconnect(m_hWndVideo); CDialog:OnCancel();2.2.4 捕捉參數(shù)設(shè)置在進(jìn)行視頻捕捉時(shí),通常需要設(shè)置視頻捕捉參數(shù)。VFW提供了capCaptureSetSetup函數(shù)用于設(shè)置視頻捕捉參數(shù),該函數(shù)語法如下:BOOL capCaptureSetSetup(HWND hwnd, LPCAPTUREPARMS psCapParms,
16、UINT wSize );參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。psCapParms:表示視頻捕捉參數(shù),該參數(shù)是CAPTUREPARMS結(jié)構(gòu)指針。CAPTUREPARMS結(jié)構(gòu)成員描述如表2.1所示。表2.1 CAPTUREPARMS結(jié)構(gòu)成員描述成員名稱成員類型描述dwRequestMicroSecPerFrameDWORD以毫秒為單位設(shè)置捕捉幀率,默認(rèn)值為66667,即每秒15幀fMakeUserHitOKToCaptureBOOL如果為TRUE,將顯示一個(gè)對(duì)話框幫助用戶快速地進(jìn)行捕捉設(shè)置wPerentDropForErrorUINT在捕捉過程中允許棄幀的最大百分比fYield
17、BOOL如果為TRUE,將產(chǎn)生一個(gè)后臺(tái)線程來進(jìn)行視頻捕捉dwIndexSizeDWORD表示AVI文件最大的索引入口數(shù)wChunkGranularityUINT以字節(jié)為單位表示AVI文件的大小fUsingDOSMemoryBOOL未使用wNumVideoRequestedUINT分配視頻緩沖區(qū)的最大數(shù)量fCaptureAudioBOOL為TRUE,表示音頻被捕捉,默認(rèn)值依賴于安裝的音頻設(shè)備wNumAudioRequestedUINT表示分配的音頻緩沖區(qū)的最大數(shù)量vKeyAbortUINT表示終止捕捉的虛擬鍵fAbortLeftMouseBOOL為TRUE,表示單擊鼠標(biāo)左鍵停止捕捉fAbortR
18、ightMouseBOOL為TRUE,表示單擊鼠標(biāo)右鍵停止捕捉fLimitEnabledBOOL為TRUE,表示設(shè)置捕捉時(shí)間限制wTimeLimitUINT以秒為單位設(shè)置捕捉的超時(shí)時(shí)間fMCIControlBOOL為TRUE,控制MCI(媒體設(shè)備接口)兼容的視頻源fStepMCIDeviceBOOL為TRUE,使用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為TRUE,捕捉的視頻幀使用兩個(gè)分辨率,它可以使用軟件在某個(gè)分辨率的基礎(chǔ)上改寫像素,將其該為高清晰度的圖像wStepCaptureAverageFramesUINT在捕捉時(shí)每幀圖像使用的時(shí)間大小dwAudioBufferSizeDWORD音頻緩沖區(qū)大小fDisableWriteCacheBOOL未使用AVStreamMasterUINT確定在寫入AVI文件時(shí),音頻流是否控制時(shí)鐘wSize:表示psCapParms參數(shù)的大小。在
20、進(jìn)行視頻捕捉時(shí),通常會(huì)根據(jù)實(shí)際需要設(shè)置捕捉參數(shù)。例如,在視頻錄像時(shí),通常會(huì)將fYield成員設(shè)置為TRUE,啟動(dòng)后臺(tái)線程來進(jìn)行視頻錄像,這樣,前臺(tái)用戶依然可以進(jìn)行其他界面有關(guān)操作。2.2.5 回調(diào)函數(shù)設(shè)計(jì)在開發(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í)精確地控制捕捉開始和結(jié)束的時(shí)間。語法如下:BOOL capSetCallbackOnCapControl(HWND hwnd, C
21、APCONTROLCALLBACK fpProc );參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示視頻捕捉回調(diào)函數(shù)指針,其定義如下:typedef LRESULT (CALLBACK* CAPCONTROLCALLBACK)(HWND hWnd, int nState);其中,hWnd表示視頻捕捉窗口句柄,nState參數(shù)如果設(shè)置為CONTROLCALLBACK_PREROLL,表示將要開啟視頻源,為CONTROLCALLBACK_CAPTURING,表示應(yīng)用程序允許通過返回FALSE去結(jié)束視頻捕捉。(2)capSetCallbackOnError該函數(shù)用于為客戶端應(yīng)用程序設(shè)置
22、錯(cuò)誤處理的回調(diào)函數(shù)。語法如下:BOOL capSetCallbackOnError(HWND hwnd, CAPERRORCALLBACKA fpProc);參數(shù)說明: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)用。語法如下:BOOL capSetCallbackOnFrame(HWND hwnd, CAPVIDEOCALLBACK fpProc );參數(shù)說明: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ù)。語法如下:BOOL capSetCallbackOnStatus(HWND hwnd, CAPSTATUSCALLBACKA fpProc );參數(shù)說明: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ù)。語法如下:BOOL capSetCallbackOnVideoStream(HWND hwnd, CAPVIDEOCALLBACK fpProc );參數(shù)說明: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ù)。語法如下:BOOL capSetCallbackOnWaveStream (HWN
26、D hwnd, CAPWAVECALLBACK fpProc );參數(shù)說明: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ù)。語法如下:BOOL capS
27、etCallbackOnYield(HWND hwnd, fpProc );參數(shù)說明: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、:光盤mr22.22.2.501(1)創(chuàng)建一個(gè)基于對(duì)話框的工程,在對(duì)話框中添加靜態(tài)文本、圖像等控件,如圖2.6所示。圖2.6 回調(diào)函數(shù)設(shè)計(jì)窗口(2)利用類向?qū)閳D像、靜態(tài)文本控件命令,如圖2.7所示。圖2.7 MFC類向?qū)Т翱冢?)在對(duì)話框的頭文件中引用“vfw.h”頭文件,并導(dǎo)入“vfw32.lib”庫文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)向?qū)υ捒蛑刑砑映蓡T變量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ì)話框的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ì)話框初始化時(shí)創(chuàng)建視頻預(yù)覽窗口,設(shè)置預(yù)覽回調(diào)函數(shù),開始視頻預(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ì)話框關(guān)閉時(shí)斷開視頻驅(qū)動(dòng)程序。void CCallbackDesigendDlg:OnCancel() /斷開驅(qū)動(dòng)程序連接 capDriverDisconnect(m_hWndVideo); CDialog:OnCancel();2.2.6 視頻錄像設(shè)計(jì)方案在VFW中,可以有3種方式實(shí)現(xiàn)視頻錄像。其中,最簡單的方式是調(diào)用
38、capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)。該種方式存在許多缺點(diǎn),例如,在錄像時(shí)無法響應(yīng)用戶界面,無法實(shí)現(xiàn)視頻壓縮等。第二種方式是調(diào)用capCaptureSetSetup函數(shù),將CAPTUREPARMS結(jié)構(gòu)的fYield成員設(shè)置為TRUE,啟動(dòng)后臺(tái)線程來實(shí)現(xiàn)錄像,然后調(diào)用capDlgVideoCompression函數(shù)讓用戶選擇壓縮器進(jìn)行壓縮,最后調(diào)用capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)開始錄像。第二種方式的缺點(diǎn)是每次錄像時(shí)都需要彈出一個(gè)對(duì)話框,讓用戶選擇一種壓縮器。第三種方式是注冊(cè)回調(diào)函數(shù)cap
39、SetCallbackOnVideoStream,在回調(diào)函數(shù)中壓縮數(shù)據(jù)并寫入AVI文件。相對(duì)于前兩種方式,第三種方式更為靈活和實(shí)用,因此在進(jìn)行視頻錄像時(shí),通常采用該種方式實(shí)現(xiàn)。具體實(shí)現(xiàn)過程如下:(1)定義一個(gè)回調(diào)函數(shù),該回調(diào)函數(shù)實(shí)現(xiàn)數(shù)據(jù)壓縮,并將壓縮的數(shù)據(jù)寫入文件流中。(2)調(diào)用capSetCallbackOnVideoStream注冊(cè)回調(diào)函數(shù)。(3)調(diào)用ICOpen函數(shù)打開一個(gè)壓縮器,并調(diào)用ICCompressBegin函數(shù)開始?jí)嚎s。(4)調(diào)用AVIFileOpen函數(shù)打開一個(gè)AVI文件,并調(diào)用AVIFileCreateStream函數(shù)創(chuàng)建文件流。(5)調(diào)用capCaptureSequenc
40、eNoFile函數(shù)開始錄像。下面以一個(gè)具體實(shí)例介紹如何采用第三種方式實(shí)現(xiàn)視頻錄像。效果如圖2.8所示。圖2.8 視頻錄像設(shè)計(jì)方案 實(shí)例位置:光盤mr22.22.2.601(1)創(chuàng)建一個(gè)基于對(duì)話框的工程,在對(duì)話框中添加按鈕、圖像控件,如圖2.9所示。圖2.9 對(duì)話框資源設(shè)計(jì)(2)在對(duì)話框的頭文件中引用“vfw.h”頭文件,并導(dǎo)入“vfw32.lib”庫文件。#include "vfw.h"#pragma comment (lib,"vfw32")(3)向?qū)υ捒蝾愔刑砑映蓡T變量。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; /是否開始捕捉(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ì)話框初始化時(shí)開始視頻預(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ū)υ捒蛑刑砑覫nitCompress方法,設(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ì)話框選擇壓縮器 / ICCompressorChoose(NULL,ICMF_CHOOSE_ALLCOMPRESSORS ,(LPVOID)&m_InI
58、nfo,NULL,&m_Com,"選擇壓縮類型"); ICCompressGetFormat(m_Com.hic,&m_InInfo.bmiHeader,&m_OutInfo.bmiHeader); /開始?jí)嚎s int ret = ICCompressBegin(m_Com.hic,(BITMAPINFO*)&m_InInfo,(BITMAPINFO*)&m_OutInfo); if (ret!=ICERR_OK )
59、 MessageBox("壓縮失敗");(7)處理“錄像”按鈕的單擊事件,開始視頻錄像。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(); /打開文件 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; /開始捕捉 capCaptureSequenceNoFile(m_hWndVideo); (8)在對(duì)話框關(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); /斷開驅(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)用。如何能夠簡單、有效地進(jìn)行流媒體處理,已成為一個(gè)焦點(diǎn)問題。為此,Microsoft推出了DirectShow,Dire
68、ctShow是Microsoft推出的基于Windows平臺(tá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主要由過濾器(Filter Graph)圖表構(gòu)成。過濾圖表中包含了各種Filter,這些Filter能夠按一定順序連接在一起,構(gòu)成一條流水線。從功能的角度劃分,F(xiàn)ilter大體可以分為3類,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ǔ)為文件。在開發(fā)DirectShow應(yīng)用程序時(shí),通常需要設(shè)計(jì)一個(gè)過濾圖表(Filter Graph),向過濾圖表中添加相應(yīng)的過濾器,最后連接過濾器的引腳就完成了功能的設(shè)計(jì)。例如,實(shí)現(xiàn)一個(gè)簡單的視頻預(yù)覽功能,需要向過濾圖表中添加一個(gè)視頻捕捉源過濾器和一個(gè)Video Renderer過濾 器,將視頻捕
70、捉源過濾器的輸出引腳與Video Renderer過濾器的輸入引腳相連就可以了。而在程序中只需要按照設(shè)計(jì)過濾圖表的捕捉添加過濾器并連接過濾器引腳就可以了。在連接過濾器引腳時(shí)需要注意:只能是輸出過濾器引腳與輸入過濾器引腳相連,兩個(gè)輸出過濾器或兩個(gè)輸入過濾器引腳是不能相連的。為了在程序中使用DirectShow,需要單獨(dú)安裝DirectX,當(dāng)前DirectX的最新版本為9.0,即DirectX9.0,用戶可以從Microsoft的官方網(wǎng)站上免費(fèi)下載。在安裝DirectX之后,程序中需要引用“dshow.h”頭文件,并導(dǎo)入“Strmiids.lib”庫文件和“quartz.lib”庫文件才可以使用D
71、irectShow。代碼如下:#pragma comment (lib,"Strmiids")#pragma comment (lib,"quartz")#include <dshow.h>2.3.2 Filter圖表設(shè)計(jì)為了方便用戶設(shè)計(jì)過濾圖表,DirectX提供了一個(gè)Graph Edit工具。用戶可以單擊“開始”菜單下的“Microsoft DirectX 9 SDKDirectX UtilitiesGraph Edit”菜單項(xiàng)打開Graph Edit工具,如圖2.10所示。圖2.10 Graph Edit工具下面
72、筆者介紹如何使用Graph Edit工具設(shè)計(jì)過濾圖表,過濾圖表的功能是實(shí)現(xiàn)視頻的預(yù)覽功能。具體步驟如下:(1)在圖2.4中單擊“Graph/Insert Filters”菜單項(xiàng)打開“添加過濾器”窗口,如圖2.11所示。圖2.11 添加過濾器窗口(2)在“Video Capture Sources”節(jié)點(diǎn)下選擇一個(gè)視頻捕捉源過濾器,單擊“Insert Filter”按鈕將其添加到過濾圖表中,如圖2.12所示圖2.12 添加視頻捕捉源過濾器窗口提示:如果系統(tǒng)中沒有安裝攝像頭及其驅(qū)動(dòng)程序,該節(jié)點(diǎn)下將不會(huì)有視頻捕捉源過濾器。(3)在“DirectShow Filters”節(jié)點(diǎn)下選
73、擇“Video Renderer”過濾器,將其添加到圖表中,如圖2.13所示。圖2.13 添加“Video Renderer”過濾器窗口(4)利用鼠標(biāo)將視頻捕捉源過濾器的“Capture”引腳與“Video Renderer”過濾器的“VMR Input0”引腳相連,如圖2.14所示。圖2.14 連接過濾器引腳窗口(5)單擊工具欄中的“”按鈕運(yùn)行過濾圖表,將顯示一個(gè)視頻預(yù)覽窗口,如圖2.15所示。圖2.15 視頻預(yù)覽窗口2.3.3 枚舉系統(tǒng)設(shè)備使用Graph Edit工具,用戶可以非常方便地獲得與某一系統(tǒng)設(shè)備相關(guān)的過濾器。但是,在程序中該如何獲得
74、這些過濾器呢?用戶可以采用枚舉的方式列舉系統(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è)備綁定到過濾器上。在上面的描述中,ICreateDevEnum實(shí)例的CreateClassEnumerator方法的第一個(gè)參數(shù)確定枚舉的系統(tǒng)設(shè)備。例如,第一個(gè)參數(shù)為CLSID_VideoInputDeviceCategory,表示將要枚舉系統(tǒng)中的視頻捕捉卡,為CLSID_VideoCompressorCategory,表示枚舉系統(tǒng)中的視頻
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025福建省晉江圳源環(huán)境科技有限責(zé)任公司招聘6人筆試參考題庫附帶答案詳解
- 長沙航空職業(yè)技術(shù)學(xué)院《精細(xì)有機(jī)合成單元反應(yīng)》2023-2024學(xué)年第二學(xué)期期末試卷
- 天津師范大學(xué)《檢驗(yàn)儀器學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 內(nèi)蒙古豐州職業(yè)學(xué)院《生物化學(xué)(Ⅰ)》2023-2024學(xué)年第二學(xué)期期末試卷
- 內(nèi)蒙古民族大學(xué)《層次局部解剖學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 新星職業(yè)技術(shù)學(xué)院《模擬電子技術(shù)課程設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 新星職業(yè)技術(shù)學(xué)院《園林工程含測量》2023-2024學(xué)年第二學(xué)期期末試卷
- 達(dá)州中醫(yī)藥職業(yè)學(xué)院《數(shù)字健康傳播》2023-2024學(xué)年第二學(xué)期期末試卷
- 湖北民族大學(xué)《交通大數(shù)據(jù)分析》2023-2024學(xué)年第二學(xué)期期末試卷
- 寧波大學(xué)科學(xué)技術(shù)學(xué)院《單片機(jī)技術(shù)及應(yīng)用(C)》2023-2024學(xué)年第二學(xué)期期末試卷
- 22G101系列圖集常用點(diǎn)全解讀
- 北師大版六年級(jí)數(shù)學(xué)下冊(cè)專項(xiàng)二 圖形與幾何含答案
- 《X線攝影檢查技術(shù)》復(fù)習(xí)考試題庫(帶答案)
- MIDASM32調(diào)音臺(tái)培訓(xùn)教程歸納
- DB63-T 2152-2023公路建設(shè)項(xiàng)目代建管理規(guī)范
- 普通地質(zhì)學(xué)教材
- 05G414-5預(yù)應(yīng)力混凝土工字形屋面梁(18m、雙坡)
- 《腦出血的外科治療》
- 六頂思考帽講義
- 光學(xué)玻璃非球面元件模壓過程仿真與實(shí)驗(yàn)
- DB23 2456-2019農(nóng)村生活污水處理設(shè)施水污染物排放標(biāo)準(zhǔn)
評(píng)論
0/150
提交評(píng)論