1. 程式人生 > >c# 呼叫攝像頭進行視訊錄製和壓縮等

c# 呼叫攝像頭進行視訊錄製和壓縮等

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Drawing;  
using System.Runtime.InteropServices;  
using System.Threading;  
using System.Windows.Forms;  
using System.IO;  
  
namespace Basic  
{  
    public class VideoAPI  //視訊API類  
    {  
        //  視訊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);  
        [DllImport("AVICAP32.dll", CharSet = CharSet.Unicode)]  
        public static extern bool capGetDriverDescription(int wDriverIndex, StringBuilder lpszName, int cbName, StringBuilder lpszVer, int cbVer);  
        [DllImport("avicap32.dll")]  
        public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);  
        [DllImport("avicap32.dll")]  
        public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] 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);  
  
        //  常量  
        // public const int WM_USER = 0x400;  
        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_DRIVER_CONNECT = WM_USER + 10;  
        //   public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;  
        public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;  
        //   public const int WM_CAP_SET_PREVIEW = WM_USER + 50;  
        //  public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;  
        //  public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;  
        //   public const int WM_CAP_START = WM_USER;  
        public const int WM_CAP_SAVEDIB = WM_CAP_START + 25;  
  
        public const string avicap32 = "avicap32.dll";  
        public const int WM_USER = 1024;  
        /// <summary>  
        ///WM_CAP_START=WM_USER=1024  
        /// </summary>  
        public const int WM_CAP_START = WM_USER;  
  
        // start of unicode messages  
        /// <summary>  
        /// 開始   WM_USER + 100=1124  
        /// </summary>  
        public const int WM_CAP_UNICODE_START = WM_USER + 100; //開始   1124  
        /// <summary>  
        /// /獲得 CAPSTR EAMPTR     
        /// WM_CAP_START + 1=1025  
        /// </summary>  
        public const int WM_CAP_GET_CAPSTREAMPTR = (WM_CAP_START + 1); //獲得 CAPSTR EAMPTR  
        /// <summary>  
        /// 設定收回錯誤   WM_CAP_START + 2=1026  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_ERROR = (WM_CAP_START + 2); //設定收回錯誤  
        /// <summary>  
        /// 設定收回狀態 WM_CAP_START + 3=1027  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_STATUS = (WM_CAP_START + 3); //設定收回狀態  
        /// <summary>  
        /// 設定收回出產  WM_CAP_START + 4=1028  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_YIELD = (WM_CAP_START + 4); //設定收回出產  
        /// <summary>  
        /// 設定收回結構  WM_CAP_START + 5=1029  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_FRame = (WM_CAP_START + 5); //設定收回結構  
        /// <summary>  
        /// 設定收回視訊流  WM_CAP_START + 6=1030  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = (WM_CAP_START + 6); //設定收回視訊流  
        /// <summary>  
        /// 設定收回視訊波流  WM_CAP_START +7=1031  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_WAVESTREAM = (WM_CAP_START + 7); //設定收回視訊波流  
        /// <summary>  
        /// 獲得使用者資料 WM_CAP_START + 8=1032  
        /// </summary>  
        public const int WM_CAP_GET_USER_DATA = (WM_CAP_START + 8); //獲得使用者資料  
        /// <summary>  
        /// 設定使用者資料 WM_CAP_START + 9=1033  
        /// </summary>  
        public const int WM_CAP_SET_USER_DATA = (WM_CAP_START + 9); //設定使用者資料  
        /// <summary>  
        /// 驅動程式連線  WM_CAP_START + 10=1034  
        /// </summary>  
        public const int WM_CAP_DRIVER_CONNECT = (WM_CAP_START + 10); //驅動程式連線  
        /// <summary>  
        /// 斷開啟動程式連線 WM_CAP_START + 11=1035  
        /// </summary>  
        public const int WM_CAP_DRIVER_DISCONNECT = (WM_CAP_START + 11); //斷開啟動程式連線  
        /// <summary>  
        /// 獲得驅動程式名字 WM_CAP_START + 12=1036  
        /// </summary>  
        public const int WM_CAP_DRIVER_GET_NAME = (WM_CAP_START + 12); //獲得驅動程式名字  
        /// <summary>  
        /// 獲得驅動程式版本 WM_CAP_START + 13=1037  
        /// </summary>  
        public const int WM_CAP_DRIVER_GET_VERSION = (WM_CAP_START + 13); //獲得驅動程式版本  
        /// <summary>  
        /// 獲得驅動程式帽子 WM_CAP_START + 14=1038  
        /// </summary>  
        public const int WM_CAP_DRIVER_GET_CAPS = (WM_CAP_START + 14); //獲得驅動程式帽子  
        /// <summary>  
        /// 設定捕獲檔案 WM_CAP_START + 20=1044  
        /// </summary>  
        public const int WM_CAP_FILE_SET_CAPTURE_FILE = (WM_CAP_START + 20); //設定捕獲檔案  
        /// <summary>  
        /// 獲得捕獲檔案 WM_CAP_START + 21=1045  
        /// </summary>  
        public const int WM_CAP_FILE_GET_CAPTURE_FILE = (WM_CAP_START + 21); //獲得捕獲檔案  
        /// <summary>  
        /// 另存檔案為  WM_CAP_START + 23=1047  
        /// </summary>  
        public const int WM_CAP_FILE_SAVEAS = (WM_CAP_START + 23); //另存檔案為  
        /// <summary>  
        /// 儲存檔案    WM_CAP_START + 25=1049  
        /// </summary>  
        public const int WM_CAP_FILE_SAVEDIB = (WM_CAP_START + 25); //儲存檔案  
  
        // out of order to save on ifdefs  
        /// <summary>  
        /// 分派檔案  WM_CAP_START + 22=1044  
        /// </summary>  
        public const int WM_CAP_FILE_ALLOCATE = (WM_CAP_START + 22); //分派檔案  
        /// <summary>  
        /// 設定開始檔案  WM_CAP_START + 24=1046  
        /// </summary>  
        public const int WM_CAP_FILE_SET_INFOCHUNK = (WM_CAP_START + 24); //設定開始檔案  
        /// <summary>  
        /// 編輯複製   WM_CAP_START + 30=1054  
        /// </summary>  
        public const int WM_CAP_EDIT_COPY = (WM_CAP_START + 30); //編輯複製  
        /// <summary>  
        /// 設定音訊格式  WM_CAP_START + 35=1059  
        /// </summary>  
        public const int WM_CAP_SET_AUDIOFORMAT = (WM_CAP_START + 35); //設定音訊格式  
        /// <summary>  
        /// 捕獲音訊格式  WM_CAP_START + 36=1060  
        /// </summary>  
        public const int WM_CAP_GET_AUDIOFORMAT = (WM_CAP_START + 36); //捕獲音訊格式  
        /// <summary>  
        /// 開啟視訊格式設定對話方塊  WM_CAP_START + 41=1065  
        /// </summary>  
        public const int WM_CAP_DLG_VIDEOFORMAT = (WM_CAP_START + 41); //1065 開啟視訊格式設定對話方塊  
        /// <summary>  
        /// 開啟屬性設定對話方塊,設定對比度、亮度等   WM_CAP_START + 42=1066  
        /// </summary>  
        public const int WM_CAP_DLG_VIDEOSOURCE = (WM_CAP_START + 42); //1066 開啟屬性設定對話方塊,設定對比度、亮度等。  
        /// <summary>  
        /// 開啟視訊顯示 WM_CAP_START + 43=1067  
        /// </summary>  
        public const int WM_CAP_DLG_VIDEODISPLAY = (WM_CAP_START + 43); //1067 開啟視訊顯示  
        /// <summary>  
        /// 獲得視訊格式 WM_CAP_START + 44=1068  
        /// </summary>  
        public const int WM_CAP_GET_VIDEOFORMAT = (WM_CAP_START + 44); //1068 獲得視訊格式  
        /// <summary>  
        /// 設定視訊格式 WM_CAP_START + 45=1069  
        /// </summary>  
        public const int WM_CAP_SET_VIDEOFORMAT = (WM_CAP_START + 45); //1069 設定視訊格式  
        /// <summary>  
        /// 開啟壓縮設定對話方塊 WM_CAP_START + 46=1070  
        /// </summary>  
        public const int WM_CAP_DLG_VIDEOCOMPRESSION = (WM_CAP_START + 46); //1070 開啟壓縮設定對話方塊  
        /// <summary>  
        /// 設定預覽 WM_CAP_START + 50=1074  
        /// </summary>  
        public const int WM_CAP_SET_PREVIEW = (WM_CAP_START + 50); //設定預覽  
        /// <summary>  
        /// 設定覆蓋 WM_CAP_START + 51=1075  
        /// </summary>  
        public const int WM_CAP_SET_OVERLAY = (WM_CAP_START + 51); //設定覆蓋  
        /// <summary>  
        /// 設定預覽比例 WM_CAP_START + 52=1076  
        /// </summary>  
        public const int WM_CAP_SET_PREVIEWRATE = (WM_CAP_START + 52); //設定預覽比例  
        /// <summary>  
        /// 設定刻度 WM_CAP_START + 53=1077  
        /// </summary>  
        public const int WM_CAP_SET_SCALE = (WM_CAP_START + 53); //設定刻度  
        /// <summary>   
        /// 獲得狀態 WM_CAP_START + 54=1078  
        /// </summary>  
        public const int WM_CAP_GET_STATUS = (WM_CAP_START + 54); //獲得狀態  
        /// <summary>  
        /// 設定卷 WM_CAP_START + 55=1079  
        /// </summary>  
        public const int WM_CAP_SET_SCROLL = (WM_CAP_START + 55); //設定卷  
        /// <summary>  
        /// 逮捕結構 WM_CAP_START + 60=1084  
        /// </summary>  
        public const int WM_CAP_GRAB_FRame = (WM_CAP_START + 60); //逮捕結構  
        /// <summary>  
        /// 停止逮捕結構 WM_CAP_START + 61=1085  
        /// </summary>  
        public const int WM_CAP_GRAB_FRame_NOSTOP = (WM_CAP_START + 61); //停止逮捕結構  
        /// <summary>  
        /// 次序 WM_CAP_START + 62=1086  
        /// </summary>  
        public const int WM_CAP_SEQUENCE = (WM_CAP_START + 62); //次序  
        /// <summary>  
        /// 沒有檔案 WM_CAP_START + 63=1087  
        /// </summary>  
        public const int WM_CAP_SEQUENCE_NOFILE = (WM_CAP_START + 63); //沒有檔案  
        /// <summary>  
        /// 設定安裝次序 WM_CAP_START + 64=1088  
        /// </summary>  
        public const int WM_CAP_SET_SEQUENCE_SETUP = (WM_CAP_START + 64); //設定安裝次序  
        /// <summary>  
        /// 獲得安裝次序 WM_CAP_START + 65=1089  
        /// </summary>  
        public const int WM_CAP_GET_SEQUENCE_SETUP = (WM_CAP_START + 65); //獲得安裝次序  
        /// <summary>  
        /// 設定媒體控制介面 WM_CAP_START + 66=1090  
        /// </summary>  
        public const int WM_CAP_SET_MCI_DEVICE = (WM_CAP_START + 66); //設定媒體控制介面  
        /// <summary>  
        /// 獲得媒體控制介面 WM_CAP_START + 67=1091  
        /// </summary>  
        public const int WM_CAP_GET_MCI_DEVICE = (WM_CAP_START + 67); //獲得媒體控制介面   
        /// <summary>  
        /// 停止 WM_CAP_START + 68=1092  
        /// </summary>  
        public const int WM_CAP_STOP = (WM_CAP_START + 68); //停止  
        /// <summary>  
        /// 異常中斷 WM_CAP_START + 69=1093  
        /// </summary>  
        public const int WM_CAP_ABORT = (WM_CAP_START + 69); //異常中斷  
        /// <summary>  
        /// 開啟單一的結構 WM_CAP_START + 68=1094  
        /// </summary>  
        public const int WM_CAP_SINGLE_FRame_OPEN = (WM_CAP_START + 70); //開啟單一的結構  
        /// <summary>  
        /// 關閉單一的結構 WM_CAP_START + 71=1095  
        /// </summary>  
        public const int WM_CAP_SINGLE_FRame_CLOSE = (WM_CAP_START + 71); //關閉單一的結構  
        /// <summary>  
        /// 單一的結構 WM_CAP_START + 72=1096  
        /// </summary>  
        public const int WM_CAP_SINGLE_FRame = (WM_CAP_START + 72); //單一的結構  
        /// <summary>  
        /// 開啟視訊 WM_CAP_START + 80=1104  
        /// </summary>  
        public const int WM_CAP_PAL_OPEN = (WM_CAP_START + 80); //開啟視訊  
        /// <summary>  
        /// 儲存視訊 WM_CAP_START + 81=1105  
        /// </summary>  
        public const int WM_CAP_PAL_SAVE = (WM_CAP_START + 81); //儲存視訊  
        /// <summary>  
        /// 貼上視訊 WM_CAP_START + 82=1106  
        /// </summary>  
        public const int WM_CAP_PAL_PASTE = (WM_CAP_START + 82); //貼上視訊  
        /// <summary>  
        /// 自動創造 WM_CAP_START + 83=1107  
        /// </summary>  
        public const int WM_CAP_PAL_AUTOCREATE = (WM_CAP_START + 83); //自動創造  
        /// <summary>  
        /// 手動創造 WM_CAP_START + 84=1108  
        /// </summary>  
        public const int WM_CAP_PAL_MANUALCREATE = (WM_CAP_START + 84); //手動創造  
  
        // Following added post VFW 1.1  
        /// <summary>  
        /// 設定收回的錯誤 WM_CAP_START + 85=1109  
        /// </summary>  
        public const int WM_CAP_SET_CALLBACK_CAPCONTROL = (WM_CAP_START + 85); // 設定收回的錯誤  
  
        public const int WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL;  
  
        public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);  
 
        #region 公共函式  
        //公共函式  
        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 公共函式  
        #region 結構 VIDEOHDR|BITMAPINFOHEADER|BITMAPINFO|CAPTUREPARMS|CAPDRIVERCAPS|CAPSTATUS  
        //========================================================VideoHdr 結構=====================================================================  
        //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 結構 VIDEOHDR|BITMAPINFOHEADER|BITMAPINFO|CAPTUREPARMS|CAPDRIVERCAPS|CAPSTATUS  
  
    }  
    public class cVideo     //視訊類  
    {  
        public bool flag = true;  
        private IntPtr lwndC;       //儲存無符號控制代碼  
        private IntPtr mControlPtr; //儲存管理指示器  
        private int mWidth;  
        private int mHeight;  
        public delegate void RecievedFrameEventHandler(byte[] data);  
        public event RecievedFrameEventHandler RecievedFrame;  
  
        public VideoAPI.CAPTUREPARMS Capparms;  
        private VideoAPI.FrameEventHandler mFrameEventHandler;  
        public VideoAPI.CAPDRIVERCAPS CapDriverCAPS;//捕獲驅動器的能力,如有無視訊疊加能力、有無控制視訊源、視訊格式的對話方塊等;  
        public VideoAPI.CAPSTATUS CapStatus;//該結構用於儲存視訊裝置捕獲視窗的當前狀態,如影象的寬、高等  
        string strFileName;  
        public cVideo(IntPtr handle, int width, int height)  
        {  
            CapDriverCAPS = new VideoAPI.CAPDRIVERCAPS();//捕獲驅動器的能力,如有無視訊疊加能力、有無控制視訊源、視訊格式的對話方塊等;  
            CapStatus = new VideoAPI.CAPSTATUS();//該結構用於儲存視訊裝置捕獲視窗的當前狀態,如影象的寬、高等  
            mControlPtr = handle; //顯示視訊控制元件的控制代碼  
            mWidth = width;      //視訊寬度  
            mHeight = height;    //視訊高度  
        }  
        /// <summary>  
        /// 開啟視訊裝置  
        /// </summary>  
        public bool StartWebCam()  
        {  
            //byte[] lpszName = new byte[100];  
            //byte[] lpszVer = new byte[100];  
            //VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);  
            //this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);  
            //if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))  
            //{  
            //    VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0);  
            //    VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0);  
            //    return true;  
            //}  
            //else  
            //{  
            //    return false;  
            //}  
            this.lwndC = VideoAPI.capCreateCaptureWindow("", VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);//AVICap類的捕捉視窗  
            VideoAPI.FrameEventHandler FrameEventHandler = new VideoAPI.FrameEventHandler(FrameCallback);  
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_ERROR, 0, 0);//註冊錯誤回撥函式  
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_STATUS, 0, 0);//註冊狀態回撥函式   
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);//註冊視訊流回調函式  
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_FRAME, 0, FrameEventHandler);//註冊幀回撥函式  
  
            //if (!CapDriverCAPS.fCaptureInitialized)//判斷當前裝置是否被其他裝置連線已經連線  
            //{  
  
            if (VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))  
            {  
                //-----------------------------------------------------------------------  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_DRIVER_GET_CAPS, VideoAPI.SizeOf(CapDriverCAPS), ref CapDriverCAPS);//獲得當前視訊 CAPDRIVERCAPS定義了捕獲驅動器的能力,如有無視訊疊加能力、有無控制視訊源、視訊格式的對話方塊等;  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_STATUS, VideoAPI.SizeOf(CapStatus), ref CapStatus);//獲得當前視訊流的尺寸 存入CapStatus結構  
  
                VideoAPI.BITMAPINFO bitmapInfo = new VideoAPI.BITMAPINFO();//設定視訊格式 (height and width in pixels, bits per frame).   
                bitmapInfo.bmiHeader = new VideoAPI.BITMAPINFOHEADER();  
                bitmapInfo.bmiHeader.biSize = VideoAPI.SizeOf(bitmapInfo.bmiHeader);  
                bitmapInfo.bmiHeader.biWidth = mWidth;  
                bitmapInfo.bmiHeader.biHeight = mHeight;  
                bitmapInfo.bmiHeader.biPlanes = 1;  
                bitmapInfo.bmiHeader.biBitCount = 24;  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 40, 0);//設定在PREVIEW模式下設定視訊視窗的重新整理率 設定每40毫秒顯示一幀,即顯示幀速為每秒25幀  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_SCALE, 1, 0);//開啟預覽視訊的縮放比例  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_VIDEOFORMAT, VideoAPI.SizeOf(bitmapInfo), ref bitmapInfo);  
  
                this.mFrameEventHandler = new VideoAPI.FrameEventHandler(FrameCallback);  
                this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler);  
  
  
                VideoAPI.CAPTUREPARMS captureparms = new VideoAPI.CAPTUREPARMS();  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_SEQUENCE_SETUP, VideoAPI.SizeOf(captureparms), ref captureparms);  
                if (CapDriverCAPS.fHasOverlay)  
                {  
                    VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_OVERLAY, 1, 0);//啟用疊加 注:據說啟用此項可以加快渲染速度      
                }  
                VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEW, 1, 0);//設定顯示影象啟動預覽模式 PREVIEW  
                VideoAPI.SetWindowPos(this.lwndC, 0, 0, 0, mWidth, mHeight, VideoAPI.SWP_NOZORDER | VideoAPI.SWP_NOMOVE);//使捕獲視窗與進來的視訊流尺寸保持一致  
                return true;  
            }  
            else  
            {   
                
                flag = false;  
                return false;  
            }  
        }  
        public void get()  
        {  
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_SEQUENCE_SETUP, VideoAPI.SizeOf(Capparms), ref Capparms);  
        }  
        public void set()  
        {  
            VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_SEQUENCE_SETUP, VideoAPI.SizeOf(Capparms), ref Capparms);  
        }  
        private bool capSetCallbackOnFrame(IntPtr lwnd, VideoAPI.FrameEventHandler lpProc)  
        {  
            return VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);  
        }  
        /// <summary>  
        /// 關閉視訊裝置  
        /// </summary>  
        public void CloseWebcam()  
        {  
            VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_DISCONNECT, 0, 0);  
        }  
        ///   <summary>     
        ///   拍照  
        ///   </summary>     
        ///   <param   name="path">要儲存bmp檔案的路徑</param>     
        public void GrabImage(IntPtr hWndC, string path)  
        {  
            IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);  
            VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SAVEDIB, 0, hBmp.ToInt32());  
        }  
        public void StarKinescope(string path)  
        {  
            strFileName = path;  
            string dir=path.Remove(path.LastIndexOf("//"));  
            if (!File.Exists(dir))  
            {  
                Directory.CreateDirectory(dir);  
            }  
            int hBmp = Marshal.StringToHGlobalAnsi(path).ToInt32();  
           bool b= VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_FILE_SET_CAPTURE_FILE, 0, hBmp);  
          b=  VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SEQUENCE, 0, 0);  
        }  
        /// <summary>  
        /// 停止錄影  
        /// </summary>  
        public void StopKinescope()  
        {  
            VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_STOP, 0, 0);  
        }  
        private void FrameCallback(IntPtr lwnd, IntPtr lpvhdr)  
        {  
            VideoAPI.VIDEOHDR videoHeader = new VideoAPI.VIDEOHDR();  
            byte[] VideoData;  
            videoHeader = (VideoAPI.VIDEOHDR)VideoAPI.GetStructure(lpvhdr, videoHeader);  
            VideoData = new byte[videoHeader.dwBytesUsed];  
            VideoAPI.Copy(videoHeader.lpData, VideoData);  
            if (this.RecievedFrame != null)  
                this.RecievedFrame(VideoData);  
        }  
        private Thread myThread;  
  
        public void CompressVideoFfmpeg()  
        {  
            //myThread = new Thread(new ThreadStart(testfn));  
            //myThread.Start();  
            testfn();  
        }  
        private void testfn() // 壓縮視訊  
        {  
            string file_name = strFileName;  
            string command_line = " -i " + file_name + " -vcodec libx264 -cqp 25 -y " + file_name.Replace(".avi", "_264") + ".avi";  
            System.Diagnostics.Process proc = new System.Diagnostics.Process();  
            proc.StartInfo.WorkingDirectory = Application.StartupPath;  
            proc.StartInfo.UseShellExecute = false; //use false if you want to hide the window  
            proc.StartInfo.CreateNoWindow = true;  
            proc.StartInfo.FileName = "ffmpeg";  
            proc.StartInfo.Arguments = command_line;  
            proc.Start();  
            proc.WaitForExit();  
            proc.Close();  
  
            // 刪除原始avi檔案  
            FileInfo file = new FileInfo(file_name);  
            if (file.Exists)  
            {  
                try  
                {  
                    file.Delete(); //刪除單個檔案  
                }  
                catch(Exception e) {  
                    Common.writeLog("刪除視訊檔案“"+file_name+"”出錯!"+e.Message);  
                }  
            }  
            //myThread.Abort();  
        }  
    }  
}  
  
   
  
   
  
用到的壓縮軟體http://download.csdn.net/source/2453028  
  
  
呼叫:  
cVideo video = new cVideo(picCapture.Handle, 640, 480);  
//開啟視訊  
if (video.StartWebCam(320, 240))  
            {  
                video.get();  
                video.Capparms.fYield = true;  
                video.Capparms.fAbortLeftMouse = false;  
                video.Capparms.fAbortRightMouse = false;  
                video.Capparms.fCaptureAudio = false;  
                video.Capparms.dwRequestMicroSecPerFrame = 0x9C40; // 設定幀率25fps: 1*1000000/25 = 0x9C40  
                video.set();  
                setCap();  
                VideoStart = true;  
            }  
//開始錄影  
  video.StarKinescope(System.IO.Path.Combine(Record.VideoDir, System.DateTime.Now.ToString("yyyy-MM-dd(HH.mm.ss)") + ".avi")))  
//停止錄影  
video.StopKinescope();  
//壓縮(壓縮效率還是很低,不要用於實際開發)  
 video.CompressVideoFfmpeg();