VFW編程執行個體

來源:互聯網
上載者:User

 VFW(Video for Windows)是Microsoft推出的關於數位視訊的一個軟體開發包,VFW的核心是AVI檔案標準。AVI(Audio Video Interleave)檔案中的音、視頻資料幀交錯存放。圍繞AVI檔案,VFW推出了一整套完整的視頻採集、壓縮、解壓縮、回放和編輯的應用程式介面(API)。由於AVI檔案格式推出較早且在數位視訊技術中有廣泛的應用,所以VFW仍然有很大的實用價值,而且進一步發展的趨勢。

  在VC++開發環境中調用VFW和使用其它開發包沒有什麼不同,只是需要將VFW32.lib檔案加入工程中,但在開放視頻捕捉與壓縮管理程式時需要其它軟體硬體設定。VFW為AVI檔案提供了豐富的處理函數和宏定義,AVI檔案的特點在於它是典型的資料流檔案,它由視頻流、音頻流、文字資料流組成。所以對AVI檔案的處理主要是處理檔案流。

編程執行個體
為了能夠捕獲視訊框架,要啟動一個捕獲幀回呼函數VideoStreamCallBack。
捕獲一個視頻流或當前裝置狀態時分別使用以下函數:
//捕獲一個視頻流
CapSetCallbackOnVideoStream;  
//得到一個裝置錯誤
CapSetCallbackOnError;  
//得到一個裝置狀態
CapSetCallbackOnStatus  
} 自訂的函數1 //定義一個幀捕獲回呼函數
CapSetCallbackOnFrame (ghCapWnd,LongInt(@VideoStreamCallBack));  
//將一個捕獲視窗與一個裝置驅程相關聯,第二個參數是個序號,當系統中裝有多個顯視驅動程式時,其值分別依次為0到總個數
CapDriverConnect(ghCapWnd, 0);  
//設定裝置屬性的結構變數
CapParms.dwRequestMicroSecPerFrame:=40000;
CapParms.fLimitEnabled := FALSE;
CapParms.fCaptureAudio := FALSE; // NO Audio
CapParms.fMCIControl := FALSE;
CapParms.fYield := TRUE;
CapParms.vKeyAbort := VK_ESCAPE;
CapParms.fAbortLeftMouse := FALSE;
CapParms.fAbortRightMouse := FALSE;
//使設定生效
CapCaptureSetSetup(ghCapWnd,LongInt(@CapParms),sizeof(TCAPTUREPARMS));  
//設定預覽時的比例
CapPreviewScale(ghCapWnd, 1);
//設定預覽時的幀頻率
CapPreviewRate(ghCapWnd,66);
//如果要捕獲視頻流,則要使用函數指定不組建檔案。否則將會自動產生AVI檔案
CapCaptureSequenceNoFile(ghCapWnd);
//指定是否使用疊加模式,使用為1,否則為0
CapOverlay(ghCapWnd, 1);
//開啟預覽
CapPreview(ghCapWnd, 1);
//停止捕獲
capCaptureAbort(ghCapWnd);  
//將捕獲窗同磁碟機斷開
capDriverDisconnect(ghCapWnd);

自訂的函數2 //定義捕獲幀回呼函數:
function FrameCallBack(hWnd:HWND; lpVHdr:LongInt) :LongInt; stdcall;
var  
DataPoint:^byte;  
DibLen,RectWidth,RectHeight:integer;
begin  
//轉換從回呼函數中得到的指標
VideoStr:=LPVIDEOHDR(lpVHdr);
//得到返回的資料大小  
DibLen:=VideoStr^.dwBufferLength;  
GetMem(DataPoint,64000);
//將幀資料COPY到一個記憶體中,注意DATAPOINT要先分配空間
CopyMemory(DataPoint,VideoStr^.lpData,Diblen);  
//一些其他處理
……
end;
靈活地使用AVICap視窗類別的回呼函數可以滿足各種不同的需求,但要注意從視訊卡中捕獲的視頻資料的格式和映像的長寬要參考視訊卡的參數。而且有些視訊卡通過設定可支援多種的格式和映像長寬,所以在還原映像時要注意參考所用的視訊卡的參數。

與視頻捕獲相關的編程。
1、定義全域變數:
HWND ghWndCap ; //捕獲窗的控制代碼
CAPDRIVERCAPS gCapDriverCaps ; //視頻磁碟機的能力

CAPSTATUS gCapStatus ; //捕獲窗的狀態
2、處理WM_CREATE訊息:
//建立捕獲窗,其中hWnd為主視窗控制代碼
ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",WS_CHILD | WS_VISIBLE, 0, 0, 300,240, (HWND) hWnd, (int) 0);
//登記三個回呼函數,它們應被提前申明
capSetCallbackOnError(ghWndCap, (FARPROC)ErrorCallbackProc); capSetCallbackOnStatus(ghWndCap, (FARPROC)StatusCallbackProc); capSetCallbackOnFrame(ghWndCap, (FARPROC)FrameCallbackProc);

capDriverConnect(ghWndCap,0); // 將捕獲窗同磁碟機串連
//獲得磁碟機的能力,相關的資訊放在結構變數gCapDriverCaps中
capDriverGetCaps(ghWndCap,&gCapDriverCaps,sizeof(CAPDRIVERCAPS)) ;
3、處理WM_CLOSE訊息:
//取消所登記的三個回呼函數
capSetCallbackOnStatus(ghWndCap, NULL);
capSetCallbackOnError(ghWndCap, NULL);
capSetCallbackOnFrame(ghWndCap, NULL);
capCaptureAbort(ghWndCap);//停止捕獲
capDriverDisconnect(ghWndCap); //將捕獲窗同磁碟機斷開

4、處理功能表項目Preview:
capPreviewRate(ghWndCap, 66); // 設定Preview模式的顯示速率
capPreview(ghWndCap, TRUE); //啟動Preview模式
5、處理功能表項目Overlay:
if(gCapDriverCaps.fHasOverlay) //檢查磁碟機是否有疊加能力
capOverlay(ghWndCap,TRUE); //啟動Overlay模式
6、處理功能表項目Exit:
SendMessage(hWnd,WM_CLOSE,wParam,lParam);
7、分別處理Setting下的三個功能表項目,它們可分別控制視頻源、視頻格式及顯示:
if (gCapDriverCaps.fHasDlgVideoSource)
capDlgVideoSource(ghWndCap); //Video source 對話方塊
if (gapDriverCaps.fHasDlgVideoFormat)
capDlgVideoFormat(ghWndCap); // Video format 對話方塊
if (CapDriverCaps.fHasDlgVideoDisplay)
capDlgVideoDisplay(ghWndCap); // Video display 對話方塊
8、處理Video Stream功能表項目,它捕獲視頻流到一個.AVI檔案:
char szCaptureFile[] = "MYCAP.AVI";
capFileSetCaptureFile( ghWndCap, szCaptureFile); //指定捕獲檔案名稱
capFileAlloc( ghWndCap, (1024L * 1024L * 5)); //為捕獲檔案分配儲存空間
capCaptureSequence(ghWndCap); //開始捕獲視頻序列
9、處理Single Frame功能表項目:
capGrabFrame(ghWndCap); //捕獲單幀映像
10、定義三個回呼函數:
LRESULT CALLBACK StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText)
{
if (!ghWndCap) return FALSE;
//獲得捕獲窗的狀態
capGetStatus(ghWndCap, &gCapStatus, sizeof (CAPSTATUS));
//更新捕獲窗的大小
SetWindowPos(ghWndCap, NULL, 0, 0, gCapStatus.uiImageWidth,
gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
if (nID == 0) { // 清除舊的狀態資訊
SetWindowText(ghWndCap, (LPSTR) gachAppName);
return (LRESULT) TRUE;
}
// 顯示狀態 ID 和狀態文本
wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);
SetWindowText(ghWndCap, (LPSTR)gachBuffer);
return (LRESULT) TRUE;
}
LRESULT CALLBACK ErrorCallbackProc(HWND hWnd, int nErrID,LPSTR lpErrorText)
{
if (!ghWndCap)
return FALSE;
if (nErrID == 0)
return TRUE;// 清除舊的錯誤
wsprintf(gachBuffer, "Error# %d", nErrID); //顯示錯誤標識和文本
MessageBox(hWnd, lpErrorText, gachBuffer,MB_OK | MB_ICONEXCLAMATION);
return (LRESULT) TRUE;
}
LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

{
if (!ghWndCap)
return FALSE;
//假設fp為一開啟的.dat檔案指標
fwrite(fp,lpVHdr->lpData,lpVHdr->dwBufferLength,1);
return (LRESULT) TRUE ;
}
值得注意的是:應在.cpp檔案中加入#include 一句,在Link設定中加入vfw32.lib。
上述的回呼函數FrameCallbackProc是將視頻資料直接從緩衝寫入檔案,也可利用memcpy函數將視頻資料直接拷貝到另一緩衝。同理,可 定義VideoStreamCallbackProc。capSetCallbackOnVideoStream的使用比 capSetCallbackOnFrame稍微複雜一些。在捕獲過程中,當一個新的視頻緩衝可得時,系統就調用它所登記的回呼函數。在預設情況下,捕獲 窗在捕獲過程中不允許其它應用程式繼續運行。為了取消這個限制,可以設定CAPTUREPARMS的成員fYield為TRUE或建立一個Yield回調 函數。為瞭解決潛在的重入(reentry)問題,可在YieldCallbackProc中用PeekMessage過濾掉一些訊息,例如滑鼠訊息。

 

常用問題代碼

Q:利用網上的代碼做了一個視頻採集的小程式,現在需要實現如下功能  
   
  已有如下函數:  
  /*******************************************************************************  
        Function       :   EnablePreviewVideo  
        Arguments     :   Parent   (input)   -   Parent   window   that   will   display   video.  
                                  x   (input)   -   X   Location   in   parent   where   video   will   be   shown.  
                                  y   (input)   -   Y   location   in   parent   where   video   will   be   shown.  
                                  Width   (input)   -   Width   of   preview   window.  
                                  Height   (input)   -   Height   of   preview   window.  
                                  PreviewRate   (input)   -   Rate   of   preview   in   FPS.  
        Return           :   TRUE   Success,   FALSE   Failed.  
        Description:   Enables   preview   video   mode.  
  *******************************************************************************/  
  BOOL   CVFWImageProcessor::EnablePreviewVideo(HWND   Parent,   INT   x,   INT   y,   INT   Width,   INT   Height,   INT   PreviewRate)  
  {  
        //   Reset   any   error   conditions.  
        GetPreviousError(NULL,NULL,TRUE);  
   
        SetParent(m_hWndVideo,Parent);  
        SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);  
   
        SetWindowPos(m_hWndVideo,NULL,x,y,  
                                  Width,  
                                  Height,  
                                  SWP_NOZORDER);  
        ShowWindow(m_hWndVideo,SW_SHOW);  
        capPreviewRate(m_hWndVideo,   PreviewRate);  
   
        return   capPreview(m_hWndVideo,TRUE);  
  }  
   
  現在已經通過擷取預覽視窗CRect   rectVideo的大小,但是視頻顯示的還是與視頻格式設定大小一致,只能在視窗內顯示視頻左上方的一部分,沒有實現視頻的縮放,所以顯示不全。我現在就想縮放視頻預覽顯示到設定地區,但實際的視頻大小不要改變,因為抓圖還是要實際大小的。   

 A:自動縮放視頻到視頻視窗大小:  
  在你的capPreviewRate(...)之後加上capPreviewScale(hwnd,TRUE)試試  
   
  附MSDN:  
  BOOL   capPreviewScale(   hwnd,   f   );  
   
  Parameters  
  hwnd    
  Handle   of   a   capture   window.    
  f    
  Preview   scaling   flag.   Specify   TRUE   for   this   parameter   to   stretch   preview   frames   to   the   size   of   the   capture   window   or   FALSE   to   display   them   at   their   natural   size.    
  Return   Values  
  Returns   TRUE   if   successful   or   FALSE   otherwise.  
   
  Remarks  
  Scaling   preview   images   controls   the   immediate   presentation   of   captured   frames   within   the   capture   window.   It   has   no   effect   on   the   size   of   the   frames   saved   to   file.  
   
  Scaling   has   no   effect   when   using   overlay   to   display   video   in   the   frame   buffer.  
   
   
  另:  
  抓圖時候設定大小:  
  HWND   m_capwnd=capCreateCaptureWindow(.......);  
  BITMAPINFO   m_bmpinfo;  
  capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));  
   
  m_bmpinfo.bmiHeader.biWidth和m_bmpinfo.bmiHeader.biHeight就是你想要的視頻寬度和高度  
   
  設定大小:  
  m_bmpinfo.bmiHeader.biWidth=176;//320  
  m_bmpinfo.bmiHeader.biHeight=144;//240  
  BOOL   ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));  

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.