談談使用VFW在windows下編程控制攝像頭(二)。 【孫濤】

版權聲明:http://blog.csdn.net/suntaoznz/article/details/448303

如要轉貼請註明轉至blog.csdn.net/suntaoznz。謝謝!

3.2使用視頻捕獲

3.2.1創建捕獲窗體

下面的例子通過使用capCreateCaptureWindow函數來創建一個捕獲窗體

hWndC = capCreateCaptureWindow (

    (LPSTR) "My Capture Window",       // 如果是Pop-up窗口的窗口名稱

    WS_CHILD | WS_VISIBLE,          // 窗口類型

    0, 0, 160, 120,                      // 窗口位置和尺寸

    (HWND) hwndParent,

    (int) nID /* child ID */);

 

3.2.2連接到一個捕獲驅動器

下面舉例,如何通過捕獲窗口的句柄hWndC連接到MS VIDEO驅動程序上,同時還演示瞭如何斷開連接。使用capDriverDisconnect

fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);

// 或者使用宏連接:

// fOK = capDriverConnect(hWndC, 0);

 

// 關閉連接

capDriverDisconnect (hWndC);

 

3.2.3列舉安裝的捕獲驅動程序

使用capGetDriverDescription 函數來獲得系統已經安裝的所有捕獲驅動程序的名稱和版本。

char szDeviceName[80];

char szDeviceVersion[80];

for (wIndex = 0; wIndex < 10; wIndex++)

{

    if (capGetDriverDescription (wIndex, szDeviceName,

        sizeof (szDeviceName), szDeviceVersion,

        sizeof (szDeviceVersion))

    {

        // 加入名字到一個已經安裝的設備列表中

        // 讓用戶選擇一個使用。

    }

}

 

 

3.2.4獲得捕獲驅動器的性能參數

       WM_CAP_DRIVER_GET_CAPS消息可以返回捕獲驅動程序以及其硬件的性能參數。這些信息存放在一個CAPDRIVERCAPS的數據結構中。當你的應用程序的捕獲窗口連接到一個新的捕獲驅動器後,都會刷新這個CAPDRIVERCAPS數據結構。下面將使用capDriverGetCaps宏來獲得捕獲設備的性能參數。

CAPDRIVERCAPS CapDrvCaps;

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

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

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

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

 

3.2.5獲得捕獲窗口狀態(Status)

下面例子使用SetWindowPos函數區設置捕獲窗口的尺寸,這個尺寸的大小是基於輸入的視頻流大小的。輸入視頻流的尺寸大小由capGetStatus宏來獲得,獲得信息放在一個CAPSTATUS的數據結構體中。

 

CAPSTATUS CapStatus;

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

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

             CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);

3.2.6顯示對話框區設置視頻屬性

       每個捕獲驅動器都可以提高3個以上的不同對話框來控制數字視頻的特性和捕獲處理。下面的例子示範如何顯示這些對話框。在顯示每個對話框前,該例會調用capDriverGetCaps宏並且檢查返回的CAPDRIVERCAPS對象來查看是否可以能夠顯示特定的對話框。

 

CAPDRIVERCAPS CapDrvCaps;

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 (CapDriverCaps.fHasDlgVideoDisplay)

    capDlgVideoDisplay(hWndC);

 

3.2.7獲得和設定視頻格式

BITMAPINFO數據結構體可以實現長度可調節地去適應標準壓縮的數據格式。因爲它的長度可以變,所以在每次獲得當前視頻格式前,都必須去查詢這個結構的長度以及分配的內存大小。該例子使用了capGetVideoFormatSize宏去獲得緩存區大小,使用capGetVideoFormat宏區獲得當前視頻格式。

 

LPBITMAPINFO lpbi;

DWORD dwSize;

 

dwSize = capGetVideoFormatSize(hWndC);

lpbi = GlobalAllocPtr (GHND, dwSize);

capGetVideoFormat(hWndC, lpbi, dwSize);

 

// 訪問視頻格式,並且釋放分配的內存。

 

應用程序使用capSetVideoFormat(WM_CAP_SET_VIDEOFORMAT),把一個BITMAPINFO結構發送給捕獲窗口,顯示修改。因爲視頻格式由設備指定的,你的應用程序可以去檢查獲得的返回值,來知道這個視頻格式是不是公開的。

 

3.2.8預覽視頻

       下面使用capPreviewRate宏來設置預覽模式的幀頻率爲66毫秒/幀,使用capPreview宏在捕獲窗口預覽圖像。

 

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

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

 

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

 

3.2.9允許視頻覆蓋(Overlay)

下面使用capDriverGetCaps宏去檢測這個捕獲驅動是否支持覆蓋(Overlay)模式,如果支持,就允許視頻覆蓋模式;

 

CAPDRIVERCAPS CapDrvCaps;

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

if (CapDrvCaps.fHasOverlay)

    capOverlay(hWndC, TRUE);

 

 

3.2.10捕獲文件命名

    下例使用capFileSetCaptureFile宏來指定一個要命名的文件名(mycap.avi),使用capFileAlloc宏去預分配5MB的文件。

 

char szCaptureFile[] = "MYCAP.AVI";

capFileSetCaptureFile( hWndC, szCaptureFile);

capFileAlloc( hWndC, (1024L * 1024L * 5));

 

3.2.11格式化音頻捕獲

下例使用capSetAudioFormat來設置音頻格式爲11-KHz PCM 8-bit,立體聲。

 

WAVEFORMATEX wfex;

wfex.wFormatTag = WAVE_FORMAT_PCM;

wfex.nChannels = 2;                     // 使用立體聲

wfex.nSamplesPerSec = 11025;

wfex.nAvgBytesPerSec = 22050;

wfex.nBlockAlign = 2;

wfex.wBitsPerSample = 8;

wfex.cbSize = 0;

capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));

 

3.2.12改變視頻捕獲設置

       下例使用capCaptureGetSetupcapCaptureSetSetup宏來改變捕獲速度,從默認值(15/)10/秒。

 

CAPTUREPARMS CaptureParms;

float FramesPerSec = 10.0;

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

CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /

    FramesPerSec);

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

 

3.2.13捕獲數據

       下例使用capCaptureSequence宏開始視頻捕獲,使用capFileSaveAs宏從捕獲文件拷貝數據到其他文件NEWFILE.AVI中。

 

char szNewName[] = "NEWFILE.AVI";

// Set up the capture operation.

capCaptureSequence(hWndC);

// Capture.

capFileSaveAs(hWndC, szNewName);

 

3.2.14加入信息塊

如果你想添加其他信息(除了音視頻),你可以建一個信息塊並把它們插入到一個捕獲文件中去。信息塊可以包含這個方面的內容。比如版權信息,視頻源的ID,外部顯示的時間信息。下面的例子保存外部時間信息SMPTE()到一個信息塊中,並加入使用capFileSetInfoChunk宏加入到捕獲文件中。

 

//  This example assumes the application controls

//  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);

 

3.2.15在程序中加入回調函數

應用程序可以註冊捕獲窗口的回調函數,這樣就可以把下面的情況通知給應用程序:

l         狀態變化了

l         錯誤發生了

l         視頻和音頻的緩衝區的數據可以使用了

l         在捕獲期間,應用程序將yield

下面的例子將創建一個捕獲窗口並在應用的消息循環中,注狀態、錯誤、視頻流、幀的回調函數。

 

case WM_CREATE:

{

    char    achDeviceName[80] ;

    char    achDeviceVersion[100] ;

    char    achBuffer[100] ;

    WORD    wDriverCount = 0 ;

    WORD    wIndex ;

    WORD    wError ;

    HMENU   hMenu ;

 

    // 使用capCreateCaptureWindow宏創建一個捕獲窗體.

    ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",

        WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);

 

    // 使用capSetCallbackOnError宏註冊錯誤回調函數

     capSetCallbackOnError(ghWndCap, fpErrorCallback);

 

    // 使用capSetCallbackOnStatus宏註冊狀態回調函數

    capSetCallbackOnStatus(ghWndCap, fpStatusCallback);

 

    //使用capSetCallbackOnVideoStream宏註冊視頻流回調函數

    capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);

 

    //使用capSetCallbackOnFrame宏註冊幀回調函數

    capSetCallbackOnFrame(ghWndCap, fpFrameCallback);

 

    // 連接到一個捕獲驅動器上

 

    break;

}

case WM_CLOSE:

{

//使用capSetCallbackOnFrame宏關閉幀回調函數

// 類似可調用其他存在的回調函數。

 

    capSetCallbackOnFrame(hWndC, NULL);

  break;

}

 

 

 

3.2.16創建一個狀態回調函數

下面的例子是一個簡單的狀態回調函數,使用capSetCallbackOnStatus宏來註冊這個回調函數。

// StatusCallbackProc: 狀態回調函數

// hWnd:            捕獲窗體句柄

// nID:              當前狀態的狀態碼

// lpStatusText:       當前狀態的文本字符

//

LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,

    LPSTR lpStatusText)

{

    if (!ghWndMain)

        return FALSE;

 

    if (nID == 0) {           // 清除舊的狀態信息

        SetWindowText(ghWndMain, (LPSTR) gachAppName);

        return (LRESULT) TRUE;

    }

    // 顯示狀態ID和狀態文本..

    wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);

 

    SetWindowText(ghWndMain, (LPSTR)gachBuffer);

    return (LRESULT) TRUE;

}

 

3.2.17創建一個錯誤的回調函數

下面例子是一個簡單的錯誤回調函數。通過capSetCallbackOnError宏來註冊回調。

// ErrorCallbackProc:    錯誤回調函數

// hWnd:              捕獲窗口句柄

// nErrID:              錯誤代碼

// lpErrorText:          關於錯誤的文本信息

//

LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,

    LPSTR lpErrorText)

{

 

    if (!ghWndMain)

        return FALSE;

 

    if (nErrID == 0)            // Starting a new major function.

        return TRUE;          // 清除舊的錯誤

 

    // 顯示錯誤ID和錯誤文本信息

    wsprintf(gachBuffer, "Error# %d", nErrID);

 

    MessageBox(hWnd, lpErrorText, gachBuffer,

               MB_OK | MB_ICONEXCLAMATION);

 

    return (LRESULT) TRUE;

}

 

3.2.18創建一個幀回調函數

下面是一個簡單的幀回調函數。通過capSetCallbackFrame宏來註冊回調函數。

 

// FrameCallbackProc:   幀回調函數

// hWnd:              捕獲窗體句柄

// lpVHdr:             指向一個包含幀信息的數據結構體

//

LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

{

    if (!ghWndMain)

        return FALSE;

 

    wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++);

    SetWindowText(ghWndMain, (LPSTR)gachBuffer);

    return (LRESULT) TRUE ;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章