利用avicap32.dll实现的实时视频传输
直接上代码吧!
在窗体上调用的类:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Threading; namespace 实时视频传输系统 { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } /// <summary> /// 声明Camera类 /// </summary> Camera ca = null; //创建一个Thread实例 private Thread thread1; //创建一个UdpClient实例 private UdpClient udpReceive; private UdpClient udpSend; private byte[] bytes; //private DialogResult result; private void btnPlay_Click(object sender, EventArgs e) { btnPlay.Enabled = false; btnStop.Enabled = true; ca = new Camera(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height); try { ca.StartWebCam(); } catch (Exception) { MessageBox.Show("未能初始化摄像头!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); btnPlay.Enabled = true; btnStop.Enabled = false; ca = null; } } private void btnStop_Click(object sender, EventArgs e) { try { ca.CloseWebcam(); btnPlay.Enabled = true; btnStop.Enabled = false; } catch (Exception) { MessageBox.Show("摄像头关闭失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); btnPlay.Enabled = true; btnStop.Enabled = false; ca = null; } } private void btnClose_Click(object sender, EventArgs e) { try { ca.CloseWebcam(); btnPlay.Enabled = true; btnStop.Enabled = false; } catch (Exception) { MessageBox.Show("摄像头关闭失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); btnPlay.Enabled = true; btnStop.Enabled = false; ca = null; } //关闭程序 this.Close(); Application.Exit(); } private IPEndPoint ipLocalPoint; private EndPoint RemotePoint; private Socket mySocket; private bool RunningFlag = false; private void btnGetIP_Click(object sender, EventArgs e) { //string GetIP; //IPAddress[] AddressList = Dns.GetHostEntry(Dns.GetHostEntry()).AddressList; //if (AddressList.Length < 1) //{ // return ""; //} //return AddressList[0].ToString(); //this.tbGetIP.Text = Convert.ToInt32(AddressList); } //IP与端口号有效验证 private int getValidPort(string port) { int lport; //测试端口号是否有效 try { //是否为空 if (port == "") { throw new ArgumentException("端口号无效,不能启动UDP"); } lport = System.Convert.ToInt32(port); } catch(Exception e) { Console.WriteLine("无效的端口号"+ e.ToString()); this.tbGetPort.AppendText("无效的端口号"+ e.ToString()+"\n"); return -1; } return lport; } private IPAddress getValidIP(string ip) { IPAddress lip = null; //测试IP是否有效 try { //是否为空 if (!IPAddress.TryParse(ip, out lip)) { throw new ArgumentException("IP无效,不能启动UDP"); } } catch(Exception e) { Console.WriteLine("无效的IP:"+ e.ToString()); this.tbGetIP.AppendText("无效的IP:"+ e.ToString() +"\n"); return null; } return lip; } private void MainForm_Load(object sender, EventArgs e) { thread1 = new Thread(new ThreadStart()); thread1.Start(); } private void btnReceive_Click(object sender, EventArgs e) { //在本机指定的端口接收 udpReceive = new UdpClient(8001); //将套接字加入组播组 udpReceive.JoinMulticastGroup(IPAddress.Parse("224.100.0.10"), 50); //接收从远程主机发送过来的信息 IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); while (true) { //ref表示引用类型的 IPPoint实例接收消息 try { bytes = udpReceive.Receive(ref iep); } catch { DialogResult result = MessageBox.Show("发送失败!"); } string str = Encoding.UTF8.GetString(bytes, 0, bytes.Length); string message = "来自" + iep.ToString() + "的消息"; //显示消息 并以message为消息的标题 DialogResult res = MessageBox.Show(str, message); } } private void btnSend_Click_1(object sender, EventArgs e) { //初始化UdpClient udpSend = new UdpClient(); //实际使用时应将127.0.0.1改为服务器的远程IP IPAddress remoteIPAddress = IPAddress.Parse("127.0.0.1"); IPEndPoint remoteIPEndPoint = new IPEndPoint(remoteIPAddress, 8002); //将发送内容转换为字节数组 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(); //设置重传次数 int retry = 0; while (true) { try { udpSend.Send(bytes, bytes.Length, remoteIPEndPoint); break; } catch { if (retry < 3) { retry++; continue; } else { DialogResult result = MessageBox.Show("发送失败!"); break; } } } } } }
视频封装类:
using System; using System.Collections.Generic; using System.Text; namespace Camera.avicap { /// <summary> /// Camera 的摘要说明。 /// </summary> public class Camera { private IntPtr lwndC; private IntPtr mControlPtr; private int mWidth; private int mHeight; // 构造函数 public Camera(IntPtr handle, int width, int height) { mControlPtr = handle; mWidth = width; mHeight = height; } // 帧回调的委托 public delegate void RecievedFrameEventHandler(byte[] data); public event RecievedFrameEventHandler RecievedFrame; private AviCapture.FrameEventHandler mFrameEventHandler; // 关闭摄像头 public void CloseWebcam() { this.capDriverDisconnect(this.lwndC); } // 开启摄像头 public void StartWebCam() { byte[] lpszName = new byte[100]; byte[] lpszVer = new byte[100]; AviCapture.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100); this.lwndC = AviCapture.capCreateCaptureWindowA(lpszName, AviCapture.WS_VISIBLE + AviCapture.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0); if (this.capDriverConnect(this.lwndC, 0)) { this.capPreviewRate(this.lwndC, 66); this.capPreview(this.lwndC, true); AviCapture.BITMAPINFO bitmapinfo = new AviCapture.BITMAPINFO(); bitmapinfo.bmiHeader.biSize = AviCapture.SizeOf(bitmapinfo.bmiHeader); bitmapinfo.bmiHeader.biWidth = this.mWidth; bitmapinfo.bmiHeader.biHeight = this.mHeight; bitmapinfo.bmiHeader.biPlanes = 1; bitmapinfo.bmiHeader.biBitCount = 24; this.capSetVideoFormat(this.lwndC, ref bitmapinfo, AviCapture.SizeOf(bitmapinfo)); this.mFrameEventHandler = new AviCapture.FrameEventHandler(FrameCallBack); this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler); AviCapture.SetWindowPos(this.lwndC, 0, 0, 0, mWidth, mHeight, 6); } } // 以下为私有函数 private bool capDriverConnect(IntPtr lwnd, short i) { return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_CONNECT, i, 0); } private bool capDriverDisconnect(IntPtr lwnd) { return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_DISCONNECT, 0, 0); } private bool capPreview(IntPtr lwnd, bool f) { return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEW, f, 0); } private bool capPreviewRate(IntPtr lwnd, short wMS) { return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEWRATE, wMS, 0); } private bool capSetCallbackOnFrame(IntPtr lwnd, AviCapture.FrameEventHandler lpProc) { return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc); } private bool capSetVideoFormat(IntPtr hCapWnd, ref AviCapture.BITMAPINFO BmpFormat, int CapFormatSize) { return AviCapture.SendMessage(hCapWnd, AviCapture.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat); } private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr) { AviCapture.VIDEOHDR videoHeader = new AviCapture.VIDEOHDR(); byte[] VideoData; videoHeader = (AviCapture.VIDEOHDR)AviCapture.GetStructure(lpVHdr, videoHeader); VideoData = new byte[videoHeader.dwBytesUsed]; AviCapture.Copy(videoHeader.lpData, VideoData); if (this.RecievedFrame != null) this.RecievedFrame(VideoData); } } }
win32的avicap32.dll封装类
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace Camera.avicap { /// <summary> /// AviCapture 的摘要说明。 /// </summary> public class AviCapture { //通过调用acicap32.dll进行读取摄像头数据 [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, 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 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; // 结构 [StructLayout(LayoutKind.Sequential)] //VideoHdr public struct VIDEOHDR { [MarshalAs(UnmanagedType.I4)] public int lpData; [MarshalAs(UnmanagedType.I4)] public int dwBufferLength; [MarshalAs(UnmanagedType.I4)] public int dwBytesUsed; [MarshalAs(UnmanagedType.I4)] public int dwTimeCaptured; [MarshalAs(UnmanagedType.I4)] public int dwUser; [MarshalAs(UnmanagedType.I4)] public int dwFlags; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public int[] dwReserved; } [StructLayout(LayoutKind.Sequential)] //BitmapInfoHeader public struct BITMAPINFOHEADER { [MarshalAs(UnmanagedType.I4)] public Int32 biSize; [MarshalAs(UnmanagedType.I4)] public Int32 biWidth; [MarshalAs(UnmanagedType.I4)] public Int32 biHeight; [MarshalAs(UnmanagedType.I2)] public short biPlanes; [MarshalAs(UnmanagedType.I2)] public short biBitCount; [MarshalAs(UnmanagedType.I4)] public Int32 biCompression; [MarshalAs(UnmanagedType.I4)] public Int32 biSizeImage; [MarshalAs(UnmanagedType.I4)] public Int32 biXPelsPerMeter; [MarshalAs(UnmanagedType.I4)] public Int32 biYPelsPerMeter; [MarshalAs(UnmanagedType.I4)] public Int32 biClrUsed; [MarshalAs(UnmanagedType.I4)] public Int32 biClrImportant; } [StructLayout(LayoutKind.Sequential)] //BitmapInfo public struct BITMAPINFO { [MarshalAs(UnmanagedType.Struct, SizeConst = 40)] public BITMAPINFOHEADER bmiHeader; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public Int32[] bmiColors; } public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr); // 公共函数 public static object GetStructure(IntPtr ptr, ValueType structure) { return Marshal.PtrToStructure(ptr, structure.GetType()); } public static object GetStructure(int ptr, ValueType structure) { return GetStructure(new IntPtr(ptr), structure); } public static void Copy(IntPtr ptr, byte[] data) { Marshal.Copy(ptr, data, 0, data.Length); } public static void Copy(int ptr, byte[] data) { Copy(new IntPtr(ptr), data); } public static int SizeOf(object structure) { return Marshal.SizeOf(structure); } } }
出处:https://blog.csdn.net/zlbdmm/article/details/105833771
https://bbs.csdn.net/topics/390039653
参考:
https://blog.csdn.net/NCTU_to_prove_safety/article/details/53584905
https://www.cnblogs.com/JUSTSOSOBLOG/p/4612801.html
https://blog.csdn.net/laolei1986/article/details/5730245
https://blog.csdn.net/waeceo/article/details/50222781
=======================================================================================
C# 使用avicap32.dll调用摄像头
目前情况是这样:调用一个摄像头是没有问题的,但调用多个报像头就无法显示第二个以后的摄像头了,望高手们赐教。。。
目前的调用代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Drawing.Imaging; using System.Net; using System.Net.Sockets; using System.Threading; namespace camera { public partial class CameraForm : Form { private int hHwnd; private const int port = 2000; public CameraForm() { InitializeComponent(); } public struct videohdr_tag { public byte[] lpData; public int dwBufferLength; public int dwBytesUsed; public int dwTimeCaptured; public int dwUser; public int dwFlags; public int[] dwReserved; } public delegate bool CallBack(int hwnd, int lParam); /// <summary> /// 必需的设计器变量。 /// </summary> [DllImport("avicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern int capCreateCaptureWindowA([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpszWindowName, int dwStyle, int x, int y, int nWidth, short nHeight, int hWndParent, int nID); [DllImport("avicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool capGetDriverDescriptionA(short wDriver, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpszName, int cbName, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpszVer, int cbVer); [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool DestroyWindow(int hndw); [DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern int SendMessage(int hwnd, int wMsg, int wParam, [MarshalAs(UnmanagedType.AsAny)] object lParam); [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern int SetWindowPos(int hwnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags); [DllImport("vfw32.dll")] public static extern string capVideoStreamCallback(int hwnd, videohdr_tag videohdr_tag); [DllImport("vicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool capSetCallbackOnFrame(int hwnd, string s); private void OpenCapture() { int intWidth = this.panel1.Width; int intHeight = this.panel1.Height; int intDevice = 0; string refDevice = intDevice.ToString(); //创建视频窗口并得到句柄 hHwnd = CameraForm.capCreateCaptureWindowA(ref refDevice, 1342177280, 0, 0, 640, 480, this.panel1.Handle.ToInt32(), 0); if (CameraForm.SendMessage(hHwnd, 0x40a, intDevice, 0) > 0) { CameraForm.SendMessage(this.hHwnd, 0x435, -1, 0); CameraForm.SendMessage(this.hHwnd, 0x434, 0x42, 0); CameraForm.SendMessage(this.hHwnd, 0x432, -1, 0); CameraForm.SetWindowPos(this.hHwnd, 1, 0, 0, intWidth, intHeight, 6); } else { CameraForm.DestroyWindow(this.hHwnd); } } private void button1_Click(object sender, EventArgs e) { this.OpenCapture(); } private void button2_Click(object sender, EventArgs e) { //停止视频注销视频句柄 CameraForm.SendMessage(this.hHwnd, 0x40b, 0, 0); CameraForm.DestroyWindow(this.hHwnd); } //截图 private void button3_Click(object sender, EventArgs e) { try { CameraForm.SendMessage(this.hHwnd, 0x41e, 0, 0); IDataObject obj1 = Clipboard.GetDataObject(); if (obj1.GetDataPresent(typeof(Bitmap))) { Image image1 = (Image)obj1.GetData(typeof(Bitmap)); SaveFileDialog SaveFileDialog1 = new SaveFileDialog(); SaveFileDialog1.FileName = DateTime.Now.ToString("yyyyMMddhhmmss"); SaveFileDialog1.Filter = "Image Files(*.JPG;*.GIF)|*.JPG;*.GIF|All files (*.*)|*.*"; if (SaveFileDialog1.ShowDialog() == DialogResult.OK) { image1.Save(SaveFileDialog1.FileName, ImageFormat.Bmp); } } } catch { } }
出处:https://bbs.csdn.net/topics/350046936
=======================================================================================
C# 捕获摄像头图像
从网上参考一些文章,自己整理一下,后续实现的功能:
1)帧回调函数
2)状态回调、错误回调函数等
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using winLogin.Hardware; namespace winLogin.Hardware { // 结构 [StructLayout(LayoutKind.Sequential)] //VideoHdr public struct VIDEOHDR { [MarshalAs(UnmanagedType.I4)] public int lpData; [MarshalAs(UnmanagedType.I4)] public int dwBufferLength; [MarshalAs(UnmanagedType.I4)] public int dwBytesUsed; [MarshalAs(UnmanagedType.I4)] public int dwTimeCaptured; [MarshalAs(UnmanagedType.I4)] public int dwUser; [MarshalAs(UnmanagedType.I4)] public int dwFlags; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public int[] dwReserved; } [StructLayout(LayoutKind.Sequential)] //BitmapInfoHeader public struct BITMAPINFOHEADER { [MarshalAs(UnmanagedType.I4)] public Int32 biSize; [MarshalAs(UnmanagedType.I4)] public Int32 biWidth; [MarshalAs(UnmanagedType.I4)] public Int32 biHeight; [MarshalAs(UnmanagedType.I2)] public short biPlanes; [MarshalAs(UnmanagedType.I2)] public short biBitCount; [MarshalAs(UnmanagedType.I4)] public Int32 biCompression; [MarshalAs(UnmanagedType.I4)] public Int32 biSizeImage; [MarshalAs(UnmanagedType.I4)] public Int32 biXPelsPerMeter; [MarshalAs(UnmanagedType.I4)] public Int32 biYPelsPerMeter; [MarshalAs(UnmanagedType.I4)] public Int32 biClrUsed; [MarshalAs(UnmanagedType.I4)] public Int32 biClrImportant; } [StructLayout(LayoutKind.Sequential)] //BitmapInfo public struct BITMAPINFO { [MarshalAs(UnmanagedType.Struct, SizeConst = 40)] public BITMAPINFOHEADER bmiHeader; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public Int32[] bmiColors; } /// <summary> /// webcam 的摘要说明。 /// </summary> public class VideoCapture { #region 消息常量(向窗口发送消息的指令) //消息常量 -------------------------------------------- public const int WM_START = 0x400; //此并非摄像头消息0x400表示的就是1024 public const int WS_CHILD = 0x40000000; public const int WS_VISIBLE = 0x10000000; public const int SWP_NOMOVE = 0x2; public const int SWP_NOZORDER = 0x4; public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1; public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2;//设置收回错误 public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3;//设置收回状态 public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4;//设置收回出产 public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5;//设置收回结构 public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6;//设置收回视频流 public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7;//设置收回视频波流 public const int WM_CAP_GET_USER_DATA = WM_START + 8;//获得使用者数据 public const int WM_CAP_SET_USER_DATA = WM_START + 9;//设置使用者数据 public const int WM_CAP_DRIVER_CONNECT = WM_START + 10;//驱动程序连接 public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11;//断开启动程序连接 public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12;//获得驱动程序名字 public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13;//获得驱动程序版本 public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14;//获得驱动程序帽子 public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20;//设置捕获文件 public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21;//获得捕获文件 public const int WM_CAP_FILE_ALLOCATE = WM_START + 22;//分派文件 public const int WM_CAP_FILE_SAVEAS = WM_START + 23;//另存文件为 public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24;//设置开始文件 public const int WM_CAP_FILE_SAVEDIB = WM_START + 25;//保存文件 public const int WM_CAP_EDIT_COPY = WM_START + 30;//编辑复制 public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35;//设置音频格式 public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36;//捕获音频格式 public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41;//1065 打开视频格式设置对话框 public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42;//1066 打开属性设置对话框,设置对比度亮度等 public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43;//1067 打开视频显示 public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44;//1068 获得视频格式 public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45;//1069 设置视频格式 public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46;//1070 打开压缩设置对话框 public const int WM_CAP_SET_PREVIEW = WM_START + 50;//设置预览 public const int WM_CAP_SET_OVERLAY = WM_START + 51;//设置覆盖 public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52;//设置预览比例 public const int WM_CAP_SET_SCALE = WM_START + 53;//设置刻度 public const int WM_CAP_GET_STATUS = WM_START + 54;//获得状态 public const int WM_CAP_SET_SCROLL = WM_START + 55;//设置卷 public const int WM_CAP_GRAB_FRAME = WM_START + 60;//逮捕结构 public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61;//停止逮捕结构 public const int WM_CAP_SEQUENCE = WM_START + 62;//次序 public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63;//使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盘文件写入数据。该消息仅在配合回调函数时有用,它允许你的应用程序直接使用音视频数据。 public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64;//设置安装次序 public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65;//获得安装次序 public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66;//设置媒体控制接口 public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67;//获得媒体控制接口 public const int WM_CAP_STOP = WM_START + 68;//停止 public const int WM_CAP_ABORT = WM_START + 69;//异常中断 public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70;//打开单一的结构 public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71;//关闭单一的结构 public const int WM_CAP_SINGLE_FRAME = WM_START + 72;//单一的结构 public const int WM_CAP_PAL_OPEN = WM_START + 80;//打开视频 public const int WM_CAP_PAL_SAVE = WM_START + 81;//保存视频 public const int WM_CAP_PAL_PASTE = WM_START + 82;//粘贴视频 public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83; //自动创造 public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84;//手动创造 public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85;// 设置收回的错误 #endregion 消息常量 //private const int WM_USER = 0x400; //private const int WS_CHILD = 0x40000000; //private const int WS_VISIBLE = 0x10000000; //private const int WM_CAP_START = WM_USER; //private const int WM_CAP_STOP = WM_CAP_START + 68; //private const int WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10; //private const int WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11; //private const int WM_CAP_SAVEDIB = WM_CAP_START + 25; //private const int WM_CAP_GRAB_FRAME = WM_CAP_START + 60; //private const int WM_CAP_SEQUENCE = WM_CAP_START + 62; //private const int WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20; //private const int WM_CAP_SEQUENCE_NOFILE = WM_CAP_START + 63; //private const int WM_CAP_SET_OVERLAY = WM_CAP_START + 51; //private const int WM_CAP_SET_PREVIEW = WM_CAP_START + 50; //private const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START + 6; //private const int WM_CAP_SET_CALLBACK_ERROR = WM_CAP_START + 2; //private const int WM_CAP_SET_CALLBACK_STATUS = WM_CAP_START + 3; //private const int WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5; //private const int WM_CAP_SET_SCALE = WM_CAP_START + 53; //private const int WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52; private IntPtr hWndC; private bool bStat = false; private IntPtr mControlPtr; private int mWidth; private int mHeight; private int mLeft; private int mTop; // 帧回调的委托 public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr); public delegate void RecievedFrameEventHandler(byte[] data); public event RecievedFrameEventHandler RecievedFrame; private FrameEventHandler mFrameEventHandler; public VideoCapture() { } /// <summary> /// 初始化摄像头参数 /// </summary> /// <param name="handle">控件的句柄</param> /// <param name="left">开始显示的左边距</param> /// <param name="top">开始显示的上边距</param> /// <param name="width">要显示的宽度</param> /// <param name="height">要显示的长度</param> public VideoCapture(IntPtr handle, int left, int top, int width, int height) { mControlPtr = handle; mWidth = width; mHeight = height; mLeft = left; mTop = top; } /// <summary> /// 视频左边距 /// </summary> public int Left { get { return mLeft; } set { mLeft = value; } } /// <summary> /// 视频上边距 /// </summary> public int Top { get { return mTop; } set { mTop = value; } } /// <summary> /// 视频宽度 /// </summary> public int Width { get { return mWidth; } set { mWidth = value; } } /// <summary> /// 视频高度 /// </summary> public int Height { get { return mHeight; } set { mHeight = value; } } #region WindowsAPI [DllImport("avicap32.dll")] private 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("avicap32.dll")] private static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize); [DllImport("User32.dll")] public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam); [DllImport("User32.dll")] private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam); [DllImport("user32.dll")] private static extern int 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")] private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, string lParam); [DllImport("Kernel32.dll")] private static extern bool CloseHandle(int hObject); [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool DestroyWindow(int hndw); [DllImport("vicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool capSetCallbackOnFrame(int hwnd, string s); [DllImport("vicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern bool capSetCallbackOnFrame(int hwnd, int s); #endregion /// <summary> /// 开始显示图像 /// </summary> public void Start(IntPtr handle, int left, int top, int width, int height) { try { if (bStat) return; mControlPtr = handle; mWidth = width; mHeight = height; mLeft = left; mTop = top; bStat = true; byte[] lpszName = new byte[100]; lpszName = System.Text.Encoding.UTF8.GetBytes("CameraAvicap32"); // byte[] lpszVer = new byte[100]; // bool flag=capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100); if (mControlPtr == IntPtr.Zero) mControlPtr = new System.Windows.Forms.Control().Handle; hWndC = capCreateCaptureWindowA(lpszName, WS_CHILD | WS_VISIBLE, mLeft, mTop, mWidth, mHeight, mControlPtr, 0); //// 使用capSetCallbackOnError宏注册错误回调函数 //capSetCallbackOnError(ghWndCap, fpErrorCallback); //// 使用capSetCallbackOnStatus宏注册状态回调函数 //capSetCallbackOnStatus(ghWndCap, fpStatusCallback); ////使用capSetCallbackOnVideoStream宏注册视频流回调函数 //capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback); ////使用capSetCallbackOnFrame宏注册帧回调函数 //capSetCallbackOnFrame(hWndC, fpFrameCallback); //// 连接到一个捕获驱动器上 //注册回调函数 mFrameEventHandler = new FrameEventHandler(FrameCallBack); //capSetCallbackOnFrame(this.hWndC, mFrameEventHandler); if (hWndC.ToInt32() != 0) { SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0); SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUS, 0, 0); SendMessage(hWndC, WM_CAP_SET_CALLBACK_FRAME, 0, mFrameEventHandler); SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); SendMessage(hWndC, WM_CAP_DRIVER_GET_NAME, 0, 0); SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0); SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0); SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 66, 0); SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0); //覆盖模式,不占用CPU处理资源 SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0); } } catch (Exception ex) { //LogClass.SystemLog.Error(ex.ToString()); } return; } /// <summary> /// 停止显示 /// </summary> public void Stop() { if (!bStat) return; SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0); //CloseHandle((int)mControlPtr); DestroyWindow((int)mControlPtr); bStat = false; } /// <summary> /// 抓图 /// </summary> public System.Drawing.Image GrabImage() { SendMessage(hWndC, WM_CAP_EDIT_COPY, 0, 0); System.Windows.Forms.IDataObject iData = System.Windows.Forms.Clipboard.GetDataObject(); System.Drawing.Image retImage = null; if (iData != null) { if (iData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap)) { retImage = (System.Drawing.Image)iData.GetData(System.Windows.Forms.DataFormats.Bitmap); } else if (iData.GetDataPresent(System.Windows.Forms.DataFormats.Dib)) { retImage = (System.Drawing.Image)iData.GetData(System.Windows.Forms.DataFormats.Dib); } } return retImage; } public System.Drawing.Image GetImage() { Start(IntPtr.Zero, 0, 0, 0, 0); SendMessage(hWndC, WM_CAP_EDIT_COPY, 0, 0); System.Drawing.Image retImage = null; if (System.Windows.Forms.Clipboard.ContainsData(System.Windows.Forms.DataFormats.Bitmap) || System.Windows.Forms.Clipboard.ContainsData(System.Windows.Forms.DataFormats.Dib)) { retImage = System.Windows.Forms.Clipboard.GetImage(); } //System.Windows.Forms.IDataObject iData = System.Windows.Forms.Clipboard.GetDataObject(); //if (iData != null) //{ // if (iData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap)) // { // retImage = (System.Drawing.Image)iData.GetData(System.Windows.Forms.DataFormats.Bitmap); // } // else if (iData.GetDataPresent(System.Windows.Forms.DataFormats.Dib)) // { // retImage = (System.Drawing.Image)iData.GetData(System.Windows.Forms.DataFormats.Dib); // } //} Stop(); return retImage; } private bool capSetCallbackOnFrame(IntPtr lwnd, FrameEventHandler lpProc) { return SendMessage(lwnd, WM_CAP_SET_CALLBACK_FRAME, 0, lpProc); } // 公共函数 private static object GetStructure(IntPtr ptr, ValueType structure) { return Marshal.PtrToStructure(ptr, structure.GetType()); } private static object GetStructure(int ptr, ValueType structure) { return GetStructure(new IntPtr(ptr), structure); } private static void CopyData(IntPtr ptr, byte[] data) { Marshal.Copy(ptr, data, 0, data.Length); } private static void CopyData(int ptr, byte[] data) { CopyData(new IntPtr(ptr), data); } private static int SizeOf(object structure) { return Marshal.SizeOf(structure); } private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr) { VIDEOHDR videoHeader = new VIDEOHDR(); byte[] VideoData; videoHeader = (VIDEOHDR)GetStructure(lpVHdr, videoHeader); VideoData = new byte[videoHeader.dwBytesUsed]; CopyData(videoHeader.lpData, VideoData); if (this.RecievedFrame != null) this.RecievedFrame(VideoData); } } }
参考:https://www.cnblogs.com/ltt1987/archive/2006/08/13/475901.html
https://www.cnblogs.com/mahaisong/archive/2011/08/25/2153653.html(可查看他后续文章对程序的分析)
https://www.cnblogs.com/JUSTSOSOBLOG/p/4612801.html
调用avicap32.dll的capCreateCaptureWindow的API接口控制摄像头的详细介绍
=======================================================================================
我使用AVICAP32.DLL来捕获图像,捕完并保存到文件后,当我关闭它后.那个黑块的窗体一直在那里,如果让它消失呢?
哈哈哈,我自己搞定了,由于那个窗体是使用API调出来的,它只是位置和大小与PANEL一样而已,因此要想控制它还是要使用API消息机制.利用它的句柄来操作它.方法如下:
public const int WM_CLOSE = 0x10;//关闭窗口句柄
//关闭摄像头
if hWndC <> 0 then
begin
SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
SendMessage(hWndC, WM_CLOSE, 0, 0);
hWndC := 0;
end;OK,完事了.
=======================================================================================
前面的代码有一个事件的处理是缺失的,就是Camera类的RecievedFrame事件;怎么把接收到的byte[] VideoData数组转成图片呢?
看看下面的文章,或许对你有所启发。
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。(●'◡'●)
因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/11249148.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
浙公网安备 33010602011771号