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

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.

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:

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:

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.

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:

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:

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:

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:

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:

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:

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:

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:

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:

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

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

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.

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"

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?

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.

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.

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.

Thank you for creating this immensely usefull set of classes - i've been glad to have it!

I found a small bug in AddAudioStream(...) which will cause VLC (and probably other applications) to complain about a broken file, although the file itself can be used in VirtualDub without problems:

AddAudioStream(...) calls Avi.AVIStreamWrite, but third parameter (iSamples) is set to streamLength (which is the number of bytes in this stream) where it _should_ be set to the number of _samples_ in this stream. Usually, with 16 bit stereo streams there are 4 bytes to each sample, so iSamples should be streamLength/4, but a more general approach is to set iSamples to streamLength / streamInfo.dwSampleSize.