1.關於avicap32.dll基本概念
VFW(Video For Window)技術是Microsoft公司為開發Windows平台下的視頻應用程序提供的軟件工具包,提供了一系列應用程序編程接口(API),用戶可以通過這些接口很 方便地實現視頻捕獲、視頻編輯及視頻播放等通用功能,還可利用回調函數開發比較復雜的視頻應用程序。該技術的特點是播放視頻時不需要專用的硬件設備,而且 應用靈活,可以滿足視頻應用程序開發的需要。Windows操作系統自身就攜帶了VFW技術,系統安裝時,會自動安裝VFW的相關組件。
AVICAP32.DLL:包含執行視頻捕獲的函數,給AVI文件的I/O處理和視頻,音頻設備驅動程序提供一個高級接口。 MSVIDEO.DLL:包含一套特殊的DrawDib函數,用來處理程序上的視頻操作。MCIAVI.DRV:包括對VFW的MCI命令解釋器的驅動程序。AVIFILE.DLL:包含由標准多媒體I/O(mmio)函數提供的更高級的命令,用來訪問.AVI文件。ICM:壓縮管理器,用於管理的視頻壓縮/解壓縮的編譯碼器。ACM:音頻壓縮管理器,提供與ICM相似的服務,適用於波形音頻。
2.關於avicap32.dll重要函數的參數的介紹
(1)capCreateCaptureWindow函數
該函數用於創建一個視頻捕捉窗口。語法如下:
[DllImport("avicap32.dll")]
public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
參數說明如下。
l lpszWindowName:標識窗口的名稱。
l dwStyle:標識窗口風格。
l x、y:標識窗口的左上角坐標。
l nWidth、nHeight:標識窗口的寬度和高度。
l hWnd:標識父窗口句柄。
l nID:標識窗口ID。
l 返回值:視頻捕捉窗口句柄。
(2)SendMessage函數
用於向Windows系統發送消息機制。
[DllImport("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
參數說明如下。
l hWnd:窗口句柄。
l wMsg:將要發送的消息。
l wParam、lParam:消息的參數,每個消息都有兩個參數,參數設置由發送的消息而定。
3.
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Text;
namespace AVI
{
public class AviCapture
{
#region 導入API函數
[DllImport("avicap32.dll")]//包含了執行視頻捕獲的函數,它給AVI文件I/O和視頻、音頻設備驅動程序提供一個高級接口
public static extern IntPtr capCreateCaptureWindow(string lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hwndParent, int nID);
/************參數說明*************
*
* 函數:capCreateCaptureWindow
*
* lpszWindowName:標識窗口的名稱
* dwStyle:標識窗口風格
* x、y:標識窗口的左上角坐標
* nWidth、nHeight:標識窗口的寬度和高度
* hWnd:標識父窗口句柄
* nID:標識窗口ID
*
* 返回值:視頻捕捉窗口句柄。
*
********************************/
[DllImport("AVICAP32.dll", CharSet = CharSet.Unicode)]
public static extern bool capGetDriverDescription(int wDriverIndex, StringBuilder lpszName, int cbName, StringBuilder lpszVer, int cbVer);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPDRIVERCAPS lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPTUREPARMS lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPSTATUS lParam);
[DllImport("User32.dll")]
public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
[DllImport("avicap32.dll")]
public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
#endregion
#region 消息常量(向窗口發送消息的指令)
//消息常量 --------------------------------------------
public const int WM_START = 0x400; //此並非攝像頭消息0x400表示的就是1024
public const int WS_CHILD = 0x40000000;
public const int WS_VISIBLE = 0x10000000;
public const int SWP_NOMOVE = 0x2;
public const int SWP_NOZORDER = 0x4;
public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1;
public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2;//設置收回錯誤
public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3;//設置收回狀態
public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4;//設置收回出產
public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5;//設置收回結構
public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6;//設置收回視頻流
public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7;//設置收回視頻波流
public const int WM_CAP_GET_USER_DATA = WM_START + 8;//獲得使用者數據
public const int WM_CAP_SET_USER_DATA = WM_START + 9;//設置使用者數據
public const int WM_CAP_DRIVER_CONNECT = WM_START + 10;//驅動程序連接
public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11;//斷開啟動程序連接
public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12;//獲得驅動程序名字
public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13;//獲得驅動程序版本
public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14;//獲得驅動程序帽子
public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20;//設置捕獲文件
public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21;//獲得捕獲文件
public const int WM_CAP_FILE_ALLOCATE = WM_START + 22;//分派文件
public const int WM_CAP_FILE_SAVEAS = WM_START + 23;//另存文件為
public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24;//設置開始文件
public const int WM_CAP_FILE_SAVEDIB = WM_START + 25;//保存文件
public const int WM_CAP_EDIT_COPY = WM_START + 30;//編輯復制
public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35;//設置音頻格式
public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36;//捕獲音頻格式
public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41;//1065 打開視頻格式設置對話框
public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42;//1066 打開屬性設置對話框,設置對比度亮度等
public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43;//1067 打開視頻顯示
public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44;//1068 獲得視頻格式
public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45;//1069 設置視頻格式
public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46;//1070 打開壓縮設置對話框
public const int WM_CAP_SET_PREVIEW = WM_START + 50;//設置預覽
public const int WM_CAP_SET_OVERLAY = WM_START + 51;//設置覆蓋
public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52;//設置預覽比例
public const int WM_CAP_SET_SCALE = WM_START + 53;//設置刻度
public const int WM_CAP_GET_STATUS = WM_START + 54;//獲得狀態
public const int WM_CAP_SET_SCROLL = WM_START + 55;//設置卷
public const int WM_CAP_GRAB_FRAME = WM_START + 60;//逮捕結構
public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61;//停止逮捕結構
public const int WM_CAP_SEQUENCE = WM_START + 62;//次序
public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63;//使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盤文件寫入數據。該消息僅在配合回調函數時有用,它允許你的應用程序直接使用音視頻數據。
public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64;//設置安裝次序
public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65;//獲得安裝次序
public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66;//設置媒體控制接口
public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67;//獲得媒體控制接口
public const int WM_CAP_STOP = WM_START + 68;//停止
public const int WM_CAP_ABORT = WM_START + 69;//異常中斷
public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70;//打開單一的結構
public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71;//關閉單一的結構
public const int WM_CAP_SINGLE_FRAME = WM_START + 72;//單一的結構
public const int WM_CAP_PAL_OPEN = WM_START + 80;//打開視頻
public const int WM_CAP_PAL_SAVE = WM_START + 81;//保存視頻
public const int WM_CAP_PAL_PASTE = WM_START + 82;//粘貼視頻
public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83; //自動創造
public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84;//手動創造
public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85;// 設置收回的錯誤
#endregion 消息常量
#region 結構體
/*********VideoHdr 結構體*********
*
* 定義了視頻數據塊的頭信息,
* 在編寫回調函數時常用到其數據成員lpData(指向數據緩存的指針)和dwBufferLength(數據緩存的大小)。
* 視頻幀到緩存的捕獲則需要應用回調函數和相應的數據塊結構 VIDEOHDR
*
*******************************/
[StructLayout(LayoutKind.Sequential)]
public struct VIDEOHDR
{
public IntPtr lpData; /* 指向數據緩存的指針 */
public int dwBufferLength; /* 數據緩存的大小 */
public int dwBytesUsed; /* Bytes actually used */
public int dwTimeCaptured; /* Milliseconds from start of stream */
public int dwUser; /* for client's use */
public int dwFlags; /* assorted flags (see defines) */
public int dwReserved; /* reserved for driver */
}
/*********BitmapInfoHeader 結構體*********
*
* BitmapInfoHeader定義了位圖的頭部信息
*
****************************************/
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
public int biSize;
public int biWidth;
public int biHeight;
public short biPlanes;
public short biBitCount;
public int biCompression;
public int biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public int biClrUsed;
public int biClrImportant;
}
/*********BitmapInfo 結構體*********
*
* BitmapInfo 定義了位圖信息
*
***********************************/
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
public BITMAPINFOHEADER bmiHeader;
public int bmiColors;
}
/*********CAPTUREPARMS 結構體*********
*
* CAPTUREPARMS 包含控制視頻流捕獲過程的參數,如捕獲幀頻、指定鍵盤或鼠標鍵以終止捕獲、捕獲時間限制等
*
***********************************/
[StructLayout(LayoutKind.Sequential)]
public struct CAPTUREPARMS
{
public int dwRequestMicroSecPerFrame; // 期望的楨播放率,以毫秒為單位,默認為66667,相當於15楨每秒。
public bool fMakeUserHitOKToCapture; // Show "Hit OK to cap" dlg?開始捕獲標志位,如果值為真,則在開始捕獲前要產生一個詢問對話框,默認為假。
public uint wPercentDropForError; //所允許的最大丟楨百分比,可以從0變化到100,默認值為10。
public bool fYield; /*另起線程標志位,如果為真,則程序重新啟動一個線程用於視頻流的捕獲,默認值是假。
但是如果你是為了真,你必須要在程序中處理一些潛在的操作,因為當視頻捕獲時,其他操作並沒有被屏蔽。*/
public int dwIndexSize; // 在AVI文件中所允許的最大數目的索引項(32K)
public uint wChunkGranularity; // AVI文件的邏輯尺寸,以字節為單位。如果值是0,則說明該尺寸漸增 在 Win32程序中無用。(2K)
public bool fUsingDOSMemory; // Use DOS buffers?
public uint wNumVideoRequested; // 所被允許分配的最大視頻緩存
public bool fCaptureAudio; // 音頻標志位,如果音頻流正在捕獲,則該值為真。
public uint wNumAudioRequested; // 最大數量的音頻緩存,默認值為10。
public uint vKeyAbort; // 終止流捕獲的虛擬鍵盤碼,默認值為VK_ESCAPE
[MarshalAs(UnmanagedType.Bool)]
public bool fAbortLeftMouse; // 終止鼠標左鍵標志位,如果該值為真,則在流捕獲過程中如果點擊鼠標左鍵則該捕獲終止,默認值為真。
public bool fAbortRightMouse; // Abort on right mouse?
public bool fLimitEnabled; // 捕獲操作時間限制,如果為真,則時間到了以后捕獲操作終止,默認為假
public uint wTimeLimit; // 具體終止時間,只有 fLimitEnabled是真時.該位才有效
public bool fMCIControl; // Use MCI video source?
public bool fStepMCIDevice; // Step MCI device?MCI 設備標志。
public int dwMCIStartTime; // Time to start in MS
public int dwMCIStopTime; // Time to stop in MS
public bool fStepCaptureAt2x; // Perform spatial averaging 2x
public int wStepCaptureAverageFrames; // 當基於平均采樣來創建楨時,楨的采樣時間,典型值是5
public int dwAudioBufferSize; // 音頻緩存的尺寸,如果用默認值0,緩存尺寸是最大0.5秒,或10k字節。
public int fDisableWriteCache; // Attempt to disable write cache
public int AVStreamMaster; //音視頻同步標志。
}
/*********CAPDRIVERCAPS 結構體*********
*
* CAPDRIVERCAPS 定義了捕獲驅動器的能力,如有無視頻疊加能力、有無控制視頻源、視頻格式的對話框等
*
**************************************/
[StructLayout(LayoutKind.Sequential)]
public struct CAPDRIVERCAPS
{
[MarshalAs(UnmanagedType.U2)]
public UInt16 wDeviceIndex; //捕獲驅動器的索引值,該值可以由0到9變化。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasOverlay; // 視頻疊加標志,如果設備支持視頻疊加這該位是真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoSource; //視頻資源對話框標志位,如果設備支持視頻選擇、控制對話框,該值為真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoFormat; //視頻格式對話框標志位,如果設備支持對視頻格式對話框的選擇,該位真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoDisplay; //視頻展示對話框標志位,如果設備支持對視頻捕獲緩存區的重新播放,該位是真。
[MarshalAs(UnmanagedType.Bool)]
public bool fCaptureInitialized; //捕獲安裝標志位,如果捕獲驅動器已經成功連接,該值為真。
//[MarshalAs(UnmanagedType.Bool)]
public bool fDriverSuppliesPalettes; //驅動器調色板標志位,如果驅動器能創建調色板,則該位是真。
[MarshalAs(UnmanagedType.I4)]
public int hVideoIn;
[MarshalAs(UnmanagedType.I4)]
public int hVideoOut;
[MarshalAs(UnmanagedType.I4)]
public int hVideoExtIn;
[MarshalAs(UnmanagedType.I4)]
public int hVideoExtOut;
}
/*********CAPSTATUS 結構體*********
*
* CAPSTATUS 定義了捕獲窗口的當前狀態,如圖像的寬、高等
*
**************************************/
[StructLayout(LayoutKind.Sequential)]
public struct CAPSTATUS
{
public int uiImageWidth; //圖像寬度
public int uiImageHeight; //圖像高度
public bool fLiveWindow; //活動窗口標記,如果窗口正以預覽的方式展示圖像,那么該值為真
public bool fOverlayWindow; //疊加窗口標志位,如果正在使用硬件疊加,則該位是真。
public bool fScale; //輸入所放標志位,如果窗口是正在縮放視頻到客戶區,那么該位是真。當使用硬件疊加時,改位無效。
public Point ptScroll; //被展示在窗口客戶區左上角的那個象素的x、y坐標偏移量。
public bool fUsingDefaultPalette; //默認調色板標志位,如果捕獲窗口正在使用當前默認調色板,該值為真
public bool fAudioHardware; // 音頻硬件標志位,如果系統已經安裝了音頻硬件,該值為真。
public bool fCapFileExists; //捕獲文件標志位,如果一個捕獲文件已經被創建,該值為真
public int dwCurrentVideoFrame; // 當前或最近流捕獲過程中,所處理的楨的數目。包括丟棄的楨。
public int dwCurrentVideoFramesDropped;//當前流捕獲過程中丟棄的楨的數目。
public int dwCurrentWaveSamples; // # of wave samples cap'td
public int dwCurrentTimeElapsedMS; // 從當前流捕獲開始計算,程序所用的時間,以毫秒為單位。
public IntPtr hPalCurrent; // 當前剪切板的句柄。
public bool fCapturingNow; // 捕獲標志位,當捕獲是正在進行時,改位是真
public int dwReturn; // 錯誤返回值,當你的應用程序不支持錯誤回調函數時可以應用改位
public int wNumVideoAllocated; // 被分配的視頻緩存的數目。
public int wNumAudioAllocated; // 被分配的音頻緩存的數目。
}
#endregion
#region 基本函數
public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);
public static object GetStructure(IntPtr ptr, ValueType structure)
{
return Marshal.PtrToStructure(ptr, structure.GetType());
}
public static object GetStructure(int ptr, ValueType structure)
{
return GetStructure(new IntPtr(ptr), structure);
}
public static void Copy(IntPtr ptr, byte[] data)
{
Marshal.Copy(ptr, data, 0, data.Length);
}
public static void Copy(int ptr, byte[] data)
{
Copy(new IntPtr(ptr), data);
}
public static int SizeOf(object structure)
{
return Marshal.SizeOf(structure);
}
#endregion
}
}
