C#控制摄像头实现画面实时播放

29 篇文章 54 订阅

C#控制摄像头实现画面实时播放

思路说明

主要是调用Win32API(avicap32.dll)实现。

关键代码

AviCapture.dll

using System;
using System.Runtime.InteropServices;

namespace Wongoing.Basic.Camera
{
    /// <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);
        }
    }
}

Camera.dll

using System;
using System.Runtime.InteropServices;

namespace Wongoing.Basic.Camera
{
	/// <summary>
	/// 相机类定义
	/// </summary>
	public class Camera
	{
		private IntPtr lwndC;
		private IntPtr mControlPtr;
		private int mWidth;
		private int mHeight;


		/// <summary>
        /// 构造函数
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="width"></param>
		/// <param name="height"></param>
		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;

		/// <summary>
        /// 关闭摄像头
		/// </summary>
		public void CloseWebcam()
		{
			this.capDriverDisconnect(this.lwndC);
		}

		/// <summary>
        /// 开启摄像头
		/// </summary>
		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);
			} 
		}

        #region 私有方法定义

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

        #endregion
    }
}

完整代码下载

完整代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值