Library for Raw Video Processing

This project is built to be used as a library to perform image processing on AVI files through exclusive use of Microsoft AVIFile API. The main task this library is built for is defined below:

  • Open AVI file on a disk
  • Read AVI video stream, frame by frame, as raw RGB data
  • Perform some processing on raw image data
  • Save the resulting video, frame by frame, into another AVI file

The main limitation in this library is that the result of AVI file generation can only be uncompressed video, which is somewhat expensive in terms of disk-space. As an attempt to make it somewhat useful, we add a stand along function to compress the video from one file into another.

The library consists of a single implementation file "RawAVIStream.cpp" and a single header file "RawAVIStream.h". In advance to the core files there is a sample code that uses this library in "test.cpp".

The code is built with "Microsoft Visual Studio 2008, 9.0.30729.1 SP" and "Microsoft Platform SDK for Windows XP SP2". All the relevant files are included, except codecs, MSVCRT redistributable, etc.

Following is an explanation on how the API is used.

Reading from an AVI File

Here is the minimal code needed to open an AVI file and initiate reading raw data:
	// Error handling is intentionally leaved out for clarity
	PAVISTREAM ppavi;
	AVIFileInit();
	AVIStreamOpenFromFile(&ppavi, filename, streamtypeVIDEO, 0, OF_READ, NULL);

	BITMAPINFOHEADER bi;
	long format_length = sizeof(bi);
	AVIStreamReadFormat(ppavi, 0, &bi, &format_length);
	bi.biBitCount = 24;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	PGETFRAME getframe = AVIStreamGetFrameOpen(ppavi, avi->bi);

	AVIStreamRelease(ppavi);

The main function in this code block is AVIStreamGetFrameOpen. In case this function runs successfully, we have a pointer that allows us to read video data, frame by frame, like this:

	void *buffer = AVIStreamGetFrame(avi->getframe, index);
	CopyMemory(target, (BYTE*)buffer + ((BITMAPINFOHEADER*)buffer)->biSize, ((BITMAPINFOHEADER*)buffer)->biSizeImage);

The auxiliary function used is AVIStreamReadFormat. Obviously, we can fill-in BITMAPINFOHEADER without this function. However, we have to determine the frame size somehow. In this code we use AVIStreamOpenFromFile because we are only interested in video processing. The alternative to this call is AVIFileOpen/AVIFileGetStream.

Writing into an AVI File

Creating an uncompressed AVI file from a set of raw data frames is performed using the same API:

	// Error handling is intentionally leaved out for clarity
	BITMAPINFOHEADER bi;
	PAVIFILE pavifile;
	AVISTREAMINFO info;
	PAVISTREAM ppavi;
	AVIFileInit();

	// Create empty AVI file
	AVIFileOpen(&pavifile, filename, OF_WRITE | OF_CREATE, NULL);

	// Create a video stream with minimum data needed.
	ZeroMemory(&info, sizeof(info));
	info.fccType = streamtypeVIDEO;
	info.dwScale = 1;
	info.dwRate = 25;	// This is rather arbitrary, although inspired by PAL TV standard
	AVIFileCreateStream(pavifile, &ppavi, &info);
	AVIFileRelease(pavifile);

	// Set data format to raw RGB, compatible to the format specified in RawAVIReader above.
	// Unfortunately, we can't specify MPEG compression, although MPEG schema is designed
	// for streaming. If we do specify compression, it must be done outside somehow.
	// We specify only minimal data needed to render a valid AVI video.
	ZeroMemory(&bi, sizeof(bi));
	bi.biSize = sizeof(bi);
	bi.biWidth = width;
	bi.biHeight = height;
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	bi.biCompression = BI_RGB;
	bi.biXPelsPerMeter = 1000;
	bi.biYPelsPerMeter = 1000;
	AVIStreamSetFormat(ppavi, 0, &bi, sizeof(bi));

After this code is performed, we have a variable 'ppavi' pointing into a valid AVI stream handler. Having this handler, we do:

	BYTE *frameRGB = new BYTE[3 * width * height];
	...
	fillInTheFrame(frameRGB, width, height); // What-ever does it mean
	AVIStreamWrite(ppavi, index, 1, frameRGB,
		3 * width * height,
		0, NULL, NULL);

MPEG Encoder

In advance of the core task of encoding/decoding raw AVI data, this library implements a stand-alone function that compresses one file into another using the Microsoft implemented MPEG codec. The choice

options.fccHandler = mmioFOURCC('M','S','V','C');

is taken from MSDN and is thought to be found on most Windows machines. The simplest use of this codec is:

	AVICOMPRESSOPTIONS options;
	PAVISTREAM ppavi;
	AVIStreamOpenFromFile(&ppavi, source, streamtypeVIDEO, 0, OF_READ, NULL);

	memset(&options, 0, sizeof(options));
	options.fccType = streamtypeVIDEO;
	options.fccHandler = mmioFOURCC('M','S','V','C');
	options.dwKeyFrameEvery = 2;
	options.dwQuality = 1;
	options.dwFlags = AVICOMPRESSF_KEYFRAMES;
	AVISave(target, NULL, NULL, 1, ppavi, &options);

The codec to be used with this API must be registered through Video Compression Manager as defined in Video Compression Manager and ICInstall Function



Downloads

Comments

  • Clarification

    Posted by arkadi on 06/19/2011 04:42pm

    The purpose of this article & library is to read *non-raw* video frame by frame.
    Any meaningful processing is out of scope.
    The library is intended for users who *know* what is a meaningful processing for them.

    • How to read the raw AVI?

      Posted by Jinwei Feng on 01/15/2014 02:13pm

      Is there any particular reason that it cannot read the raw AVI? I have to read the raw AVI files. How to do that? Thanks

      Reply
    Reply
  • Missing the point...

    Posted by PeejAvery on 06/19/2011 03:23pm

    The title is misleading. This is not reading any RAW video format. It's frame-by-frame video conversion of non-RAW video encodings.
    
    The whole premise of this article is to read frame-by-frame in order to do editing with each individual frame. However, nowhere in the article is anything discussed about what is being done to the frames. In essence, the article only shows how to duplicate encoded video to a non-compressed copy of the exact same video. Which...if you started with compressed video in the first place...is just wasting disk space.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Not all enterprise applications are created equal. Sophisticated applications need developer support but other more basic apps do not. With the right tools, everyone is a potential app developer with ideas and a perspective to share. Trends such as low-code development and model driven development are fundamentally changing how and who creates applications. Is your organization ready? Read this report and learn: The seven personas of enterprise app delivery How application ownership is spreading to the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds