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();


相關推薦

c# 攝像頭錄影 視訊儲存壓縮

來自於 網路: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Runti

openwrt實現掛載usb攝像頭視訊儲存

路由器要實現掛載usb攝像頭功能首先就需要路由器帶USB介面,理論上帶USB介面、支援openwrt刷機應該就能實現掛載usb攝像頭的功能。 一、路由器配置 1.路由器刷好openwrt後,PC通過網線連線路由器用SecureCRT或者別的工具登入ope

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

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Runtim

阿里雲 javascript上傳檔案(圖片、視訊壓縮檔案)到 物件儲存 OSS ,返回上傳檔案、圖片、音訊、視訊URL路徑

目的:前端上傳檔案(圖片、視訊、音訊等)到阿里雲伺服器裡面,並且獲得上傳檔案的URL路徑 前提:首先要買一個阿里雲伺服器,自己百度不會; 第一步:登入阿里雲賬號,點選管理控制檯-->物件儲存 OSS 第二步:新建儲存空間(圖一、圖二) (圖一) (圖二

ckeil調試

配置 blog ref -s static 如果 表達 span 打開 data, keil調試(對debug用處極大), 關於c語言類型轉換 C的一些細節: ()&&()先計算前面若為0,後面不執行 a--先用後減 --a先減再用

PHP -- 用TP5實現二維碼和logo的生成與設定路徑儲存

本文利用TP5實現二維碼的生成與設定,logo的新增與設定。 1. 利用 composer 獲取 qr_code 外掛 composer require endroid/qr-code 我用的編譯器是PhpStorm ,所以在下面的Terminal中可以輸入以上命令即可。如下圖:

資料結構(c語言)——鏈棧儲存結構實現

鏈棧:就是一種特殊的單鏈表,FILO(先進後出) 通常對於連結串列來說: 1.是不需要頭節點的。 2.基本不存在滿棧的情況,除非記憶體已沒有可用的空間。   不多bibi你們都懂哈,直接上程式碼:  鏈棧結構: typedef struct Stock

Swing攝像頭拍照並截圖,比縮放後儲存到資料庫後再顯示到桌面

一.功能介面展示: 二.程式碼展示: 以下是Swing窗體,按鈕設定。 /**攝像頭面板*/ static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameCo

資料結構(c語言)——鏈佇列儲存結構實現

是佇列鴨,FIFO,先進先出! 對於帶頭節點的和不帶頭節點的鏈佇列的操作有個小小的區別: 不帶頭結點的鏈佇列在入佇列的時候,第一個元素時要先判斷是否為空,再插入。而帶頭結點不需要,操作更方便些;  我是分割線-----------------------------

攝像頭的實時視訊拼接目標跟蹤(二)

視訊拼接演算法 視訊拼接思想及總體框圖 影象拼接是視訊拼接的基礎,是將多張影象生成一張全景圖,衡量的指標主要在於全景圖的質量,而對拼接速度的要求並不高。對於視訊拼接而言,視訊流的輸入是源源不斷的,需要將多個攝像頭採集的圖片進行拼接,每個攝像頭的影象幀序列必須一一

攝像頭的實時視訊拼接目標跟蹤(三)

實時視訊拼接 初步視訊拼接虛影問題的探討 經過上述方案處理之後的初步拼接視訊,將會存在目前視訊拼接技術中一個普遍的問題,即重合區域存在運動物體產生虛影。效果圖如下, 產生偽影的影象幀 可以看到,重疊區域內,存在運動物體時,出現了虛影,並且都

攝像頭的實時視訊拼接目標跟蹤(五)

實時視訊拼接速度的優化方案 優化方案,提高拼接速度 根據之前章節的方法,進行初步視訊拼接得到的效果,其速度並不是最快,需要進行一定的優化。通過實驗,得到下面幾種優化方式。 1.程式碼執行的環境是在VS2017上執行的,其中有兩種執行模式,分別為Debug模式和R

HTML5利用WebRTC的getUserMedia獲取攝像頭資訊模擬拍照視訊(完整示例(轉))

轉至https://blog.csdn.net/journey191/article/details/40744015    (如有冒犯聯絡我刪掉謝謝) 最近公司做的app涉及攝像頭,由於我們使用HTML5開發app,自然瞭解到getUserMedia介面。 關鍵是使用的

TLV格式 VARINT數值壓縮儲存方法

使用Thrift格式進行資料序列化反序列化,thrift的儲存格式,主要使用thrift的TCompactProtocol。 發現該序列化方式主要使用了TLV格式式來儲存每個欄位,使用VARINT來表示其中的L。 1. TLV 格式 很簡單,Type-length-value(型別-長度-值)。在一串位

基於opencv的攝像頭臉部識別抓取格式儲存(python)

剛接觸opencv,參照opencv的sample例子做了一個視訊頭像抓取的小程式碼,順便一起學習著用,先上視訊抓取及儲存程式碼: ? 1 2 3 4 5 6 7 8 9 10

基於C語言的稀疏矩陣的壓縮儲存和運算

稀疏矩陣的壓縮儲存和運算 #include<stdio.h> #define m 6 #define n 8 #define max 50 void CreateMatrix(int A[m][n],int B[50]) { int i

libjpeg庫編碼圖片為jpg(ffmpeg解碼視訊儲存圖片:RGB格式點陣圖壓縮為jpg格式圖片)

壓縮流程(結合網上大家的資料以及libjpeg庫的example.c示例:都大同小異): 1、如何分配和初始化一個jpeg壓縮物件:      在libjpeg中jpeg壓縮物件被定義為struct

資料結構(c語言)——順序佇列儲存結構實現

使用迴圈佇列,避免出現偽滿佇列的情況 判斷佇列為空的條件:rear == front; 判斷佇列為滿的條件:(rear+1)%MAXSIZE == front; 空出一個數組元素空間,用以區別開來滿佇列和空佇列。 一個順序佇列的結構:  typedef struc

直播技術總結(四)音視訊資料壓縮編解碼基礎

音視訊壓縮技術是編解碼中難點,常常會涉及很多演算法處理問題。資料封裝,轉封裝等,看下Agenda: 音視訊為何需要壓縮? 壓縮編碼的分類 常用壓縮編碼的方法 編碼器中的關鍵技術 預測 量化 變換 熵編碼 編解碼中的情況 音視訊為何需要壓縮? 未經

儲存介面DAS,NAS,SAN概念

介面 IDE:並行介面 SATA:序列介面 SCSI:原來的IDE介面的硬碟轉速太慢,傳輸速率太低,因此高速的SCSI硬碟出現。其實SCSI並不是專為硬碟設計的,實際上它是一種匯流排型介面,獨立於系