Click here to Skip to main content
Click here to Skip to main content

A Simple C# Wrapper for the AviFile Library

By , 12 Nov 2012
 

Introduction

This is an article for everyone who does not want to spend hours messing around with the AVIFile functions, if he only wants to read or change a simple AVI video. I have wrapped the most important AVIFile functions into three easy to use C# classes that can handle the following tasks:

  • Read images from the video stream.
  • Decompress a compressed video stream.
  • Compress an uncompressed video stream.
  • Change the compression of a video stream.
  • Export the video stream into a separate .avi file.
  • Export the audio stream into a .wav file.
  • Copy a couple of seconds from audio and video stream into a new .avi file.
  • Add sound from a .wav file to the video.
  • Create a new video stream from a list of bitmaps.
  • Add frames to an existing video stream, compressed or not.
  • Insert frames into a stream.
  • Copy or delete frames from a stream.

These features cover the common use cases like creating a video from a couple of images and a wave sound, extracting the sound track from a video, cutting out short clips, or grabbing a single picture from a movie.

This article has got two sections:

  • First, I'll explain the demo application so that you can use it to explore the library on your own.
  • Then, I'll explain how the library works step by step.

How to use the library - A walk through the demo application

The Explore tab

The Explore tab lets you explore an AVI file, and offers simple tasks that don't need editable streams:

At the top of the form, you can choose the AVI file you want to explore. text.avi from the test data folder is pre-selected. On the left side, you can display header information about the video and the wave sound stream (if available). Also, you can see image frames from the video in a PictureBox:

The images are read by a VideoStream object. GetFrameOpen prepares the stream for decompressing frames, GetFrameClose releases the resources used to decompress the frame, and GetBitmap decompresses a frame and converts it to a System.Drawing.Bitmap.

AviManager aviManager = new AviManager(txtAviFileName.Text, true);
VideoStream aviStream = aviManager.GetVideoStream();
aviStream.GetFrameOpen();
picFrame.Image = 
  aviStream.GetBitmap(Convert.ToInt32(numPosition.Value));
aviStream.GetFrameClose();
aviManager.Close();

In the middle of the demo form, you can work with whole streams:

Decompress removes the compression from a video stream. It creates a new file and video stream, decompresses each frame from the old stream, and writes it into the new stream. The result is a large new .avi file with the same video but no compression.

Compress changes the compression of the video, or applies compression to an uncompressed video. It does the same as Uncompress, but compresses the new stream. These two functions use the same method CopyFile:

private void CopyFile(String newName, bool compress){
    //open compressed file
    AviManager aviManager = 
        new AviManager(txtAviFileName.Text, true);
    VideoStream aviStream = aviManager.GetVideoStream();
    //create un-/re-compressed file
    AviManager newManager = 
        aviStream.DecompressToNewFile(newName, compress);

    //close compressed file
    aviManager.Close();
    //save and close un-/re-compressed file
    newManager.Close();
}

Whenever an instance of VideoStream creates a compressed stream, it asks you for a codec and settings:

Extract Bitmaps splits the video into many separate bitmap files:

VideoStream stream = aviManager.GetVideoStream();
stream.GetFrameOpen();

String path = @"..\..\testdata\";
for(int n=0; n<stream.CountFrames; n++){
    stream.ExportBitmap(n, path+n.ToString()+".bmp");
}

stream.GetFrameClose();

Of course, you can save the images in any format. ExportBitmap is just a shortcut for these three lines:

Bitmap bmp = stream.GetBitmap(position);
bmp.Save(FileName);
bmp.Dispose();

Extract Video copies the whole video stream into a new AVI file. You can use it to get rid of all the other streams like MIDI, text and Wave sound.

The lower box deals with Wave sound. Extract Sound copies the whole sound stream into a Wave file. This is not a big task, it requires only four lines of code:

AviManager aviManager = 
    new AviManager(txtAviFileName.Text, true);
AudioStream audioStream = aviManager.GetWaveStream();
audioStream.ExportStream( @"..\..\testdata\sound.wav" );
aviManager.Close();

Extract a few Seconds lets you copy video and sound between second X and second Y. First, a CopyForm dialog lets you enter X and Y, then these parts are cut out of the video and sound streams:

AviManager aviManager = new AviManager(txtAviFileName.Text, true);
VideoStream aviStream = aviManager.GetVideoStream();
CopyForm dialog = new CopyForm(0,
  aviStream.CountFrames / aviStream.FrameRate);
if (dialog.ShowDialog() == DialogResult.OK) {
  int startSecond = dialog.Start;
  int stopSecond = dialog.Stop;

  AviManager newFile = aviManager.CopyTo(
    "..\\..\\testdata\\video.avi", startSecond, stopSecond);
  newFile.Close();
}
aviManager.Close();

Add Sound lets you choose a .wav file, and adds it to the video. You can use this feature to add a sound track to a silent video, for example, re-add the sound to a video extracted with Extract Video. Adding sound is a simple task of three lines:

String fileName = GetFileName("Sounds (*.wav)|*.wav");
if(fileName != null){
    AviManager aviManager = 
        new AviManager(txtAviFileName.Text, true);
    aviManager.AddAudioStream(fileName);
    aviManager.Close();
}

The last set of functions is about creating new video streams. Enter a list of image files in the box and animate them:

Create uncompressed builds a new video from the images, and saves it without any compression. Create and Compress does the same, except that it displays the compression settings dialog and compresses the images. Both methods create a new file, and pass a sample bitmap to AddVideoStream. The sample bitmap is used to set the format of the new stream. Then, all the images from the list are added to the video.

//load the first image
Bitmap bitmap = (Bitmap)Image.FromFile(txtFileNames.Lines[0]);
//create a new AVI file
AviManager aviManager = 
    new AviManager(@"..\..\testdata\new.avi", false);
//add a new video stream and one frame to the new file
VideoStream aviStream = 
    aviManager.AddVideoStream(true, 2, bitmap);

Bitmap bitmap;
int count = 0;
for(int n=1; n<txtFileNames.Lines.Length; n++){
    if(txtFileNames.Lines[n].Trim().Length > 0){
        bitmap = 
           (Bitmap)Bitmap.FromFile(txtFileNames.Lines[n]);
        aviStream.AddFrame(bitmap);
        bitmap.Dispose();
        count++;
    }
}
aviManager.Close();

Add Frames appends the images to the existing video stream. To an uncompressed video stream, we could append frames by simply opening the stream and adding frames as usual. But a compressed stream cannot be re-compressed. AVIStreamWrite - used by AddFrame - would not return any error; but anyway, it would add the new frames uncompressed and produce nothing but strangely colored pixel storms. To add frames to a compressed stream, the existing frames must be decompressed and added to a new compressed stream. Then the additional frames can be added to that stream:

//open file
Bitmap bmp = (Bitmap)Image.FromFile(txtFileNames.Lines[0]);
AviManager aviManager = 
    new AviManager(txtAviFileName.Text, true);
VideoStream aviStream = aviManager.GetVideoStream();

//streams cannot be edited - copy to a new file
AviManager newManager = aviStream.DecompressToNewFile(
                        @"..\..\testdata\temp.avi", true);
aviStream = newManager.GetOpenStream(0);

//add images
Bitmap bitmap;
for(int n=0; n<txtFileNames.Lines.Length; n++){
    if(txtFileNames.Lines[n].Trim().Length > 0){
        bitmap = 
            (Bitmap)Bitmap.FromFile(txtFileNames.Lines[n]);
        aviStream.AddFrame(bitmap);
        bitmap.Dispose();
    }
}

aviManager.Close(); //close old file
newManager.Close(); //save and close new file

//delete old file, replace with new file
System.IO.File.Delete(txtAviFileName.Text);
System.IO.File.Move(@"..\..\testdata\temp.avi", 
                            txtAviFileName.Text);

Now that you know how to use the AVIFile wrapper classes, let's have a look at the background.

The Edit tab

The Edit tab demonstrates tasks for editable AVI streams, like pasting frames at any position in the stream, or changing the frame rate:

When you have chosen a file to edit, an editable stream is created from the video stream, and the editor buttons become enabled. A normal video stream is locked; for inserting and deleting frames, you need an editable stream:

AviManager file = new AviManager(fileName, true);
VideoStream stream = file.GetVideoStream();
EditableVideoStream editableStream = 
           new EditableVideoStream(stream);
file.Close();

On the left side, you can copy or cut frame sequences, and paste them at another position in the same stream:

Copying frames from one stream, and pasting them into another or the same stream, is only two lines of code:

//copy frames
IntPtr copiedData = editableStream.Copy(start, length);

//insert frames
editableStream.Paste(copiedData, 0, position, length);

There is no other method for deleting frames than just cut and forget them:

//cut and paste frames
IntPtr copiedData = editableStream.Cut(start, length);
editableStream.Paste(copiedData, 0, position, length);

//delete frames == cut without paste
IntPtr deletedData = editableStream.Cut(start, length);

In the middle of the dialog, you can insert frames from image files anywhere in the stream, and change the frame rate to make the video play back slower or faster:

We can paste only streams, not bitmaps, so the bitmaps from the list are written into a temporary AVI file and then pasted as a stream:

//create temporary video file
String tempFileName = System.IO.Path.GetTempFileName() + ".avi";
AviManager tempFile = new AviManager(tempFileName, false);

//write the new frames into the temporary video stream
Bitmap bitmap = 
  (Bitmap)Image.FromFile(txtNewFrameFileName.Lines[0].Trim());
tempFile.AddVideoStream(false, 1, bitmap);
VideoStream stream = tempFile.GetVideoStream();

for (int n=1; n<txtNewFrameFileName.Lines.Length; n++) {
   if (txtNewFrameFileName.Lines[n].Trim().Length > 0) {
       stream.AddFrame(
         (Bitmap)Image.FromFile(txtNewFrameFileName.Lines[n]));
   }
}

//paste the video into the editable stream
editableStream.Paste(stream, 0,
   (int)numPastePositionBitmap.Value, stream.CountFrames);

Do you find your video too slow, or too fast? Tell the player application to play more/less frames per second:

Avi.AVISTREAMINFO info = editableStream.StreamInfo;
info.dwRate = (int)(numFrameRate.Value * 10000);
info.dwScale = 10000;
editableStream.SetInfo(info);

The last box is not for editing, it is only a preview player. You should preview your editable stream before saving it to an AVI file.

A preview player is easy to implement, you only need a PictureBox and the video stream you want to play. A label displaying the current frame index can be helpful, too. A start button, a stop button, and there you are:

private void btnPlay_Click(object sender, EventArgs e) {
    player = new AviPlayer(editableStream, 
                pictureboxPreview, labelFrameIndex);
    player.Stopped += new System.EventHandler(player_Stopped);
    player.Start();
    SetPreviewButtonsState();
}

private void player_Stopped(object sender, EventArgs e) {
        btnPlay.Invoke(
           new SimpleDelegate(SetPreviewButtonsState));
}

private void SetPreviewButtonsState() {
        btnPlay.Enabled = ! player.IsRunning;
        btnStop.Enabled = player.IsRunning;
}

private void btnStop_Click(object sender, EventArgs e) {
        player.Stop();
}

How it works

AviManger manages the streams in an AVI file. The constructor takes the name of the file and opens it. Close closes all opened streams and the file itself. You can add new streams with AddVideoStream and AddAudioStream. New video streams are empty, Wave streams can only be created from Wave files. After you have created an empty video stream, use the methods of VideoStream to fill it. But what actually happens when you add a stream?

Create a video stream

There are two methods for creating a new video stream: create from a sample bitmap, or create from explicit format information. Both methods do the same, they pass their parameter on to VideoStream and add the new stream to the internal list of opened streams, to close them before closing the file:

public VideoStream AddVideoStream(
    bool isCompressed, //display the compression dialog,
     // create a compressed stream
    int frameRate, //frames per second
    int frameSize, //size of one frame in bytes
    int width, int height, PixelFormat format //format of 
                                              //the bitmaps
    ){

    VideoStream stream = new VideoStream(
        aviFile,
        isCompressed,
        frameRate,
        frameSize,
        width, height, format);

    streams.Add(stream);
    return stream;
}

public VideoStream AddVideoStream(
    bool isCompressed, //display the compression dialog,
      // create a compressed stream
    int frameRate, //frames per second
    Bitmap firstFrame //get the format from this image
      // and add it to the new stream
    ){

    VideoStream stream = new VideoStream(
        aviFile,
        isCompressed,
        frameRate,
        firstFrame);

    streams.Add(stream);
    return stream;
}

Then, VideoStream uses the format data to create a new stream. It calls AVIFileCreateStream and, if writeCompressed says so, AVIMakeCompressedStream:

public VideoStream(
    int aviFile, //pointer to the file object
    bool writeCompressed, //true: create compressed stream
    int frameRate, //frames per second
    ...
    ){

    //store format information
    //...

    //create the stream
    CreateStream();
}

private void CreateStream(){
    //fill stream information
    Avi.AVISTREAMINFO strhdr = new Avi.AVISTREAMINFO();
    strhdr.fccType = Avi.mmioStringToFOURCC("vids", 0);
    strhdr.fccHandler = Avi.mmioStringToFOURCC("CVID", 0);
    strhdr.dwScale = 1;
    strhdr.dwRate = frameRate;
    strhdr.dwSuggestedBufferSize = frameSize;
    strhdr.dwQuality = -1; //default
    strhdr.rcFrame.bottom = (uint)height;
    strhdr.rcFrame.right = (uint)width;
    strhdr.szName = new UInt16[64];

    //create the stream
    int result = Avi.AVIFileCreateStream(aviFile, 
                          out aviStream, ref strhdr);

    if(writeCompressed){
        //create a compressed stream from 
        //the uncompressed stream
        CreateCompressedStream();
    }
}

private void CreateCompressedStream(){
    Avi.AVICOMPRESSOPTIONS_CLASS options = 
             new Avi.AVICOMPRESSOPTIONS_CLASS();
    options.fccType = (uint)Avi.streamtypeVIDEO;
    options.lpParms = IntPtr.Zero;
    options.lpFormat = IntPtr.Zero;

    //display the compression options dialog
    Avi.AVISaveOptions(
      IntPtr.Zero,
      Avi.ICMF_CHOOSE_KEYFRAME | Avi.ICMF_CHOOSE_DATARATE,
      1, ref aviStream, ref options);

    //get a compressed stream
    Avi.AVICOMPRESSOPTIONS structOptions = 
                            options.ToStruct();
    int result = Avi.AVIMakeCompressedStream(
        out compressedStream,
        aviStream,
        ref structOptions, 0);

    //format the compressed stream
    SetFormat(compressedStream);
}

AVICOMPRESSOPTIONS_CLASS is the AVICOMPRESSOPTIONS structure as a class. Using classes instead of structures is the easiest way to deal with pointers to pointers. If you don't know what I'm talking about, you probably have never used AVISaveOptions or AVISaveV in .NET. Take a look at the original declaration:

BOOL AVISaveOptions(
  HWND hwnd,
  UINT uiFlags,
  int nStreams,
  PAVISTREAM * ppavi,
  LPAVICOMPRESSOPTIONS * plpOptions
);

LPAVICOMPRESSOPTIONS is a pointer to a pointer to an AVICOMPRESSOPTIONS structure. In C#, structures are passed by value. If you pass a structure by ref, a pointer to the structure is passed. Instances of classes are always passed to methods as pointers. So a class-parameter by ref means a pointer to a pointer to the object. The C# declarations of AVISaveOptions and AVICOMPRESSOPTIONS are:

[DllImport("avifil32.dll")]
public static extern bool AVISaveOptions(
    IntPtr hwnd,
    UInt32 uiFlags,
    Int32 nStreams,
    ref IntPtr ppavi,
    ref AVICOMPRESSOPTIONS_CLASS plpOptions
    );

[StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct AVICOMPRESSOPTIONS {
    public UInt32   fccType;
    public UInt32   fccHandler;
    public UInt32   dwKeyFrameEvery;
    public UInt32   dwQuality;
    public UInt32   dwBytesPerSecond;
    public UInt32   dwFlags;
    public IntPtr   lpFormat;
    public UInt32   cbFormat;
    public IntPtr   lpParms;
    public UInt32   cbParms;
    public UInt32   dwInterleaveEvery;
}

[StructLayout(LayoutKind.Sequential, Pack=1)]
public class AVICOMPRESSOPTIONS_CLASS {
    public UInt32   fccType;
    public UInt32   fccHandler;
    public UInt32   dwKeyFrameEvery;
    public UInt32   dwQuality;
    public UInt32   dwBytesPerSecond;
    public UInt32   dwFlags;
    public IntPtr   lpFormat;
    public UInt32   cbFormat;
    public IntPtr   lpParms;
    public UInt32   cbParms;
    public UInt32   dwInterleaveEvery;

    public AVICOMPRESSOPTIONS ToStruct(){
        AVICOMPRESSOPTIONS returnVar = new AVICOMPRESSOPTIONS();
        returnVar.fccType = this.fccType;
        returnVar.fccHandler = this.fccHandler;
        returnVar.dwKeyFrameEvery = this.dwKeyFrameEvery;
        returnVar.dwQuality = this.dwQuality;
        returnVar.dwBytesPerSecond = this.dwBytesPerSecond;
        returnVar.dwFlags = this.dwFlags;
        returnVar.lpFormat = this.lpFormat;
        returnVar.cbFormat = this.cbFormat;
        returnVar.lpParms = this.lpParms;
        returnVar.cbParms = this.cbParms;
        returnVar.dwInterleaveEvery = this.dwInterleaveEvery;
        return returnVar;
    }
}

With this workaround, we are able to call AVISaveOptions and (later on) AVISaveV in C#. Now, the new stream can be filled with image frames using AddFrame

public void AddFrame(Bitmap bmp){
    bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);

    if (countFrames == 0){
       //  the format of the first frame defines the format of the stream
       CopyPalette(bmp.Palette);
       SetFormat(writeCompressed ? compressedStream : aviStream,
                 countFrames);
    }

    //lock the memory block
    BitmapData bmpDat = bmp.LockBits(
        new Rectangle(
        0,0, bmp.Width, bmp.Height),
        ImageLockMode.ReadOnly, bmp.PixelFormat);

    //add the bitmap to the (un-)compressed stream
    int result = Avi.AVIStreamWrite(
        writeCompressed ? compressedStream : aviStream,
        countFrames, 1,
        bmpDat.Scan0,
        (Int32)(bmpDat.Stride * bmpDat.Height),
        0, 0, 0);

    //unlock the memory block
    bmp.UnlockBits(bmpDat);

    //count the frames, so that we don't have to
    //call AVIStreamLength for every new frame
    countFrames++;
}    

Now, we are able to fill an empty stream with images. But what can we do to add frames to an existing stream? Well, first, we have to open the stream with the third constructor.

Re-compress a video stream

public VideoStream(int aviFile, IntPtr aviStream){

    this.aviFile = aviFile;
    this.aviStream = aviStream;

    //read the stream's format
    Avi.BITMAPINFOHEADER bih = new Avi.BITMAPINFOHEADER();
    int size = Marshal.SizeOf(bih);
    Avi.AVIStreamReadFormat(aviStream, 0, ref bih, ref size);
    Avi.AVISTREAMINFO streamInfo = GetStreamInfo(aviStream);

    //store the important format values
    this.frameRate = streamInfo.dwRate / streamInfo.dwScale;
    this.width = (int)streamInfo.rcFrame.right;
    this.height = (int)streamInfo.rcFrame.bottom;
    this.frameSize = bih.biSizeImage;
    this.countBitsPerPixel = bih.biBitCount;

    //get the count of frames that are already there
    int firstFrame = Avi.AVIStreamStart(aviStream.ToInt32());
    countFrames = 
       firstFrame + Avi.AVIStreamLength(aviStream.ToInt32());
}

If you are sure the video stream is not compressed, you can call AddFrame now. Otherwise, you have to decompress the existing frames, and recompress them into a new stream:

public AviManager DecompressToNewFile(String fileName, 
                                        bool recompress){
    //create a new AVI file
    AviManager newFile = new AviManager(fileName, false);

    //create a video stream in the new file
    this.GetFrameOpen();
    Bitmap frame = GetBitmap(0);
    VideoStream newStream = 
        newFile.AddVideoStream(recompress, frameRate, frame);

    //decompress each frame and add it to the new stream
    for(int n=1; n<countFrames; n++){
        frame = GetBitmap(n);
        newStream.AddFrame(frame);
    }

    this.GetFrameClose();

    return newFile;
}

DecompressToNewFile creates a writeable copy of the stream in a new file. You can add frames to this new stream, close the new AviManager to save it, and then add the sound stream from the old file to complete the copy. Adding frames to a video is not easy, but this way it works.

Separate a stream

Sometimes, you might have a video file with sound, but you only need the silent video, or only the sound. It is not necessary to copy each frame, you can open the stream as usual and export it with AVISaveV. This works with all kinds of streams, only the compression options are different:

public override void ExportStream(String fileName){
    Avi.AVICOMPRESSOPTIONS_CLASS opts = 
                new Avi.AVICOMPRESSOPTIONS_CLASS();

    //for video streams
    opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vids", 0);
    opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CVID", 0);

    //for audio streams
    //opts.fccType = (UInt32)Avi.mmioStringToFOURCC("auds", 0);
    //opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CAUD", 0);

    //export the stream
    Avi.AVISaveV(fileName, 0, 0, 1, ref aviStream, ref opts);
}

Import sound from a Wave file

Now, we are able to build a video from bitmaps, and extract sound from it. And how does the sound get into the file? We could use AVISaveV again, to combine the video and audio streams in a new file - but we don't have to. The easiest way to add a new audio stream is to open the Wave file as an AVI file with only one stream, and then copy that stream:

public void AddAudioStream(String waveFileName){
    //open the wave file
    AviManager audioManager = 
        new AviManager(waveFileName, true);
    //get the wave sound as an audio stream...
    AudioStream newStream = audioManager.GetWaveStream();
    //...and add it to the file
    AddAudioStream(newStream);
    audioManager.Close();
}

public void AddAudioStream(AudioStream newStream){
    Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
    Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
    int streamLength = 0;

    //read header info, format and length, 
    //and get a pointer to the wave data
    IntPtr waveData = newStream.GetStreamData(
        ref streamInfo,
        ref streamFormat,
        ref streamLength);

    //create new stream
    IntPtr aviStream;
    Avi.AVIFileCreateStream(aviFile, out aviStream, 
                                      ref streamInfo);

    //add format new stream
    Avi.AVIStreamSetFormat(
        aviStream, 0,
        ref streamFormat,
        Marshal.SizeOf(streamFormat));

    //copy the raw wave data into the new stream
    Avi.AVIStreamWrite(
        aviStream, 0,
        streamLength,
        waveData,
        streamLength,
        Avi.AVIIF_KEYFRAME, 0, 0);

    Avi.AVIStreamRelease(aviStream);
}

Copy a clip from video and sound

I have added this method, because many people asked me how this could be done. To copy a part of the video stream from second X to second Y, the indices of the first and last frames have to be calculated from the frame rate and second. For the Wave stream, we must calculate the byte offsets from samples per second, bits per sample, and the requested seconds. The rest is only copy and paste:

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

    try {
        //copy video stream

        VideoStream videoStream = GetVideoStream();

        int startFrameIndex = 
             videoStream.FrameRate * startAtSecond;
        int stopFrameIndex = 
             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;
}

If you are still interested in AVI videos, download the wrapper library and the demo application. Finally, I dare to say: have fun with AVIFile!

Known issues

Adding frames to an existing stream does not work with all video codecs and/or bitmaps. You might get a StackOverflowException or broken frames. If you find out why this happens, please let me know.

History

  • 9th July, 2004 - updated downloads.
  • 3rd October, 2004 - new method AviManager.CopyTo.
  • 18th December, 2004 - new classes EditableVideoStream and AviPlayer, and a few memory leaks fixed.
  • 26th November, 2005 - removed performance reducers from VideoStream.GetBitmap.
  • 01st January, 2006 - Corrections for invalid colour depth and interlaced video in VideoStream.GetFrameOpen, new property VideoStream.FirstFrame. Thanks a lot to Michael Covington!

License

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

About the Author

Corinna John
Software Developer
Germany Germany
Member
Corinna lives in Hannover/Germany (CeBIT City) and works as a Delphi developer, though her favorite language is C#.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionProblems when running in Windows 7memberNick Humphries19 Apr '13 - 2:46 
Thanks for this cool wrapper for AVI files, just what I was looking for and I got a little demo up and running in no time, under XP. However on my 64bit Win 7 machine neither my program nor the demo you provide works with any avi, except the one you provide in the testdata folder.
 
I get the error {"Exception in VideoStreamGetFrameOpen!"} from VideoStream.GetFrameOpen() following getFrameObject = Avi.AVIStreamGetFrameOpen(StreamPointer, ref bih);
 
Is there something (a codec perhaps) missing from my installation? Windows media player plays all the avis without a problem.
 
Thanks,
 
Nick.
AnswerRe: Problems when running in Windows 7memberrejuwi10 May '13 - 0:05 
I can confirm that it does not work on 64bit win7. And I can confirm that it works when you change platform target to x32 running win7. I think this could be the trivial cause: DllImport("avifil32.dll").
GeneralRe: Problems when running in Windows 7memberNick Humphries10 May '13 - 0:16 
Thanks for the info, however, I have already compiled to x86 as it didn't work at all otherwise. I still get 'Exception in VideoStreamGetFrameOpen!' with any .avi I try.
GeneralRe: Problems when running in Windows 7memberrejuwi10 May '13 - 0:20 
Bad luck. It worked for me with my different AVIs when changing the Platform Target to x86 for both the AviDemo and AviFile projects.
Questionhow can i get h.264 video (not large but good quality)? [modified]memberwildboar4718 Apr '13 - 1:30 
i have program that takes screenshot 5-10 times per second (5-10fps) and add it to VideoStream.
i have tried all compression options in dialog (on my system i have microsoft rle, microsoft video 1, intel iyuv and ffdshow) but resulting video is too large, best was 105 MB per minute using microsoft video 1.
video resolution is 1280x1024 (because it is my desktop resolution).
 
so my question is how can i get good quality of video and also have size about 30 MB per minute?
maybe there are some ways to use h.264 compression or some other video compression via c#, but i don't know how.
 
ANSWER: If you want higher compression, use ffmpeg.
i used this article: http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/[^]
and added method to compress avi to mp4 video (i suppose ffmpeg implements h.264 standart for this)
public string ConvertH264(string inputPath,string outPath)
        {
            //-i D:\temp\compress\new-microsoft1.avi -vcodec mpeg4 -acodec aac output.mp4
            string params1 = string.Format("-i {0}  -vcodec mpeg4 -acodec aac -strict -2 -ar 22050 -b:a 128k {1}", inputPath, outPath);
            string output = RunProcess(params1);
            return output;
        }
result is very good for me.

modified 18 Apr '13 - 12:10.

GeneralMy vote of 5memberchocolade9 Apr '13 - 9:21 
Great Work !
QuestionThis is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade9 Apr '13 - 9:17 
My code is using a timer that take a screenshot of my screen each 100ms.
Then im adding with the timer the frames(screenshots) to the avi file in memory each 100ms.
In the end when i click on a button to stop the recording im getting an avi file on my hard disk with all screenshots. In other words i can record my screen as a video.
 
First my AviFile class:
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using AviFile;
using ScreenShotDemo;
 
namespace ScreenVideoRecorder
{
    class AviFile
    {
        AviManager aviManager;
 
        Bitmap bmp;
        int count = 0;
        VideoStream aviStream;
 
        public AviFile()
        {
            aviManager = new AviManager(@"d:\testdata\new.avi", false);
        }
 
        public void CreateAvi(ScreenCapture sc)
        {
            bmp = new Bitmap(sc.CaptureScreen());
            count++;
                if (count == 1)
                {
                 aviStream = aviManager.AddVideoStream(false, 25, bmp);
                }
            aviStream.AddFrame(bmp);
            bmp.Dispose();
        }
 
        public AviManager avim
        {
            get
            {
                return aviManager;
            }
            set
            {
                aviManager = value;
            }
        }
    }
}
 
Then in Form1 in timer1 tick event i did:
 
private void timer1_Tick(object sender, EventArgs e)
        {
            if (playImages == true)
            {
                timer1.Enabled = false;
                play();
                timer1.Enabled = true;
            }
            else
            {
                af.CreateAvi(this.sc);
            }
        }
 
af is a variable of the class AviFile and sc is a variable of my class ScreenShot that take the screenshots.
 
This is button click event where i click to stop the recording:
 
private void button3_Click(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            if (af != null)
            {
                af.avim.Close();
            }
        }
 
Now it's working i can do anything in my pc and it will record anything in the end i will have a new avi file wich i can play and see what i did on my pc like a video.
 

My question is how can i implent a new class/code of the compression so i can compress the avi file in real time or maybe after i click the button3 after the process stop then to compress the file ?
AnswerRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberwildboar4718 Apr '13 - 0:34 
you can use Threading. i've tried something like this:
class screenVideo
    {
        public void Start()
        {
            Thread th = new Thread(StartCapture);
            th.Start();
        }
        AviManager aviManager;
 
        Bitmap bmp;
        int count = 0;
        VideoStream aviStream;
        private object timerState;
        private System.Threading.Timer tim;
 
        private void myTimerCallback(object state)
        {
            aviStream.AddFrame(shotDesctopWithCursor());
 
        }
 
        private int fps = 5;
        public  void StartCapture()
        {
            aviManager = new AviManager(@"d:\temp\desctop.avi", false);
            aviStream = aviManager.AddVideoStream(false, fps, shotDesctopWithCursor());
            tim = new System.Threading.Timer(myTimerCallback, timerState, 0, 1000 / fps);
        }        
        public Bitmap shotDesctopWithCursor()
        {
            
            try
            {
                Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
 
                Graphics graphics = Graphics.FromImage(printscreen as Image);
                //cursor
                Point p = new Point(0, 0);
                graphics.CopyFromScreen(p, p, printscreen.Size);
                Rectangle cursorBounds = new Rectangle(Cursor.Position, Cursor.Current.Size);
                Cursors.Default.Draw(graphics, cursorBounds);
                Bitmap currDesc = (Bitmap)printscreen.Clone();
 
                printscreen.RotateFlip(RotateFlipType.RotateNoneFlipY);
                return printscreen;
            }
            catch (Exception ex)
            {
                return TakeScreenShot(Screen.PrimaryScreen);
            }
        }
        private Bitmap TakeScreenShot(Screen currentScreen)
        {
            try
            {
                Bitmap bmpScreenShot = new Bitmap(currentScreen.Bounds.Width,
                                                  currentScreen.Bounds.Height,
                                                  PixelFormat.Format32bppArgb);
 
                Graphics gScreenShot = Graphics.FromImage(bmpScreenShot);
 
                gScreenShot.CopyFromScreen(currentScreen.Bounds.X,
                                           currentScreen.Bounds.Y,
                                           0, 0,
                                           currentScreen.Bounds.Size,
                                           CopyPixelOperation.SourceCopy);
                bmpScreenShot.RotateFlip(RotateFlipType.RotateNoneFlipY);
                return bmpScreenShot;
            }
            catch
            {
                return new Bitmap(currentScreen.Bounds.Width,
                                                  currentScreen.Bounds.Height,
                                                  PixelFormat.Format32bppArgb);
            }
        }
        public void StopCapture()
        {
            tim.Dispose();
            aviManager.Close();
        }
    }
 
and so in my form i've just called Start() and stopcapture()
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade18 Apr '13 - 5:48 
wildboar47 hi,
 
I tried your class code. I have two buttons in Form1 in the start button i did:
 
af.Start();
 
af = AviFile wich is the class im using with your code.
 
I click on the button sometimes after a second or sometimes less then a second it's throwing an exception in your code on the line: aviStream.AddFrame(shotDesctopWithCursor());
The exception error is: Exception in VideoStreamWrite: -2147205019
 
The full exception error:
 
System.Exception was unhandled
HResult=-2146233088
Message=Exception in VideoStreamWrite: -2147205019
Source=AviFile
StackTrace:
at AviFile.VideoStream.AddFrame(Bitmap bmp)
at ScreenVideoRecorder.AviFile.myTimerCallback(Object state) in d:\C-Sharp\ScreenVideoRecorder\ScreenVideoRecorder\ScreenVideoRecorder\AviFile.cs:line 41
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
InnerException:
 

I didn't have this exception before. Any ideas what could it be ?
 

This is my code using your code same excatly same as your code:
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using AviFile;
using ScreenShotDemo;
using System.Threading;
using System.Drawing.Imaging;
 
namespace ScreenVideoRecorder
{
class AviFile
{
public AviFile()
{

}
 
public void Start()
{
Thread th = new Thread(StartCapture);
th.Start();
}
AviManager aviManager;
 
VideoStream aviStream;
private object timerState;
private System.Threading.Timer tim;
 
private void myTimerCallback(object state)
{
aviStream.AddFrame(shotDesctopWithCursor());
 
}
 
private int fps = 5;
public void StartCapture()
{
aviManager = new AviManager(@"d:\temp\desctop.avi", false);
aviStream = aviManager.AddVideoStream(false, fps, shotDesctopWithCursor());
tim = new System.Threading.Timer(myTimerCallback, timerState, 0, 1000 / fps);
}
public Bitmap shotDesctopWithCursor()
{
 
try
{
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
 
Graphics graphics = Graphics.FromImage(printscreen as Image);
//cursor
Point p = new Point(0, 0);
graphics.CopyFromScreen(p, p, printscreen.Size);
Rectangle cursorBounds = new Rectangle(Cursor.Position, Cursor.Current.Size);
Cursors.Default.Draw(graphics, cursorBounds);
Bitmap currDesc = (Bitmap)printscreen.Clone();
 
printscreen.RotateFlip(RotateFlipType.RotateNoneFlipY);
return printscreen;
}
catch (Exception ex)
{
return TakeScreenShot(Screen.PrimaryScreen);
}
}
private Bitmap TakeScreenShot(Screen currentScreen)
{
try
{
Bitmap bmpScreenShot = new Bitmap(currentScreen.Bounds.Width,
currentScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
 
Graphics gScreenShot = Graphics.FromImage(bmpScreenShot);
 
gScreenShot.CopyFromScreen(currentScreen.Bounds.X,
currentScreen.Bounds.Y,
0, 0,
currentScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
bmpScreenShot.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmpScreenShot;
}
catch
{
return new Bitmap(currentScreen.Bounds.Width,
currentScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
}
}
public void StopCapture()
{
tim.Dispose();
aviManager.Close();
}
}
}
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade18 Apr '13 - 5:52 
wildboar47 hi,
 
Another thing.
Could you show me or mark the part in your code that is doing the compression of the file while recording(creating) it ?
 
What i wanted is to record/create the avi file and also compress it in same time realtime.
 
So in your code where is the compression part and how can i change the rate or the compression ?
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberwildboar4718 Apr '13 - 6:08 
hmm, maybe Exception in VideoStreamWrite: -2147205019
is thrown because avimanager was disposed. however, it is not relevant.
 
compression is my key question too. in this AviFile project, it is hidden in VideoStream.cs
class in method CreateCompressedStream(). there you can define compression using dialog or set options hardcoded. normally i use "microsoft video 1" compression:
private void CreateCompressedStream(){
Avi.AVICOMPRESSOPTIONS opts = new Avi.AVICOMPRESSOPTIONS();
            //opts.fccType         = (UInt32)Avi.mmioStringToFOURCC("vids", 0);
            //opts.fccHandler      = (UInt32)Avi.mmioStringToFOURCC("CVID", 0);
            opts.fccType = (UInt32)0;
            opts.fccHandler = (UInt32)1668707181;//microsoft vid1
            opts.dwKeyFrameEvery = 0;
            opts.dwQuality = (UInt32)9500;  // 0 .. 10000
            opts.dwFlags = (UInt32)8;  // AVICOMRPESSF_KEYFRAMES = 4
            opts.dwBytesPerSecond= 0;
            opts.lpFormat        = new IntPtr(0);
            opts.cbFormat        = 0;
            opts.lpParms = new IntPtr(0);//0
            opts.cbParms = (UInt32)0;
            opts.dwInterleaveEvery = 0;//0
            this.compressOptions = opts;
            //get the compressed stream
            int result = Avi.AVIMakeCompressedStream(out compressedStream, aviStream, ref compressOptions, 0);
            if(result != 0) {
                throw new Exception("Exception in AVIMakeCompressedStream: "+result.ToString());
            }
            //Avi.AVISaveOptionsFree(1, ref options);
            SetFormat(compressedStream);
        }
 
Resulting video is about 25-30 MB (5 fps, 640x480 resolution)
 
If you want higher compression, use ffmpeg.
i used this article: http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/[^]
and added method to compress avi to mp4 video (i suppose ffmpeg implements h.264 standart for this)
public string ConvertH264(string inputPath,string outPath)
        {
            //-i D:\temp\compress\new-microsoft1.avi -vcodec mpeg4 -acodec aac output.mp4
            string params1 = string.Format("-i {0}  -vcodec mpeg4 -acodec aac -strict -2 -ar 22050 -b:a 128k {1}", inputPath, outPath);
            string output = RunProcess(params1);
            return output;
        }
 
Results are awesome, for example I had video from my desktop in 1280x1024 res,
it was 5MB, and after compression - 270 KB!
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade18 Apr '13 - 6:14 
Great thank you.
I will try this methods in a few.
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade18 Apr '13 - 12:16 
wildboar47 Hi,
 
Another question.
You gave in your last answer a link: http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/[^]
 
So i copied and managed to use this code in the link i mean to add it to my class but there is there something called: ConfigurationManager and i didn't see anything about it in the link there.
 
Any idea how should i use and create this ConfigurationManager ?
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberwildboar4718 Apr '13 - 22:13 
ConfigurationManager is part of System.Configutation namespace, but to use it you must add reference to system.configuration. then you app will be able to get settings from app.config file.
 
or you can replace ConfigurationManager.AppSettings["ffmpeg:ExeLocation"] with path to ffmpeg.exe,
for example try _ffExe=@"D:\temp\compress\ffmpeg\ffmpeg.exe"; and
_WorkingPath=@"D:\temp\compress\ffmpeg\";
 
feel free to contact me at wild4748@gmail.com
GeneralRe: This is my working code for creating an avi file in real time with a timer but how do i compress the avi file ?memberchocolade19 Apr '13 - 6:35 
wildboar47 Hi,
 
Just sent you an email an hour ago or so.
GeneralMy vote of 5memberwilliechen5 Mar '13 - 5:11 
wonderful work!
QuestionSaving monochrome byte arraymemberolymind14 Mar '13 - 0:59 
Hey!
 
I have a bunch of byte arrays which store monochromatic pictures. I tried to save them in several way, but finally the avi cannot be opened. I get no Exceptions and the avi file is correct size. The bitmap format is PixelFormat = Format8bppIndexed and for the stream countBitsPerPixel = 8.
 
Did anyone tried to create avi with 8bit depth? If yes, please help me!
 
Thanks!
Dani
QuestionTo Reduce or decrease file sizegroupchetanparekar13 Mar '13 - 21:02 
Hi ,
 
Please guide how to decrease file size or reducing file , when i have passes 8 image to Avi lib produce video file tooooo large near about 120MB. But i want file size 2 to 3Mb.
QuestionWorks GreatmemberUlrich Max Schild23 Feb '13 - 2:53 
I just tried to make a video from my own Pictures. It took me only a few minutes to manage this. Pretty easy to use. Thx for uploading!
QuestionCompressionmemberMember 870531711 Feb '13 - 3:30 
How can i do the compression instead of the window form pops-up?
QuestionSuggestions for CreateCompressedStream in VideoStream.csmemberMoxxis25 Jan '13 - 18:11 
I found that if I wanted to compress the output, I had to make changes to this function. The dialog did not work reliably, and it was easier to set the compression options myself to ones that did for me the best balance between quality and file size. Below is my modified version:
 
// Codec options
//0: fccType vidc, fccHandler CVID, description Cinepak Codec by Radius, driver C:\WINNT\System32\iccvid.dll, name Cinepak Codec, dwVersion 10000, dwVersionICM 0104
//1: fccType vidc, fccHandler I420, description Intel 4:2:0 Video V2.50, driver C:\WINNT\System32\msh263.drv, name MS H.263, dwVersion 232a, dwVersionICM 0104
//3: fccType vidc, fccHandler IV32, description Intel Indeo(R) Video R3.2, driver C:\WINNT\System32\ir32_32.dll, name IR32, dwVersion 0020, dwVersionICM 100000
//4: fccType vidc, fccHandler IYUV, description Intel IYUV codec, driver C:\WINNT\System32\iyuv_32.dll, name IYUV codec, dwVersion 0000, dwVersionICM 0104
//5: fccType vidc, fccHandler MRLE, description Microsoft RLE, driver C:\WINNT\System32\msrle32.dll, name MS-RLE, dwVersion 0104, dwVersionICM 0104
//6: fccType vidc, fccHandler MSVC, description Microsoft Video 1, driver C:\WINNT\System32\msvidc32.dll, name MS-CRAM, dwVersion 10000, dwVersionICM 0104
//11: fccType vidc, fccHandler M263, description Microsoft H.263 Video Codec, driver C:\WINNT\System32\msh263.drv, name MS H.263, dwVersion 232a, dwVersionICM 0104
//12: fccType vidc, fccHandler M261, description Microsoft H.261 Video Codec, driver C:\WINNT\System32\msh261.drv, name MS H.261, dwVersion 232a, dwVersionICM 0104
//13: fccType vidc, fccHandler DIVX, description DivX 5.0.5 Codec, driver C:\WINNT\System32\DivX.dll, name DivX codec, dwVersion 0000, dwVersionICM 0104

		/// <summary>Create a compressed stream from an uncompressed stream</summary>
		private void CreateCompressedStream(){
            Avi.AVICOMPRESSOPTIONS_CLASS opts = new Avi.AVICOMPRESSOPTIONS_CLASS();
            opts.fccType = (uint)Avi.streamtypeVIDEO;
            ///////////////////////////////////////////////////////////////
            opts.lpParms = IntPtr.Zero;
            opts.lpFormat = IntPtr.Zero;
            //display the compression options dialog...
            //            Avi.AVISaveOptions(IntPtr.Zero, Avi.ICMF_CHOOSE_KEYFRAME | Avi.ICMF_CHOOSE_DATARATE, 1, ref aviStream, ref opts);
            ///////////////////////////////////////////////////////////////
            //..or set static options
            // opt 1
            opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vidc", 0);
            opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("IYUV", 0);
            // opt 2 (crashes for me [MLM])
            //opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vidc", 0);
            //opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("MRLE", 0);
            // opt 3
            //opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vidc", 0);
            //opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("MSVC", 0);
 
            opts.dwKeyFrameEvery = 0;
            opts.dwQuality = 9000;  // 0 .. 10000
            opts.dwFlags = 0;  // AVICOMRPESSF_KEYFRAMES = 4
            opts.dwBytesPerSecond = 0;
            opts.lpFormat = new IntPtr(0);
            opts.cbFormat = 0;
            opts.lpParms = new IntPtr(0);
            opts.cbParms = 0;
            opts.dwInterleaveEvery = 0;
            ///////////////////////////////////////////////////////////////
            ////get the compressed stream
            this.compressOptions = opts.ToStruct();
            int result = Avi.AVIMakeCompressedStream(out compressedStream, aviStream, ref compressOptions, 0);
            if(result != 0) {
                throw new Exception("Exception in AVIMakeCompressedStream: "+result.ToString());
            }
 
            Avi.AVISaveOptionsFree(1, ref opts);
            SetFormat(compressedStream, 0);
		}

AnswerRe: Suggestions for CreateCompressedStream in VideoStream.csmemberMoxxis25 Jan '13 - 18:14 
BTW I found the fccType and fccHandler values in comments on Wine code at: archiveorange
GeneralVisual Studio Projectmemberluisperezphd2 Jan '13 - 9:15 
I wanted to be able to open the file in Visual Studio, in case anyone else wanted the same thing, you can download it here: https://dl.dropbox.com/u/18385692/ForDownload/CodeProject/avifilewrapperdemo.zip[^]
QuestionWinRT / Metro / Windows Store App Supprt?memberkinect_dev30 Dec '12 - 9:27 
Can this library be used by a WinRT app? (By WinRT I mean the new Windows 8 Store Apps.)
GeneralRe: WinRT / Metro / Windows Store App Supprt?memberGeekforChrist3 Apr '13 - 17:01 
:BUMP:
 
I'd like to know this too.
Questionnew AVI-File always 0 kBmembermagneticc2229 Dec '12 - 5:10 
Dear Corinna,
 
thxs for the wrapper. Now i wrote my code around it and all works but i cannot save the result in a file Frown | :(
 
Here is what i will do.
 
EditableVideoStream editableStream = new EditableVideoStream(aviStream);
IntPtr deletedData = editableStream.Cut(0, i);
AviManager.MakeFileFromStream(fileName + "2.avi", editableStream);
editableStream.Close();
 
At least i get a windows popup to select the codec in which type i want to save, but with all selections i always get a 0 kB file. Please help, it is the last step on my project.
 
Thxs a lot
 
Timo
AnswerRe: new AVI-File always 0 kBmemberluckan14 Jan '13 - 16:31 
Do you have solven the problem?I meet the problem too.
QuestionAVI output file is ruinedmemberGilelgrably24 Dec '12 - 3:53 
Hi,
 
I'm having 2 problems with the AVI file output:
 
First, my movie is made of 900 KB frames (each frame is 24bpp, 640*480) and 30 fps.
as long as I keep the movie relatively short (under 2000 frames) everything workes great!
 
But...
 
1. When I tried making a movie of 2500 frames I'm getting "Index not found or damaged" error when trying to play it (i.e. VirtualDub) therefore forced to automatically reconstructing missing index block in order to play the movie.
 
2. When I tried making a movie of 5000 frames I found out that the last ~330 frames I've inserted run over the the same amount of the initial frames (circular) and ruined them.
I've also noticed that no matter the amount of frames I'm inserting the output file of the movie is getting no bigger than 4,195,000 KB. I think this is what causing the frames mixed up issue. Is there any limitations on the size of the AVI file output? anyway to fix that?
 
Please noticed that I need this application to support a big size of AVI files that are able to contain big amount of frames (above 30000 frames, 30 fps).
 
I'll appreciate any help in this matter.
 
Gil.
GeneralMy vote of 5memberNicolasG24 Nov '12 - 9:19 
Really good job, and very well documented article.
Worked fine for me!
GeneralMy vote of 5memberJavier Jiménez18 Nov '12 - 23:16 
Great !!
GeneralMy vote of 5memberEdo Tzumer12 Nov '12 - 19:53 
Splendid piece!
QuestionProblem : Adding frame to VideomembersandeepGorant2 Nov '12 - 0:15 
Thanks for ur post.. its nice,
 
My actual problem is when iam trying to add a new image to existing video its throwing an exception (Exception: Problem in pasting -23416789 etc).. How to overcome this
 
Thanks in advance
Sandeep

Questionunable to start avifilestreammemberputrevu lakshmi11 Oct '12 - 0:32 
i downloaded avifilestream demo .when i ma trying to start the project solution i get an error there is no executable file ....cannot invoke class directly....which file should i make as a stratup project
AnswerRe: unable to start avifilestreammemberCorinna John11 Oct '12 - 10:08 
There are two projects in the solution. One is the library project and the other one is the AviDemo project. Please select the AviDemo project for startup.
This statement is false.

QuestionDecompressToNewFile documentation is wrongmemberx3n0ph0b3@yahoo.com4 Sep '12 - 8:25 
I'm attempting to delete a file using System.IO.File.Delete - I'm attempting the deletion after using AviManager.Close(). It gives me a file-still-in-use error that I can't seem to get around. After looking at the documentation for DecompressToNewFile, I see that the overload you are using no longer exists. The only thing I seem to have takes three parameters, String filepath, boolean compresed and an out VideoStream which must be a variable.
 
The overload shown in one of your examples only contains the first two parameters.
 
I was wondering if and when this changed, and how to properly dispose of resources to avoid the error. If it's not as simple as closing the avi manager prior to attempting to call System.IO.File.Delete, I'm extremely confused. At that point in my program, all relevant Avi Managers have been properly disposed of, to the best of my knowledge.
 
Basically the order I'm trying to do things is this. I have a camera set up, I'm using raw bitmap sources from that camera each frame (10 times per second) to add a raw frame to the avi stream. Since I'm adding frames live-over-time rather than from a list of files, the stream has to stay uncompressed until I get to the end of the recording process (via stop button).
 
Once the user hits the stop button, it decompresses the open stream to a new file, with the compression boolean true. The third parameter I'm using is the ORIGINAL stream variable (the uncompressed one.. is this wrong?); the application then opens the compression dialogue and saves. Those things all seem to work fine, but at that point, I want to DELETE the uncompressed data.
 
Immediately after I Close() BOTH the uncompressed AviManager and the new, temporary one, two new buttons appear allowing you to dispose of the original uncompressed video, or dispose of BOTH (erase the entire recording).
 
Both of these buttons throw File errors, in spite of both AviManagers being closed. Is there some other disposal command I need to use?
 
Anyways, any help would be appreciated.
Pastebin of the code, apologies for lack of comments. <_<
http://pastebin.com/dz8eBkci
AnswerRe: DecompressToNewFile documentation is wrongmemberCorinna John11 Oct '12 - 10:13 
That looks pretty confusing. Maybe it has to do with some deprecated VfW-functions that have been partially removed in Windows7.
But I'm afraid I won't be of much help for the rest of the year, as I have to work on my thesis every night. Frown | :(
This statement is false.

QuestionexceptionmemberAnandagowda8 Jul '12 - 16:17 
Hi, i am working on a project named object tracking in video files as part of my academics. I made use of AviFile project for my project. It is working well in my system for my inputs and getting output as expected.
 
My system configuration
 
os: windows 7
 
.net version: Visual studio 2010(version 4)
 
And when i tried to run the same code on different system with same
configuration as mine it is not working.
 
and also i tried to do with different configuration as shown below.
 
os: windows XP Service pack 2
 
.net version: Visual studio 2008 (version 3.5)
 
it is also not working.
 
no errors.
 
no warnings.
 

I'm getting exception showing "process or thread has changed since last step"

exception at
 
" if(getFrameObject == 0){ throw new Exception("Exception in
VideoStreamGetFrameOpen!"); }" in VideoStream.cs file.

I'm not getting the solution what changes i've make to run the code on
other system.
AnswerRe: exceptionmemberwatchara.knot22 Jul '12 - 6:14 
installed the DivX codec is work
 
http://www.divx.com/en/software/divx-plus/codec-pack/avi[^]
Questionbitmap to AVI conversion-memberMember 825274627 Jun '12 - 7:04 
Hi-
 
I have a stream of 8bpp monochrome bitmaps I am trying to convert to an uncompressed AVI. It works without error, however the output is not the correct size and the data appears to be skewed and shifted (e.g. the stuff on the left appears on the right, the stuff on the right appears to have looped around and is displayed on the left). I have tried defining the dimensions explicitly with no luck. Any ideas what I am doing wrong?
 
            AviManager aviManager = new AviManager(@"c:\new.avi", false);
         //   byte bitsPerPixel = GetBitsPerPixel(myImages[0].PixelFormat);
            //add a new video stream and one frame to the new file
            VideoStream aviStream = aviManager.AddVideoStream(false, 17, byteCount, width, height, myImages[0].PixelFormat);
 
Thanks!
GeneralMy vote of 5memberCharles Bryan7 Jun '12 - 23:31 
Thank you so much !!!
QuestionProblem in inserting a frame in an existing video.membershubhamjoshi15 May '12 - 0:44 
I am trying to read a bitmap from an avi and change some colors in it.
When i try to write this new bitmap into an editablestream of the same video it does not happen.
The output video is still the same.
Here is the code.
 

 
        int noOfFrames;
        AviManager tempFile;
        VideoStream streamWrite;
        EditableVideoStream editableStream;
        AviManager coverFile;
        VideoStream streamRead;
 
        coverFile = new AviManager(loadedOriginalVidPath, true);
        streamRead = coverFile.GetVideoStream();
        editableStream = new EditableVideoStream(streamRead );
        noOfFrames = streamRead.CountFrames;
        streamRead.GetFrameOpen();
            
        currentFrameAsBitmap = streamReadIn.GetBitmap(noOfFrames - 1);
 
        // EncryptFileNameFrame is a method that changes the input bitmap file
        Bitmap fileNameFrame = EncryptFileNameFrame(currentFrameAsBitmap); 
 
        tempFile = new AviManager(System.IO.Path.GetTempFileName() + ".avi", false);
        tempFile.AddVideoStream(false, 1, bmp);
        streamWrite = tempFile.GetVideoStream();
        streamWrite.AddFrame(fileNameFrame );      
        editableStreamPaste(streamWrite, 0, noOfFrames - 1, streamWrite.CountFrames);
        tempFile.Close();
        streamWrite.Close()
        string OutputVidPath="some path";
        AviManager.MakeFileFromStream(OutputVidPath, editableStream);

QuestionSlow bitmap to avi creation with CVID (Cinepak) codecmembersmpack19 Apr '12 - 2:19 
First off, just wanted to say thanks for sharing your work -- this is really excellent.
 
I borrowed specific parts of your project to include in a simple screen capture to video project that I've been working on. My project simply captures bitmaps of the screen then uses your code to convert those bitmaps to avi. The problem I'm having is that it takes a really long time to encode the bitmaps to avi using the CVID codec. For example, a 30 second video composed of roughly 400 bitmaps will take about 20 minutes to create. The bitmaps are captured as jpegs and are typically about 180k each. Using the MSVC codec it's much quicker, but the quality is much worse. I created static AVICOPRESSOPTIONS for the CVID codec following some other posts I read.
 
I'm wondering if this is normal for the CVID codec, or if I may not have incorporated part of your code that would increase the efficiency of the avi creation? Or, perhaps, I haven't set static AVICOMPRESSOPTIONS correctly? Thanks for any ideas/suggestions and again for posting your project.
Questionhow to write part of application widow to vga or usb out as video streammemberjayachanakya14 Mar '12 - 20:11 
how to write part of application widow to vga or usb out as video stream, what i want is part of application (square selection of app winfrom window) view on LCD (not in my lap top other LCD ) screen.
QuestionChanging frame ratememberMember 768211925 Jan '12 - 21:40 
I try to change frame rate in an avi file using the demo application (Edit->Start Editing -> Change Frame Rate), but nothing happens with the file. What is wrong? Do I miss some important step?
 
Regards,
Aliaksei
QuestionCreate video from parts of other videomemberasdsa29 Nov '11 - 0:42 
Hi,
 
I'm trying to create a video from part of other video with the 'Paste' method
but I'm getting this exception:
 
'Exception in Paste: -214720518'
 
How can I fix this problem?
 
Thanks.
Question"Exception in VideoStreamGetFrameOpen!"memberCPBrendan23 Oct '11 - 1:12 
I downloaded and built the DLL for the AviFile library (using Microsoft C# Visual Studio 2010 Express).
 
I built a quick demo project, which includes -
 
AviManager aviManager = new AviManager(@"c:\a.avi", true);

VideoStream aviStream = aviManager.GetVideoStream();

aviStream.GetFrameOpen();
 
and ran it - it dies with "Exception in VideoStreamGetFrameOpen!" on the GetFrameOpen call.
 
Any best guesses as to what might be wrong? if I double click on the AVI file it opens and plays fine with Windows Media Player, so I'm assuming any necessary codecs are in place. The file is 687 MB in size. The VideoStream object seems to have correct information about the AVI file so it looks like the GetVideoStream call worked.
 

Brendan
AnswerRe: "Exception in VideoStreamGetFrameOpen!"memberskain22 May '12 - 10:54 
hi,
 
i have the same problem.
 
it fails at VideoStream.cs
 
GetFrameOpen()
.
.
.
if(getFrameObject == 0){ throw new Exception("Exception in VideoStreamGetFrameOpen!"); }
 
please assist
GeneralRe: "Exception in VideoStreamGetFrameOpen!"memberwatchara.knot22 Jul '12 - 6:17 
installed the DivX codec is work

http://www.divx.com/en/software/divx-plus/codec-pack/avi
GeneralRe: "Exception in VideoStreamGetFrameOpen!"memberMartin Lottering24 Sep '12 - 9:31 
Umm I tried your suggestion.
 
It didn't work, and now my media player crashes when I try to open an AVI that used to work.
 
Arrrrrgggggggg Java | [Coffee] Cry | :((
QuestionFLIP IMAGEmemberShargon_8511 Oct '11 - 2:34 
why is needed this?
 
public void AddFrame(Bitmap bmp)
{
           bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
}

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 12 Nov 2012
Article Copyright 2004 by Corinna John
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid