// AForge Video for Windows Library
// AForge.NET framework
// http://www.aforgenet.com/framework/
//
// Copyright © Andrew Kirillov, 2007-2009
// andrew.kirillov@aforgenet.com
//
//
using System;
using System.Runtime.InteropServices;
using GreenshotPlugin.UnmanagedHelpers;
using System.Collections.Generic;
using System.IO;
namespace Greenshot.Helpers {
///
/// AVI files writing using Video for Windows interface.
///
///
/// The class allows to write AVI files using Video for Windows API.
///
/// Sample usage:
/// /// // 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( );
///
///
///
public class AVIWriter : IDisposable {
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(AVIWriter));
// AVI file
private IntPtr file;
// video stream
private IntPtr stream;
// compressed stream
private IntPtr streamCompressed;
// 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 = null; //"DIB ";
///
/// Width of video frames.
///
///
/// The property specifies the width of video frames, which are acceptable
/// by method for saving, which is set in
/// method.
///
public int Width {
get {
return width;
}
}
///
/// Height of video frames.
///
///
/// The property specifies the height of video frames, which are acceptable
/// by method for saving, which is set in
/// method.
///
public int Height {
get {
return height;
}
}
///
/// Current position in video stream.
///
///
/// The property tell current position in video stream, which actually equals
/// to the amount of frames added using method.
///
public int Position {
get {
return position;
}
}
///
/// Desired playing frame rate.
///
///
/// The property sets the video frame rate, which should be use during playing
/// of the video to be saved.
///
/// The property should be set befor opening new file to take effect.
///
/// Default frame rate is set to 25.
///
public int FrameRate {
get {
return rate;
}
set {
rate = value;
}
}
///
/// Codec used for video compression.
///
///
/// The property sets the FOURCC code of video compression codec, which needs to
/// be used for video encoding.
///
/// The property should be set befor opening new file to take effect.
///
/// Default video codec is set "DIB ", which means no compression.
///
public string Codec {
get {
return codec;
}
set {
codec = value;
}
}
///
/// Compression video quality.
///
///
/// 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.
///
/// The property should be set befor opening new file to take effect.
///
/// Default value is set to -1 - default compression quality of the codec.
///
public int Quality {
get {
return quality;
}
set {
quality = value;
}
}
///
/// Initializes a new instance of the class.
///
///
/// Initializes Video for Windows library.
///
public AVIWriter() {
Avi32.AVIFileInit();
}
///
/// Initializes a new instance of the class.
///
///
/// Codec to use for compression. eg [CVID],[IV50]
///
/// Initializes Video for Windows library.
///
public AVIWriter(string codec)
: this() {
this.codec = codec;
}
///
/// Destroys the instance of the class.
///
///
~AVIWriter() {
Dispose(false);
}
///
/// Dispose the object.
///
///
/// Frees unmanaged resources used by the object. The object becomes unusable
/// after that.
///
public void Dispose() {
Dispose(true);
// remove me from the Finalization queue
GC.SuppressFinalize(this);
}
///
/// Dispose the object.
///
///
/// Indicates if disposing was initiated manually.
///
protected virtual void Dispose(bool disposing) {
if (disposing) {
// dispose managed resources
}
// close current AVI file if any opened and uninitialize AVI library
Close();
Avi32.AVIFileExit();
}
///
/// Create new AVI file and open it for writing.
///
///
/// AVI file name to create.
/// Video width.
/// Video height.
///
/// The method opens (creates) a video files, configure video codec and prepares
/// the stream for saving video frames with a help of method.
///
/// Failure of opening video files (the exception message
/// specifies the issues).
///
public bool Open(string fileName, int width, int height) {
lock (this) {
// calculate stride
stride = width * 4;
if ((stride % 4) != 0) {
stride += (4 - stride % 4);
}
this.width = width;
this.height = height;
// describe new stream
Avi32.AVISTREAMINFO info = new Avi32.AVISTREAMINFO();
LOG.InfoFormat("Available codecs: {0}", String.Join(", ", Avi32.AvailableCodecs.ToArray()));
info.type = Avi32.mmioFOURCC("vids");
if (codec != null) {
info.handler = Avi32.mmioFOURCC(codec);
} else {
info.handler = Avi32.mmioFOURCC("DIB ");
}
info.scale = 1;
info.rate = rate;
info.suggestedBufferSize = stride * height;
try {
// create new file
if (Avi32.AVIFileOpen(out file, fileName, Avi32.OpenFileMode.Create | Avi32.OpenFileMode.Write, IntPtr.Zero) != 0) {
throw new ApplicationException("Failed opening file");
}
// create stream
if (Avi32.AVIFileCreateStream(file, out stream, ref info) != 0) {
throw new ApplicationException("Failed creating stream");
}
// describe compression options
Avi32.AVICOMPRESSOPTIONS options = new Avi32.AVICOMPRESSOPTIONS();
// uncomment if video settings dialog is required to show
int retCode = 0;
if (codec == null) {
retCode = Avi32.AVISaveOptions(stream, ref options);
if (retCode == 0) {
LOG.Debug("Cancel clicked!");
return false;
}
codec = Avi32.decode_mmioFOURCC(options.handler);
quality = options.quality;
} else {
options.handler = Avi32.mmioFOURCC(codec);
options.quality = quality;
}
LOG.DebugFormat("Codec {0} selected with quality {1}.", codec, quality);
AviError retval;
// create compressed stream
try {
retval = Avi32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero);
} catch (Exception exCompress) {
LOG.Warn("Couldn't use compressed stream.", exCompress);
retval = AviError.AVIERR_OK;
}
if (retval != AviError.AVIERR_OK) {
throw new ApplicationException(string.Format("Failed creating compressed stream: {0}", retval));
}
// describe frame format
BitmapInfoHeader bitmapInfoHeader = new BitmapInfoHeader(width, height, 32);
// set frame format
if (streamCompressed != IntPtr.Zero) {
retval = Avi32.AVIStreamSetFormat(streamCompressed, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType()));
} else {
retval = Avi32.AVIStreamSetFormat(stream, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType()));
}
if (retval != 0) {
throw new ApplicationException(string.Format("Failed creating stream: {0}", retval));
}
position = 0;
return true;
} catch (Exception ex) {
Close();
Avi32.AVIFileExit();
if (File.Exists(fileName)) {
File.Delete(fileName);
}
throw ex;
}
}
}
///
/// Close video file.
///
///
public void Close() {
LOG.Debug("Close called");
lock (this) {
// release compressed stream
if (streamCompressed != IntPtr.Zero) {
LOG.Debug("AVIStreamRelease streamCompressed");
Avi32.AVIStreamRelease(streamCompressed);
streamCompressed = IntPtr.Zero;
}
// release stream
if (stream != IntPtr.Zero) {
LOG.Debug("AVIStreamRelease stream");
Avi32.AVIStreamRelease(stream);
stream = IntPtr.Zero;
}
// release file
if (file != IntPtr.Zero) {
LOG.Debug("AVIFileRelease file");
Avi32.AVIFileRelease(file);
file = IntPtr.Zero;
}
}
}
public void AddEmptyFrames(int frames) {
lock (this) {
position += frames;
}
}
///
/// Add new frame to the AVI file.
///
/// New frame data.
public void AddLowLevelFrame(IntPtr frameData) {
lock (this) {
// write to stream
if (Avi32.AVIStreamWrite(streamCompressed, position, 1, frameData, stride * height, 0, IntPtr.Zero, IntPtr.Zero) != 0) {
throw new ApplicationException("Failed adding frame");
}
position++;
}
}
}
///
/// Windows API functions and structures.
///
///
/// The class provides Video for Windows and some other Avi32 functions and structurs.
///
internal static class Avi32 {
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(Avi32));
[DllImport("MSVFW32", CharSet = CharSet.Ansi)]
static extern bool ICInfo(int fccType, int fccHandler, ref ICINFO lpicinfo);
[DllImport("MSVFW32"), PreserveSig]
static extern IntPtr ICOpen(int fccType, int fccHandler, ICMODE wMode);
[DllImport("MSVFW32")]
static extern int ICClose(IntPtr hic);
[DllImport("MSVFW32", CharSet = CharSet.Ansi)]
static extern int ICGetInfo(IntPtr hic, ref ICINFO lpicinfo, int cb);
// --- Video for Windows Functions
///
/// Initialize the AVIFile library.
///
///
[DllImport("avifil32")]
public static extern void AVIFileInit();
///
/// Exit the AVIFile library.
///
[DllImport("avifil32")]
public static extern void AVIFileExit();
///
/// Open an AVI file.
///
///
/// Opened AVI file interface.
/// AVI file name.
/// Opening mode (see ).
/// Handler to use (null to use default).
///
/// Returns zero on success or error code otherwise.
///
[DllImport("avifil32", CharSet = CharSet.Unicode)]
public static extern AviError AVIFileOpen(out IntPtr aviHandler, String fileName, OpenFileMode mode, IntPtr handler);
///
/// Release an open AVI stream.
///
///
/// Open AVI file interface.
///
/// Returns the reference count of the file.
///
[DllImport("avifil32")]
public static extern int AVIFileRelease(IntPtr aviHandler);
///
/// Get stream interface that is associated with a specified AVI file
///
///
/// Handler to an open AVI file.
/// Stream interface.
/// Stream type to open.
/// Count of the stream type. Identifies which occurrence of the specified stream type to access.
///
///
///
[DllImport("avifil32")]
public static extern int AVIFileGetStream(IntPtr aviHandler, out IntPtr streamHandler, int streamType, int streamNumner);
///
/// Create a new stream in an existing file and creates an interface to the new stream.
///
///
/// Handler to an open AVI file.
/// Stream interface.
/// Pointer to a structure containing information about the new stream.
///
/// Returns zero if successful or an error otherwise.
///
[DllImport("avifil32")]
public static extern int AVIFileCreateStream(IntPtr aviHandler, out IntPtr streamHandler, ref AVISTREAMINFO streamInfo);
///
/// Release an open AVI stream.
///
///
/// Handle to an open stream.
///
/// Returns the current reference count of the stream.
///
[DllImport("avifil32")]
public static extern int AVIStreamRelease(IntPtr streamHandler);
///
/// Set the format of a stream at the specified position.
///
///
/// Handle to an open stream.
/// Position in the stream to receive the format.
/// Pointer to a structure containing the new format.
/// Size, in bytes, of the block of memory referenced by format.
///
/// Returns zero if successful or an error otherwise.
///
[DllImport("avifil32")]
public static extern AviError AVIStreamSetFormat(IntPtr streamHandler, int position, ref BitmapInfoHeader format, int formatSize);
///
/// Get the starting sample number for the stream.
///
///
/// Handle to an open stream.
///
/// Returns the number if successful or – 1 otherwise.
///
[DllImport("avifil32")]
public static extern int AVIStreamStart(IntPtr streamHandler);
///
/// Get the length of the stream.
///
/// Handle to an open stream.
/// Returns the stream's length, in samples, if successful or -1 otherwise.
[DllImport("avifil32")]
public static extern int AVIStreamLength(IntPtr streamHandler);
///
/// Obtain stream header information.
///
///
/// Handle to an open stream.
/// Pointer to a structure to contain the stream information.
/// Size, in bytes, of the structure used for streamInfo.
///
/// Returns zero if successful or an error otherwise.
///
[DllImport("avifil32", CharSet = CharSet.Unicode)]
public static extern int AVIStreamInfo(IntPtr streamHandler, ref AVISTREAMINFO streamInfo, int infoSize);
///
/// Prepare to decompress video frames from the specified video stream
///
/// Pointer to the video stream used as the video source.
/// Pointer to a structure that defines the desired video format. Specify NULL to use a default format.
/// Returns an object that can be used with the function.
[DllImport("avifil32")]
public static extern IntPtr AVIStreamGetFrameOpen(IntPtr streamHandler, ref BitmapInfoHeader wantedFormat);
///
/// Prepare to decompress video frames from the specified video stream.
///
/// Pointer to the video stream used as the video source.
/// Pointer to a structure that defines the desired video format. Specify NULL to use a default format.
/// Returns a GetFrame object that can be used with the function.
[DllImport("avifil32")]
public static extern IntPtr AVIStreamGetFrameOpen(IntPtr streamHandler, int wantedFormat);
///
/// Releases resources used to decompress video frames.
///
/// Handle returned from the function.
/// Returns zero if successful or an error otherwise.
[DllImport("avifil32")]
public static extern int AVIStreamGetFrameClose(IntPtr getFrameObject);
///
/// Return the address of a decompressed video frame.
///
/// Pointer to a GetFrame object.
/// Position, in samples, within the stream of the desired frame.
/// Returns a pointer to the frame data if successful or NULL otherwise.
[DllImport("avifil32")]
public static extern IntPtr AVIStreamGetFrame(IntPtr getFrameObject, int position);
///
/// Write data to a stream.
///
/// Handle to an open stream.
/// First sample to write.
/// Number of samples to write.
/// Pointer to a buffer containing the data to write.
/// Size of the buffer referenced by buffer.
/// Flag associated with this data.
/// Pointer to a buffer that receives the number of samples written. This can be set to NULL.
/// Pointer to a buffer that receives the number of bytes written. This can be set to NULL.
///
/// Returns zero if successful or an error otherwise.
///
[DllImport("avifil32")]
public static extern AviError AVIStreamWrite(IntPtr streamHandler, int start, int samples, IntPtr buffer, int bufferSize, int flags, IntPtr samplesWritten, IntPtr bytesWritten);
///
/// Retrieve the save options for a file and returns them in a buffer.
///
/// Handle to the parent window for the Compression Options dialog box.
/// Flags for displaying the Compression Options dialog box.
/// Number of streams that have their options set by the dialog box.
/// Pointer to an array of stream interface pointers.
/// Pointer to an array of pointers to AVICOMPRESSOPTIONS structures.
/// Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise.
[DllImport("avifil32")]
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);
///
/// Free the resources allocated by the AVISaveOptions function.
///
/// Count of the AVICOMPRESSOPTIONS structures referenced in options.
/// Pointer to an array of pointers to AVICOMPRESSOPTIONS structures.
/// Returns 0.
[DllImport("avifil32")]
public static extern AviError AVISaveOptionsFree(int streams, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] options);
///
/// Create a compressed stream from an uncompressed stream and a
/// compression filter, and returns the address of a pointer to
/// the compressed stream.
///
/// Pointer to a buffer that receives the compressed stream pointer.
/// Pointer to the stream to be compressed.
/// Pointer to a structure that identifies the type of compression to use and the options to apply.
/// Pointer to a class identifier used to create the stream.
/// Returns 0 if successful or an error otherwise.
[DllImport("avifil32")]
public static extern AviError AVIMakeCompressedStream(out IntPtr compressedStream, IntPtr sourceStream, ref AVICOMPRESSOPTIONS options, IntPtr clsidHandler);
///
/// Code type
///
public enum ICMODE {
ICMODE_COMPRESS = 1,
ICMODE_DECOMPRESS = 2,
ICMODE_FASTDECOMPRESS = 3,
ICMODE_QUERY = 4,
ICMODE_FASTCOMPRESS = 5,
ICMODE_DRAW = 8
}
// --- structures
///
/// Structor for the codec info
/// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dd743162%28v=vs.85%29.aspx
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ICINFO {
public int dwSize;
public int fccType;
public int fccHandler;
public int dwFlags;
public int dwVersion;
public int dwVersionICM;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string szName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szDriver;
public ICINFO(int type) {
dwSize = Marshal.SizeOf(typeof(ICINFO));
fccType = type;
fccHandler = 0;
dwFlags = 0;
dwVersion = 0;
dwVersionICM = 0;
szName = null;
szDescription = null;
szDriver = null;
}
}
///
/// Structure, which contains information for a single stream .
///
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
public struct AVISTREAMINFO {
///
/// Four-character code indicating the stream type.
///
///
[MarshalAs(UnmanagedType.I4)]
public int type;
///
/// Four-character code of the compressor handler that will compress this video stream when it is saved.
///
///
[MarshalAs(UnmanagedType.I4)]
public int handler;
///
/// Applicable flags for the stream.
///
///
[MarshalAs(UnmanagedType.I4)]
public int flags;
///
/// Capability flags; currently unused.
///
///
[MarshalAs(UnmanagedType.I4)]
public int ñapabilities;
///
/// Priority of the stream.
///
///
[MarshalAs(UnmanagedType.I2)]
public short priority;
///
/// Language of the stream.
///
///
[MarshalAs(UnmanagedType.I2)]
public short language;
///
/// Time scale applicable for the stream.
///
///
/// Dividing rate by scale gives the playback rate in number of samples per second.
///
[MarshalAs(UnmanagedType.I4)]
public int scale;
///
/// Rate in an integer format.
///
///
[MarshalAs(UnmanagedType.I4)]
public int rate;
///
/// Sample number of the first frame of the AVI file.
///
///
[MarshalAs(UnmanagedType.I4)]
public int start;
///
/// Length of this stream.
///
///
/// The units are defined by rate and scale.
///
[MarshalAs(UnmanagedType.I4)]
public int length;
///
/// Audio skew. This member specifies how much to skew the audio data ahead of the video frames in interleaved files.
///
///
[MarshalAs(UnmanagedType.I4)]
public int initialFrames;
///
/// Recommended buffer size, in bytes, for the stream.
///
///
[MarshalAs(UnmanagedType.I4)]
public int suggestedBufferSize;
///
/// Quality indicator of the video data in the stream.
///
///
/// Quality is represented as a number between 0 and 10,000.
///
[MarshalAs(UnmanagedType.I4)]
public int quality;
///
/// Size, in bytes, of a single data sample.
///
///
[MarshalAs(UnmanagedType.I4)]
public int sampleSize;
///
/// Dimensions of the video destination rectangle.
///
///
[MarshalAs(UnmanagedType.Struct, SizeConst = 16)]
public RECT rectFrame;
///
/// Number of times the stream has been edited.
///
///
[MarshalAs(UnmanagedType.I4)]
public int editCount;
///
/// Number of times the stream format has changed.
///
///
[MarshalAs(UnmanagedType.I4)]
public int formatChangeCount;
///
/// Description of the stream.
///
///
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string name;
}
///
/// Structure, which contains information about a stream and how it is compressed and saved.
///
///
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AVICOMPRESSOPTIONS {
///
/// Four-character code indicating the stream type.
///
///
[MarshalAs(UnmanagedType.I4)]
public int type;
///
/// Four-character code for the compressor handler that will compress this video stream when it is saved.
///
///
[MarshalAs(UnmanagedType.I4)]
public int handler;
///
/// Maximum period between video key frames.
///
///
[MarshalAs(UnmanagedType.I4)]
public int keyFrameEvery;
///
/// Quality value passed to a video compressor.
///
///
[MarshalAs(UnmanagedType.I4)]
public int quality;
///
/// Video compressor data rate.
///
///
[MarshalAs(UnmanagedType.I4)]
public int bytesPerSecond;
///
/// Flags used for compression.
///
///
[MarshalAs(UnmanagedType.I4)]
public int flags;
///
/// Pointer to a structure defining the data format.
///
///
[MarshalAs(UnmanagedType.I4)]
public int format;
///
/// Size, in bytes, of the data referenced by format.
///
///
[MarshalAs(UnmanagedType.I4)]
public int formatSize;
///
/// Video-compressor-specific data; used internally.
///
///
[MarshalAs(UnmanagedType.I4)]
public int parameters;
///
/// Size, in bytes, of the data referenced by parameters.
///
[MarshalAs(UnmanagedType.I4)]
public int parametersSize;
///
/// Interleave factor for interspersing stream data with data from the first stream.
///
///
[MarshalAs(UnmanagedType.I4)]
public int interleaveEvery;
}
// --- enumerations
///
/// File access modes.
///
///
[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
}
///
/// .NET replacement of mmioFOURCC macros. Converts four characters to code.
///
///
/// Four characters string.
///
/// Returns the code created from provided characters.
///
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));
}
///
/// Inverse to . Converts code to fout characters string.
///
///
/// Code to convert.
///
/// Returns four characters string.
///
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);
}
///
/// Get a list of available codecs.
///
/// List
public static List AvailableCodecs {
get {
List returnValues = new List();
int codecNr = 0;
ICINFO codecInfo = new ICINFO(mmioFOURCC("VIDC"));
bool success = true;
do {
success = ICInfo(codecInfo.fccType, codecNr++, ref codecInfo);
if (success) {
IntPtr hic = ICOpen(codecInfo.fccType, codecInfo.fccHandler, ICMODE.ICMODE_QUERY);
if (hic != IntPtr.Zero) {
ICGetInfo(hic, ref codecInfo, Marshal.SizeOf(codecInfo));
string codecName = decode_mmioFOURCC(codecInfo.fccHandler);
returnValues.Add(codecName);
LOG.DebugFormat("Found codec {0} {4}, with name {1} and description {2}, driver {3}", codecName, codecInfo.szName, codecInfo.szDescription, codecInfo.szDriver, codecInfo.dwVersion);
ICClose(hic);
}
}
} while (success);
return returnValues;
}
}
///
/// Version of for one stream only.
///
///
/// Stream to configure.
/// Stream options.
///
/// Returns TRUE if the user pressed OK, FALSE for CANCEL, or an error otherwise.
///
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;
}
}
///
/// AVI Error Codes
///
[Flags]
public enum AviError : uint {
///
/// Compression is not supported for this type of data.
/// This error might be returned if you try to compress
/// data that is not audio or video.
///
AVIERR_UNSUPPORTED = 0x80044065,
///
/// The file couldn't be read, indicating a corrupt file or an unrecognized format
///
AVIERR_BADFORMAT = 0x80044066,
///
/// There is not enough memory to complete the operation.
///
AVIERR_MEMORY = 0x80044067,
///
///
///
// TODO : Put documentation
AVIERR_INTERNAL = 0x80044068,
///
///
///
// TODO : Put documentation
AVIERR_BADFLAGS = 0x80044069,
///
///
///
// TODO : Put documentation
AVIERR_BADPARAM = 0x8004406A,
///
///
///
// TODO : Put documentation
AVIERR_BADSIZE = 0x8004406B,
///
///
///
// TODO : Put documentation
AVIERR_BADHANDLE = 0x8004406C,
///
/// A disk error occurred while reading the file
///
AVIERR_FILEREAD = 0x8004406D,
///
///
///
// TODO : Put documentation
AVIERR_FILEWRITE = 0x8004406E,
///
/// A disk error occurred while opening the file
///
AVIERR_FILEOPEN = 0x8004406F,
///
///
///
// TODO : Put documentation
AVIERR_COMPRESSOR = 0x80044070,
///
/// A suitable compressor cannot be found.
///
AVIERR_NOCOMPRESSOR = 0x80044071,
///
///
///
// TODO : Put documentation
AVIERR_READONLY = 0x80044072,
///
///
///
// TODO : Put documentation
AVIERR_NODATA = 0x80044073,
///
///
///
// TODO : Put documentation
AVIERR_BUFFERTOOSMALL = 0x80044074,
///
///
///
// TODO : Put documentation
AVIERR_CANTCOMPRESS = 0x80044075,
///
///
///
// TODO : Put documentation
AVIERR_USERABORT = 0x800440C6,
///
///
///
// TODO : Put documentation
AVIERR_ERROR = 0x800440C7,
///
/// Operation successful
///
AVIERR_OK = 0x0
}
}