星期四, 4月 02, 2009

Week 7: 如何從記憶體直接擷取視訊畫面?

本週要進行的討論主題是 - 如何從記憶體直接擷取視訊畫面?

我們所設定的實驗是: 透過使用 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
 

沒有留言: