本週要進行的討論主題是 - 如何從記憶體直接擷取視訊畫面?
我們所設定的實驗是: 透過使用 callback function 的方式, 將所擷取到的畫面顯示到另一個影像元件之中。
首先, 我們先在 MainMenu 這個元件中建立一個視訊擷取視窗 Callback function 的控制開關, 透過這個 on/off , 我們可以隨時開啟或關閉是否要對擷取視窗的畫面進行處理。
SampleProgram6.txt
透過 capSetCallbackOnFrame 這個函式設定: 當視訊擷取視窗(代碼為 hwndViedo) 取得一個 frame 後, 必須執行我們所定義的 callback function: FrameCallBack,
capSetCallbackOnFrame(hwndVideo, &FrameCallBack);
LRESULT CALLBACK FrameCallBack( HWND hwndCapture, PVIDEOHDR lpvhdr );
在我們所自行定義的 FrameCallBack callback function 中, 有兩個輸入參數, 第一個參數 HWND hwndCapture, 指明哪一個視訊擷取視窗, 即該視訊擷取視窗的 handle, 第二個參數 PVIDEOHDR lpvhdr, capSetCallbackOnFrame 這個函式會自動把視訊擷取視窗的相關資訊透過 PVIDEOHDR lpvhdr 這個結構變數, 讓 FrameCallBack callback function 來使用。
有關 PVIEDOHDR 這個結構的相關資訊, 可以在 vfw.h 中, 找到如下的結構定義:
/* video data block header */
typedef struct videohdr_tag {
LPBYTE lpData; /* pointer to locked data buffer */
DWORD dwBufferLength; /* Length of data buffer */
DWORD dwBytesUsed; /* Bytes actually used */
DWORD dwTimeCaptured; /* Milliseconds from start of stream */
DWORD_PTR dwUser; /* for client's use */
DWORD dwFlags; /* assorted flags (see defines) */
DWORD_PTR dwReserved[4]; /* reserved for driver */
} VIDEOHDR, NEAR *PVIDEOHDR, FAR * LPVIDEOHDR;
透過 結構 videohdr_tag 的宣告, 我們獲知擷取視窗的 data buffer 的指標可以用 lpData 這個變數來取得, 即
CaptureData = LPVIDEOHDR(lpvhdr);
ptrCapture = CaptureData->lpData;
// 全域變數宣告
LPVIDEOHDR CaptureData;
BYTE *ptrCapture, *ptrImage;
說明:
1. CaptureData 是全域結構變數, 其資料型態亦為 PVIDEOHDR。
2. *ptrCapture 與 *ptrImage 是兩個指向記憶體位址的全域指標變數。
本週的第一個實驗要做的事, 說穿了就是把某一塊記憶體(視訊擷取視窗資料暫時存放區/data buffer)複製到另一塊記憶體(影像物件存放色彩資料的記憶體)之中。因此, 我們只要弄清楚兩個記憶體的起始位址, 自然可以輕鬆完成實驗。
SampleProgram7.txt
第二個實驗則是需要針對監視畫面內容稍做計算, 畫面的下角是背景圖, 監視畫面與背景圖相減所得到的差異影像, 則會被放到右下角的圖片中。
SampleProgram8.txt
沒有留言:
張貼留言