Click here to Skip to main content
15,883,989 members
Articles / Programming Languages / C#

A Simple C# Wrapper for the AviFile Library

Rate me:
Please Sign up or sign in to vote.
4.94/5 (209 votes)
12 Nov 2012CPOL9 min read 2M   72K   511  
Edit AVI files in .NET.
/* This class has been written by
 * Corinna John (Hannover, Germany)
 * cj@binary-universe.net
 * 
 * You may do with this code whatever you like,
 * except selling it or claiming any rights/ownership.
 * 
 * Please send me a little feedback about what you're
 * using this code for and what changes you'd like to
 * see in later versions. (And please excuse my bad english.)
 * 
 * WARNING: This is experimental code.
 * Please do not expect "Release Quality".
 * */

using System;
using System.IO;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace AviFile
{
	public class AviManager
	{
		private int aviFile = 0;
		private ArrayList streams = new ArrayList();

		/// <summary>Open or create an AVI file</summary>
		/// <param name="fileName">Name of the AVI file</param>
		/// <param name="open">true: Open the file; false: Create or overwrite the file</param>
		public AviManager(String fileName, bool open){
			Avi.AVIFileInit();
			int result;

			if(open){ //open existing file
				
				result = Avi.AVIFileOpen(
					ref aviFile, fileName,
					Avi.OF_READWRITE, 0);

			}else{ //create empty file
				
				result = Avi.AVIFileOpen(
					ref aviFile, fileName, 
					Avi.OF_WRITE | Avi.OF_CREATE, 0);
			
			}

			if(result != 0) {
				throw new Exception("Exception in AVIFileOpen: "+result.ToString());
			}
		}
		
		/// <summary>Get the first video stream - usually there is only one video stream</summary>
		/// <returns>VideoStream object for the stream</returns>
		public VideoStream GetVideoStream(){
			IntPtr aviStream;

			int result = Avi.AVIFileGetStream(
				aviFile,
				out aviStream,
				Avi.streamtypeVIDEO, 0);
			
			if(result != 0){
				throw new Exception("Exception in AVIFileGetStream: "+result.ToString());
			}

			VideoStream stream = new VideoStream(aviFile, aviStream);
			streams.Add(stream);
			return stream;
		}

		/// <summary>Getthe first wave audio stream</summary>
		/// <returns>AudioStream object for the stream</returns>
		public AudioStream GetWaveStream(){
			IntPtr aviStream;

			int result = Avi.AVIFileGetStream(
				aviFile,
				out aviStream,
				Avi.streamtypeAUDIO, 0);
			
			if(result != 0){
				throw new Exception("Exception in AVIFileGetStream: "+result.ToString());
			}

			AudioStream stream = new AudioStream(aviFile, aviStream);
			streams.Add(stream);
			return stream;
		}

		/// <summary>Get a stream from the internal list of opened streams</summary>
		/// <param name="index">Index of the stream. The streams are not sorted, the first stream is the one that was opened first.</param>
		/// <returns>VideoStream at position [index]</returns>
		/// <remarks>
		/// Use this method after DecompressToNewFile,
		/// to get the copied stream from the new AVI file
		/// </remarks>
		/// <example>
		/// //streams cannot be edited - copy to a new file
		///	AviManager newManager = aviStream.DecompressToNewFile(@"..\..\testdata\temp.avi", true);
		/// //there is only one stream in the new file - get it and add a frame
		///	VideoStream aviStream = newManager.GetOpenStream(0);
		///	aviStream.AddFrame(bitmap);
		/// </example>
		public VideoStream GetOpenStream(int index){
			return (VideoStream)streams[index];
		}

		/// <summary>Add an empty video stream to the file</summary>
		/// <param name="isCompressed">true: Create a compressed stream before adding frames</param>
		/// <param name="frameRate">Frames per second</param>
		/// <param name="frameSize">Size of one frame in bytes</param>
		/// <param name="width">Width of each image</param>
		/// <param name="height">Height of each image</param>
		/// <param name="format">PixelFormat of the images</param>
		/// <returns>VideoStream object for the new stream</returns>
		public VideoStream AddVideoStream(bool isCompressed, int frameRate, int frameSize, int width, int height, PixelFormat format){
			VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, frameSize, width, height, format);
			streams.Add(stream);
			return stream;
		}

		/// <summary>Add an empty video stream to the file</summary>
		/// <param name="isCompressed">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>
		/// <returns>VideoStream object for the new stream</returns>
		public VideoStream AddVideoStream(bool isCompressed, double frameRate, Bitmap firstFrame){
			VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, firstFrame);
			streams.Add(stream);
			return stream;
		}

		/// <summary>Add a wave audio stream from another file to this file</summary>
		/// <param name="waveFileName">Name of the wave file to add</param>
		public void AddAudioStream(String waveFileName){
			AviManager audioManager = new AviManager(waveFileName, true);
			AudioStream newStream = audioManager.GetWaveStream();
			AddAudioStream(newStream);
			audioManager.Close();
		}

		/// <summary>Add an existing wave audio stream to the file</summary>
		/// <param name="newStream">The stream to add</param>
		public void AddAudioStream(AudioStream newStream){			
			Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
			Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
			int streamLength = 0;
			IntPtr waveData = newStream.GetStreamData(ref streamInfo, ref streamFormat, ref 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());
			}
		}

        /// <summary>Add an existing wave audio stream to the file</summary>
        /// <param name="newStream">The stream to add</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());
            }
        }

        public AviManager CopyTo(String newFileName, int startAtSecond, int stopAtSecond) {
            AviManager newFile = new AviManager(newFileName, false);

            try {
                //copy video stream

                VideoStream videoStream = GetVideoStream();

                int startFrameIndex = (int)(videoStream.FrameRate * startAtSecond);
                int stopFrameIndex = (int)(videoStream.FrameRate * stopAtSecond);

                videoStream.GetFrameOpen();
                Bitmap bmp = videoStream.GetBitmap(startFrameIndex);
                VideoStream newStream = newFile.AddVideoStream(false, videoStream.FrameRate, bmp);
                for (int n = startFrameIndex + 1; n <= stopFrameIndex; n++) {
                    bmp = videoStream.GetBitmap(n);
                    newStream.AddFrame(bmp);
                }
                videoStream.GetFrameClose();

                //copy audio stream

                AudioStream waveStream = GetWaveStream();

                Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
                Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
                int streamLength = 0;
                IntPtr ptrRawData = waveStream.GetStreamData(
                    ref streamInfo,
                    ref streamFormat,
                    ref streamLength);

                int startByteIndex = waveStream.CountSamplesPerSecond * startAtSecond * waveStream.CountBitsPerSample / 8;
                int stopByteIndex = waveStream.CountSamplesPerSecond * stopAtSecond * waveStream.CountBitsPerSample / 8;

                ptrRawData = new IntPtr(ptrRawData.ToInt32() + startByteIndex);

                byte[] rawData = new byte[stopByteIndex - startByteIndex];
                Marshal.Copy(ptrRawData, rawData, 0, rawData.Length);

                streamInfo.dwLength = rawData.Length;
                streamInfo.dwStart = 0;

                IntPtr unmanagedRawData = Marshal.AllocHGlobal(rawData.Length);
                Marshal.Copy(rawData, 0, unmanagedRawData, rawData.Length);
                newFile.AddAudioStream(unmanagedRawData, streamInfo, streamFormat, rawData.Length);
            } catch (Exception ex) {
                newFile.Close();
                throw ex;
            }

            return newFile;
        }

        /// <summary>Release all ressources</summary>
		public void Close(){
			foreach(AviStream stream in streams){
				stream.Close();
			}
			
			Avi.AVIFileRelease(aviFile);
			Avi.AVIFileExit();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
Corinna lives in Hanover/Germany and works as a C# developer.

Comments and Discussions