




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(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ù)進行視頻采集。2.2.1 開發(fā)流程分析VFW使用的視頻函數(shù)被封裝在vfw32.lib庫文件中,該庫文件默認(rèn)情況下沒有被連接到MFC工程中,因此使用VFW進行視頻開發(fā)的第一步是導(dǎo)入vfw32.lib庫文件。方法如下:(1)引用v
2、fw.h頭文件。#include "vfw.h"(2)導(dǎo)入vfw32.lib庫文件。#pragma comment (lib,"vfw32")步驟2也可以在通過工程選項窗口的連接選項卡進行設(shè)置。如圖2.1所示。連接vfw32.lib庫文件 圖2.1 工程選項窗口在導(dǎo)入vfw32.lib庫文件后便可以使用視頻函數(shù)了。首先調(diào)用capCreateCaptureWindow函數(shù)創(chuàng)建具有WS_POPUP風(fēng)格的視頻捕捉窗口。然后調(diào)用capDriverConnect函數(shù)連接驅(qū)動程序,設(shè)置視頻捕捉窗口的大小、顯示位置。最后調(diào)用capPreviewR
3、ate函數(shù)設(shè)置預(yù)覽速率,調(diào)用capPreview函數(shù)進行視頻預(yù)覽。總結(jié)上述流程分析,VFW視頻捕捉開發(fā)流程具體步驟如下:(1)引用“vfw.h”頭文件并導(dǎo)入vfw32.lib庫。(2)創(chuàng)建一個線程,在線程函數(shù)中調(diào)用capCreateCaptureWindow創(chuàng)建視頻捕捉窗口。(3)調(diào)用capDriverConnect連接驅(qū)動程序,設(shè)置視頻捕捉窗口風(fēng)格、大小及父窗口。(4)調(diào)用capPreviewRate函數(shù)設(shè)置預(yù)覽速度,調(diào)用capPreview函數(shù)開始預(yù)覽。2.2.2 視頻窗口創(chuàng)建在進行視頻程序開發(fā)時,第一步需要創(chuàng)建一個視頻預(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)識。在創(chuàng)建視頻捕捉窗口之后,需要將其顯示在對話框中的適當(dāng)位置??梢栽趯υ捒蛑蓄A(yù)先放置一個靜態(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ù)覽實現(xiàn)在開發(fā)視頻應(yīng)用程序時,第一步需要實現(xiàn)的功能便是視頻預(yù)覽。在2.2.1節(jié)中筆者曾分析了視頻預(yù)覽的實現(xiàn)過程,下面以一個具體實例來說明VFW視頻預(yù)覽的實現(xiàn)過程。效果如圖2.2所示。圖2.2 視頻預(yù)覽實現(xiàn)程序設(shè)計步驟如下: 實例位置:光盤mr22.22.2.301(1)創(chuàng)建一個基于對話框的工程,在對話框中添加Picture控件,如圖2.3所示。圖2.3 視頻預(yù)覽設(shè)計窗口(2)在類向?qū)У摹癕ember Variables”選項卡中為Picture控件命名,如圖2.4所示。圖2.4 類向?qū)Т翱冢?)在對話
8、框的頭文件中引用“vfw.h”頭文件,然后鏈接“vfw32.lib”庫文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)在對話框中定義一個視頻預(yù)覽窗口的句柄。HWND m_hWndVideo; /視頻顯示窗口(5)在對話框初始化時創(chuàng)建視頻預(yù)覽窗口,連接視頻驅(qū)動程序,設(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ū)動程序 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、在對話框關(guān)閉時斷開視頻驅(qū)動程序。void CVideoPreviewDlg:OnCancel() /斷開驅(qū)動程序連接 capDriverDisconnect(m_hWndVideo); CDialog:OnCancel();2.2.4 捕捉參數(shù)設(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,將顯示一個對話框幫助用戶快速地進行捕捉設(shè)置wPerentDropForErrorUINT在捕捉過程中允許棄幀的最大百分比fYield
17、BOOL如果為TRUE,將產(chǎ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è)置捕捉時間限制wTimeLimitUINT以秒為單位設(shè)置捕捉的超時時間fMCIControlBOOL為TRUE,控制MCI(媒體設(shè)備接口)兼容的視頻源fStepMCIDeviceBOOL為TRUE,使用MCI設(shè)備使用步進幀進行捕捉,為FALSE,使用MCI設(shè)備進行時時捕捉,如果fMCIControl成員為FALSE,該成員被忽略dwMCIStartTimeDWORD以毫秒為單位標(biāo)識MCI設(shè)備視頻捕捉序列的起始位置,如果fMCIControl成員為FALSE,該成員被忽略dwMCIS
19、topTimeDWORD以毫秒為單位標(biāo)識MCI設(shè)備視頻捕捉序列的停止位置,如果fMCIControl成員為FALSE,該成員被忽略fStepCaptureAt2xBOOL為TRUE,捕捉的視頻幀使用兩個分辨率,它可以使用軟件在某個分辨率的基礎(chǔ)上改寫像素,將其該為高清晰度的圖像wStepCaptureAverageFramesUINT在捕捉時每幀圖像使用的時間大小dwAudioBufferSizeDWORD音頻緩沖區(qū)大小fDisableWriteCacheBOOL未使用AVStreamMasterUINT確定在寫入AVI文件時,音頻流是否控制時鐘wSize:表示psCapParms參數(shù)的大小。在
20、進行視頻捕捉時,通常會根據(jù)實際需要設(shè)置捕捉參數(shù)。例如,在視頻錄像時,通常會將fYield成員設(shè)置為TRUE,啟動后臺線程來進行視頻錄像,這樣,前臺用戶依然可以進行其他界面有關(guān)操作。2.2.5 回調(diào)函數(shù)設(shè)計在開發(fā)視頻應(yīng)用程序時,可以為視頻捕捉窗口設(shè)計一些回調(diào)函數(shù),這樣,當(dāng)視頻應(yīng)用程序的某些狀態(tài)改變時,可以在回調(diào)函數(shù)中進行處理。VFW提供了如下的函數(shù)進行回調(diào)函數(shù)注冊。(1)capSetCallbackOnCapControl該函數(shù)提供了視頻捕捉時精確地控制捕捉開始和結(jié)束的時間。語法如下: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、錯誤處理的回調(diào)函數(shù)。語法如下:BOOL capSetCallbackOnError(HWND hwnd, CAPERRORCALLBACKA fpProc);參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示錯誤處理的回調(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是一個VIDEOHDR結(jié)構(gòu)指針,表示視頻數(shù)據(jù)頭。(4)capSetCallbackOnStatus該函數(shù)用于在程序中設(shè)置一個
24、狀態(tài)回調(diào)函數(shù)。語法如下:BOOL capSetCallbackOnStatus(HWND hwnd, CAPSTATUSCALLBACKA fpProc );參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)應(yīng)用程序的狀態(tài)改變時將調(diào)用該函數(shù)。其定義如下:typedef LRESULT (CALLBACK* CAPSTATUSCALLBACKA) (HWND hWnd, int nID, LPCSTR lpsz);其中, hWnd表示視頻捕捉窗口句柄,nID表示狀態(tài)碼,lpsz表示狀態(tài)文本描述。(5)capSetCallbackOnVideoStream該函
25、數(shù)用于注冊一個回調(diào)函數(shù),使得視頻緩沖區(qū)被填充時調(diào)用回調(diào)函數(shù)。語法如下:BOOL capSetCallbackOnVideoStream(HWND hwnd, CAPVIDEOCALLBACK fpProc );參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)視頻緩沖區(qū)被填充時調(diào)用回調(diào)函數(shù),其定義與capSetCallbackOnFrame函數(shù)的fpProc參數(shù)相同。(6)capSetCallbackOnWaveStream該函數(shù)用于注冊一個回調(diào)函數(shù),使得音頻緩沖區(qū)被填充時調(diào)用回調(diào)函數(shù)。語法如下:BOOL capSetCallbackOnWaveStream (HWN
26、D hwnd, CAPWAVECALLBACK fpProc );參數(shù)說明:hwnd:表示視頻捕捉窗口句柄。fpProc:表示回調(diào)函數(shù)指針,當(dāng)音頻緩沖區(qū)被填充時調(diào)用回調(diào)函數(shù)。其定義如下:typedef LRESULT (CALLBACK* CAPWAVECALLBACK) (HWND hWnd, LPWAVEHDR lpWHdr);其中, hWnd表示視頻捕捉窗口句柄,lpWHdr是一個WAVEHDR結(jié)構(gòu)指針,表示音頻數(shù)據(jù)頭。(7)capSetCallbackOnYield該函數(shù)用于注冊一個回調(diào)函數(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ù)覽、視頻錄像、視頻壓縮等多個地方被廣泛使用。下面以統(tǒng)計預(yù)覽幀數(shù)為例介紹VFW回調(diào)函數(shù)的使用。效果如圖2.5所示。統(tǒng)計預(yù)覽幀數(shù) 圖2.5 回調(diào)函數(shù)設(shè)計程序設(shè)計步驟如下: 實例位置
28、:光盤mr22.22.2.501(1)創(chuàng)建一個基于對話框的工程,在對話框中添加靜態(tài)文本、圖像等控件,如圖2.6所示。圖2.6 回調(diào)函數(shù)設(shè)計窗口(2)利用類向?qū)閳D像、靜態(tài)文本控件命令,如圖2.7所示。圖2.7 MFC類向?qū)Т翱冢?)在對話框的頭文件中引用“vfw.h”頭文件,并導(dǎo)入“vfw32.lib”庫文件。#include "vfw.h"#pragma comment (lib,"vfw32")(4)向?qū)υ捒蛑刑砑映蓡T變量m_hWndVideo,作為預(yù)覽窗口的句柄。HWND m_hWndVideo; /
29、視頻顯示窗口(5)定義一個全局變量,記錄當(dāng)前的預(yù)覽幀數(shù)。long num = 0;(6)定義一個全局函數(shù),作為視頻預(yù)覽的回調(diào)函數(shù)。LRESULT CALLBACK PreviewCallback (HWND hWnd) num+; return 0;(7)處理對話框的WM_TIMER消息,將num數(shù)值顯示在界面中。void CCallbackDesigendDlg:OnTimer(UINT nIDEvent) CString str; str.Format("%i"
30、,num); m_FrameNum.SetWindowText(str); CDialog:OnTimer(nIDEvent);(8)在對話框初始化時創(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ū)動程序 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)在對話框關(guān)閉時斷開視頻驅(qū)動程序。void CCallbackDesigendDlg:OnCancel() /斷開驅(qū)動程序連接 capDriverDisconnect(m_hWndVideo); CDialog:OnCancel();2.2.6 視頻錄像設(shè)計方案在VFW中,可以有3種方式實現(xiàn)視頻錄像。其中,最簡單的方式是調(diào)用
38、capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)。該種方式存在許多缺點,例如,在錄像時無法響應(yīng)用戶界面,無法實現(xiàn)視頻壓縮等。第二種方式是調(diào)用capCaptureSetSetup函數(shù),將CAPTUREPARMS結(jié)構(gòu)的fYield成員設(shè)置為TRUE,啟動后臺線程來實現(xiàn)錄像,然后調(diào)用capDlgVideoCompression函數(shù)讓用戶選擇壓縮器進行壓縮,最后調(diào)用capFileSetCaptureFile函數(shù)和capCaptureSequence函數(shù)開始錄像。第二種方式的缺點是每次錄像時都需要彈出一個對話框,讓用戶選擇一種壓縮器。第三種方式是注冊回調(diào)函數(shù)cap
39、SetCallbackOnVideoStream,在回調(diào)函數(shù)中壓縮數(shù)據(jù)并寫入AVI文件。相對于前兩種方式,第三種方式更為靈活和實用,因此在進行視頻錄像時,通常采用該種方式實現(xiàn)。具體實現(xiàn)過程如下:(1)定義一個回調(diào)函數(shù),該回調(diào)函數(shù)實現(xiàn)數(shù)據(jù)壓縮,并將壓縮的數(shù)據(jù)寫入文件流中。(2)調(diào)用capSetCallbackOnVideoStream注冊回調(diào)函數(shù)。(3)調(diào)用ICOpen函數(shù)打開一個壓縮器,并調(diào)用ICCompressBegin函數(shù)開始壓縮。(4)調(diào)用AVIFileOpen函數(shù)打開一個AVI文件,并調(diào)用AVIFileCreateStream函數(shù)創(chuàng)建文件流。(5)調(diào)用capCaptureSequenc
40、eNoFile函數(shù)開始錄像。下面以一個具體實例介紹如何采用第三種方式實現(xiàn)視頻錄像。效果如圖2.8所示。圖2.8 視頻錄像設(shè)計方案 實例位置:光盤mr22.22.2.601(1)創(chuàng)建一個基于對話框的工程,在對話框中添加按鈕、圖像控件,如圖2.9所示。圖2.9 對話框資源設(shè)計(2)在對話框的頭文件中引用“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)定義一個回調(diào)函數(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)在對話框初始化時開始視頻預(yù)覽,設(shè)置視頻參數(shù)。m_Captured = FALSE;m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,1,1,10,10,m_hWnd,0);/連接驅(qū)動程序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; /利用對話框選擇壓縮器 / ICCompressorChoose(NULL,ICMF_CHOOSE_ALLCOMPRESSORS ,(LPVOID)&m_InI
58、nfo,NULL,&m_Com,"選擇壓縮類型"); ICCompressGetFormat(m_Com.hic,&m_InInfo.bmiHeader,&m_OutInfo.bmiHeader); /開始壓縮 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)在對話框關(guān)閉時停止視頻
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ū)動程序連接 capDriverDisconnect(m_hWndVideo); CDialog:OnCancel();2.3 DirectShow視頻采集方案流媒體處理技術(shù)以其復(fù)雜性和技術(shù)性一直受到人們的關(guān)注。隨著網(wǎng)絡(luò)技術(shù)的不斷發(fā)展,流媒體在網(wǎng)絡(luò)上得到了廣泛地應(yīng)用。如何能夠簡單、有效地進行流媒體處理,已成為一個焦點問題。為此,Microsoft推出了DirectShow,Dire
68、ctShow是Microsoft推出的基于Windows平臺的流媒體處理開發(fā)包,它與DirectX一起發(fā)布。DirectShow對流媒體的捕捉、回放提供了強大的支持,使用它還可以在基于WDM驅(qū)動的采集卡上進行數(shù)據(jù)捕捉。本節(jié)將介紹有關(guān)DirectShow的相關(guān)知識。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ù),可以是一個文件、一個采集卡、聲卡或數(shù)碼相機等。Transform Filters負(fù)責(zé)數(shù)據(jù)的轉(zhuǎn)換、傳輸。例如各種編碼器、解碼器等。Rendering Filters負(fù)責(zé)數(shù)據(jù)的最終去向,例如將數(shù)據(jù)傳送到聲卡、顯卡或存儲為文件。在開發(fā)DirectShow應(yīng)用程序時,通常需要設(shè)計一個過濾圖表(Filter Graph),向過濾圖表中添加相應(yīng)的過濾器,最后連接過濾器的引腳就完成了功能的設(shè)計。例如,實現(xiàn)一個簡單的視頻預(yù)覽功能,需要向過濾圖表中添加一個視頻捕捉源過濾器和一個Video Renderer過濾 器,將視頻捕
70、捉源過濾器的輸出引腳與Video Renderer過濾器的輸入引腳相連就可以了。而在程序中只需要按照設(shè)計過濾圖表的捕捉添加過濾器并連接過濾器引腳就可以了。在連接過濾器引腳時需要注意:只能是輸出過濾器引腳與輸入過濾器引腳相連,兩個輸出過濾器或兩個輸入過濾器引腳是不能相連的。為了在程序中使用DirectShow,需要單獨安裝DirectX,當(dāng)前DirectX的最新版本為9.0,即DirectX9.0,用戶可以從Microsoft的官方網(wǎng)站上免費下載。在安裝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è)計為了方便用戶設(shè)計過濾圖表,DirectX提供了一個Graph Edit工具。用戶可以單擊“開始”菜單下的“Microsoft DirectX 9 SDKDirectX UtilitiesGraph Edit”菜單項打開Graph Edit工具,如圖2.10所示。圖2.10 Graph Edit工具下面
72、筆者介紹如何使用Graph Edit工具設(shè)計過濾圖表,過濾圖表的功能是實現(xiàn)視頻的預(yù)覽功能。具體步驟如下:(1)在圖2.4中單擊“Graph/Insert Filters”菜單項打開“添加過濾器”窗口,如圖2.11所示。圖2.11 添加過濾器窗口(2)在“Video Capture Sources”節(jié)點下選擇一個視頻捕捉源過濾器,單擊“Insert Filter”按鈕將其添加到過濾圖表中,如圖2.12所示圖2.12 添加視頻捕捉源過濾器窗口提示:如果系統(tǒng)中沒有安裝攝像頭及其驅(qū)動程序,該節(jié)點下將不會有視頻捕捉源過濾器。(3)在“DirectShow Filters”節(jié)點下選
73、擇“Video Renderer”過濾器,將其添加到圖表中,如圖2.13所示。圖2.13 添加“Video Renderer”過濾器窗口(4)利用鼠標(biāo)將視頻捕捉源過濾器的“Capture”引腳與“Video Renderer”過濾器的“VMR Input0”引腳相連,如圖2.14所示。圖2.14 連接過濾器引腳窗口(5)單擊工具欄中的“”按鈕運行過濾圖表,將顯示一個視頻預(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è)備為例,首先定義一個設(shè)備列舉接口ICreateDevEnum的一個指針,調(diào)用CoCreateInstance方法創(chuàng)建ICreateDevEnum實例,然后定義一個列舉監(jiān)視器IEnumMoniker的一個指針,調(diào)用ICreateDevEnum實例的CreateClassEnumerator方法創(chuàng)建IEnumMoniker實例,最后以循環(huán)的方式調(diào)用IEnumMoniker實例的Next方法遍歷系統(tǒng)設(shè)備,調(diào)用IEnumMoniker實例的BindToObject方法將系統(tǒng)設(shè)備綁定到過濾器上。在上面的描述中,ICreateDevEnum實例的CreateClassEnumerator方法的第一個參數(shù)確定枚舉的系統(tǒng)設(shè)備。例如,第一個參數(shù)為CLSID_VideoInputDeviceCategory,表示將要枚舉系統(tǒng)中的視頻捕捉卡,為CLSID_VideoCompressorCategory,表示枚舉系統(tǒng)中的視頻
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 神經(jīng)介入考試題及答案
- 云程發(fā)軔 踵事增華-明德小學(xué)新學(xué)期數(shù)學(xué)學(xué)科業(yè)務(wù)培訓(xùn)
- 中風(fēng)后遺癥中醫(yī)護理方案
- 綜合部辦公室管理制度培訓(xùn)
- 急重癥護理學(xué)
- 幼兒園安全培訓(xùn)
- 體育培訓(xùn)課程介紹
- 旋轉(zhuǎn)噴泉科學(xué)課件
- 2025年中國摩托車頭盔面罩和遮陽板行業(yè)市場全景分析及前景機遇研判報告
- 愛己愛人健康成長
- 《中醫(yī)藥健康知識講座》課件
- 藝術(shù)欣賞與實踐(高職)全套教學(xué)課件
- 民俗文化的產(chǎn)業(yè)化發(fā)展
- 班級讀書會《城南舊事》課件
- 胃早癌-經(jīng)典課件
- 中央廣播電視大學(xué)畢業(yè)生登記表-6
- 垃圾滲濾液應(yīng)急處理服務(wù)投標(biāo)方案技術(shù)標(biāo)
- 質(zhì)量管理體系全套文件
- 夜市治安管理應(yīng)急預(yù)案
- 明德云學(xué)堂義務(wù)教育心得
- 珍愛生命中學(xué)生心理健康主題班會
評論
0/150
提交評論