Find all our projects in development below.
All source code is GNU General Public License (GPL)
Browsing vfw/AVIReader.cs (5.29 KB)
namespace Tiger.Video.VFW
{
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
/// <summary>
/// Reading AVI files using Video for Windows
/// </summary>
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;
}
}
}