diff --git a/Greenshot/Helpers/AviHelper.cs b/Greenshot/Helpers/AviHelper.cs
index ba8b623cb..29b307ae8 100644
--- a/Greenshot/Helpers/AviHelper.cs
+++ b/Greenshot/Helpers/AviHelper.cs
@@ -12,314 +12,355 @@ using System.Drawing.Imaging;
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( );
- ///
+
+ ///
+ /// 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);
-
- // create new file
- if (Avi32.AVIFileOpen(out file, fileName, Avi32.OpenFileMode.Create | Avi32.OpenFileMode.Write, IntPtr.Zero) != 0) {
- throw new ApplicationException("Failed opening file");
- }
-
- this.width = width;
- this.height = height;
-
- // describe new stream
- Avi32.AVISTREAMINFO info = new Avi32.AVISTREAMINFO();
-
- 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;
-
- // describe compression options
- Avi32.AVICOMPRESSOPTIONS options = new Avi32.AVICOMPRESSOPTIONS();
+ ///
+ 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 ";
- // create stream
- if (Avi32.AVIFileCreateStream(file, out stream, ref info) != 0) {
- throw new ApplicationException("Failed creating stream");
+ ///
+ /// 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);
}
-
- // 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;
- }
- } else {
- options.handler = Avi32.mmioFOURCC(codec);
- options.quality = quality;
- }
+
+ 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));
+ }
- // create compressed stream
- int retval = Avi32.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero);
- if (retval != 0) {
- throw new ApplicationException("Failed creating compressed stream: " + retval);
- }
-
- // describe frame format
- BitmapInfoHeader bitmapInfoHeader = new BitmapInfoHeader(width, height, 32);
-
- // set frame format
- retval = Avi32.AVIStreamSetFormat(streamCompressed, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType()));
- if (retval != 0) {
- throw new ApplicationException("Failed creating compressed stream: "+ retval);
- }
- position = 0;
- return true;
- }
- }
-
- ///
- /// 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;
- }
- }
- }
+ // 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) {
@@ -328,581 +369,753 @@ namespace Greenshot.Helpers {
}
///
- /// 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 {
- ///
- /// Copy a block of memory.
- ///
- ///
- /// Destination pointer.
- /// Source pointer.
- /// Memory block's length to copy.
- ///
- /// Return's the value of dst - pointer to destination.
- ///
- [DllImport("ntdll.dll")]
- public static extern int memcpy(int dst, int src, int count);
-
-
- // --- Video for Windows Functions
-
- ///
- /// Initialize the AVIFile library.
- ///
- ///
- [DllImport("avifil32.dll")]
- public static extern void AVIFileInit();
-
- ///
- /// Exit the AVIFile library.
- ///
- [DllImport("avifil32.dll")]
- 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.dll", CharSet = CharSet.Unicode)]
- public static extern int 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.dll")]
- 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.dll")]
- 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.dll")]
- 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.dll")]
- 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.dll")]
- public static extern int 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.dll")]
- 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.dll")]
- 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.dll", 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.dll")]
- 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.dll")]
- 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.dll")]
- 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.dll")]
- 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.dll")]
- public static extern int 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.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);
-
- ///
- /// 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.dll")]
- public static extern int 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.dll")]
- public static extern int AVIMakeCompressedStream(out IntPtr compressedStream, IntPtr sourceStream, ref AVICOMPRESSOPTIONS options, IntPtr clsidHandler);
-
- // --- structures
-
- ///
- /// 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);
- }
-
-
- ///
- /// 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;
- }
- }
+ /// 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
+ }
}
diff --git a/Greenshot/Helpers/ScreenCaptureHelper.cs b/Greenshot/Helpers/ScreenCaptureHelper.cs
index defa01a44..c43ab0097 100644
--- a/Greenshot/Helpers/ScreenCaptureHelper.cs
+++ b/Greenshot/Helpers/ScreenCaptureHelper.cs
@@ -93,6 +93,11 @@ namespace Greenshot.Helpers {
return exceptionToThrow;
}
+ ///
+ /// Start the recording
+ ///
+ ///
+ ///
public bool Start(int framesPerSecond) {
if (recordingWindow != null) {
string windowTitle = Regex.Replace(recordingWindow.Text, @"[^\x20\d\w]", "");
@@ -176,8 +181,8 @@ namespace Greenshot.Helpers {
aviWriter = new AVIWriter();
// Comment the following 2 lines to make the user select it's own codec
- //aviWriter.Codec = "msvc";
- //aviWriter.Quality = 99;
+ aviWriter.Codec = "msvc";
+ aviWriter.Quality = 10000;
aviWriter.FrameRate = framesPerSecond;
if (aviWriter.Open(filename, recordingSize.Width, recordingSize.Height)) {
@@ -195,6 +200,9 @@ namespace Greenshot.Helpers {
return false;
}
+ ///
+ /// Do the actual frame capture
+ ///
private void CaptureFrame() {
int MSBETWEENCAPTURES = 1000/framesPerSecond;
int msToNextCapture = MSBETWEENCAPTURES;
@@ -262,6 +270,9 @@ namespace Greenshot.Helpers {
Cleanup();
}
+ ///
+ /// Stop the recording, after the next frame
+ ///
public void Stop() {
stop = true;
if (backgroundTask != null) {
@@ -269,6 +280,7 @@ namespace Greenshot.Helpers {
}
Cleanup();
}
+
///
/// Free resources
///
@@ -297,7 +309,9 @@ namespace Greenshot.Helpers {
if (ffmpegexe != null) {
try {
string webMFile = filename.Replace(".avi", ".webm");
- ProcessStartInfo processStartInfo = new ProcessStartInfo(ffmpegexe, "-i \"" + filename + "\" -vcodec libvpx \"" + webMFile + "\"");
+ string arguments = "-i \"" + filename + "\" -codec:v libvpx -quality good -cpu-used 0 -b:v 1000k -qmin 10 -qmax 42 -maxrate 1000k -bufsize 4000k -threads 4 \"" + webMFile + "\"";
+ LOG.DebugFormat("Starting {0} with arguments {1}", ffmpegexe, arguments);
+ ProcessStartInfo processStartInfo = new ProcessStartInfo(ffmpegexe, arguments);
processStartInfo.CreateNoWindow = false;
processStartInfo.RedirectStandardOutput = false;
processStartInfo.UseShellExecute = false;