這段時間閑來無事,看了看MSDN的文檔,自己翻譯了一下。一是為了學習,二是對空閑時間的打發。是以也希望大家在拍磚的同時,尊重我的勞動,如要轉貼請注明轉至blog.csdn.net/suntaoznz。謝謝!
孫濤 2005-8-6
Microsoft? Video for Windows? (VFW) 提供的函數可以讓應用程式去處理視訊資料。 VFW 在16位Windows的時候就被引入了。它的許多重要功能已經被DirectX取代了。 要獲得更多的資訊,你可以參考DirectX 的文檔。
下面講介紹VFW的視訊捕獲:
3.視訊捕獲
你可以使用windows的AVICap 類輕松地完成視訊捕獲。AVICap 提供給應用程式一個簡單的、基于消息的接口去通路視訊裝置和錄音裝置,并且可以控制處理視訊流捕獲。
3.1 關于視訊捕獲
AVICap支援實是視訊流捕獲和實時單幀圖像捕獲。另外,AVICap 提供了對視訊源的控制(MCI媒體控制接口裝置),是以使用者可以通過應用程式控制一個視訊源開始和結束的位置,并且可以加大對幀捕獲的控制。
你使用AVICap 類可以完成如下的任務:
l 捕獲聲音和視訊,并将他們寫入到一個AVI檔案中。
l 動态連接配接和斷開視訊和音頻的輸入裝置。
l 使用覆寫或預覽的方法去顯示目前的視訊信号。
l 指定一個檔案用于捕獲,并且把這個捕獲檔案的内容拷貝給另一個檔案。
l 設定捕獲圖像速度(好多幀)。
l 顯示對話框用于控制視訊源和格式。
l 建立、儲存、加載調色闆。
l 拷貝圖像和調色闆到剪貼闆中。
l 捕獲并把圖像作為一個DIB位圖儲存。
3.1.1視訊捕獲:最簡單的方法
視訊捕獲将數字化一個視訊流和音頻資料,并且将他們儲存在硬碟和其他儲存設備上。
這裡将描述如何在應用程式中簡單地應用視訊捕獲,它通過三句代碼實作。它還介紹了如何通過發送消息給視訊捕獲視窗來結束或中斷一個視訊會話。
AVICap 捕獲視窗可以把捕獲的音視訊資訊寫入一個AVI檔案中。你的應用程式可以自由地處理這個AVI檔案、管理緩存區的音視訊資料、還可以在底層通路音視訊裝置的驅動器。AVICap為應用程式提供了一個靈活的接口。你可以使用下面的代碼,在你的應用程式中加入視訊捕獲:
HWndC = capCreateCaptureWindow ( "My Own Capture Window",
WS_CHILD | WS_VISIBLE , 0 , 0, 160, 120, hwndParent, nID);
SendMessage ( hWndC, WM_CAP_DRIVER_CONNECT, 0 , 0L);
SendMessage ( hWndC, WM_CAP_SEQUENCE, 0, 0L);
宏接口同樣有用,你可以選擇是使用宏接口還是SendMessage 函數來實作上面的功能,不過宏接口可以讓你的代碼更加容易了解。下面就使用了宏接口。
HWndC = capCreateCaptureWindow (" My Own Capture Window ",
WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);
capDriverConnect ( hWndC, 0); // 宏接口
capCaptureSequence ( hWndC); // 宏接口
你的應用程式建立AVICap捕獲視窗,并和視訊裝置建立連接配接後。你建立的這個捕獲視窗就準備捕獲資料了。這時,你可以通過發送WM_CAP_SEQUENCE消息(或capCaptureSequence 宏)開始對資料進行捕獲。
WM_CAP_SEQUENCE将使用預設設定,開始對視訊和音頻進行捕獲,并把資料放在一個CAPTURE.AVI的檔案中,捕獲動作将一直持續,除非有下面的事件發生:
l 使用者按了ESC鍵或者滑鼠的按鈕。
l 你的應用程式停止或者退出了捕獲操作。
l 磁盤寫滿了。
在應用程式中,你可以通過發送WM_CAP_STOP指令(或capCaptureStop)給捕獲視窗,讓它停止向檔案寫資料。你還可以通過發送WM_CAP_ABORT指令(或capCaptureAbort)給捕獲視窗,讓它中斷捕獲操作。
3.1.2捕獲基本設定
通過對定義在CAPTUREPARMS結構中的捕獲參數進行修改,你可以完成:
l 改變捕獲的幀頻律(幀/秒);
l 指定用鍵盤或滑鼠去結束一個捕獲會話;
l 為一個捕獲會話指定時間周期;
捕獲的幀頻率
捕獲的幀頻率表示在一個捕獲會話中,每秒要捕獲多少幀。你通過WM_CAP_GET_SEQUENCE_SETUP 消息(capCaptureGetSetup宏)可以得到目前捕獲的幀頻率。目前的幀頻率被儲存在CAPTUREPARMS結構的dwRequestMicroSecPerFrame 成員中。你可以對該值進行修改,進而去改變幀頻率。該值為捕獲一幀要用的時間(機關是微秒 1/1000000秒),修改後,你可以發送WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)給你的捕獲窗體,來重新整理CAPTUREPARMS 結構。dwRequestMicroSecPerFrame 預設值是66667微秒,表示每秒15幀。(1000000/15=66667)
退出資料捕獲
你可以讓使用者按這幾種方法退出一個捕獲會話,按鍵盤上的一個鍵或幾個組合鍵、或者按滑鼠的左鍵或者是右鍵。如果使用者退出一個實時的捕獲會話,那麼捕獲檔案中的内容将被系統丢棄掉。如果使用者退出一個步幀(step-frame)捕獲的會話,捕獲檔案将儲存到退出時刻前的所有資料。
你可以通過發WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏)給捕獲視窗,來獲得捕獲退出的設定資訊。目前的退出按鈕設定儲存在CAPTUREPARMS結構的vKeyAbort 成員中,目前的退出滑鼠設定儲存在fAbortLeftMouse和 fAbortRightMouse成員中。你可以改變這幾個成員,實作對目前值的修改。當你修改完成後,你可以發送WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)給你的捕獲窗體,來重新整理CAPTUREPARMS 結構。
vKeyAbort 預設值是 VK_ESCAPE。在重新指定其他按鍵前,你必須調用RegisterHotKey 函數。fAbortLeftMouse 和 fAbortRightMouse 是TRUE。
時間限定
通過使用CAPTUREPARMS結構的fLimitEnabled 和wTimeLimit成員,你可以去限定一個捕獲操作的時間周期。fLimitEnabled 表示是否要對捕獲操作限定時間, wTimeLimit 用于指定限定時間的最大值。
你發WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup宏)給捕獲視窗,就可以得到fLimitEnabled 和 wTimeLimit的值。 FLimitEnabled為TRUE表示要指定時間周期。WTimeLimit機關為秒。修改完成後,你可以發送WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)給你的捕獲窗體,來重新整理CAPTUREPARMS 結構。
fLimitEnabled 預設值為FALSE.
3.1.3捕獲視窗
捕獲窗體類似于一個标準控件(不如按鈕、清單框…),它一般使用WS_CHILD 和 WS_VISIBLE視窗類型。.
建立一個AVICap捕獲視窗
使用capCreateCaptureWindow 函數可以建立一個AVICap的捕獲視窗。這個函數傳回一個視窗句柄,這個句柄就是捕獲視窗的句柄,後面其他操作就是通過發送消息給該句柄來實作。你可以在一個程式中建立多個捕獲視窗,并且每個視窗連接配接到不同的捕獲裝置上。
建立捕獲視窗到捕獲裝置的連接配接
你可以動态地連接配接或斷開捕獲視窗與裝置間的連結。通過使用WM_CAP_DRIVR_CONNECT消息(或capDriverConnect宏),可以實作捕獲窗體與裝置驅動間的連接配接。當捕獲窗體和捕獲裝置驅動連接配接後,你就可以發送針對裝置的消息給該窗體了。
如果你的系統安裝了多個捕獲裝置,你可以通過在發送WM_CAP_DRIVER_CONNECT消息時,設定wPrarm參數(integer)。來指定捕獲視窗與那個具體的視訊捕獲裝置相連接配接。
WPrarm參數是一個整數,它表示一個系統已經安裝的視訊捕獲裝置清單的索引(系統資料庫中或這System.ini [drivers]中的資訊)。該清單的索引從0開始。
通過capGetDriverDescription函數可以獲得安裝的捕獲驅動程式的名稱和版本。你的應用程式可以使用這個函數列舉除安裝的所有捕獲裝置,讓使用者可以選擇其中一個去與捕獲視窗相聯。
通過發送WM_CAP_DRIVER_GET_NAME消息(capDriverGetName宏),可以獲得與指定窗體連接配接的捕獲裝置的名稱。通過發送WM_CAP_DRIVER_GET_VERSION消息(capDriverGetVersion宏),可以獲得與指定窗體連接配接的捕獲裝置的版本。
通過發送WM_CAP_DRIVER_DISCONNECT消息(capDriverGetDisconnect宏),可以斷開連接配接。當捕獲窗體銷毀後,任何連接配接的視訊捕獲裝置都将自動斷開。
父子窗體傳遞
一些系統級的消息,比如 WM_PALETTECHANGED、WM_QUERYNEWPALETTE,隻被發送到頂層(top-level)和overlapped視窗。如果一個捕獲窗體是一個資窗體,那它的父視窗應該來轉寄這些消息。
同樣地,假如父視窗尺寸改變了,它可能需要發送一個通知消息給捕獲視窗。相反,如果捕獲視訊尺寸變化了,捕獲視窗可能需要發一個通知消息給父視窗。最簡單的管理方法是讓捕獲視窗的尺寸等于捕獲視訊流的尺寸,随時把改變的尺寸告訴給父視窗。
捕獲窗體狀态
通過發送WM_CAP_GET_STATUS消息(capGetStatus宏),可以獲得目前捕獲視窗的狀态。這個消息得到一個CAPSTATUS結構體的拷貝,狀态資訊就在這個結構體的成員中。
CAPSTATUS 結構體包含了圖形尺寸大小、滾動位置(scroll position)、是否覆寫(overlay)或者預覽(preview)等資訊。因為在CAPSTATUS 中的資訊是動态的,你的應用程式應該随時去重新整理這個結構體中的内容。
改變捕獲視窗的尺寸對實際的視訊流的尺寸沒有影響。
3.1.4捕獲和音頻驅動器
視訊捕獲可以做這幾個方面的工作:通路 視訊源、顯示選項、格式和壓縮選項。音頻捕獲包括指定音頻格式和選擇壓縮方式。
捕獲驅動性能
通過發送WM_CAP_DRIVER_GET_CAPS消息(capDriverGetCaps宏),可以獲得目前連接配接的捕獲裝置的性能。發送該消息後,會傳回一個CAPDRIVERCAPS結構的對象。裝置的性能資訊,就在這個對象中。
視訊對話框(Video Dialog Boxes)
每個捕獲裝置的驅動程式都可以為控制視訊信号和捕獲處理和視訊壓縮提供4個對話框。這些對話框中的内容都是視訊捕獲驅動程式定義的。
視訊源對話框(Video Source dialog box)用于選擇視訊輸入通道和視訊圖像的動态參數。 它可以列舉出目前連接配接視訊裝置的信号類型(SVHS和複合類型),并且可以通過該對話框去修改圖像的色調、亮度、飽和度。你可以通過使用WM_CAP_DLG_VIDEOSOURCE 消息 (或 capDlgVideoSource 宏)來顯示和重新整理這個視窗。
視訊格式對話框(Video Format dialog box)用于選擇數字視訊的架構大小和視訊圖像的色深,以及捕獲視訊圖像的壓縮格式。你可以通過使用WM_CAP_DLG_VIDEOFORMAT消息 (或 capDlgVideoFormat宏)來顯示和重新整理這個視窗。
視訊顯示對話框(Video Display dialog box)用于控制視訊外觀。在該對話框上進行了修改隻是對視訊顯示起作用,對于實際的視訊資料是不會造成改變的。比如,可以改變顯示的顔色,飽和度等等....。你可以通過使用WM_CAP_DLG_VIDEODISPLAY消息 (或 capDlgVideoDisplay宏)來顯示和重新整理這個視窗。
視訊壓縮對話框(Video Compression dialog box)用于設定視訊壓縮的格式。通過使用WM_CAP_DLG_VIDEOCOMPRESSION消息 (或 capDlgVideoCompression宏)來顯示和重新整理這個視窗。
預覽和覆寫模式 (Preview and Overlay )
一般,一個捕獲驅動提供兩種方式來觀看輸入的視訊流:預覽模式和覆寫模式。如果捕獲驅動可以提供上面兩種模式,那麼使用者就可以選擇其中的模式來使用。
預覽模式從捕獲裝置硬體傳輸資料幀到系統的記憶體中,并且在捕獲視窗中使用GDI函數來顯示這些資料幀。當捕獲視窗的父窗體失去焦點的時候,在應用程式的視訊預覽的資料将變慢,如果父窗體獲的焦點後,将對預覽顯示進行加速。因為預覽處理的這種處理方式将大大提高整個系統的效率。
這裡用3個消息用于控制預覽操作。
l WM_CAP_SET_PREVIEW消息(capPreview宏)可以打開或者關閉預覽模式。
l WM_CAP_SET_PREVIEWRATE 消息(capPreviewRate宏)可以設定預覽模式下圖像的幀速度。
l WM_CAP_SET_SCALE 消息 (capPreviewScale 宏) 打開或者關閉預覽視訊的縮放比例。
當預覽和縮放比例屬性都打開後,那麼視訊将被縮放到和捕獲視窗尺寸一樣大。打開預覽模式後,系統将自動關閉覆寫模式。
覆寫模式,将不占用CPU的處理資源,直接在顯示器上顯示視訊内容。所用的處理是有捕獲裝置硬體來完成。發送WM_CAP_SET_OVERLAY消息(或capOverlay宏)給捕獲視窗,可以打開覆寫模式。打開覆寫模式後,将自動關閉預覽格式。
無論是預覽模式還是覆寫模式,都可以通過發送WM_CAP_SETSCROLL消息(capSetScroollPos宏),可以設定圖像的在整個視訊幀的滾動位置(scroll position)。
視訊格式
通過發送WM_CAP_GET_VIDEOFORMAT消息(capGetVideoFormat宏)給視訊捕獲視窗可以得到一個結構,在這個結構體中就包含了視訊的格式、大小。
通過發送WM_CAP_SET_VIDEOFORMAT消息(capSetVideoFormat宏)給視訊捕獲視窗可以對視訊格式進行修改設定。
You can set the format of captured video data by sending the WM_CAP_SET_VIDEOFORMAT message (or the capSetVideoFormat macro) to a capture window.
視訊捕獲設定
CAPTUREPARMS 資料結構包括了視訊流的控制參數。它允許完成如下的任務:
l 指定幀速度(Frame rate)。
l 指定為視訊配置設定的緩存大小。
l 關閉或者打開音頻捕獲。
l 設定捕獲的時間間隔。
l 指定捕獲裝置(MCI裝置、VCR或者影碟)。
l 指定鍵盤或滑鼠去控制結束捕獲。
l 指定适用的視訊類型
通過發送WM_CAP_GET_SEQENCE_SETUP消息(capCaptureGetSetup)給捕獲窗體,可以獲得一個CAPTUREPARMS資料結構的對象,目前視訊捕獲的設定資訊就在這裡面。
你可以改寫CAPTUREPARMS對象的成員,來實作對視訊捕獲資訊的修改。修改後,發送WM_CAP_SET_SEQUENCE_SETUP消息(capCaptureSetSetup)給捕獲窗體,并把這個CAPTUREPARMS 對象發給捕獲窗體,就可以實作修改。
音頻格式
通過發送WM_CAP_GET_AUDIOFORMAT消息(capGetAudioFormat 和capGetAudioFormatSize宏)給捕獲窗體,你就可以獲得目前的音頻資料格式或音頻資料結構的大小。預設音頻捕獲格式是 mono, 8-bit, 11 kHz PCM。
當你使用WM_CAP_GET_AUDIOFORMAT消息得到音頻格式後,通常會使用WAVEFORMATEX這個資料結構。
通過發送WM_CAP_SET_AUDIOFORMAT消息(capSetAudioFormat宏)給捕獲窗體,你可以設定音頻資料捕獲格式。當設定這個音頻格式時,你可以通過一個指針指向一個WAVEFORMAT ,WAVEFORMATEX,或者PCMWAVEFORMAT資料結構。
3.1.5捕獲檔案和緩存區
捕獲檔案名
AVICap預設,把音視訊資料從捕獲視窗儲存到目前驅動得根目錄下,檔案名稱為CAPTURE.AVI。發送WM_CAP_FILE_SET_CAPTURE_FILE消息(capFileSetCaptureFile)給捕獲窗體,可以改變儲存的檔案名。這個消息指定檔案名;它不實際建立檔案,配置設定空間,也不能打開檔案。通過發送WM_CAP_FILE_GET_CAPTURE_FILE消息(capFileFGetCaptureFile宏)給捕獲視窗,就可以得到目前檔案名。
儲存捕獲資料到一個新檔案
如果使用者想儲存捕獲資料,把資料存到另外一個檔案中。可以使用WM_CAP_FILE_SAVEAS消息(capFileSaveAs宏) 。這個消息不能改變捕獲檔案的名稱和内容。你必須去指定建立的檔案名,因為捕獲檔案将保留原來的檔案名稱。
為捕獲檔案預配置設定磁盤空間
在捕獲操作前,先在磁盤上為捕獲檔案建一個指定大小的檔案。預配置設定空間将減少資料儲存時的處理時間。可以通過WM_CAP_FILE_ALLOCATE消息(capFileAlloc宏)來預配置設定一個捕獲檔案。
你要預配置設定足夠大的磁盤空間去儲存預計最大的捕獲檔案。預配置設定磁盤空間沒有限定捕獲檔案的大小。如果捕獲的資料大于了配置設定的空間,檔案尺寸将自動變大。對一個捕獲檔案進行重寫資料,将對檔案的已經配置設定的磁盤空間進行重寫。
通過對捕獲檔案進行磁盤碎片整理可以提高捕獲性能。要對檔案進行碎片整理,可以使用一個碎片整理工具來完成,比如Disk Defragmenter。
通過使用沒壓縮的磁盤來儲存資料,同樣可以提高性能。因為在捕獲期間壓縮資料将對磁盤的吞吐量進行限制。
索引大小
在每個AVI檔案中都會使用一個指定大小的索引去查找音視訊資料塊。在一個索引的入口定位了一個視訊幀或者一個波形聲音的緩存器。是以,這個索引的大小簡接地限定了一個捕獲檔案所能儲存的幀的數量上限。
通過發送WM_CAP_GET_SEQUENCE_SETUP消息(capCaptureGetSetup宏)給捕獲視窗就可以得到目前的索引大小。這個索引大小就儲存在CAPTUREPARMS資料結構對象的一個成員中(dwIndexSize)。你可以在dwIndexSize中指定一個新的索引大小,并通過發送消息WM_CAP_SET_SEQUENCE_SETUP(capCaptureSetSetup宏)給捕獲視窗完成資訊設定。索引預設大小34,952 (允許32K 幀和想比對的聲音緩存器).
音視訊塊的間隔尺寸(Granularity)
資料塊的間隔尺寸是一個AVI檔案的邏輯塊大小。它用于寫和讀音視訊資料塊。當向磁盤寫音視訊資料時, AVICap 将在每個資料塊中加入一個必須的填充塊(filler chunks (RIFF "JUNK" chunks)) 去填充滿該資料塊。
你可以使用WM_CAP_GET_SEQUENC_SETUP消息(capCaptureGetSetup)去獲得目前的塊間隔尺寸(Granularity)。CAPTUREPARMS的wChunkGranularity 成員儲存的是目前的塊間隔尺寸資訊。通過對該成員的改寫,并發送WM_CAP_GET_SEQUENC_SETUP消息(capCaptureSetSetup),可以對其進行修改。你設定該參數為零的話,那麼塊間隔尺寸的值就為磁盤的扇區大小。
視訊緩存區
這個緩存區将視訊資料放在記憶體的堆中。緩存區的大小可以改變,并且它的大小是由CAPTUREPARMS的wNumVideoRequested 成員和系統可以的記憶體大小來決定。
你可以使用WM_CAP_GET_SEQUENC_SETUP消息(capCaptureGetSetup)去獲得目前的視訊緩存區的大小。CAPTUREPARMS的wNumVideoRequested 成員儲存的是目前的緩存區尺寸。通過對該成員的改寫,并發送WM_CAP_GET_SEQUENC_SETUP消息(capCaptureSetSetup),可以對其進行修改。
音頻緩存區
你可以使用下面三種方法來控制捕獲的音頻資料:
l 在捕獲中包含音頻或者不包含音頻
l 按要求指定音頻緩存區的大小
l Request that audio buffers be a specific size.
你可以使用WM_CAP_GET_SEQUENC_SETUP消息(capCaptureGetSetup)去獲得目前的音頻緩存區的設定。CAPTUREPARMS的fCaptureAudio指定在這次捕獲操作中是否包括對聲音的捕獲。WNumAudioRequested儲存目前要求的音頻緩存區的大小。dwAudioBufferSize 儲存目前的音頻緩存區的大小。
通過對該成員的改寫,并發送WM_CAP_GET_SEQUENC_SETUP消息(capCaptureSetSetup),可以對其進行修改。
fCaptureAudio 預設值是TRUE。The default buffer size (the value of) can contain 0.5 seconds of audio data or 10K, whichever is greater.
3.1.6捕獲變化
除了對基于持續時間間隔的流捕獲外,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 消息 ( capGrabFrameNoStop
或capGrabFrame 宏) 在一個幀緩存區中捕獲一個圖像。你可以通過使用下面的消息來抓獲目前顯示的圖形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宏),可以不向磁盤檔案寫入資料。該消息僅在配合回調函數時有用,它允許你的應用程式直接使用音視訊資料。例如,在視訊會議中,應用程式使用該消息區獲得視訊流。回調函數将傳輸捕獲的圖像傳送給遠端的計算機。
從MCI裝置進行流捕獲
MCI裝置加強了實時捕獲和步進幀(step-frame)捕獲的處理操作。你可以指定一個MCI裝置,比如一張影碟或者一盤錄像帶(VCR)來充當視訊源。通過發送消息并指定你要標明的MCI裝置的名稱。消息:WM_CAP_SET_MCI_DEVICE (capSetMCIDeviceName宏)。獲得目前使用的裝置可以使用WM_CAP_GET_MCI_DEVICE(capGetMCIDeviceName)消息。
在實時捕獲中, the capture window synchronizes the capture operation and compensates for delays associated with positioning the MCI video source and initializing the resources (such as capture buffers) required for capturing data. The capture window expects a valid MCI video device to be installed in the system for capturing data this way.
控制MCI裝置的規格資訊儲存在CAPTRUEPARMS資料結構體的資料成員中。MCI相容的視訊源包括錄像機(VCR)和光碟。如果fMCIControl資料成員為TRUE,捕獲視窗采用MCI操作。捕獲視窗使用dwMCIStartTime和dwMCIStopTime來獲得開始和結束位置(毫秒)。 如果fMCIControl資料成員的值為FALSE, dwMCIStartTime和dwMCIStopTime的值将被忽略不見。
你可以使用Media Player 去快速檢查MCI裝置是否正确地連接配接到了你的系統上,如果在視訊顯示顯示了圖像,就表示這個視訊源正确連接配接到了捕獲硬體上。
在步進幀(step-frame)捕獲情況下, the capture window synchronizes the capture operation and compensates for the delays associated with positioning the MCI video source and initializing the resources required for capturing data. In addition, the capture window ensures that no frames are dropped; it steps through the video frames individually, ensuring that the frame is captured and stored before capturing the next frame in the video stream.
步進幀(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上的資訊。
3.1.7進階捕獲選項
這節描述在一個捕獲操作中,你還可以進行的其他選擇。
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_消息去設定該值。
3.1.8 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(産生?)
精确捕獲控制
捕獲視窗可以提供捕獲回調函數,這個回調函數可以對流捕獲的開始和結束時刻進行精确的控制。在捕獲驅動程式(capture driver)完成所有緩存區配置設定和其他捕獲準備後,捕獲驅動程式就發送第一個消息給回調處理程式,把nState參數設定為:
CONTROLCALLBACK_PREROLL
這個消息告訴應用程式将要開啟視訊源了。(這個回調函數指定nState為它的第二個參數)回調函數将在開始時刻産生傳回值。傳回值為TRUE那麼将繼續捕獲。為FALSE就中斷捕獲。一旦捕獲開始,這個回調函數将頻繁的調用,把nState設定為:
CONTROLCALLBACK_CAPTURING
将允許應用程式通過傳回false去結束捕獲。
錯 誤
捕獲視窗使用錯誤通知消息去告訴你的應用程式,發生了AVICap錯誤,比如磁盤空間已經用完了,嘗試對一個隻讀檔案進行寫操作,不能通路硬體,掉幀太多。錯誤通知内容報價一個消息ID和一個格式化的文本字元(用來顯示)。你的應用程式可以通過使用這個消息ID去過濾錯誤通報,還可以讓該錯誤資訊不顯示給使用者。消息ID為0表示一個新操作正在開始并且這個回調函數會清除掉所有的顯示的錯誤資訊。
幀(Frame)
A capture window uses frame callback notification messages to notify your application when a new video frame is available. The capture window enables these callback notifications only if the preview rate is nonzero and streaming capture is not in progress.
狀态回調函數
當視訊捕獲向磁盤寫資料,或者在其他較長的操作期間,捕獲視窗可以發送消息給狀态回調函數通知你正在處理該操作的應用程式。狀态資訊包括一個消息ID和和一個格式化的文本字元(用來顯示)。你的應用程式可以通過使用消息ID去過濾通報,還可以限制該資訊是否顯示給使用者。在捕獲操作期間,發給回調函數的第一個消息總是ID_CAP_GEGIN,最後一個總是ID_CAP_END。消息ID為0表示,一個新操作正在進行并且回調函數将清除目前狀态。
視訊流
在流捕獲期間,應用程式可以使用視訊流回調函數去處理一個捕獲的視訊幀。視訊窗體隻能在每次向磁盤寫資料幀前,調用視訊流回調函數。
音頻流
在流捕獲期間,應用程式可以使用音頻流回調函數去處理音頻緩存區。視訊窗體隻能在每次向磁盤寫資料幀前,調用音頻流回調函數。
Yield 回調函數
應用程式在流捕獲期間可以使用Yield回調函數。(Yield回調函數一般是由一個消息循環組成,可以調用PeekMessage,TranslateMessage,DispatchMessage)。捕獲視窗在每次捕獲視訊幀時至少調用一次Yield回調函數。但是具體要調用多少次由幀率來決定。
關閉回調函數
你可以暫時或永久關閉所有的回調函數的功能,在發送消息設定回調函數的時候,用NULL替換調回調函數就可以了。
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 );
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 ;
}