使用視頻捕獲

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改變視頻捕獲設置

下例使用capCaptureGetSetup和capCaptureSetSetup宏來改變捕獲速度,從默認值(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 ;

}

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