/// <summary>Initialize a new VideoStream and add the first frame</summary>
 /// <param name="aviFile">The file that contains the stream</param>
 /// <param name="writeCompressed">true: create a compressed stream before adding frames</param>
 /// <param name="frameRate">Frames per second</param>
 /// <param name="firstFrame">Image to write into the stream as the first frame</param>
 public VideoStream(int aviFile, Avi.AVICOMPRESSOPTIONS compressOptions, double frameRate, Bitmap firstFrame)
 {
     Initialize(aviFile, true, frameRate, firstFrame);
     CreateStream(compressOptions);
     AddFrame(firstFrame);
 }
        /// <summary>Change the AviStreamInfo values and update the frame rate</summary>
        /// <param name="info"></param>
        public void SetInfo(Avi.AVISTREAMINFO info)
        {
            int result = Avi.EditStreamSetInfo(editableStream, ref info, Marshal.SizeOf(info));
            if (result != 0) {
                throw new Exception("Exception in SetInfo: " + result.ToString());
            }

            frameRate = info.dwRate / info.dwScale;
        }
        /// <summary>Create a compressed stream from an uncompressed stream</summary>
        private void CreateCompressedStream(Avi.AVICOMPRESSOPTIONS options)
        {
            int result = Avi.AVIMakeCompressedStream(out compressedStream, aviStream, ref options, 0);
            if (result != 0) {
                throw new Exception("Exception in AVIMakeCompressedStream: " + result.ToString());
            }

            this.compressOptions = options;

            SetFormat(compressedStream);
        }
 /// <summary>Create a new stream</summary>
 private void CreateStream(Avi.AVICOMPRESSOPTIONS options)
 {
     CreateStreamWithoutFormat();
     CreateCompressedStream(options);
 }
 /// <summary>Copy all properties from one VideoStream to another one</summary>
 /// <remarks>Used by EditableVideoStream</remarks>
 /// <param name="frameSize"></param><param name="frameRate"></param>
 /// <param name="width"></param><param name="height"></param>
 /// <param name="countBitsPerPixel"></param>
 /// <param name="countFrames"></param><param name="compressOptions"></param>
 internal VideoStream(int frameSize, double frameRate, int width, int height, Int16 countBitsPerPixel, int countFrames, Avi.AVICOMPRESSOPTIONS compressOptions, bool writeCompressed)
 {
     this.frameSize = frameSize;
     this.frameRate = frameRate;
     this.width = width;
     this.height = height;
     this.countBitsPerPixel = countBitsPerPixel;
     this.countFrames = countFrames;
     this.compressOptions = compressOptions;
     this.writeCompressed = writeCompressed;
     this.firstFrame = 0;
 }
        /// <summary>Returns all data needed to copy the stream</summary>
        /// <remarks>Do not forget to call Marshal.FreeHGlobal and release the raw data pointer</remarks>
        /// <param name="streamInfo">Receives the header information</param>
        /// <param name="format">Receives the format</param>
        /// <param name="streamLength">Receives the length of the stream</param>
        /// <returns>Pointer to the wave data</returns>
        public IntPtr GetStreamData(ref Avi.AVISTREAMINFO streamInfo, ref Avi.PCMWAVEFORMAT format, ref int streamLength)
        {
            streamInfo = GetStreamInfo();

            format = GetFormat();
            //length in bytes = length in samples * length of a sample
            streamLength = Avi.AVIStreamLength(aviStream.ToInt32()) * streamInfo.dwSampleSize;
            IntPtr waveData = Marshal.AllocHGlobal(streamLength);

            int result = Avi.AVIStreamRead(aviStream, 0, streamLength, waveData, streamLength, 0, 0);
            if(result != 0){
                throw new Exception("Exception in AVIStreamRead: "+result.ToString());
            }

            return waveData;
        }
        private IntPtr InsertSilence(int countSilentSamples, IntPtr waveData, int lengthWave, ref Avi.AVISTREAMINFO streamInfo)
        {
            //initialize silence
            int lengthSilence = countSilentSamples * streamInfo.dwSampleSize;
            byte[] silence = new byte[lengthSilence];

            //initialize new sound
            int lengthNewStream = lengthSilence + lengthWave;
            IntPtr newWaveData = Marshal.AllocHGlobal(lengthNewStream);

            //copy silence
            Marshal.Copy(silence, 0, newWaveData, lengthSilence);

            //copy sound
            byte[] sound = new byte[lengthWave];
            Marshal.Copy(waveData, sound, 0, lengthWave);
            IntPtr startOfSound = new IntPtr(newWaveData.ToInt32() + lengthSilence);
            Marshal.Copy(sound, 0, startOfSound, lengthWave);

            Marshal.FreeHGlobal(newWaveData);

            streamInfo.dwLength = lengthNewStream;
            return newWaveData;
        }
 /// <summary>Add an empty video stream to the file</summary>
 /// <remarks>Compresses the stream without showing the codecs dialog</remarks>
 /// <param name="compressOptions">Compression options</param>
 /// <param name="frameRate">Frames per second</param>
 /// <param name="firstFrame">Image to write into the stream as the first frame</param>
 /// <returns>VideoStream object for the new stream</returns>
 public VideoStream AddVideoStream(Avi.AVICOMPRESSOPTIONS compressOptions, double frameRate, Bitmap firstFrame)
 {
     VideoStream stream = new VideoStream(aviFile, compressOptions, frameRate, firstFrame);
     streams.Add(stream);
     return stream;
 }
        /// <summary>Add an existing wave audio stream to the file</summary>
        /// <param name="waveData">The new stream's data</param>
        /// <param name="streamInfo">Header info for the new stream</param>
        /// <param name="streamFormat">The new stream' format info</param>
        /// <param name="streamLength">Length of the new stream</param>
        public void AddAudioStream(IntPtr waveData, Avi.AVISTREAMINFO streamInfo, Avi.PCMWAVEFORMAT streamFormat, int streamLength)
        {
            IntPtr aviStream;
            int result = Avi.AVIFileCreateStream(aviFile, out aviStream, ref streamInfo);
            if (result != 0) {
                throw new Exception("Exception in AVIFileCreateStream: " + result.ToString());
            }

            result = Avi.AVIStreamSetFormat(aviStream, 0, ref streamFormat, Marshal.SizeOf(streamFormat));
            if (result != 0) {
                throw new Exception("Exception in AVIStreamSetFormat: " + result.ToString());
            }

            result = Avi.AVIStreamWrite(aviStream, 0, streamLength, waveData, streamLength, Avi.AVIIF_KEYFRAME, 0, 0);
            if (result != 0) {
                throw new Exception("Exception in AVIStreamWrite: " + result.ToString());
            }

            result = Avi.AVIStreamRelease(aviStream);
            if (result != 0) {
                throw new Exception("Exception in AVIStreamRelease: " + result.ToString());
            }
        }