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 } }