视频捕捉全教程(MFC+vfw)
| 目 錄 一. 視頻捕獲快速入門 二.基本的捕獲設(shè)置 ?????????? 1.設(shè)置捕獲速度: ?????????? 2.設(shè)置終止捕獲 ?????????? 3.捕獲的時(shí)間限制 三.關(guān)于捕獲窗口 ????????? 1.創(chuàng)建一個(gè)AVICAP捕獲窗口 ????????? 2.將一個(gè)捕獲窗口連接至捕獲設(shè)備 ?????????? 3. 父窗口與子窗口的交互 ????????? 4.捕獲窗口的狀態(tài) 四.視頻捕獲驅(qū)動(dòng)和音頻驅(qū)動(dòng) ????????? 1.視頻捕獲驅(qū)動(dòng)的性能: ?????????? 2.視頻對(duì)話框: ???????? 3.PREVIEW 和 OVERLAY模式: ??????? ?? 4.視頻格式 ????? ???? 5.視頻捕獲設(shè)置 ?????? ?? 6.聲頻格式 五.使用視頻捕獲 ???????? 1.創(chuàng)建捕獲窗口(CREATING A CAPTURE WINDOW) ??????? 2.連接到捕獲驅(qū)動(dòng)(CONNECTING TO A CAPTURE DRIVER) ???????? 3.列舉所有已安裝的捕獲驅(qū)動(dòng)(ENUMERATING INSTALLED CAPTURE DRIVERS) ???????? 4.得到捕獲驅(qū)動(dòng)的性能(OBTAINING THE CAPABILITIES OF A CAPTURE DRIVER) ???????? 5.得到捕獲窗口的狀態(tài)(OBTAINING THE STATUS OF A CAPTURE WINDOW) ???????? 6.顯示對(duì)話框設(shè)置視頻特征(DISPLAYING DIALOG BOXES TO SET VIDEO CHARACTERISTICS) ???????? 7.得到和設(shè)置視頻格式(OBTAINING AND SETTING THE VIDEO FORMAT) ???????? 8. 預(yù)覽視頻(PREVIEWING VIDEO) ???????? 9.將視頻設(shè)置為OVERLAY模式(ENABLING VIDEO OVERLAY) ???????? 10.命名捕獲文件(NAMING THE CAPTURE FILE) ???????? 11.格式化聲頻捕獲(FORMATTING AUDIO CAPTURE) ???????? 12.改變視頻捕獲設(shè)置(CHANGING A VIDEO CAPTURE SETTING) ??????? 13.捕獲數(shù)據(jù)(CAPTURING DATA) ???????? 14.增加一個(gè)信息塊(ADDING AN INFORMATION CHUNK) ???????? 15.在程序中加入一個(gè)回調(diào)函數(shù)(ADDING CALLBACK FUNCTIONS TO AN APPLICATION) ??????? 16.創(chuàng)建一個(gè)狀態(tài)回調(diào)函數(shù)(CREATING A STATUS CALLBACK FUNCTION) ???????? 17.創(chuàng)建一個(gè)錯(cuò)誤回調(diào)函數(shù)( CREATING AN ERROR CALLBACK FUNCTION) ??????? 18.創(chuàng)建一個(gè)框架回調(diào)函數(shù)(CREATING A FRAME CALLBACK FUNCTION) 六.將四個(gè)標(biāo)準(zhǔn)對(duì)話框改成函數(shù)調(diào)用形式 ???????? AUDIOFORMAT對(duì)話框 ???????? VIDEOFORMAT對(duì)話框 ???????? VIDEOSOURCE對(duì)話框 ???????? VIDEO COMPRESSION對(duì)話框 前 言 ????????? 視頻捕獲是指由專用的視頻采集卡捕獲聲頻和視頻信息,然后將其進(jìn)行數(shù)據(jù)化處理,再經(jīng)過軟件的壓縮進(jìn)行處理,這時(shí)就可對(duì)這些數(shù)據(jù)進(jìn)行保存、回放、傳輸?shù)雀鞣N操作。 ???????? Windows專門提供了Video for Windows來對(duì)視頻處理進(jìn)行支持,提供的接口可以被大多數(shù)的視頻采集卡支持,并有多種視頻壓縮驅(qū)動(dòng)供選擇(當(dāng)然視頻壓縮可以自己開發(fā)),采集卡支持?jǐn)z像頭,TV等多種輸入。
????????? 視頻捕捉將一個(gè)視頻流和音頻流數(shù)字化, 然后存儲(chǔ)在硬盤或其他存儲(chǔ)介質(zhì)上. ????????? 一個(gè)AVICap視窗口句柄描述了聲頻與視頻流的細(xì)節(jié), 這樣就使你的應(yīng)用程序從AVI文件格式, 聲頻視頻緩沖管理, 低層聲頻視頻驅(qū)動(dòng)訪問等等解脫出來, AVICap為應(yīng)用程序提供了一個(gè)靈活的介面, 你可以僅僅使用如下幾行代碼就可以將視頻捕捉加入你的程序: hWndC = capCreateCaptureWindow ( "My Own Capture Window", WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID); SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0 /* wIndex */, 0L); SendMessage (hWndC, WM_CAP_SEQUENCE, 0, 0L); ?????????? 一個(gè)宏其實(shí)也是使用SendMessage, 只不過提供給程序一個(gè)更易讀的代碼而已, 下面的這些示例就是使用宏的方法將視頻捕捉加入程序: hWndC = capCreateCaptureWindow ( "My Own Capture Window", WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID); capDriverConnect (hWndC, 0); capCaptureSequence (hWndC);
????????? 如果是缺省的設(shè)置, WM_CAP_SEQUENCE會(huì)開始捕捉視頻音頻流到CAPTURE.AVI文件中, 直到下面的某一事件發(fā)生為止: 用戶按下了ESC鍵或者一個(gè)鼠標(biāo)鍵 你的應(yīng)用程序終止或異常中斷捕捉操作 磁盤已滿
????????? 基本的捕獲設(shè)置包括:設(shè)置捕獲速度(每秒捕獲多少幀),是否同時(shí)捕獲聲頻,捕獲緩沖,允許最大丟失多少幀,是否使用DOS內(nèi)存,以及用鍵盤的哪個(gè)鍵或鼠標(biāo) 的哪個(gè)鍵來終止捕獲等等。這些基本的設(shè)置都可以使用CAPTUREPARAMS結(jié)構(gòu)來描述,你可以使用capCaptureGetSetup宏來得到當(dāng)前 的設(shè)置,然后改變此結(jié)構(gòu)的成員變量,再使用capCaptureSetSetup宏設(shè)置新的設(shè)置。 例如: 1.設(shè)置捕獲速度: ?????????? 捕捉速度是指捕捉任務(wù)每秒鐘捕獲的幀數(shù), 你可以發(fā)送WM_CAP_GET_SEQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)來得到當(dāng)前的捕捉速度, 當(dāng)前的捕捉速度保存在CAPTUREPARAMS結(jié)構(gòu)的dwRequestMicroSecPerFrame成員變量中, 你可以通過設(shè)置此變量來改變當(dāng)前設(shè)置, 單位是每毫秒連續(xù)的幀數(shù), 你可以發(fā)送WM_CAP_SET_SEQUENCE_SETUP消息(或者使用capCaptureSetSetup宏), dwRequestMicroSecPerFrame的值是66667, 相當(dāng)于每秒15幀.
?????????? 你可以允許用戶按下某鍵或某組合鍵或者鼠標(biāo)的左右鍵來終止一個(gè)捕獲任務(wù), 如果是實(shí)時(shí)的捕獲, 則捕獲的文件將會(huì)被丟棄; 如果是單步捕獲, 在終止之前所捕獲的內(nèi)容將會(huì)被保存. ????????? 你可以通過發(fā)送WM_CAP_GETQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)來得到當(dāng)前的設(shè)置, 當(dāng)前的按鍵設(shè)置保存在CAPTUREPARAMS的vKeyAbort成員中, 當(dāng)前的鼠標(biāo)設(shè)置保存在fAbortLeftMouse和fAbortRightMouse成員中. 你可以設(shè)置新的按鍵或按鍵組合, 或者鼠標(biāo)左右鍵, 當(dāng)你修改的CAPTUREPARAMS后,應(yīng)該發(fā)送WM_CAP_SET_SEQUENCE_SETUP消息來進(jìn)行更新(或者使用 capCaptureSetSetup宏). 缺省的按鍵是VK_ESCAPE. 你必須在指定按鍵之前使用RegisterHotKey函數(shù), 鼠標(biāo)缺省的值是fAbortLeftMouse和fAbortRightMouse都為TRUE.
?????????? CAPTUREPARAMS結(jié)構(gòu)中的fLimitEnabled指示是否有時(shí)間限度, wTimeLimit指示最大的持續(xù)時(shí)間, 單位為秒. ????????? 得到fLimitEnabled和wTimeLimit的值可以發(fā)送WM_CAP_GET_SEQUENCE_SETUP消息(或使用 capCatureGetSetup宏), 當(dāng)設(shè)置了這些成員變量后, 應(yīng)該發(fā)送消息WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)來更新CAPTUREPARAMS結(jié) 構(gòu).
??????? 在捕獲之前必須創(chuàng)建一個(gè)捕獲窗口(capture window),在發(fā)送消息或使用宏的過程中都需要使用此窗口。 1.創(chuàng)建一個(gè)AVICap捕獲窗口 ??????? 你可以使用capCreateCaptureWindow函數(shù)來創(chuàng)建一個(gè)AVICap捕獲窗口, 此函數(shù)將會(huì)返回一個(gè)句柄, 此句柄以后在發(fā)送消息時(shí)要用. ??????? 你可以在一個(gè)程序里創(chuàng)建一個(gè)或多個(gè)捕獲窗口, 然后給每一個(gè)窗口連接不同的捕獲設(shè)置.
?????????? 你可以動(dòng)態(tài)的在一個(gè)捕獲窗口與一個(gè)捕獲設(shè)備之前連接或斷接, 你可以發(fā)送WM_CAP_DRIVER_CONNECT消息來使一個(gè)捕獲窗口與一個(gè)捕獲設(shè)備連接或關(guān)聯(lián). 當(dāng)連接上以后, 你就可以通過捕獲窗口向捕獲設(shè)備發(fā)送各種消息. ??????? 如果你的系統(tǒng)里裝有多個(gè)捕獲設(shè)備, 你可以在發(fā)送WM_CAP_DRIVER_CONNECT消息時(shí)用wParam參數(shù)指定使用哪一個(gè), 此參數(shù)是登記在SYSTEM.INI文件的[drivers]一節(jié)里的列表中的某一項(xiàng), 0為第一個(gè). ????????? 你可以使用capGetDriverDescription函數(shù)來得到已安裝的捕獲設(shè)備的名稱及版本, 這樣你的程序就可以列舉所有已安裝的捕獲設(shè)備和驅(qū)動(dòng), 這樣用戶就可以選擇其中的一個(gè)來與你的捕獲窗口連接. ???????? 你可以發(fā)送WM_CAP_DRIVER_GET_NAME消息(或capDriverGetName宏)來得到連接到捕獲窗口的捕獲設(shè)備的名稱, 得到版本發(fā)送WM_CAP_DRIVER_GET_VERSION消息(或capDriverGetVersion宏) ???????? 你可以發(fā)送WM_CAP_DRIVER_DISCONNECT消息(或capDriverDisconnect宏)來斷接.
?????????? 一些象WM_PALETTECHANGED和WM_QUERYNEWPALETTE的系統(tǒng)級(jí)消息只能發(fā)送到頂級(jí)窗口或OVERLAPPED窗口, 如果一個(gè)捕獲窗口是子窗口,就必須通過父窗口轉(zhuǎn)送. ???????? 同樣的, 如果父窗口的尺寸改變了, 它就需要通知捕獲窗口, 相反地, 如果捕獲窗口的尺寸改變了, 捕獲窗口就需要發(fā)送消息給父窗口, 一個(gè)簡(jiǎn)單的方法就是始終保持捕獲窗口的尺寸與視頻流的尺寸一致, 并隨時(shí)將尺寸的改變通知父窗口.
????????? 你可以發(fā)送WM_CAP_GET_STATUS消息(或capGetStatus宏)來得到當(dāng)前捕獲窗口的狀態(tài), 得到的是一個(gè)CAPSTATUS結(jié)構(gòu)的拷貝, 它包含圖片的尺寸, 卷軸的當(dāng)前位置, overlay和preview是否已設(shè)置. ??????? 因?yàn)镃APSTATUS信息是動(dòng)態(tài)的, 你的程序應(yīng)該只要捕獲的視頻流的尺寸或格式可能發(fā)生了改變就應(yīng)該進(jìn)行刷新(例如: 顯示了捕獲設(shè)備的視頻格式以后). ??????? 改變捕獲窗口的尺寸并不影響實(shí)際的捕獲的視頻流的尺寸, 視頻捕獲設(shè)備的格式對(duì)話框捕獲頻流的尺寸.
1.視頻捕獲驅(qū)動(dòng)的性能: ????????? 你可以通過發(fā)送WM_CAP_DRIVER_GET_CAPS消息(或者capDriverGetCaps宏)來得到當(dāng)前連接的視頻驅(qū)動(dòng)的硬件性能. 得到的信息保存在CAPDRIVERCAPS結(jié)構(gòu)中.
????????? 每一個(gè)視頻驅(qū)動(dòng)能夠提供四個(gè)對(duì)話框來控制視頻捕獲和數(shù)字化處理, 定義壓縮品質(zhì)等, 這些對(duì)話框都定義在視頻捕獲驅(qū)動(dòng)中. ????????? Video Source對(duì)話框用于控制選擇視頻來源, 此對(duì)話框列舉了此視頻捕獲卡連接的所有視頻源(典型的例如:SVHS和合成輸入), 并提供了改變色調(diào), 對(duì)比度, 飽和度. 如果視頻驅(qū)動(dòng)支持此對(duì)話框, 你就可以顯示并更新它, 使用WM_CAP_DLG_VIDEOSOURCE消息(或capDlgVideoSource宏). ?????????? Video Format對(duì)話框定義視頻幀的尺寸以及精度, 視頻捕獲卡的壓縮設(shè)置. 如果卡支持的話, 可以發(fā)送消息WM_CAP_DLG_VIDEOFORMAT消息或(capDlgVideoFormat宏). ?????????? Video Display對(duì)話框控制在視頻捕獲期間在顯示器上的顯示, 此控制不會(huì)影響視頻數(shù)字?jǐn)?shù)據(jù), 但是他們可能會(huì)影響數(shù)字信號(hào)的表現(xiàn)形式, 例如: 如果捕獲設(shè)備支持overlay, 可能允許改變色調(diào)和飽和度, 關(guān)鍵色彩 或者overlay隊(duì)列. 如果卡支持, 你可以發(fā)送WM_CAP_DLG_VIDEODISPLAY消息(或者使用capDlgVideoDisplay宏). ?????????? Video Compression對(duì)話框控制壓縮品質(zhì), 如果卡支持, 發(fā)送消息WM_CAP_DLG_VIDEOCOMPRESSION(或capDlgVideoCompression宏).
???????????????? 一個(gè)視頻捕獲驅(qū)動(dòng)對(duì)進(jìn)入的視頻流有兩種工作模式: Preview模式和overlay模式, 如果一個(gè)捕獲驅(qū)動(dòng)能夠執(zhí)行兩種方法, 用戶可以在其中選擇一種. ?????????????? Preview模式把從捕獲硬件傳來的數(shù)據(jù)送入系統(tǒng)內(nèi)存并使用圖形設(shè)備介面(GDI)將數(shù)字化幀顯示在捕獲窗口內(nèi). 應(yīng)用程序可以在父窗口失去焦點(diǎn)時(shí)減緩顯示速度, 當(dāng)重新又得到焦點(diǎn)后加快顯示速度, 此種模式要占用大量CPU時(shí)間. 有三種消息控制Preview操作: WM_CAP_SET_PREIVEW消息(capPreview宏)允許或禁止preview模式 WM_CAP_SET_PREVIEWRATE(capPreviewRate宏)當(dāng)幀在preview模式顯示時(shí)設(shè)置速度. WM_CAP_SET_SCALE(capPreviewScale宏)允許或禁止preview視頻的縮放比例. ????????? 當(dāng)preview和scaling同時(shí)使用, 捕獲的視頻幀將會(huì)根據(jù)捕獲窗口的尺寸自動(dòng)縮放, 允許preview模式會(huì)自動(dòng)關(guān)閉overlay模式. ????????????????????? overlay模式是一個(gè)硬件函數(shù)它將數(shù)據(jù)送入捕獲緩沖區(qū)中因而不占用CPU資源. 你可以發(fā)送消息WM_CAP_SET_OVERLAY(或capOverlay宏)給捕獲窗口來啟用或終止overlay模式, 允許overlay模式會(huì)自動(dòng)禁止preview模式. ?????????????? 你同時(shí)也可以在preview模式或overlay模式里發(fā)送WM_CAP_SET_SCROLL消息(或capSetScrollPos宏)來設(shè)置視頻幀的客戶區(qū)卷軸位置.
??????????? 你可以通過發(fā)送WM_CAP_GET_VIDEOFORMAT消息(或capGetVideoFormat和capGetVideoFormatSize 宏)來得到視頻格式的結(jié)構(gòu)或結(jié)構(gòu)的尺寸. 你可以通過發(fā)送CAP_SET_VIDEOFORMAT消息(或capSetVideoFormat宏)來設(shè)置視頻格式.
?????????? CAPTUREPARMS結(jié)構(gòu)包含了對(duì)視頻捕獲流的控制參數(shù), 你可以完成以下這些任務(wù): 指定幀數(shù) 指定分配多少視頻緩沖 允許或禁止聲頻捕獲 指定捕獲的時(shí)間間隔 指定在捕獲的過程中是否使用MCI設(shè)置(VCR或者videodisc) 指定終止流的鍵盤或鼠標(biāo) specify the type of video averaging applied during capture.
設(shè)置:WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)
?????????????? 你可以通過發(fā)送WM_CAP_GET_AUDIOFORMAT消息(或capGetAudioFormat宏和 capGetAudioFormatSize宏)來得到當(dāng)前捕獲音頻數(shù)據(jù)的格式或尺寸格式。缺省的聲頻格式是:單聲道、8位、11kHz PCM。 當(dāng)你使用WM_CAP_GET_AUDIOFORMAT時(shí),總是使用WAVEFORMATEX結(jié)構(gòu)。 ???????????? 設(shè)置發(fā)送消息WM_CAP_SET_AUDIOFORMAT消息(或capSetAudioFormat宏),可以傳送WAVEFORMAT,WAVEFORMATEX,PCMWAVEFORMAT結(jié)構(gòu)指針。 五.使用視頻捕獲 1.創(chuàng)建捕獲窗口(Creating a Capture Window) hWndC = capCreateCaptureWindow ( (LPSTR) "My Capture Window", // window name if pop-up WS_CHILD | WS_VISIBLE, // window style 0, 0, 160, 120, // window position and dimensions (HWND) hwndParent, (int) nID /* child ID */);
?????????? 下面的例子是將MSVIDEO驅(qū)動(dòng)連接到句柄為hWndC的捕獲窗口, 然后調(diào)用capDriverDisconnect宏來斷接. fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L); // // Or, use the macro to connect to the MSVIDEO driver: // fOK = capDriverConnect(hWndC, 0); // // Place code to set up and capture video here. // capDriverDisconnect (hWndC);
?????????? 下面的例子使用capGetDriverDescription函數(shù)得到已安裝的捕獲驅(qū)動(dòng)的名稱及版本: char szDeviceName[80]; char szDeviceVersion[80];
{ if (capGetDriverDescription (wIndex, szDeviceName, sizeof (szDeviceName), szDeviceVersion, sizeof (szDeviceVersion)) { // Append name to list of installed capture drivers // and then let the user select a driver to use. } }
????????????? 發(fā)送WM_CAP_DRIVER_GET_CAPS消息可以得到捕獲驅(qū)動(dòng)的性能,并保存入一個(gè)CAPDRIVERCAPS結(jié)構(gòu).每當(dāng)程序連接一個(gè)新的捕獲 驅(qū)動(dòng)到一個(gè)捕獲窗口時(shí), 就應(yīng)該更新CAPDRIVERCAPS結(jié)構(gòu). 下面的程序舉例說明了如何使用capDriverGetCaps宏來得到捕獲驅(qū)動(dòng)的性能:
SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS, sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps); // Or, use the macro to retrieve the driver capabilities. // capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));
???????????????? 下面的例子使用SetWindowPos函數(shù)使捕獲窗口與進(jìn)來的視頻流尺寸保持一致, 視頻流的基本信息是使用capGetStatus宏得到的, 保存在CAPSTATUS結(jié)構(gòu)中.
capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS)); SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth, CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
????????????? 每個(gè)視頻捕獲卡一般能提供三個(gè)不同的對(duì)話框用于控制視頻捕獲及數(shù)字化處理. 下面的例子說明如何顯示這些對(duì)話框, 在顯示這些對(duì)話框之前,使用了capDriverGetCaps宏來檢查CAPDRIVERCAPS結(jié)構(gòu), 以檢測(cè)該卡是否有顯示這些對(duì)話框:
capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));
if (CapDriverCaps.fHasDlgVideoSource) capDlgVideoSource(hWndC);
if (CapDriverCaps.fHasDlgVideoFormat) { capDlgVideoFormat(hWndC); // Are there new image dimensions? capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS)); // If so, notify the parent of a size change. }
if (CapDriverCaps.fHasDlgVideoDisplay) capDlgVideoDisplay(hWndC);
?????????????????? BITMAPINFO結(jié)構(gòu)的長(zhǎng)度既適應(yīng)于標(biāo)準(zhǔn)的也適應(yīng)于壓縮的數(shù)據(jù)格式, 所有程序必須總是詢問此結(jié)構(gòu)的尺寸以便在得到當(dāng)前的視頻格式之前分配內(nèi)存. 下面的例子就是使用capGetVideoFormatSize宏來得到緩沖區(qū)尺寸并調(diào)用capGetVideoFormat宏來得到當(dāng)前的視頻格式.
DWORD dwSize; dwSize = capGetVideoFormatSize(hWndC); lpbi = GlobalAllocPtr (GHND, dwSize); capGetVideoFormat(hWndC, lpbi, dwSize);
???????????? 下面的例子使用capPreviewRate宏來設(shè)置每66毫秒顯示一幀, 并使用capPreview宏將它放置在捕獲窗口里.
capPreview(hWndC, TRUE); // starts preview // Preview capPreview(hWnd, FALSE); // disables preview
??????????? 下面的例子: capDriverGetCaps宏確定此捕獲卡是否有overlay功能, 如果有就使用宏來設(shè)置它
capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));
capOverlay(hWndC, TRUE);
???????????? 下面的例子: 使用capFileSetCaptureFile宏來指定預(yù)備文件名為:MYCAP.AVI, capFileAlloc宏預(yù)先指定它的大小為5M.
capFileSetCaptureFile( hWndC, szCaptureFile); capFileAlloc( hWndC, (1024L * 1024L * 5));
???????????? 下面的例子使用capSetAudioFormat來設(shè)置聲頻格式為:11kHz, PCM 8位, 立體聲
wfex.wFormatTag = WAVE_FORMAT_PCM; wfex.nChannels = 2; // Use stereo wfex.nSamplesPerSec = 11025; wfex.nAvgBytesPerSec = 22050; wfex.nBlockAlign = 2; wfex.wBitsPerSample = 8; wfex.cbSize = 0;
?????????????? 下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得將捕獲幀數(shù)從缺省的15幀改成每秒10幀.
float FramesPerSec = 10.0;
capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));
??????????????? 下面的例子使用capCaptureSequence宏來開始捕獲視頻并使用capFileSaveAs宏來將捕獲的數(shù)據(jù)拷貝至NEWFILE.AVI文件中.
// Set up the capture operation. capCaptureSequence(hWndC); // Capture. capFileSaveAs(hWndC, szNewName);
?????????????? 如果你需要在你的程序捕獲的聲頻和視頻數(shù)據(jù)中加入你的其他信息, 你可以創(chuàng)建一個(gè)信息塊并將它們插入捕獲文件中, 信息塊可以包含一些典型的信息, 例如:版權(quán)信息,視頻來源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏來插入一個(gè)信息塊, 里面包含了一個(gè)SMPTE的時(shí)間代碼.
// the video source for preroll and postroll. CAPINFOCHUNK cic; // . // . // . cic.fccInfoID = infotypeSMPTE_TIME; cic.lpData = "00:20:30:12"; cic.cbData = strlen (cic.lpData) + 1; capFileSetInfoChunk (hwndC, &cic);
?????????????? 一個(gè)程序可以為捕獲窗口登記一個(gè)回調(diào)函數(shù)以便在以下的這些情況下通知程序.
錯(cuò)誤發(fā)生 視頻框架和聲頻緩沖區(qū)變得可用 程序應(yīng)用在捕獲視頻流的過程中接收
{ char achDeviceName[80] char achDeviceVersion[100] char achBuffer[100] WORD wDriverCount = 0 WORD wIndex WORD wError HMENU hMenu
ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window", WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);
// capSetCallbackOnError macro. capSetCallbackOnError(ghWndCap, fpErrorCallback);
// capSetCallbackOnStatus macro. capSetCallbackOnStatus(ghWndCap, fpStatusCallback);
// capSetCallbackOnVideoStream macro. capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);
// capSetCallbackOnFrame macro. capSetCallbackOnFrame(ghWndCap, fpFrameCallback);
} case WM_CLOSE: { // Use the capSetCallbackOnFrame macro to // disable the frame callback. Similar calls exist for the other // callback functions.
}
??????????? 下面的例子是創(chuàng)建一個(gè)簡(jiǎn)單的狀態(tài)回調(diào)函數(shù),登記此回調(diào)函數(shù)使用capSetCallbackOnStatus宏.
// hWnd: capture window handle // nID: status code for the current status // lpStatusText: status text string for the current status // LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText) { if (!ghWndMain) return FALSE;
SetWindowText(ghWndMain, (LPSTR) gachAppName); return (LRESULT) TRUE; } // Show the status ID and status text... wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);
return (LRESULT) TRUE; }
???????????? 下面的例子是創(chuàng)建一個(gè)簡(jiǎn)單的錯(cuò)誤回調(diào)函數(shù),登記此回調(diào)函數(shù)使用capsetCallbackOnError宏:
// hWnd: capture window handle // nErrID: error code for the encountered error // lpErrorText: error text string for the encountered error // LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText) { if (!ghWndMain) return FALSE;
return TRUE; // Clear out old errors.
wsprintf(gachBuffer, "Error# %d", nErrID);
MB_OK | MB_ICONEXCLAMATION);
}
????????????? 登記此回調(diào)函數(shù)使用capSetCallbackOnFrame宏:
// hWnd: capture window handle // lpVHdr: pointer to struct containing captured // frame information // LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) { if (!ghWndMain) return FALSE;
SetWindowText(ghWndMain, (LPSTR)gachBuffer); return (LRESULT) TRUE }
六.將四個(gè)標(biāo)準(zhǔn)對(duì)話框改成函數(shù)調(diào)用形式 ????????????? 系統(tǒng)提供了四個(gè)標(biāo)準(zhǔn)的對(duì)話框:AudioFormat, VideoFormat, VideoSource, Video Compression,但有時(shí)程序希望通過函數(shù)控制它們,而不是使用系統(tǒng)提供的那個(gè)單一的對(duì)話框,此時(shí)就應(yīng)該使用函數(shù)調(diào)用的方法:
??????????? 可以通過使用capSetAudioFormat來實(shí)現(xiàn),此時(shí)要使用WAVEFORMATEX結(jié)構(gòu)。 例如:改成PCM格式,立體聲,16聲道,12.05kHz,則: WAVEFORMATEX audioFormat; // 確定寬度 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,&dwSize); dwSize = max (dwSize, capGetAudioFormatSize (m_hwCapCapturing)); // 設(shè)置參數(shù) audioFormat.wFormatTag = WAVE_FORMAT_PCM; audioFormat.nChannels = 2; audioFormat.nSamplesPerSec = 120500; audioFormat.wBitsPerSample =16; audioFormat.nBlockAlign = nBitsPerSample * nChannels / 8; audioFormat.nAvgBytesPerSec = audioFormat.nBlockAlign * nSamplesPerSec; // 更新 capSetAudioFormat(ghCapWnd,&audioFormat,dwSize); VideoFormat對(duì)話框 ????????????????? 可以通過使用capSetVideoFormat來實(shí)現(xiàn),此時(shí)要使用BITMAPINFOHEADER結(jié)構(gòu)。 例如:設(shè)置圖片大小為RGB24位歲,大小為230X160 BITMAPINFOHEADER bi; DWORD dwSize,dw; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = 320; // 起作用 bi.biHeight = 160; // 起作用 bi.biPlanes = 1; bi.biBitCount = 24; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 176; bi.biYPelsPerMeter = 144; bi.biClrUsed = 0; bi.biClrImportant = 0; dwSize = bi.biSize + ((bi.biBitCount > 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY))); dw = capSetVideoFormat(m_hwCapCapturing, &bi, dwSize); VideoSource對(duì)話框 ??????????????? 沒有找到現(xiàn)成的方法,但視頻捕獲卡提供的CD里面有一個(gè)動(dòng)態(tài)鏈接庫可以實(shí)現(xiàn)。 Video Compression對(duì)話框 ???????????? 可以通過使用ICOpen,ICInfo等函數(shù)聯(lián)合起來,得到當(dāng)前系統(tǒng)里面的視頻壓縮驅(qū)動(dòng)的列表,并可選擇其一,MSDN里面有一個(gè)程序示范了此用戶,程序名叫:ICWalk。 |
總結(jié)
以上是生活随笔為你收集整理的视频捕捉全教程(MFC+vfw)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021年全球人工智能物流无人机行业调研
- 下一篇: 欧姆龙CJ系列PLC五大扩展模块实战演示