AVIWRITER
AForge Video for Windows Library
AVIWriter.cs
// AForge Video for Windows Library // AForge.NET framework // http://www.aforgenet.com/framework/ // // Copyright © Andrew Kirillov, 2007-2009 // [email protected] // // using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; /// <summary> /// AVI files writing using Video for Windows interface. /// </summary> /// /// <remarks><para>The class allows to write AVI files using Video for Windows API.</para> /// /// <para>Sample usage:</para> /// /// // instantiate AVI writer, use WMV3 codec /// AVIWriter writer = new AVIWriter( "wmv3" ); /// // create new AVI file and open it /// writer.Open( "test.avi", 320, 240 ); /// // create frame image /// Bitmap image = new Bitmap( 320, 240 ); /// /// for ( int i = 0; i < 240; i++ ) /// { /// // update image /// image.SetPixel( i, i, Color.Red ); /// // add the image as a new frame of video file /// writer.AddFrame( image ); /// } /// writer.Close( ); /// /// </remarks> /// public class AVIWriter : IDisposable { // AVI file private IntPtr file; // video stream private IntPtr stream; // compressed stream private IntPtr streamCompressed; // buffer private IntPtr buffer = IntPtr.Zero; // width of video frames private int width; // height of vide frames private int height; // length of one line private int stride; // quality private int quality = -1; // frame rate private int rate = 25; // current position private int position; // codec used for video compression private string codec = "DIB "; /// <summary> /// Width of video frames. /// </summary> /// /// <remarks><para>The property specifies the width of video frames, which are acceptable /// by <see cref="AddFrame"/> method for saving, which is set in <see cref="Open"/> /// method.</para></remarks> /// public int Width { get { return (buffer != IntPtr.Zero) ? width : 0; } } /// <summary> /// Height of video frames. /// </summary> /// /// <remarks><para>The property specifies the height of video frames, which are acceptable /// by <see cref="AddFrame"/> method for saving, which is set in <see cref="Open"/> /// method.</para></remarks> /// public int Height { get { return (buffer != IntPtr.Zero) ? height : 0; } } /// <summary> /// Current position in video stream. /// </summary> /// /// <remarks><para>The property tell current position in video stream, which actually equals /// to the amount of frames added using <see cref="AddFrame"/> method.</para></remarks> /// public int Position { get { return position; } } /// <summary> /// Desired playing frame rate. /// </summary> /// /// <remarks><para>The property sets the video frame rate, which should be use during playing /// of the video to be saved.</para> /// /// <para><note>The property should be set befor opening new file to take effect.</note></para> /// /// <para>Default frame rate is set to <b>25</b>.</para></remarks> /// public int FrameRate { get { return rate; } set { rate = value; } } /// <summary> /// Codec used for video compression. /// </summary> /// /// <remarks><para>The property sets the FOURCC code of video compression codec, which needs to /// be used for video encoding.</para> /// /// <para><note>The property should be set befor opening new file to take effect.</note></para> /// /// <para>Default video codec is set <b>"DIB "</b>, which means no compression.</para></remarks> /// public string Codec { get { return codec; } set { codec = value; } } /// <summary> /// Compression video quality. /// </summary> /// /// <remarks><para>The property sets video quality used by codec in order to balance compression rate /// and image quality. The quality is measured usually in the [0, 100] range.</para> /// /// <para><note>The property should be set befor opening new file to take effect.</note></para> /// /// <para>Default value is set to <b>-1</b> - default compression quality of the codec.</para></remarks> /// public int Quality { get { return quality; } set { quality = value; } } /// <summary> /// Initializes a new instance of the <see cref="AVIWriter"/> class. /// </summary> /// /// <remarks>Initializes Video for Windows library.</remarks> /// public AVIWriter() { Win32.AVIFileInit(); } /// <summary> /// Initializes a new instance of the <see cref="AVIWriter"/> class. /// </summary> /// /// <param name="codec">Codec to use for compression. eg [CVID],[IV50]</param> /// /// <remarks>Initializes Video for Windows library.</remarks> /// public AVIWriter(string codec) : this() { this.codec = codec; } /// <summary> /// Destroys the instance of the <see cref="AVIWriter"/> class. /// </summary> /// ~AVIWriter() { Dispose(false); } /// <summary> /// Dispose the object. /// </summary> /// /// <remarks>Frees unmanaged resources used by the object. The object becomes unusable /// after that.</remarks> /// public void Dispose() { Dispose(true); // remove me from the Finalization queue GC.SuppressFinalize(this); } /// <summary> /// Dispose the object. /// </summary> /// /// <param name="disposing">Indicates if disposing was initiated manually.</param> /// protected virtual void Dispose(bool disposing) { if (disposing) { // dispose managed resources } // close current AVI file if any opened and uninitialize AVI library Close(); Win32.AVIFileExit(); } /// <summary> /// Create new AVI file and open it for writing. /// </summary> /// /// <param name="fileName">AVI file name to create.</param> /// <param name="width">Video width.</param> /// <param name="height">Video height.</param> /// /// <remarks><para>The method opens (creates) a video files, configure video codec and prepares /// the stream for saving video frames with a help of <see cref="AddFrame"/> method.</para></remarks> /// /// <exception cref="ApplicationException">Failure of opening video files (the exception message /// specifies the issues).</exception> /// public void Open(string fileName, int width, int height) { // close previous file Close(); lock (this) { // calculate stride stride = width * 3; if ((stride % 4) != 0) stride += (4 - stride % 4); // create new file if (Win32.AVIFileOpen(out file, fileName, Win32.OpenFileMode.Create | Win32.OpenFileMode.Write, IntPtr.Zero) != 0) throw new ApplicationException("Failed opening file"); this.width = width; this.height = height; // describe new stream Win32.AVISTREAMINFO info = new Win32.AVISTREAMINFO(); info.type = Win32.mmioFOURCC("vids"); info.handler = Win32.mmioFOURCC(codec); info.scale = 1; info.rate = rate; info.suggestedBufferSize = stride * height; // create stream if (Win32.AVIFileCreateStream(file, out stream, ref info) != 0) throw new ApplicationException("Failed creating stream"); // describe compression options Win32.AVICOMPRESSOPTIONS options = new Win32.AVICOMPRESSOPTIONS(); options.handler = Win32.mmioFOURCC(codec); options.quality = quality; // uncomment if video settings dialog is required to show // Win32.AVISaveOptions( stream, ref options ); // create compressed stream if (Win32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero) != 0) throw new ApplicationException("Failed creating compressed stream"); // describe frame format Win32.BITMAPINFOHEADER bitmapInfoHeader = new Win32.BITMAPINFOHEADER(); bitmapInfoHeader.size = Marshal.SizeOf(bitmapInfoHeader.GetType()); bitmapInfoHeader.width = width; bitmapInfoHeader.height = height; bitmapInfoHeader.planes = 1; bitmapInfoHeader.bitCount = 24; bitmapInfoHeader.sizeImage = 0; bitmapInfoHeader.compression = 0; // BI_RGB // set frame format if (Win32.AVIStreamSetFormat(streamCompressed, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType())) != 0) throw new ApplicationException("Failed creating compressed stream"); // alloc unmanaged memory for frame buffer = Marshal.AllocHGlobal(stride * height); if (buffer ===== IntPtr.Zero) throw new ApplicationException("Insufficient memory for internal buffer"); position = 0; } } /// <summary> /// Close video file. /// </summary> /// public void Close() { lock (this) { // free unmanaged memory if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); buffer = IntPtr.Zero; } // release compressed stream if (streamCompressed != IntPtr.Zero) { Win32.AVIStreamRelease(streamCompressed); streamCompressed = 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; } } } /// <summary> /// Add new frame to the AVI file. /// </summary> /// /// <param name="frameImage">New frame image.</param> /// /// <remarks><para>The method adds new video frame to an opened video file. The width and heights /// of the frame should be the same as it was specified in <see cref="Open"/> method /// (see <see cref="Width"/> and <see cref="Height"/> properties).</para></remarks> /// /// <exception cref="ApplicationException">Failure of opening video files (the exception message /// specifies the issues).</exception> /// public void AddFrame(Bitmap frameImage) { lock (this) { // check if AVI file was properly opened if (buffer ===== IntPtr.Zero) throw new ApplicationException("AVI file should be successfully opened before writing"); // check image dimension if ((frameImage.Width != width) || (frameImage.Height != height)) throw new ApplicationException("Invalid image dimension"); // lock bitmap data BitmapData imageData = frameImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); // copy image data int srcStride = imageData.Stride; int dstStride = stride; int src = imageData.Scan0.ToInt32() + srcStride * (height - 1); int dst = buffer.ToInt32(); for (int y = 0; y < height; y++) { Win32.memcpy(dst, src, dstStride); dst += dstStride; src -= srcStride; } // unlock bitmap data frameImage.UnlockBits(imageData); // write to stream if (Win32.AVIStreamWrite(streamCompressed, position, 1, buffer, stride * height, 0, IntPtr.Zero, IntPtr.Zero) != 0) throw new ApplicationException("Failed adding frame"); position++; } } }
win32.cs
// AForge Video for Windows Library // AForge.NET framework // http://www.aforgenet.com/framework/ // // Copyright © Andrew Kirillov, 2007-2009 // [email protected] // using System; using System.Runtime.InteropServices; /// <summary> /// Windows API functions and structures. /// </summary> /// /// <remarks>The class provides Video for Windows and some other Win32 functions and structurs.</remarks> /// internal static class Win32 { /// <summary> /// Copy a block of memory. /// </summary> /// /// <param name="dst">Destination pointer.</param> /// <param name="src">Source pointer.</param> /// <param name="count">Memory block's length to copy.</param> /// /// <returns>Return's the value of <b>dst</b> - pointer to destination.</returns> /// [DllImport("ntdll.dll")] public static extern int memcpy( int dst, int src, int count); // --- Video for Windows Functions /// <summary> /// Initialize the AVIFile library. /// </summary> /// [DllImport("avifil32.dll")] public static extern void AVIFileInit(); /// <summary> /// Exit the AVIFile library. /// </summary> [DllImport("avifil32.dll")] public static extern void AVIFileExit(); /// <summary> /// Open an AVI file. /// </summary> /// /// <param name="aviHandler">Opened AVI file interface.</param> /// <param name="fileName">AVI file name.</param> /// <param name="mode">Opening mode (see <see cref="OpenFileMode"/>).</param> /// <param name="handler">Handler to use (<b>null</b> to use default).</param> /// /// <returns>Returns zero on success or error code otherwise.</returns> /// [DllImport("avifil32.dll", CharSet = CharSet.Unicode)] public static extern int AVIFileOpen( out IntPtr aviHandler, String fileName, OpenFileMode mode, IntPtr handler); /// <summary> /// Release an open AVI stream. /// </summary> /// /// <param name="aviHandler">Open AVI file interface.</param> /// /// <returns>Returns the reference count of the file.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIFileRelease( IntPtr aviHandler); /// <summary> /// Get stream interface that is associated with a specified AVI file /// </summary> /// /// <param name="aviHandler">Handler to an open AVI file.</param> /// <param name="streamHandler">Stream interface.</param> /// <param name="streamType">Stream type to open.</param> /// <param name="streamNumner">Count of the stream type. Identifies which occurrence of the specified stream type to access. </param> /// /// <returns></returns> /// [DllImport("avifil32.dll")] public static extern int AVIFileGetStream( IntPtr aviHandler, out IntPtr streamHandler, int streamType, int streamNumner); /// <summary> /// Create a new stream in an existing file and creates an interface to the new stream. /// </summary> /// /// <param name="aviHandler">Handler to an open AVI file.</param> /// <param name="streamHandler">Stream interface.</param> /// <param name="streamInfo">Pointer to a structure containing information about the new stream.</param> /// /// <returns>Returns zero if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIFileCreateStream( IntPtr aviHandler, out IntPtr streamHandler, ref AVISTREAMINFO streamInfo); /// <summary> /// Release an open AVI stream. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// /// <returns>Returns the current reference count of the stream.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamRelease( IntPtr streamHandler); /// <summary> /// Set the format of a stream at the specified position. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// <param name="position">Position in the stream to receive the format.</param> /// <param name="format">Pointer to a structure containing the new format.</param> /// <param name="formatSize">Size, in bytes, of the block of memory referenced by <b>format</b>.</param> /// /// <returns>Returns zero if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamSetFormat( IntPtr streamHandler, int position, ref BITMAPINFOHEADER format, int formatSize); /// <summary> /// Get the starting sample number for the stream. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// /// <returns>Returns the number if successful or – 1 otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamStart( IntPtr streamHandler); /// <summary> /// Get the length of the stream. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// /// <returns>Returns the stream's length, in samples, if successful or -1 otherwise. </returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamLength( IntPtr streamHandler); /// <summary> /// Obtain stream header information. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// <param name="streamInfo">Pointer to a structure to contain the stream information.</param> /// <param name="infoSize">Size, in bytes, of the structure used for <b>streamInfo</b>.</param> /// /// <returns>Returns zero if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll", CharSet = CharSet.Unicode)] public static extern int AVIStreamInfo( IntPtr streamHandler, ref AVISTREAMINFO streamInfo, int infoSize); /// <summary> /// Prepare to decompress video frames from the specified video stream /// </summary> /// /// <param name="streamHandler">Pointer to the video stream used as the video source.</param> /// <param name="wantedFormat">Pointer to a structure that defines the desired video format. Specify NULL to use a default format.</param> /// /// <returns>Returns an object that can be used with the <see cref="AVIStreamGetFrame"/> function.</returns> /// [DllImport("avifil32.dll")] public static extern IntPtr AVIStreamGetFrameOpen( IntPtr streamHandler, ref BITMAPINFOHEADER wantedFormat); /// <summary> /// Prepare to decompress video frames from the specified video stream. /// </summary> /// /// <param name="streamHandler">Pointer to the video stream used as the video source.</param> /// <param name="wantedFormat">Pointer to a structure that defines the desired video format. Specify NULL to use a default format.</param> /// /// <returns>Returns a <b>GetFrame</b> object that can be used with the <see cref="AVIStreamGetFrame"/> function.</returns> /// [DllImport("avifil32.dll")] public static extern IntPtr AVIStreamGetFrameOpen( IntPtr streamHandler, int wantedFormat); /// <summary> /// Releases resources used to decompress video frames. /// </summary> /// /// <param name="getFrameObject">Handle returned from the <see cref="AVIStreamGetFrameOpen(IntPtr,int)"/> function.</param> /// /// <returns>Returns zero if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamGetFrameClose( IntPtr getFrameObject); /// <summary> /// Return the address of a decompressed video frame. /// </summary> /// /// <param name="getFrameObject">Pointer to a GetFrame object.</param> /// <param name="position">Position, in samples, within the stream of the desired frame.</param> /// /// <returns>Returns a pointer to the frame data if successful or NULL otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern IntPtr AVIStreamGetFrame( IntPtr getFrameObject, int position); /// <summary> /// Write data to a stream. /// </summary> /// /// <param name="streamHandler">Handle to an open stream.</param> /// <param name="start">First sample to write.</param> /// <param name="samples">Number of samples to write.</param> /// <param name="buffer">Pointer to a buffer containing the data to write. </param> /// <param name="bufferSize">Size of the buffer referenced by <b>buffer</b>.</param> /// <param name="flags">Flag associated with this data.</param> /// <param name="samplesWritten">Pointer to a buffer that receives the number of samples written. This can be set to NULL.</param> /// <param name="bytesWritten">Pointer to a buffer that receives the number of bytes written. This can be set to NULL.</param> /// /// <returns>Returns zero if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIStreamWrite( IntPtr streamHandler, int start, int samples, IntPtr buffer, int bufferSize, int flags, IntPtr samplesWritten, IntPtr bytesWritten); /// <summary> /// Retrieve the save options for a file and returns them in a buffer. /// </summary> /// /// <param name="window">Handle to the parent window for the Compression Options dialog box.</param> /// <param name="flags">Flags for displaying the Compression Options dialog box.</param> /// <param name="streams">Number of streams that have their options set by the dialog box.</param> /// <param name="streamInterfaces">Pointer to an array of stream interface pointers.</param> /// <param name="options">Pointer to an array of pointers to AVICOMPRESSOPTIONS structures.</param> /// /// <returns>Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVISaveOptions( IntPtr window, int flags, int streams, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] streamInterfaces, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] options); /// <summary> /// Free the resources allocated by the AVISaveOptions function. /// </summary> /// /// <param name="streams">Count of the AVICOMPRESSOPTIONS structures referenced in <b>options</b>.</param> /// <param name="options">Pointer to an array of pointers to AVICOMPRESSOPTIONS structures.</param> /// /// <returns>Returns 0.</returns> /// [DllImport("avifil32.dll")] public static extern int AVISaveOptionsFree( int streams, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] options); /// <summary> /// Create a compressed stream from an uncompressed stream and a /// compression filter, and returns the address of a pointer to /// the compressed stream. /// </summary> /// /// <param name="compressedStream">Pointer to a buffer that receives the compressed stream pointer.</param> /// <param name="sourceStream">Pointer to the stream to be compressed.</param> /// <param name="options">Pointer to a structure that identifies the type of compression to use and the options to apply.</param> /// <param name="clsidHandler">Pointer to a class identifier used to create the stream.</param> /// /// <returns>Returns 0 if successful or an error otherwise.</returns> /// [DllImport("avifil32.dll")] public static extern int AVIMakeCompressedStream( out IntPtr compressedStream, IntPtr sourceStream, ref AVICOMPRESSOPTIONS options, IntPtr clsidHandler); // --- structures /// <summary> /// Structure to define the coordinates of the upper-left and /// lower-right corners of a rectangle. /// </summary> /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct RECT { /// <summary> /// x-coordinate of the upper-left corner of the rectangle. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int left; /// <summary> /// y-coordinate of the upper-left corner of the rectangle. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int top; /// <summary> /// x-coordinate of the bottom-right corner of the rectangle. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int right; /// <summary> /// y-coordinate of the bottom-right corner of the rectangle. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int bottom; } /// <summary> /// Structure, which contains information for a single stream . /// </summary> /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)] public struct AVISTREAMINFO { /// <summary> /// Four-character code indicating the stream type. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int type; /// <summary> /// Four-character code of the compressor handler that will compress this video stream when it is saved. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int handler; /// <summary> /// Applicable flags for the stream. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int flags; /// <summary> /// Capability flags; currently unused. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int ñapabilities; /// <summary> /// Priority of the stream. /// </summary> /// [MarshalAs(UnmanagedType.I2)] public short priority; /// <summary> /// Language of the stream. /// </summary> /// [MarshalAs(UnmanagedType.I2)] public short language; /// <summary> /// Time scale applicable for the stream. /// </summary> /// /// <remarks>Dividing <b>rate</b> by <b>scale</b> gives the playback rate in number of samples per second.</remarks> /// [MarshalAs(UnmanagedType.I4)] public int scale; /// <summary> /// Rate in an integer format. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int rate; /// <summary> /// Sample number of the first frame of the AVI file. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int start; /// <summary> /// Length of this stream. /// </summary> /// /// <remarks>The units are defined by <b>rate</b> and <b>scale</b>.</remarks> /// [MarshalAs(UnmanagedType.I4)] public int length; /// <summary> /// Audio skew. This member specifies how much to skew the audio data ahead of the video frames in interleaved files. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int initialFrames; /// <summary> /// Recommended buffer size, in bytes, for the stream. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int suggestedBufferSize; /// <summary> /// Quality indicator of the video data in the stream. /// </summary> /// /// <remarks>Quality is represented as a number between 0 and 10,000.</remarks> /// [MarshalAs(UnmanagedType.I4)] public int quality; /// <summary> /// Size, in bytes, of a single data sample. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int sampleSize; /// <summary> /// Dimensions of the video destination rectangle. /// </summary> /// [MarshalAs(UnmanagedType.Struct, SizeConst = 16)] public RECT rectFrame; /// <summary> /// Number of times the stream has been edited. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int editCount; /// <summary> /// Number of times the stream format has changed. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int formatChangeCount; /// <summary> /// Description of the stream. /// </summary> /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string name; } /// <summary> /// Structure, which contains information about the dimensions and color format of a DIB. /// </summary> /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BITMAPINFOHEADER { /// <summary> /// Specifies the number of bytes required by the structure. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int size; /// <summary> /// Specifies the width of the bitmap, in pixels. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int width; /// <summary> /// Specifies the height of the bitmap, in pixels. /// </summary> /// /// <remarks>If <b>heigh</b>t is positive, the bitmap is a bottom-up DIB and its origin is /// the lower-left corner. If <b>height</b> is negative, the bitmap is a top-down DIB and its /// origin is the upper-left corner.</remarks> /// [MarshalAs(UnmanagedType.I4)] public int height; /// <summary> /// Specifies the number of planes for the target device. This value must be set to 1. /// </summary> /// [MarshalAs(UnmanagedType.I2)] public short planes; /// <summary> /// Specifies the number of bits-per-pixel. /// </summary> /// [MarshalAs(UnmanagedType.I2)] public short bitCount; /// <summary> /// Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int compression; /// <summary> /// Specifies the size, in bytes, of the image. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int sizeImage; /// <summary> /// Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int xPelsPerMeter; /// <summary> /// Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int yPelsPerMeter; /// <summary> /// Specifies the number of color indexes in the color table that are actually used by the bitmap. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int colorsUsed; /// <summary> /// Specifies the number of color indexes that are required for displaying the bitmap. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int colorsImportant; } /// <summary> /// Structure, which contains information about a stream and how it is compressed and saved. /// </summary> /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct AVICOMPRESSOPTIONS { /// <summary> /// Four-character code indicating the stream type. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int type; /// <summary> /// Four-character code for the compressor handler that will compress this video stream when it is saved. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int handler; /// <summary> /// Maximum period between video key frames. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int keyFrameEvery; /// <summary> /// Quality value passed to a video compressor. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int quality; /// <summary> /// Video compressor data rate. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int bytesPerSecond; /// <summary> /// Flags used for compression. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int flags; /// <summary> /// Pointer to a structure defining the data format. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int format; /// <summary> /// Size, in bytes, of the data referenced by <b>format</b>. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int formatSize; /// <summary> /// Video-compressor-specific data; used internally. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int parameters; /// <summary> /// Size, in bytes, of the data referenced by <b>parameters</b>. /// </summary> [MarshalAs(UnmanagedType.I4)] public int parametersSize; /// <summary> /// Interleave factor for interspersing stream data with data from the first stream. /// </summary> /// [MarshalAs(UnmanagedType.I4)] public int interleaveEvery; } // --- enumerations /// <summary> /// File access modes. /// </summary> /// [Flags] public 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 } /// <summary> /// .NET replacement of mmioFOURCC macros. Converts four characters to code. /// </summary> /// /// <param name="str">Four characters string.</param> /// /// <returns>Returns the code created from provided characters.</returns> /// public 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)); } /// <summary> /// Inverse to <see cref="mmioFOURCC"/>. Converts code to fout characters string. /// </summary> /// /// <param name="code">Code to convert.</param> /// /// <returns>Returns four characters string.</returns> /// public 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); } /// <summary> /// Version of <see cref="AVISaveOptions(IntPtr, int, int, IntPtr[], IntPtr[])"/> for one stream only. /// </summary> /// /// <param name="stream">Stream to configure.</param> /// <param name="options">Stream options.</param> /// /// <returns>Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise.</returns> /// public static int AVISaveOptions(IntPtr stream, ref AVICOMPRESSOPTIONS options) { IntPtr[] streams = new IntPtr[1]; IntPtr[] infPtrs = new IntPtr[1]; IntPtr mem; int ret; // alloc unmanaged memory mem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(AVICOMPRESSOPTIONS))); // copy from managed structure to unmanaged memory Marshal.StructureToPtr(options, mem, false); streams[0] = stream; infPtrs[0] = mem; // show dialog with a list of available compresors and configuration ret = AVISaveOptions(IntPtr.Zero, 0, 1, streams, infPtrs); // copy from unmanaged memory to managed structure options = (AVICOMPRESSOPTIONS)Marshal.PtrToStructure(mem, typeof(AVICOMPRESSOPTIONS)); // free AVI compression options AVISaveOptionsFree(1, infPtrs); // clear it, because the information already freed by AVISaveOptionsFree options.format = 0; options.parameters = 0; // free unmanaged memory Marshal.FreeHGlobal(mem); return ret; } }
====