天天看點

基于vfw的攝像頭視訊浏覽和捕獲的程式

使用基于VFW的方式進行攝像頭視訊浏覽和捕獲,優點是編碼簡單,缺點是功能受限

方法: 建立一個基于對話框的工程,引用頭檔案<vfw.h> , 導入 vfw32.lib 庫,庫檔案可以在vc 存在路徑中找到; 如:D:/Program Files/Microsoft Visual Studio/VC98/Lib/vfw32.lib

在窗體上添加四個個按鈕,修改ID 為IDC_VIDEO , IDC_CAPTURE , IDC_STOPVIDEO , IDC_STOPCAPTURE;

為按鈕IDC_VIDEO 添加代碼開始浏覽視訊 :

{

// create a window for captureWindow 

 CWnd  * mywnd = new  CWnd;

 mywnd -> Create(_T( " STATIC " ),  "" , WS_CHILD  |  WS_VISIBLE,CRect( 0 ,  0 ,  400 ,  400 ),  this ,  1234 );

 mywnd -> ShowWindow(SW_SHOW);

 CRect rect;

 mywnd -> GetWindowRect(rect);

// create capture window

 ghCapWnd = capCreateCaptureWindow(  " My Own Capture Window " ,WS_CHILD  |  WS_VISIBLE , 0 ,  0 , (rect.right - rect.left), (rect.bottom - rect.top), mywnd -> GetSafeHwnd(),  1235 );

// connect device

 capDriverConnect (ghCapWnd,  0 );

// get params

 CAPTUREPARMS CapParms;

 capCaptureGetSetup(ghCapWnd, & CapParms, sizeof  (CAPTUREPARMS));

// 設定桢速

 CapParms.dwRequestMicroSecPerFrame = 40000 ; 

// 有無時間限制 

 CapParms.fLimitEnabled  =  FALSE; 

// 是否捕捉音頻

// CapParms.fCaptureAudio = FALSE; 

// MCI Device支援

 CapParms.fMCIControl  =  FALSE;  

// 設定視窗,如果為false,捕捉畫面在桌面上              

 CapParms.fYield  =  TRUE;

// 停止捕捉鍵設定

 CapParms.vKeyAbort  =  VK_ESCAPE;

 CapParms.fAbortLeftMouse  =  FALSE;

 CapParms.fAbortRightMouse  =  FALSE;

 capCaptureSetSetup(ghCapWnd, & CapParms, sizeof  (CAPTUREPARMS));

// 設定預覽時的比例

 capPreviewScale(ghCapWnd,  1 );

// 設定預覽時的幀頻率

 capPreviewRate(ghCapWnd, 66 );

// 是否支援比例變化

 capPreviewScale(ghCapWnd,FALSE);

// 打開預覽

 capPreview(ghCapWnd,  1 );

}

為 IDC_CAPTURE 添加代碼開始捕獲視訊 :

{

 capCaptureSequence(ghCapWnd);

}

為IDC_STOPCAPTURE添加代碼停止捕捉:

{

 capCaptureAbort(ghCapWnd);

}

為IDC_STOPVIDEO添加代碼斷開連接配接:

{

 capDriverDisconnect(ghCapWnd);

}

補充:

一、捕獲的幀頻率

捕獲的幀頻率表示在一個捕獲會話中,每秒要捕獲多少幀。你通過WM_CAP_GET_SEQUENCE_SETUP 消息(capCaptureGetSetup宏)可以得到目前捕獲的幀頻率。目前的幀頻率被儲存在CAPTUREPARMS結構的dwRequestMicroSecPerFrame 成員中。你可以對該值進行修改,進而去改變幀頻率。該值為捕獲一幀要用的時間(機關是微秒 1/1000000秒),修改後,你可以發送WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup 宏)給你的捕獲窗體,來重新整理CAPTUREPARMS 結構。dwRequestMicroSecPerFrame 預設值是66667微秒,表示每秒15幀。(1000000/15=66667)

下例使用capCaptureGetSetup和capCaptureSetSetup宏來改變捕獲速度,從預設值(15幀/秒)到10幀/秒。

基于vfw的攝像頭視訊浏覽和捕獲的程式

CAPTUREPARMS CaptureParms;

基于vfw的攝像頭視訊浏覽和捕獲的程式

float  FramesPerSec  =   10.0 ;

基于vfw的攝像頭視訊浏覽和捕獲的程式

capCaptureGetSetup(hWndC,  & CaptureParms,  sizeof (CAPTUREPARMS));

基于vfw的攝像頭視訊浏覽和捕獲的程式

CaptureParms.dwRequestMicroSecPerFrame  =  (DWORD) ( 1.0e6   /  FramesPerSec);

基于vfw的攝像頭視訊浏覽和捕獲的程式

capCaptureSetSetup(hWndC,  & CaptureParms,  sizeof  (CAPTUREPARMS)); 

基于vfw的攝像頭視訊浏覽和捕獲的程式

二、捕獲窗體狀态

通過發送WM_CAP_GET_STATUS消息(capGetStatus宏),可以獲得目前捕獲視窗的狀态。這個消息得到一個CAPSTATUS結構體的拷貝,狀态資訊就在這個結構體的成員中。CAPSTATUS 結構體包含了圖形尺寸大小、滾動位置(scroll position)、是否覆寫(overlay)或者預覽(preview)等資訊。因為在CAPSTATUS 中的資訊是動态的,你的應用程式應該随時去重新整理這個結構體中的内容。 改變捕獲視窗的尺寸對實際的視訊流的尺寸沒有影響。視訊捕獲可以做這幾個方面的工作:通路 視訊源、顯示選項、格式和壓縮選項。音頻捕獲包括指定音頻格式和選擇壓縮方式。

CAPSTATUS CapStatus;

capGetStatus(hWndC,  & CapStatus,  sizeof  (CAPSTATUS)); 

SetWindowPos(hWndC, NULL,  0 ,  0 , CapStatus.uiImageWidth, 

             CapStatus.uiImageHeight, SWP_NOZORDER  |  SWP_NOMOVE); 

三、捕獲驅動性能

通過發送WM_CAP_DRIVER_GET_CAPS消息(capDriverGetCaps宏),可以獲得目前連接配接的捕獲裝置的性能。發送該消息後,會傳回一個CAPDRIVERCAPS 結構的對象。裝置的性能資訊,就在這個對象中。

基于vfw的攝像頭視訊浏覽和捕獲的程式

CAPDRIVERCAPS CapDrvCaps; 

基于vfw的攝像頭視訊浏覽和捕獲的程式

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS, 

基于vfw的攝像頭視訊浏覽和捕獲的程式

     sizeof  (CAPDRIVERCAPS), (LONG) (LPVOID)  & CapDrvCaps); 

基于vfw的攝像頭視訊浏覽和捕獲的程式

//  或者,使用宏來獲得驅動器的新能參數 

基于vfw的攝像頭視訊浏覽和捕獲的程式

//  capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS)); 

四、預覽和覆寫模式 (Preview and Overlay )

一般,一個捕獲驅動提供兩種方式來觀看輸入的視訊流:預覽模式和覆寫模式。如果捕獲驅動可以提供上面兩種模式,那麼使用者就可以選擇其中的模式來使用。

預覽模式從捕獲裝置硬體傳輸資料幀到系統的記憶體中,并且在捕獲視窗中使用GDI函數來顯示這些資料幀。當捕獲視窗的父窗體失去焦點的時候,在應用程式的視訊預覽的資料将變慢,如果父窗體獲的焦點後,将對預覽顯示進行加速。因為預覽處理的這種處理方式将大大提高整個系統的效率。

這裡用3個消息用于控制預覽操作。

l     WM_CAP_SET_PREVIEW消息(capPreview 宏)可以打開或者關閉預覽模式。

l     WM_CAP_SET_PREVIEWRATE 消息(capPreviewRate 宏)可以設定預覽模式下圖像的幀速度。

l     WM_CAP_SET_SCALE 消息 (capPreviewScale 宏) 打開或者關閉預覽視訊的縮放比例。

當預覽和縮放比例屬性都打開後,那麼視訊将被縮放到和捕獲視窗尺寸一樣大。打開預覽模式後,系統将自動關閉覆寫模式。

基于vfw的攝像頭視訊浏覽和捕獲的程式

capPreviewRate(hWndC,  66 );       //  速度,微秒

基于vfw的攝像頭視訊浏覽和捕獲的程式

capPreview(hWndC, TRUE);        //  開始預覽 

基于vfw的攝像頭視訊浏覽和捕獲的程式

capPreview(hWnd, FALSE);         //  屏蔽預覽 

基于vfw的攝像頭視訊浏覽和捕獲的程式

覆寫模式,将不占用CPU的處理資源,直接在顯示器上顯示視訊内容。所用的處理是有捕獲裝置硬體來完成。發送WM_CAP_SET_OVERLAY消息(或capOverlay 宏)給捕獲視窗,可以打開覆寫模式。打開覆寫模式後,将自動關閉預覽格式。

基于vfw的攝像頭視訊浏覽和捕獲的程式

CAPDRIVERCAPS CapDrvCaps; 

基于vfw的攝像頭視訊浏覽和捕獲的程式

capDriverGetCaps(hWndC,  & CapDrvCaps,  sizeof  (CAPDRIVERCAPS)); 

基于vfw的攝像頭視訊浏覽和捕獲的程式

if  (CapDrvCaps.fHasOverlay) 

基于vfw的攝像頭視訊浏覽和捕獲的程式

    capOverlay(hWndC, TRUE);

無論是預覽模式還是覆寫模式,都可以通過發送WM_CAP_SETSCROLL消息(capSetScroollPos 宏),可以設定圖像的在整個視訊幀的滾動位置(scroll position)。

五、捕獲變化

除了對基于持續時間間隔的流捕獲外,AVICap還支援如下的捕獲:

l     手控制幀捕獲

l     Still-image 捕獲

l     不使用磁盤存儲的捕獲

l     從一個MCI裝置的流捕獲(real-time and step-frame)

手動幀捕獲

如果你向指定捕獲視訊流中個别幀,你可以通過WM_CAP_SINGLE_FRAME_OPEN消息、WM_CAP_SINGLE_FRAME消息、WM_CAP_SINGLE_FRMAE_CLOSE消息來控制幀序列(capCaptureSingleFrameOpen 、/capCaptureSingleFrame 、capCaptureSigleFrameClose )。

 典型應用是,這些消息用于向捕獲檔案添加單獨的幀來建立一個動畫, WM_CAP_SINGLE_FRAME_OPEN 為手動捕獲操作打開一個檔案,WM_CAP_SINGLE_FRAME用于捕獲一個單獨的幀放在檔案中。

WM_CAP_SINGLE_FRMAE_CLOSE用于關閉這個捕獲檔案。

注:  該操作支援音視訊同時捕獲。

Still-Image 捕獲

如果要捕獲一個單獨的幀作為一個靜态圖像,你可以使用WM_CAP_GRAB_FRAME_NOSTOP或者 WM_CAP_GRAB_FRAME 消息 (

或 宏) 在一個幀緩存區中捕獲一個圖像。你可以通過使用下面的消息來抓獲目前顯示的圖形WM_CAP_GRAB_FRAME ,否則,使用WM_CAP_GRAB_FRAME_NOSTOP。

一旦開始捕獲,你可以拷貝圖像給其他應用程式。你可以從幀緩存區拷貝一個圖像到剪貼闆(使用WM_CAP_EDIT_COPY 消息或capEditCopy 宏)。你還可以使用如下的消息,将緩存區的一張圖像拷貝到一個DIB位圖中(WM_CAP_FILE_SAVEDIB消息或capFileSaveDIB 宏)。

不使用磁盤存儲的捕獲

使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile 宏),可以不向磁盤檔案寫入資料。該消息僅在配合回調函數時有用,它允許你的應用程式直接使用音視訊資料。例如,在視訊會議中,應用程式使用該消息區獲得視訊流。回調函數将傳輸捕獲的圖像傳送給遠端的計算機。

基于vfw的攝像頭視訊浏覽和捕獲的程式

capCaptureSequenceNoFile(m_hWndCapture);  //  預設開始視訊

擷取記憶體中圖像位置指針的方法:

基于vfw的攝像頭視訊浏覽和捕獲的程式

LRESULT CALLBACK FrameCallbackProc(HWND ghWnd,LPVIDEOHDR lpVData)

     unsigned  char *  data;

    data = lpVData -> lpData; // 獲得視訊資料首址并将資料存入data數組中以便處理

     return  (LRESULT) TRUE;

}

基于vfw的攝像頭視訊浏覽和捕獲的程式

// 在捉圖的時候調用

基于vfw的攝像頭視訊浏覽和捕獲的程式

capSetCallbackOnVideoStream(hCapWnd,capVideoStreamCallback);

基于vfw的攝像頭視訊浏覽和捕獲的程式

capCaptureSequenceNoFile(hwndCap); 

基于vfw的攝像頭視訊浏覽和捕獲的程式

// 調用完成後關閉

基于vfw的攝像頭視訊浏覽和捕獲的程式

capSetCallbackOnVideoStream(hwndCap,NULL); 

從MCI 裝置進行流捕獲

MCI裝置加強了實時捕獲和步進幀(step-frame)捕獲的處理操作。你可以指定一個MCI裝置,比如一張影碟或者一盤錄像帶(VCR)來充當視訊源。通過發送消息并指定你要標明的MCI裝置的名稱。消息:WM_CAP_SET_MCI_DEVICE (capSetMCIDeviceName 宏)。獲得目前使用的裝置可以使用WM_CAP_GET_MCI_DEVICE(capGetMCIDeviceName )消息。

控制MCI裝置的規格資訊儲存在CAPTRUEPARMS 資料結構體的資料成員中。MCI相容的視訊源包括錄像機(VCR)和光碟。如果fMCIControl 資料成員為TRUE,捕獲視窗采用MCI操作。捕獲視窗使用dwMCIStartTime 和dwMCIStopTime 來獲得開始和結束位置(毫秒)。 如果fMCIControl 資料成員的值為FALSE, dwMCIStartTime 和dwMCIStopTime 的值将被忽略不見。

你可以使用Media Player 去快速檢查MCI裝置是否正确地連接配接到了你的系統上,如果在視訊顯示顯示了圖像,就表示這個視訊源正确連接配接到了捕獲硬體上。

步進幀(step-frame)捕獲控制的規格資訊儲存在CAPTRUEPARMS 資料結構體的資料成員中。步進幀(step-frame)捕獲除了使用視訊捕獲要用的資料成員外,還使用其他的資料成員:fStepMCIDevice , fStepCaptureAt2x , 和 wStepCaptureAverageFrames 。如果資料成員fStepMCIDevice 的值為TRUE,捕獲視窗采用步進幀(step-frame)捕獲。捕獲視窗将使用這兩個參數來指定捕獲的開始和結束位置(dwMCIStartTime 和dwMCIStopTime 毫秒)。捕獲視窗使用fStepCaptureAt2x 來決定捕獲硬體捕獲的視訊幀使用兩個普通的分辨率。使用 wStepCaptureAverageFrames 來指定捕獲時每幀圖像使用的時間大小。

    如果在一個步進幀(step-frame)捕獲中,指定fStepCaptureAt2x 為TRUE,那麼捕獲硬體将使用兩個指定的解析度來進行捕獲(高和寬的解析度都是雙倍的)。它使用軟體,在指定的解析度的基礎上改寫圖像的象素,讓其成為更高解析度的圖像。如果硬體不支援基于硬體的批量處理,你也可以使用該選項。并且捕獲為RGB格式。

注意:  如果你的硬體步支援基于硬體的批量處理(hardware-based decimation), it can capture samples at a higher rate than specified and use these additional samples to obtain color definitions that are more consistent with the original image. The additional samples are discarded after they are used, and the hardware passes samples to the capture driver at the specified rate。

如果指定了步進幀捕獲, wStepCaptureAverageFrames 成員用于指定捕獲一幀圖像要使用的時間,它是一個采樣的标準時間。以後捕獲圖像捕獲平均時間都會基于這個時間。采用這種機制,降會減少在一個圖像幀的随機數字化噪音。這個資料成員的标準值是5。

關于MCI的資訊可以檢視MSDN上的資訊。

六、進階捕獲選項

這節描述在一個捕獲操作中,你還可以進行的其他選擇。

l     測量視訊品質

l     使用者初始化捕獲

l     和調色闆一起工作

l     在AVI檔案中的嵌入資訊塊

l     使用者資料消息(Messages)

測量視訊品質

測量視訊品質的一個方法是去限定在一個捕獲操作期間丢掉的捕獲圖像幀的數字。當流捕獲完成後,品質 = 丢掉的幀 / 所有的幀。如果這個數(百分數)大于wPercentDropForError 的值,AVICap将發一個錯誤資訊給錯誤回調函數。WPercentDropForError 是CAPTUREPARMS 資料結構體的一個資料成員。

通過WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup 宏)可以得到目前設定的丢掉幀的限定值。同樣對wPercentDropForError 進行修改,再把修改後的資料結構體發送給捕獲窗體就可以完成對限定值的修改。WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureSetSetup ), wPercentDropForErrorm 預設值10 (10%)。

使用者初始化捕獲

   通過WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup 宏)可以得到目前使用者初始化捕獲的狀态值。該值存放在fMakeUserHitOKToCapture 中。在開始一個捕獲會話前,設定該值為TRUE,可以為使用者提供精确的控制。系統為所有的音視訊配置設定好資料緩存區後,AVICap會顯示一個對話框。它讓使用者清除因為軟體初始化導緻的捕獲延遲。如果你的應用程式為視訊資料配置設定的資料緩存區很小,那麼這個對話框可能就沒的必要了。該值的預設值是FALSE。

和調色闆一起工作

    最初,如果視訊捕獲格式需要一個調色闆,那麼捕獲視窗将使用捕獲驅動提供的調色闆來代替。這個調色闆可能由灰階值,或者可選的彩色值組成。使用WM_CAP_PAL_PASTE或者WM_CAP_PAL_OPEN消息(capPalettePaste 或capPaletteOpen )可以獲得一個現存的調色闆去替換預設的調色闆。你還可以建立一個自定義的調色闆去替換預設的調色闆,你要使用WM_CAP_PAL_AUTOCREATE 或者 WM_CAP_PAL_MANUALCREATE消息 ( capPaletteAuto 或 capPaletteManual )。當你替換了調色闆後,捕獲窗體和驅動程式将使用替換後的調色闆,直到你建立或打開其他的調色闆為止。

WM_CAP_PAL_AUTOCREATE 或者 WM_CAP_PAL_MANUALCREATE 消息将建立一個基于目前視訊輸入最優化的調色闆。這個自定義的調色闆将為視訊提供一個最好的顔色逼真度,因為這個調色闆的顔色是基于這個視訊的。捕獲視窗建立一個采樣顔色的3維柱狀圖。它會減小真實顔色和漸近色間的值。

在發送WM_CAP_PAL_AUTOCREATE消息時, 你必須指定AVICap采樣的幀數以及調色闆的顔色尺寸。在指定幀數時,要保證幀數足夠大以保證所有的視訊顔色可以被采樣收集到。

   使用WM_CAP_PAL_MANUALCREATE消息可以對目前幀進行采樣。通過該消息,進行幾次手動選擇幀采樣操作,你可以建立自己的調色闆,它包含了你想要的顔色資訊。

一個調色闆可以包含256種顔色。如果你要合并調色闆,或者在視訊隊列中同時在顯示其他視訊或圖像。你可以去使用一個小的顔色集合,這樣不同圖像或視訊的顔色就可以共存了。

使用WM_CAP_PAL_SAVE消息(capPaletteSave ),可以保促一個新的調色闆。通過WM_CAP_PAL_OPEN消息還可以得到目前的調色闆。你可以在調色闆處理前儲存一個調色闆,或者為其他應用程式使用去儲存一個調色闆。

使用WM_CAP_PAL_PASTE可以把剪貼闆中的調色闆粘貼到捕獲視窗中。捕獲視窗通過這個調色闆到捕獲驅動。其他程式可以拷貝調色闆到剪貼闆中。你也可以把調色闆粘貼到剪貼闆中。使用WM_CAP_ENDIT_COPY消息(capEditCopy )。它将拷貝視訊緩存區(包括調色闆)到剪貼區。

在AVI 檔案中的嵌入資訊塊

你可以在一個AVI檔案中插入資訊塊,比如文本或者自定義的資料。通過使用下面的消息:WM_CAP_FILE_SET_INFOCHUNK(capFileSetInfoChunk )。可以使用這個消息還可以清除掉一個AVI檔案中的資訊塊。

使用者資料消息

    通過使用WM_CAP_GET_USER_DATA和WM_CAP_SET_USER_DATA消息可以關聯資料到一個捕獲窗體。(capGetUserData 和 capSetUserData 宏)。使用…Get…消息可以得到一個LONG資料值,可以通過_Set_消息去設定該值。

七、AVICap回調函數

    你的應用程式可以為一個捕獲視窗注冊一些回調函數,它們可以告訴你的應用程式一些變化。比如捕獲狀态發生變化了,或者有錯誤發生了,音視訊緩存區可使用了。下面的消息設定回調函數。

消      息 說      明

WM_CAP_SET_CALLBACK_CAPCONTROL

CapSetCallbackOnCapControl 宏

在應用程式中指定回調函數用于控制捕獲的開始和結束。

WM_CAP_SET_CALLBACK_ERROR

CapSetCallbackOnError 宏

在應用程式中指定回調函數,當出錯的時候就調用它。

WM_CAP_SET_CALLBACK_FRAME

CapSetCallbackOnFrame 宏

在應用程式中指定回調函數,當預覽圖像幀被捕獲了的時候就調用它。

WM_CAP_SET_CALLBACK_STATUS

CapSetCallbackOnStatus 宏

在應用程式中指定回調函數,當狀态(status)改變的時候就調用它。

WM_CAP_SET_CALLBACK_VIDEOSTREAM

CapSetCallbackOnVideoStream 宏

在應用程式中指定回調函數,在流捕獲期間,當一個新的視訊緩存區可用的時候就調用它。

WM_CAP_SET_CALLBACK_WAVESTREAM

CapSetCallbackOnWaveStream 宏

在應用程式中指定回調函數,在流捕獲期間,當一個新的音頻緩存區可用的時候就調用它。

WM_CAP_SET_CALLBACK_YIELD

CapSetCallbackOnYield 宏

在應用程式中指定回調函數,在流捕獲期間Yielding(産生?)

轉自blog.csdn.net/suntaoznz  

繼續閱讀