Click here to Skip to main content
15,888,610 members
Articles / Multimedia / DirectX

Cam Alarm 2.0 - Alarm system run from a web camera

Rate me:
Please Sign up or sign in to vote.
4.86/5 (33 votes)
16 Jun 2010CPOL3 min read 85.8K   9.5K   150  
Simple alarm system for those on a budget..
namespace CamAlarm
{
    #region Directives
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;
    #endregion

    public class AviReader : IDisposable
    {
        #region Enums
        [Flags]
        private enum OpenFileMode
        {
            Read = 0x00000000,
            Write = 0x00000001,
            ReadWrite = 0x00000002,
            ShareCompat = 0x00000000,
            ShareExclusive = 0x00000010,
            ShareDenyWrite = 0x00000020,
            ShareDenyRead = 0x00000030,
            ShareDenyNone = 0x00000040,
            Parse = 0x00000100,
            Delete = 0x00000200,
            Verify = 0x00000400,
            Cancel = 0x00000800,
            Create = 0x00001000,
            Prompt = 0x00002000,
            Exist = 0x00004000,
            Reopen = 0x00008000
        }
        #endregion

        #region Structs
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private struct RECT
        {
            [MarshalAs(UnmanagedType.I4)]
            public int left;
            [MarshalAs(UnmanagedType.I4)]
            public int top;
            [MarshalAs(UnmanagedType.I4)]
            public int right;
            [MarshalAs(UnmanagedType.I4)]
            public int bottom;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
        private struct AVISTREAMINFO
        {
            [MarshalAs(UnmanagedType.I4)]
            public int fccType;
            [MarshalAs(UnmanagedType.I4)]
            public int fccHandler;
            [MarshalAs(UnmanagedType.I4)]
            public int dwFlags;
            [MarshalAs(UnmanagedType.I4)]
            public int dwCaps;
            [MarshalAs(UnmanagedType.I2)]
            public short wPriority;
            [MarshalAs(UnmanagedType.I2)]
            public short wLanguage;
            [MarshalAs(UnmanagedType.I4)]
            public int dwScale;
            [MarshalAs(UnmanagedType.I4)]
            public int dwRate;		// dwRate / dwScale == samples/second
            [MarshalAs(UnmanagedType.I4)]
            public int dwStart;
            [MarshalAs(UnmanagedType.I4)]
            public int dwLength;
            [MarshalAs(UnmanagedType.I4)]
            public int dwInitialFrames;
            [MarshalAs(UnmanagedType.I4)]
            public int dwSuggestedBufferSize;
            [MarshalAs(UnmanagedType.I4)]
            public int dwQuality;
            [MarshalAs(UnmanagedType.I4)]
            public int dwSampleSize;
            [MarshalAs(UnmanagedType.Struct, SizeConst = 16)]
            public RECT rcFrame;
            [MarshalAs(UnmanagedType.I4)]
            public int dwEditCount;
            [MarshalAs(UnmanagedType.I4)]
            public int dwFormatChangeCount;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string szName;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private struct BITMAPINFOHEADER
        {
            [MarshalAs(UnmanagedType.I4)]
            public int biSize;
            [MarshalAs(UnmanagedType.I4)]
            public int biWidth;
            [MarshalAs(UnmanagedType.I4)]
            public int biHeight;
            [MarshalAs(UnmanagedType.I2)]
            public short biPlanes;
            [MarshalAs(UnmanagedType.I2)]
            public short biBitCount;
            [MarshalAs(UnmanagedType.I4)]
            public int biCompression;
            [MarshalAs(UnmanagedType.I4)]
            public int biSizeImage;
            [MarshalAs(UnmanagedType.I4)]
            public int biXPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            public int biYPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            public int biClrUsed;
            [MarshalAs(UnmanagedType.I4)]
            public int biClrImportant;
        }
        #endregion

        #region API
        [DllImport("avifil32.dll")]
        private static extern void AVIFileInit();

        [DllImport("avifil32.dll")]
        private static extern void AVIFileExit();

        [DllImport("avifil32.dll", CharSet = CharSet.Unicode)]
        private static extern int AVIFileOpen(out IntPtr ppfile, String szFile, OpenFileMode mode, IntPtr pclsidHandler);

        [DllImport("avifil32.dll")]
        private static extern int AVIFileGetStream(IntPtr pfile, out IntPtr ppavi, int fccType, int lParam);

        [DllImport("avifil32.dll", CharSet = CharSet.Unicode)]
        private static extern int AVIStreamInfo(IntPtr pavi, ref AVISTREAMINFO psi,int lSize);

        [DllImport("avifil32.dll")]
        private static extern IntPtr AVIStreamGetFrameOpen(IntPtr pavi, ref BITMAPINFOHEADER lpbiWanted);
        [DllImport("avifil32.dll")]
        private static extern IntPtr AVIStreamGetFrameOpen(IntPtr pavi, int lpbiWanted);

        [DllImport("avifil32.dll")]
        private static extern int AVIStreamGetFrameClose(IntPtr pget);

        [DllImport("avifil32.dll")]
        private static extern int AVIStreamRelease(IntPtr pavi);

        [DllImport("avifil32.dll")]
        private static extern int AVIFileRelease(IntPtr pfile);

        [DllImport("avifil32.dll")]
        private static extern IntPtr AVIStreamGetFrame(IntPtr pget, int lPos);

        [DllImport("ntdll.dll")]
        private static extern IntPtr memcpy(IntPtr dst, IntPtr src, int count);
        [DllImport("ntdll.dll")]
        private static extern int memcpy(int dst, int src, int count);
        #endregion

        #region Fields
        private IntPtr	_hFile;
		private IntPtr	_pStream;
		private IntPtr	_pFrame;
		private int		_iFrameWidth;
		private int		_iFrameHeight;
		private int		_iPosition;
		private int		_iStart;
		private int		_iLength;
		private float	_fRate;
		private string	_sCodec;
        #endregion

        #region Constructor
        public AviReader()
        {
            AVIFileInit();
        }

        ~AviReader()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //
            }
            Close();
            AVIFileExit();
        }
        #endregion

        #region Properties
        /// <summary>Width</summary>
        public int Width
        {
            get { return _iFrameWidth; }
        }

        /// <summary>Height</summary>
        public int Height
        {
            get { return _iFrameHeight; }
        }

        /// <summary>FramesRate</summary>
        public float FrameRate
        {
            get { return _fRate; }
        }

        /// <summary>CurrentPosition</summary>
        public int CurrentPosition
        {
            get { return _iPosition; }
            set
            {
                if ((value < _iStart) || (value >= _iStart + _iLength))
                    _iPosition = _iStart;
                else
                    _iPosition = value;
            }
        }

        /// <summary>Length</summary>
        public int Length
        {
            get { return _iLength; }
        }

        /// <summary>Codec</summary>
        public string Codec
        {
            get { return _sCodec; }
        }
        #endregion

        #region Methods
        private static int mmioFOURCC(string str)
        {
            return (
                ((int)(byte)(str[0])) |
                ((int)(byte)(str[1]) << 8) |
                ((int)(byte)(str[2]) << 16) |
                ((int)(byte)(str[3]) << 24));
        }

        private static string decode_mmioFOURCC(int code)
        {
            char[] chs = new char[4];

            for (int i = 0; i < 4; i++)
            {
                chs[i] = (char)(byte)((code >> (i << 3)) & 0xFF);
                if (!char.IsLetterOrDigit(chs[i]))
                    chs[i] = ' ';
            }
            return new string(chs);
        }

		public bool Open(string fname)
		{
			// close previous file
			Close();

			// open file
			if (AVIFileOpen(out _hFile, fname, OpenFileMode.ShareDenyWrite, IntPtr.Zero) != 0)
				throw new ApplicationException("Failed opening file");

			// get first video stream
			if (AVIFileGetStream(_hFile, out _pStream, mmioFOURCC("vids"), 0) != 0)
				throw new ApplicationException("Failed getting video stream");

			// get stream info
			AVISTREAMINFO	info = new AVISTREAMINFO();
			AVIStreamInfo(_pStream, ref info, Marshal.SizeOf(info));

			_iFrameWidth		= info.rcFrame.right;
			_iFrameHeight		= info.rcFrame.bottom;
			_iPosition	= info.dwStart;
			_iStart		= info.dwStart;
			_iLength		= info.dwLength;
			_fRate		= (float) info.dwRate / (float) info.dwScale;
			_sCodec		= decode_mmioFOURCC(info.fccHandler);

			// prepare decompressor
			BITMAPINFOHEADER bih = new BITMAPINFOHEADER();

			bih.biSize			= Marshal.SizeOf(bih.GetType());
			bih.biWidth			= _iFrameWidth;
			bih.biHeight		= _iFrameHeight;
			bih.biPlanes		= 1;
			bih.biBitCount		= 24;
			bih.biCompression	= 0; // BI_RGB

			// get frame open object
			if ((_pFrame = AVIStreamGetFrameOpen(_pStream, ref bih)) == IntPtr.Zero)
			{
				bih.biHeight = -_iFrameHeight;

                if ((_pFrame = AVIStreamGetFrameOpen(_pStream, ref bih)) == IntPtr.Zero)
                    return false;
			}
            return true;
		}

		// Close file
		public void Close()
		{
			// release frame open object
			if (_pFrame != IntPtr.Zero)
			{
				AVIStreamGetFrameClose(_pFrame);
				_pFrame = IntPtr.Zero;
			}
			// release stream
			if (_pStream != IntPtr.Zero)
			{
				AVIStreamRelease(_pStream);
				_pStream = IntPtr.Zero;
			}
			// release file
			if (_hFile != IntPtr.Zero)
			{
				AVIFileRelease(_hFile);
				_hFile = IntPtr.Zero;
			}
		}

		// Get next video frame
		public Bitmap GetNextFrame()
		{
			// get frame at specified position
			IntPtr pdib = AVIStreamGetFrame(_pFrame, _iPosition);
			if (pdib == IntPtr.Zero)
				throw new ApplicationException("Failed getting frame");

			BITMAPINFOHEADER bih;

			// copy BITMAPINFOHEADER from unmanaged memory
			bih = (BITMAPINFOHEADER) Marshal.PtrToStructure(pdib, typeof(BITMAPINFOHEADER));

			// create new bitmap
			Bitmap	bmp = new Bitmap(_iFrameWidth, _iFrameHeight, PixelFormat.Format24bppRgb);

			// lock bitmap data
			BitmapData	bmData = bmp.LockBits(
				new Rectangle(0, 0, _iFrameWidth, _iFrameHeight),
				ImageLockMode.ReadWrite,
				PixelFormat.Format24bppRgb);

			// copy image data
			int srcStride = bmData.Stride;	// width * 3;
			int dstStride = bmData.Stride;

			// check image direction
			if (bih.biHeight > 0)
			{
				// it`s a bottom-top image
				int dst = bmData.Scan0.ToInt32() + dstStride * (_iFrameHeight - 1);
				int src = pdib.ToInt32() + Marshal.SizeOf(typeof(BITMAPINFOHEADER));

				for (int y = 0; y < _iFrameHeight; y++)
				{
					memcpy(dst, src, srcStride);
					dst -= dstStride;
					src += srcStride;
				}
			}
			else
			{
				// it`s a top-bottom image
				int dst = bmData.Scan0.ToInt32();
				int src = pdib.ToInt32() + Marshal.SizeOf(typeof(BITMAPINFOHEADER));

				if (srcStride != dstStride)
				{
					// copy line by line
					for (int y = 0; y < _iFrameHeight; y++)
					{
						memcpy(dst, src, srcStride);
						dst += dstStride;
						src += srcStride;
					}
				}
				else
				{
					// copy the whole image
					memcpy(dst, src, srcStride * _iFrameHeight);
				}
			}

			// unlock bitmap data
			bmp.UnlockBits(bmData);
			_iPosition++;

			return bmp;
		}
        #endregion


    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Network Administrator vtdev.com
Canada Canada
Network and programming specialist. Started in C, and have learned about 14 languages since then. Cisco programmer, and lately writing a lot of C# and WPF code, (learning Java too). If I can dream it up, I can probably put it to code. My software company, (VTDev), is on the verge of releasing a couple of very cool things.. keep you posted.

Comments and Discussions