www.pudn.com > motion.zip > AVIReader.cs


namespace Tiger.Video.VFW 
{ 
	using System; 
	using System.Drawing; 
	using System.Drawing.Imaging; 
	using System.Runtime.InteropServices; 
 
	///  
	/// Reading AVI files using Video for Windows 
	///  
	public class AVIReader : IDisposable 
	{ 
		private IntPtr	file; 
		private IntPtr	stream; 
		private IntPtr	getFrame; 
 
		private int		width; 
		private int		height; 
		private int		position; 
		private int		start; 
		private int		length; 
		private float	rate; 
		private string	codec; 
 
		// Width property 
		public int Width 
		{ 
			get { return width; } 
		} 
		// Height property 
		public int Height 
		{ 
			get { return height; } 
		} 
		// FramesRate property 
		public float FrameRate 
		{ 
			get { return rate; } 
		} 
		// CurrentPosition property 
		public int CurrentPosition 
		{ 
			get { return position; } 
			set 
			{ 
				if ((value < start) || (value >= start + length)) 
					position = start; 
				else 
					position = value; 
			} 
		} 
		// Length property 
		public int Length 
		{ 
			get { return length; } 
		} 
		// Codec property 
		public string Codec 
		{ 
			get { return codec; } 
		} 
 
 
		// Constructor 
		public AVIReader() 
		{ 
			Win32.AVIFileInit(); 
		} 
 
		// Desctructor 
		~AVIReader() 
		{ 
			Dispose(false); 
		} 
 
		// Free all unmanaged resources 
		public void Dispose() 
		{ 
			Dispose(true); 
			// Remove me from the Finalization queue  
			GC.SuppressFinalize(this); 
		} 
 
		protected virtual void Dispose(bool disposing) 
		{ 
			if (disposing) 
			{ 
				// Dispose managed resources 
				 
				// there is nothing managed yet 
			} 
			Close(); 
			Win32.AVIFileExit(); 
		} 
 
		// Open an AVI file 
		public void Open(string fname) 
		{ 
			// close previous file 
			Close(); 
 
			// open file 
			if (Win32.AVIFileOpen(out file, fname, Win32.OpenFileMode.ShareDenyWrite, IntPtr.Zero) != 0) 
				throw new ApplicationException("Failed opening file"); 
 
			// get first video stream 
			if (Win32.AVIFileGetStream(file, out stream, Win32.mmioFOURCC("vids"), 0) != 0) 
				throw new ApplicationException("Failed getting video stream"); 
 
			// get stream info 
			Win32.AVISTREAMINFO	info = new Win32.AVISTREAMINFO(); 
			Win32.AVIStreamInfo(stream, ref info, Marshal.SizeOf(info)); 
 
			width		= info.rcFrame.right; 
			height		= info.rcFrame.bottom; 
			position	= info.dwStart; 
			start		= info.dwStart; 
			length		= info.dwLength; 
			rate		= (float) info.dwRate / (float) info.dwScale; 
			codec		= Win32.decode_mmioFOURCC(info.fccHandler); 
 
			// prepare decompressor 
			Win32.BITMAPINFOHEADER bih = new Win32.BITMAPINFOHEADER(); 
 
			bih.biSize			= Marshal.SizeOf(bih.GetType()); 
			bih.biWidth			= width; 
			bih.biHeight		= height; 
			bih.biPlanes		= 1; 
			bih.biBitCount		= 24; 
			bih.biCompression	= 0; // BI_RGB 
 
			// get frame open object 
			if ((getFrame = Win32.AVIStreamGetFrameOpen(stream, ref bih)) == IntPtr.Zero) 
			{ 
				bih.biHeight = -height; 
 
				if ((getFrame = Win32.AVIStreamGetFrameOpen(stream, ref bih)) == IntPtr.Zero) 
					throw new ApplicationException("Failed initializing decompressor"); 
			} 
		} 
 
		// Close file 
		public void Close() 
		{ 
			// release frame open object 
			if (getFrame != IntPtr.Zero) 
			{ 
				Win32.AVIStreamGetFrameClose(getFrame); 
				getFrame = IntPtr.Zero; 
			} 
			// release stream 
			if (stream != IntPtr.Zero) 
			{ 
				Win32.AVIStreamRelease(stream); 
				stream = IntPtr.Zero; 
			} 
			// release file 
			if (file != IntPtr.Zero) 
			{ 
				Win32.AVIFileRelease(file); 
				file = IntPtr.Zero; 
			} 
		} 
 
		// Get next video frame 
		public Bitmap GetNextFrame() 
		{ 
			// get frame at specified position 
			IntPtr pdib = Win32.AVIStreamGetFrame(getFrame, position); 
			if (pdib == IntPtr.Zero) 
				throw new ApplicationException("Failed getting frame"); 
 
			Win32.BITMAPINFOHEADER bih; 
 
			// copy BITMAPINFOHEADER from unmanaged memory 
			bih = (Win32.BITMAPINFOHEADER) Marshal.PtrToStructure(pdib, typeof(Win32.BITMAPINFOHEADER)); 
 
			// create new bitmap 
			Bitmap	bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 
 
			// lock bitmap data 
			BitmapData	bmData = bmp.LockBits( 
				new Rectangle(0, 0, width, height), 
				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 * (height - 1); 
				int src = pdib.ToInt32() + Marshal.SizeOf(typeof(Win32.BITMAPINFOHEADER)); 
 
				for (int y = 0; y < height; y++) 
				{ 
					Win32.memcpy(dst, src, srcStride); 
					dst -= dstStride; 
					src += srcStride; 
				} 
			} 
			else 
			{ 
				// it`s a top bootom image 
				int dst = bmData.Scan0.ToInt32(); 
				int src = pdib.ToInt32() + Marshal.SizeOf(typeof(Win32.BITMAPINFOHEADER)); 
 
				if (srcStride != dstStride) 
				{ 
					// copy line by line 
					for (int y = 0; y < height; y++) 
					{ 
						Win32.memcpy(dst, src, srcStride); 
						dst += dstStride; 
						src += srcStride; 
					} 
				} 
				else 
				{ 
					// copy the whole image 
					Win32.memcpy(dst, src, srcStride * height); 
				} 
			} 
 
			// unlock bitmap data 
			bmp.UnlockBits(bmData); 
 
			position++; 
 
			return bmp; 
		} 
	} 
}