1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Drawing; 6 using System.Runtime.InteropServices; 7 using System.Threading; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace Basic 12 { 13 public class VideoAPI //视频API类 14 { 15 // 视频API调用 16 [DllImport("avicap32.dll")]//包含了执行视频捕获的函数,它给AVI文件I/O和视频、音频设备驱动程序提供一个高级接口 17 public static extern IntPtr capCreateCaptureWindow(string lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hwndParent, int nID); 18 [DllImport("AVICAP32.dll", CharSet = CharSet.Unicode)] 19 public static extern bool capGetDriverDescription(int wDriverIndex, StringBuilder lpszName, int cbName, StringBuilder lpszVer, int cbVer); 20 [DllImport("avicap32.dll")] 21 public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID); 22 [DllImport("avicap32.dll")] 23 public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer); 24 [DllImport("User32.dll")] 25 public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam); 26 [DllImport("User32.dll")] 27 public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam); 28 [DllImport("User32.dll")] 29 public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); 30 [DllImport("User32.dll")] 31 public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam); 32 [DllImport("User32.dll")] 33 public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam); 34 [DllImport("User32.dll")] 35 public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPDRIVERCAPS lParam); 36 [DllImport("User32.dll")] 37 public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPTUREPARMS lParam); 38 [DllImport("User32.dll")] 39 public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPSTATUS lParam); 40 [DllImport("User32.dll")] 41 public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags); 42 [DllImport("avicap32.dll")] 43 public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize); 44 45 // 常量 46 // public const int WM_USER = 0x400; 47 public const int WS_CHILD = 0x40000000; 48 public const int WS_VISIBLE = 0x10000000; 49 50 public const int SWP_NOMOVE = 0x2; 51 public const int SWP_NOZORDER = 0x4; 52 // public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10; 53 // public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11; 54 public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5; 55 // public const int WM_CAP_SET_PREVIEW = WM_USER + 50; 56 // public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52; 57 // public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45; 58 // public const int WM_CAP_START = WM_USER; 59 public const int WM_CAP_SAVEDIB = WM_CAP_START + 25; 60 61 public const string avicap32 = "avicap32.dll"; 62 public const int WM_USER = 1024; 63 /// <summary> 64 ///WM_CAP_START=WM_USER=1024 65 /// </summary> 66 public const int WM_CAP_START = WM_USER; 67 68 // start of unicode messages 69 /// <summary> 70 /// 开始 WM_USER + 100=1124 71 /// </summary> 72 public const int WM_CAP_UNICODE_START = WM_USER + 100; //开始 1124 73 /// <summary> 74 /// /获得 CAPSTR EAMPTR 75 /// WM_CAP_START + 1=1025 76 /// </summary> 77 public const int WM_CAP_GET_CAPSTREAMPTR = (WM_CAP_START + 1); //获得 CAPSTR EAMPTR 78 /// <summary> 79 /// 设置收回错误 WM_CAP_START + 2=1026 80 /// </summary> 81 public const int WM_CAP_SET_CALLBACK_ERROR = (WM_CAP_START + 2); //设置收回错误 82 /// <summary> 83 /// 设置收回状态 WM_CAP_START + 3=1027 84 /// </summary> 85 public const int WM_CAP_SET_CALLBACK_STATUS = (WM_CAP_START + 3); //设置收回状态 86 /// <summary> 87 /// 设置收回出产 WM_CAP_START + 4=1028 88 /// </summary> 89 public const int WM_CAP_SET_CALLBACK_YIELD = (WM_CAP_START + 4); //设置收回出产 90 /// <summary> 91 /// 设置收回结构 WM_CAP_START + 5=1029 92 /// </summary> 93 public const int WM_CAP_SET_CALLBACK_FRame = (WM_CAP_START + 5); //设置收回结构 94 /// <summary> 95 /// 设置收回视频流 WM_CAP_START + 6=1030 96 /// </summary> 97 public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = (WM_CAP_START + 6); //设置收回视频流 98 /// <summary> 99 /// 设置收回视频波流 WM_CAP_START +7=1031 100 /// </summary> 101 public const int WM_CAP_SET_CALLBACK_WAVESTREAM = (WM_CAP_START + 7); //设置收回视频波流 102 /// <summary> 103 /// 获得使用者数据 WM_CAP_START + 8=1032 104 /// </summary> 105 public const int WM_CAP_GET_USER_DATA = (WM_CAP_START + 8); //获得使用者数据 106 /// <summary> 107 /// 设置使用者数据 WM_CAP_START + 9=1033 108 /// </summary> 109 public const int WM_CAP_SET_USER_DATA = (WM_CAP_START + 9); //设置使用者数据 110 /// <summary> 111 /// 驱动程序连接 WM_CAP_START + 10=1034 112 /// </summary> 113 public const int WM_CAP_DRIVER_CONNECT = (WM_CAP_START + 10); //驱动程序连接 114 /// <summary> 115 /// 断开启动程序连接 WM_CAP_START + 11=1035 116 /// </summary> 117 public const int WM_CAP_DRIVER_DISCONNECT = (WM_CAP_START + 11); //断开启动程序连接 118 /// <summary> 119 /// 获得驱动程序名字 WM_CAP_START + 12=1036 120 /// </summary> 121 public const int WM_CAP_DRIVER_GET_NAME = (WM_CAP_START + 12); //获得驱动程序名字 122 /// <summary> 123 /// 获得驱动程序版本 WM_CAP_START + 13=1037 124 /// </summary> 125 public const int WM_CAP_DRIVER_GET_VERSION = (WM_CAP_START + 13); //获得驱动程序版本 126 /// <summary> 127 /// 获得驱动程序帽子 WM_CAP_START + 14=1038 128 /// </summary> 129 public const int WM_CAP_DRIVER_GET_CAPS = (WM_CAP_START + 14); //获得驱动程序帽子 130 /// <summary> 131 /// 设置捕获文件 WM_CAP_START + 20=1044 132 /// </summary> 133 public const int WM_CAP_FILE_SET_CAPTURE_FILE = (WM_CAP_START + 20); //设置捕获文件 134 /// <summary> 135 /// 获得捕获文件 WM_CAP_START + 21=1045 136 /// </summary> 137 public const int WM_CAP_FILE_GET_CAPTURE_FILE = (WM_CAP_START + 21); //获得捕获文件 138 /// <summary> 139 /// 另存文件为 WM_CAP_START + 23=1047 140 /// </summary> 141 public const int WM_CAP_FILE_SAVEAS = (WM_CAP_START + 23); //另存文件为 142 /// <summary> 143 /// 保存文件 WM_CAP_START + 25=1049 144 /// </summary> 145 public const int WM_CAP_FILE_SAVEDIB = (WM_CAP_START + 25); //保存文件 146 147 // out of order to save on ifdefs 148 /// <summary> 149 /// 分派文件 WM_CAP_START + 22=1044 150 /// </summary> 151 public const int WM_CAP_FILE_ALLOCATE = (WM_CAP_START + 22); //分派文件 152 /// <summary> 153 /// 设置开始文件 WM_CAP_START + 24=1046 154 /// </summary> 155 public const int WM_CAP_FILE_SET_INFOCHUNK = (WM_CAP_START + 24); //设置开始文件 156 /// <summary> 157 /// 编辑复制 WM_CAP_START + 30=1054 158 /// </summary> 159 public const int WM_CAP_EDIT_COPY = (WM_CAP_START + 30); //编辑复制 160 /// <summary> 161 /// 设置音频格式 WM_CAP_START + 35=1059 162 /// </summary> 163 public const int WM_CAP_SET_AUDIOFORMAT = (WM_CAP_START + 35); //设置音频格式 164 /// <summary> 165 /// 捕获音频格式 WM_CAP_START + 36=1060 166 /// </summary> 167 public const int WM_CAP_GET_AUDIOFORMAT = (WM_CAP_START + 36); //捕获音频格式 168 /// <summary> 169 /// 打开视频格式设置对话框 WM_CAP_START + 41=1065 170 /// </summary> 171 public const int WM_CAP_DLG_VIDEOFORMAT = (WM_CAP_START + 41); //1065 打开视频格式设置对话框 172 /// <summary> 173 /// 打开属性设置对话框,设置对比度、亮度等 WM_CAP_START + 42=1066 174 /// </summary> 175 public const int WM_CAP_DLG_VIDEOSOURCE = (WM_CAP_START + 42); //1066 打开属性设置对话框,设置对比度、亮度等。 176 /// <summary> 177 /// 打开视频显示 WM_CAP_START + 43=1067 178 /// </summary> 179 public const int WM_CAP_DLG_VIDEODISPLAY = (WM_CAP_START + 43); //1067 打开视频显示 180 /// <summary> 181 /// 获得视频格式 WM_CAP_START + 44=1068 182 /// </summary> 183 public const int WM_CAP_GET_VIDEOFORMAT = (WM_CAP_START + 44); //1068 获得视频格式 184 /// <summary> 185 /// 设置视频格式 WM_CAP_START + 45=1069 186 /// </summary> 187 public const int WM_CAP_SET_VIDEOFORMAT = (WM_CAP_START + 45); //1069 设置视频格式 188 /// <summary> 189 /// 打开压缩设置对话框 WM_CAP_START + 46=1070 190 /// </summary> 191 public const int WM_CAP_DLG_VIDEOCOMPRESSION = (WM_CAP_START + 46); //1070 打开压缩设置对话框 192 /// <summary> 193 /// 设置预览 WM_CAP_START + 50=1074 194 /// </summary> 195 public const int WM_CAP_SET_PREVIEW = (WM_CAP_START + 50); //设置预览 196 /// <summary> 197 /// 设置覆盖 WM_CAP_START + 51=1075 198 /// </summary> 199 public const int WM_CAP_SET_OVERLAY = (WM_CAP_START + 51); //设置覆盖 200 /// <summary> 201 /// 设置预览比例 WM_CAP_START + 52=1076 202 /// </summary> 203 public const int WM_CAP_SET_PREVIEWRATE = (WM_CAP_START + 52); //设置预览比例 204 /// <summary> 205 /// 设置刻度 WM_CAP_START + 53=1077 206 /// </summary> 207 public const int WM_CAP_SET_SCALE = (WM_CAP_START + 53); //设置刻度 208 /// <summary> 209 /// 获得状态 WM_CAP_START + 54=1078 210 /// </summary> 211 public const int WM_CAP_GET_STATUS = (WM_CAP_START + 54); //获得状态 212 /// <summary> 213 /// 设置卷 WM_CAP_START + 55=1079 214 /// </summary> 215 public const int WM_CAP_SET_SCROLL = (WM_CAP_START + 55); //设置卷 216 /// <summary> 217 /// 逮捕结构 WM_CAP_START + 60=1084 218 /// </summary> 219 public const int WM_CAP_GRAB_FRame = (WM_CAP_START + 60); //逮捕结构 220 /// <summary> 221 /// 停止逮捕结构 WM_CAP_START + 61=1085 222 /// </summary> 223 public const int WM_CAP_GRAB_FRame_NOSTOP = (WM_CAP_START + 61); //停止逮捕结构 224 /// <summary> 225 /// 次序 WM_CAP_START + 62=1086 226 /// </summary> 227 public const int WM_CAP_SEQUENCE = (WM_CAP_START + 62); //次序 228 /// <summary> 229 /// 没有文件 WM_CAP_START + 63=1087 230 /// </summary> 231 public const int WM_CAP_SEQUENCE_NOFILE = (WM_CAP_START + 63); //没有文件 232 /// <summary> 233 /// 设置安装次序 WM_CAP_START + 64=1088 234 /// </summary> 235 public const int WM_CAP_SET_SEQUENCE_SETUP = (WM_CAP_START + 64); //设置安装次序 236 /// <summary> 237 /// 获得安装次序 WM_CAP_START + 65=1089 238 /// </summary> 239 public const int WM_CAP_GET_SEQUENCE_SETUP = (WM_CAP_START + 65); //获得安装次序 240 /// <summary> 241 /// 设置媒体控制接口 WM_CAP_START + 66=1090 242 /// </summary> 243 public const int WM_CAP_SET_MCI_DEVICE = (WM_CAP_START + 66); //设置媒体控制接口 244 /// <summary> 245 /// 获得媒体控制接口 WM_CAP_START + 67=1091 246 /// </summary> 247 public const int WM_CAP_GET_MCI_DEVICE = (WM_CAP_START + 67); //获得媒体控制接口 248 /// <summary> 249 /// 停止 WM_CAP_START + 68=1092 250 /// </summary> 251 public const int WM_CAP_STOP = (WM_CAP_START + 68); //停止 252 /// <summary> 253 /// 异常中断 WM_CAP_START + 69=1093 254 /// </summary> 255 public const int WM_CAP_ABORT = (WM_CAP_START + 69); //异常中断 256 /// <summary> 257 /// 打开单一的结构 WM_CAP_START + 68=1094 258 /// </summary> 259 public const int WM_CAP_SINGLE_FRame_OPEN = (WM_CAP_START + 70); //打开单一的结构 260 /// <summary> 261 /// 关闭单一的结构 WM_CAP_START + 71=1095 262 /// </summary> 263 public const int WM_CAP_SINGLE_FRame_CLOSE = (WM_CAP_START + 71); //关闭单一的结构 264 /// <summary> 265 /// 单一的结构 WM_CAP_START + 72=1096 266 /// </summary> 267 public const int WM_CAP_SINGLE_FRame = (WM_CAP_START + 72); //单一的结构 268 /// <summary> 269 /// 打开视频 WM_CAP_START + 80=1104 270 /// </summary> 271 public const int WM_CAP_PAL_OPEN = (WM_CAP_START + 80); //打开视频 272 /// <summary> 273 /// 保存视频 WM_CAP_START + 81=1105 274 /// </summary> 275 public const int WM_CAP_PAL_SAVE = (WM_CAP_START + 81); //保存视频 276 /// <summary> 277 /// 粘贴视频 WM_CAP_START + 82=1106 278 /// </summary> 279 public const int WM_CAP_PAL_PASTE = (WM_CAP_START + 82); //粘贴视频 280 /// <summary> 281 /// 自动创造 WM_CAP_START + 83=1107 282 /// </summary> 283 public const int WM_CAP_PAL_AUTOCREATE = (WM_CAP_START + 83); //自动创造 284 /// <summary> 285 /// 手动创造 WM_CAP_START + 84=1108 286 /// </summary> 287 public const int WM_CAP_PAL_MANUALCREATE = (WM_CAP_START + 84); //手动创造 288 289 // Following added post VFW 1.1 290 /// <summary> 291 /// 设置收回的错误 WM_CAP_START + 85=1109 292 /// </summary> 293 public const int WM_CAP_SET_CALLBACK_CAPCONTROL = (WM_CAP_START + 85); // 设置收回的错误 294 295 public const int WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL; 296 297 public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr); 298 299 #region 公共函数 300 //公共函数 301 public static object GetStructure(IntPtr ptr, ValueType structure) 302 { 303 return Marshal.PtrToStructure(ptr, structure.GetType()); 304 } 305 306 public static object GetStructure(int ptr, ValueType structure) 307 { 308 return GetStructure(new IntPtr(ptr), structure); 309 } 310 311 public static void Copy(IntPtr ptr, byte[] data) 312 { 313 Marshal.Copy(ptr, data, 0, data.Length); 314 } 315 316 public static void Copy(int ptr, byte[] data) 317 { 318 Copy(new IntPtr(ptr), data); 319 } 320 321 public static int SizeOf(object structure) 322 { 323 return Marshal.SizeOf(structure); 324 } 325 #endregion 公共函数 326 #region 结构 VIDEOHDR|BITMAPINFOHEADER|BITMAPINFO|CAPTUREPARMS|CAPDRIVERCAPS|CAPSTATUS 327 //========================================================VideoHdr 结构===================================================================== 328 //VideoHdr 结构 定义了视频数据块的头信息,在编写回调函数时常用到其数据成员lpData(指向数据缓存的指针)和dwBufferLength(数据缓存的大小)。 329 //视频帧到缓存的捕获则需要应用回调函数和相应的数据块结构 VIDEOHDR 330 [StructLayout(LayoutKind.Sequential)] 331 public struct VIDEOHDR 332 { 333 public IntPtr lpData; /* 指向数据缓存的指针 */ 334 public int dwBufferLength; /* 数据缓存的大小 */ 335 public int dwBytesUsed; /* Bytes actually used */ 336 public int dwTimeCaptured; /* Milliseconds from start of stream */ 337 public int dwUser; /* for client‘s use */ 338 public int dwFlags; /* assorted flags (see defines) */ 339 public int dwReserved; /* reserved for driver */ 340 } 341 //=======================================================BitmapInfoHeader结构=================================================================== 342 //BitmapInfoHeader定义了位图的头部信息 343 [StructLayout(LayoutKind.Sequential)] 344 public struct BITMAPINFOHEADER 345 { 346 public int biSize; 347 public int biWidth; 348 public int biHeight; 349 public short biPlanes; 350 public short biBitCount; 351 public int biCompression; 352 public int biSizeImage; 353 public int biXPelsPerMeter; 354 public int biYPelsPerMeter; 355 public int biClrUsed; 356 public int biClrImportant; 357 } 358 //========================================================================================================================================= 359 360 //======================================================BitmapInfo结构===================================================================== 361 //BitmapInfo 位图信息 362 [StructLayout(LayoutKind.Sequential)] 363 public struct BITMAPINFO 364 { 365 public BITMAPINFOHEADER bmiHeader; 366 public int bmiColors; 367 } 368 369 //=====================================================CAPTUREPARMS结构====================================================================== 370 //CAPTUREPARMS 包含控制视频流捕获过程的参数,如捕获帧频、指定键盘或鼠标键以终止捕获、捕获时间限制等; 371 [StructLayout(LayoutKind.Sequential)] 372 public struct CAPTUREPARMS 373 { 374 public int dwRequestMicroSecPerFrame; // 期望的桢播放率,以毫秒为单位,默认为66667,相当于15桢每秒。 375 public bool fMakeUserHitOKToCapture; // Show "Hit OK to cap" dlg?开始捕获标志位,如果值为真,则在开始捕获前要产生一个询问对话框,默认为假。 376 public uint wPercentDropForError; //所允许的最大丢桢百分比,可以从0变化到100,默认值为10。 377 public bool fYield; /*另起线程标志位,如果为真,则程序重新启动一个线程用于视频流的捕获,默认值是假。 378 但是如果你是为了真,你必须要在程序中处理一些潜在的操作,因为当视频捕获时,其他操作并没有被屏蔽。*/ 379 public int dwIndexSize; // 在AVI文件中所允许的最大数目的索引项(32K) 380 public uint wChunkGranularity; // AVI文件的逻辑尺寸,以字节为单位。如果值是0,则说明该尺寸渐增 在 Win32程序中无用。(2K) 381 public bool fUsingDOSMemory; // Use DOS buffers? 382 public uint wNumVideoRequested; // 所被允许分配的最大视频缓存 383 public bool fCaptureAudio; // 音频标志位,如果音频流正在捕获,则该值为真。 384 public uint wNumAudioRequested; // 最大数量的音频缓存,默认值为10。 385 public uint vKeyAbort; // 终止流捕获的虚拟键盘码,默认值为VK_ESCAPE 386 [MarshalAs(UnmanagedType.Bool)] 387 public bool fAbortLeftMouse; // 终止鼠标左键标志位,如果该值为真,则在流捕获过程中如果点击鼠标左键则该捕获终止,默认值为真。 388 public bool fAbortRightMouse; // Abort on right mouse? 389 public bool fLimitEnabled; // 捕获操作时间限制,如果为真,则时间到了以后捕获操作终止,默认为假 390 public uint wTimeLimit; // 具体终止时间,只有 fLimitEnabled是真时.该位才有效 391 public bool fMCIControl; // Use MCI video source? 392 public bool fStepMCIDevice; // Step MCI device?MCI 设备标志。 393 public int dwMCIStartTime; // Time to start in MS 394 public int dwMCIStopTime; // Time to stop in MS 395 public bool fStepCaptureAt2x; // Perform spatial averaging 2x 396 public int wStepCaptureAverageFrames; // 当基于平均采样来创建桢时,桢的采样时间,典型值是5 397 public int dwAudioBufferSize; // 音频缓存的尺寸,如果用默认值0,缓存尺寸是最大0.5秒,或10k字节。 398 public int fDisableWriteCache; // Attempt to disable write cache 399 public int AVStreamMaster; //音视频同步标志。 400 } 401 //========================================================================================================================================= 402 403 //=================================================CAPDRIVERCAPS结构======================================================================= 404 //CAPDRIVERCAPS定义了捕获驱动器的能力,如有无视频叠加能力、有无控制视频源、视频格式的对话框等; 405 [StructLayout(LayoutKind.Sequential)] 406 public struct CAPDRIVERCAPS 407 { 408 [MarshalAs(UnmanagedType.U2)] 409 public UInt16 wDeviceIndex; //捕获驱动器的索引值,该值可以由0到9变化。 410 [MarshalAs(UnmanagedType.Bool)] 411 public bool fHasOverlay; // 视频叠加标志,如果设备支持视频叠加这该位是真。 412 [MarshalAs(UnmanagedType.Bool)] 413 public bool fHasDlgVideoSource; //视频资源对话框标志位,如果设备支持视频选择、控制对话框,该值为真。 414 [MarshalAs(UnmanagedType.Bool)] 415 public bool fHasDlgVideoFormat; //视频格式对话框标志位,如果设备支持对视频格式对话框的选择,该位真。 416 [MarshalAs(UnmanagedType.Bool)] 417 public bool fHasDlgVideoDisplay; //视频展示对话框标志位,如果设备支持对视频捕获缓存区的重新播放,该位是真。 418 [MarshalAs(UnmanagedType.Bool)] 419 public bool fCaptureInitialized; //捕获安装标志位,如果捕获驱动器已经成功连接,该值为真。 420 //[MarshalAs(UnmanagedType.Bool)] 421 public bool fDriverSuppliesPalettes; //驱动器调色板标志位,如果驱动器能创建调色板,则该位是真。 422 [MarshalAs(UnmanagedType.I4)] 423 public int hVideoIn; 424 [MarshalAs(UnmanagedType.I4)] 425 public int hVideoOut; 426 [MarshalAs(UnmanagedType.I4)] 427 public int hVideoExtIn; 428 [MarshalAs(UnmanagedType.I4)] 429 public int hVideoExtOut; 430 } 431 //========================================================================================================================================= 432 433 434 //=====================================================CAPSTATUS结构======================================================================== 435 //CAPSTATUS定义了捕获窗口的当前状态,如图像的宽、高等; 436 [StructLayout(LayoutKind.Sequential)] 437 public struct CAPSTATUS 438 { 439 public int uiImageWidth; //图像宽度 440 public int uiImageHeight; //图像高度 441 public bool fLiveWindow; //活动窗口标记,如果窗口正以预览的方式展示图像,那么该值为真 442 public bool fOverlayWindow; //叠加窗口标志位,如果正在使用硬件叠加,则该位是真。 443 public bool fScale; //输入所放标志位,如果窗口是正在缩放视频到客户区,那么该位是真。当使用硬件叠加时,改位无效。 444 public Point ptScroll; //被展示在窗口客户区左上角的那个象素的x、y坐标偏移量。 445 public bool fUsingDefaultPalette; //默认调色板标志位,如果捕获窗口正在使用当前默认调色板,该值为真 446 public bool fAudioHardware; // 音频硬件标志位,如果系统已经安装了音频硬件,该值为真。 447 public bool fCapFileExists; //捕获文件标志位,如果一个捕获文件已经被创建,该值为真 448 public int dwCurrentVideoFrame; // 当前或最近流捕获过程中,所处理的桢的数目。包括丢弃的桢。 449 public int dwCurrentVideoFramesDropped;//当前流捕获过程中丢弃的桢的数目。 450 public int dwCurrentWaveSamples; // # of wave samples cap‘td 451 public int dwCurrentTimeElapsedMS; // 从当前流捕获开始计算,程序所用的时间,以毫秒为单位。 452 public IntPtr hPalCurrent; // 当前剪切板的句柄。 453 public bool fCapturingNow; // 捕获标志位,当捕获是正在进行时,改位是真 454 public int dwReturn; // 错误返回值,当你的应用程序不支持错误回调函数时可以应用改位 455 public int wNumVideoAllocated; // 被分配的视频缓存的数目。 456 public int wNumAudioAllocated; // 被分配的音频缓存的数目。 457 } 458 //========================================================================================================================================= 459 460 461 #endregion 结构 VIDEOHDR|BITMAPINFOHEADER|BITMAPINFO|CAPTUREPARMS|CAPDRIVERCAPS|CAPSTATUS 462 463 } 464 public class cVideo //视频类 465 { 466 public bool flag = true; 467 private IntPtr lwndC; //保存无符号句柄 468 private IntPtr mControlPtr; //保存管理指示器 469 private int mWidth; 470 private int mHeight; 471 public delegate void RecievedFrameEventHandler(byte[] data); 472 public event RecievedFrameEventHandler RecievedFrame; 473 474 public VideoAPI.CAPTUREPARMS Capparms; 475 private VideoAPI.FrameEventHandler mFrameEventHandler; 476 public VideoAPI.CAPDRIVERCAPS CapDriverCAPS;//捕获驱动器的能力,如有无视频叠加能力、有无控制视频源、视频格式的对话框等; 477 public VideoAPI.CAPSTATUS CapStatus;//该结构用于保存视频设备捕获窗口的当前状态,如图像的宽、高等 478 string strFileName; 479 public cVideo(IntPtr handle, int width, int height) 480 { 481 CapDriverCAPS = new VideoAPI.CAPDRIVERCAPS();//捕获驱动器的能力,如有无视频叠加能力、有无控制视频源、视频格式的对话框等; 482 CapStatus = new VideoAPI.CAPSTATUS();//该结构用于保存视频设备捕获窗口的当前状态,如图像的宽、高等 483 mControlPtr = handle; //显示视频控件的句柄 484 mWidth = width; //视频宽度 485 mHeight = height; //视频高度 486 } 487 public bool StartWebCam() 488 { 489 return StartWebCam(mWidth, mHeight); 490 } 491 /// <summary> 492 /// 打开视频设备 493 /// </summary> 494 /// <param name="width">捕获窗口的宽度</param> 495 /// <param name="height">捕获窗口的高度</param> 496 /// <returns></returns> 497 public bool StartWebCam(int width,int height) 498 { 499 //byte[] lpszName = new byte[100]; 500 //byte[] lpszVer = new byte[100]; 501 //VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100); 502 //this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0); 503 //if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0)) 504 //{ 505 // VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0); 506 // VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0); 507 // return true; 508 //} 509 //else 510 //{ 511 // return false; 512 //} 513 this.lwndC = VideoAPI.capCreateCaptureWindow("", VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);//AVICap类的捕捉窗口 514 VideoAPI.FrameEventHandler FrameEventHandler = new VideoAPI.FrameEventHandler(FrameCallback); 515 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_ERROR, 0, 0);//注册错误回调函数 516 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_STATUS, 0, 0);//注册状态回调函数 517 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);//注册视频流回调函数 518 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_FRAME, 0, FrameEventHandler);//注册帧回调函数 519 520 //if (!CapDriverCAPS.fCaptureInitialized)//判断当前设备是否被其他设备连接已经连接 521 //{ 522 523 if (VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0)) 524 { 525 //----------------------------------------------------------------------- 526 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_DRIVER_GET_CAPS, VideoAPI.SizeOf(CapDriverCAPS), ref CapDriverCAPS);//获得当前视频 CAPDRIVERCAPS定义了捕获驱动器的能力,如有无视频叠加能力、有无控制视频源、视频格式的对话框等; 527 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_STATUS, VideoAPI.SizeOf(CapStatus), ref CapStatus);//获得当前视频流的尺寸 存入CapStatus结构 528 529 VideoAPI.BITMAPINFO bitmapInfo = new VideoAPI.BITMAPINFO();//设置视频格式 (height and width in pixels, bits per frame). 530 bitmapInfo.bmiHeader = new VideoAPI.BITMAPINFOHEADER(); 531 bitmapInfo.bmiHeader.biSize = VideoAPI.SizeOf(bitmapInfo.bmiHeader); 532 bitmapInfo.bmiHeader.biWidth = mWidth; 533 bitmapInfo.bmiHeader.biHeight = mHeight; 534 bitmapInfo.bmiHeader.biPlanes = 1; 535 bitmapInfo.bmiHeader.biBitCount = 24; 536 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 40, 0);//设置在PREVIEW模式下设定视频窗口的刷新率 设置每40毫秒显示一帧,即显示帧速为每秒25帧 537 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_SCALE, 1, 0);//打开预览视频的缩放比例 538 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_VIDEOFORMAT, VideoAPI.SizeOf(bitmapInfo), ref bitmapInfo); 539 540 this.mFrameEventHandler = new VideoAPI.FrameEventHandler(FrameCallback); 541 this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler); 542 543 544 VideoAPI.CAPTUREPARMS captureparms = new VideoAPI.CAPTUREPARMS(); 545 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_SEQUENCE_SETUP, VideoAPI.SizeOf(captureparms), ref captureparms); 546 if (CapDriverCAPS.fHasOverlay) 547 { 548 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_OVERLAY, 1, 0);//启用叠加 注:据说启用此项可以加快渲染速度 549 } 550 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEW, 1, 0);//设置显示图像启动预览模式 PREVIEW 551 VideoAPI.SetWindowPos(this.lwndC, 0, 0, 0, width, height, VideoAPI.SWP_NOZORDER | VideoAPI.SWP_NOMOVE);//使捕获窗口与进来的视频流尺寸保持一致 552 return true; 553 } 554 else 555 { 556 557 flag = false; 558 return false; 559 } 560 } 561 public bool ReSizePic(int width, int height) 562 { 563 try 564 { 565 // CloseWebcam(); 566 // StartWebCam(); 567 // this.lwndC = VideoAPI.capCreateCaptureWindow("", VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0); 568 569 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_STATUS, VideoAPI.SizeOf(CapStatus), ref CapStatus);//获得当前视频流的尺寸 存入CapStatus结构 570 // VideoAPI.FrameEventHandler FrameEventHandler = new VideoAPI.FrameEventHandler(FrameCallback); 571 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_ERROR, 0, 0);//注册错误回调函数 572 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_STATUS, 0, 0);//注册状态回调函数 573 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);//注册视频流回调函数 574 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_FRAME, 0, FrameEventHandler);//注册帧回调函数 575 //// if (VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0)) 576 // { 577 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_SCALE, 1, 0); 578 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 40, 0); 579 // VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_PREVIEW, 1, 0); 580 581 return VideoAPI.SetWindowPos(this.lwndC, 0, 0, 0, width, height, VideoAPI.SWP_NOZORDER | VideoAPI.SWP_NOMOVE) > 0; 582 // } 583 // return false; 584 } 585 catch 586 { 587 return false; 588 } 589 } 590 public void get() 591 { 592 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_GET_SEQUENCE_SETUP, VideoAPI.SizeOf(Capparms), ref Capparms); 593 } 594 public void set() 595 { 596 VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_SEQUENCE_SETUP, VideoAPI.SizeOf(Capparms), ref Capparms); 597 } 598 private bool capSetCallbackOnFrame(IntPtr lwnd, VideoAPI.FrameEventHandler lpProc) 599 { 600 return VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc); 601 } 602 /// <summary> 603 /// 关闭视频设备 604 /// </summary> 605 public void CloseWebcam() 606 { 607 VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_DISCONNECT, 0, 0); 608 } 609 /// <summary> 610 /// 拍照 611 /// </summary> 612 /// <param name="path">要保存bmp文件的路径</param> 613 public void GrabImage(IntPtr hWndC, string path) 614 { 615 IntPtr hBmp = Marshal.StringToHGlobalAnsi(path); 616 VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SAVEDIB, 0, hBmp.ToInt32()); 617 } 618 public bool StarKinescope(string path) 619 { 620 try 621 { 622 strFileName = path; 623 string dir = path.Remove(path.LastIndexOf("\\")); 624 if (!File.Exists(dir)) 625 { 626 Directory.CreateDirectory(dir); 627 } 628 int hBmp = Marshal.StringToHGlobalAnsi(path).ToInt32(); 629 bool b = VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_FILE_SET_CAPTURE_FILE, 0, hBmp); 630 b = b && VideoAPI.SendMessage(this.lwndC, VideoAPI.WM_CAP_SEQUENCE, 0, 0); 631 return b; 632 } 633 catch 634 { 635 return false; 636 } 637 } 638 /// <summary> 639 /// 停止录像 640 /// </summary> 641 public bool StopKinescope() 642 { 643 return VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_STOP, 0, 0); 644 } 645 private void FrameCallback(IntPtr lwnd, IntPtr lpvhdr) 646 { 647 VideoAPI.VIDEOHDR videoHeader = new VideoAPI.VIDEOHDR(); 648 byte[] VideoData; 649 videoHeader = (VideoAPI.VIDEOHDR)VideoAPI.GetStructure(lpvhdr, videoHeader); 650 VideoData = new byte[videoHeader.dwBytesUsed]; 651 VideoAPI.Copy(videoHeader.lpData, VideoData); 652 if (this.RecievedFrame != null) 653 this.RecievedFrame(VideoData); 654 } 655 private Thread myThread; 656 657 public void CompressVideoFfmpeg() 658 { 659 myThread = new Thread(new ThreadStart(testfn)); 660 myThread.Start(); 661 testfn(); 662 } 663 private void testfn() 664 { 665 string file_name = strFileName; 666 string command_line = " -i " + file_name + " -vcodec libx264 -cqp 25 -y " + file_name.Replace(".avi", "_264") + ".avi"; 667 System.Diagnostics.Process proc = new System.Diagnostics.Process(); 668 proc.StartInfo.WorkingDirectory = Application.StartupPath; 669 proc.StartInfo.UseShellExecute = false; //use false if you want to hide the window 670 proc.StartInfo.CreateNoWindow = true; 671 proc.StartInfo.FileName = "ffmpeg"; 672 proc.StartInfo.Arguments = command_line; 673 proc.Start(); 674 proc.WaitForExit(); 675 proc.Close(); 676 Common.writeLog("视频"+strFileName+"压缩完毕"); 677 // 删除原始avi文件 678 FileInfo file = new FileInfo(file_name); 679 if (file.Exists) 680 { 681 try 682 { 683 file.Delete(); //删除单个文件 684 } 685 catch (Exception e) 686 { 687 // Common.writeLog("删除视频文件“" + file_name + "”出错!准备" ); 688 689 (new Thread(() => 690 { 691 bool b = false; 692 for (int i = 0; i < 5; i++) 693 { 694 Thread.Sleep(10000*(i*i)); 695 try 696 { 697 file.Delete(); 698 b = true; 699 break; 700 } 701 catch 702 { 703 } 704 }; 705 if (!b) 706 Common.writeLog("删除视频文件“" + file_name + "”出错"); 707 } 708 )).Start(); 709 } 710 } 711 //myThread.Abort(); 712 } 713 } 714 }
时间: 2024-10-23 19:14:02