Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
96 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Introduction
 Files
 Streams
 Processing
 Cleaning Up

 Printable version
 Discuss this article
 in the forums


Processing an Audio Stream

Streams of this type are typically uncompressed, so it’s probably best to describe that method. We’ll start by determining the size of the audio data contained in the stream.

LONG lSize; if(AVIStreamRead(pStream, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL)) // error

Since we already know the stream’s format, we’ll load the sound data into a byte buffer.

LPBYTE pBuffer = new BYTE[lSize]; if(!pBuffer) // error if(AVIStreamRead(pStream, 0, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, NULL)) // error

So now with the sound format and data, it’s a simple task to create a DirectSound buffer, play it back through a Win32 multimedia function, or custom library. Changing the function calls won’t do anything special, but you can read about the parameters if you want in the online docs.

Processing a Video Stream

The great thing about AVIFile is that it handles decompression of video for us. We’ll initialize that feature in the following code.

Since we determined what format the frames are stored in earlier, you can modify it slightly, or calculate a new format from scratch, and have AVIFile convert the frames into whatever format best suits your rendering system.

The PGETFRAME pointer is used by the system to handle the decompression of the video frames. The NULL parameter says I just want AVIFile to leave the image format the way it is. You can try passing a BITMAPINFO pointer, perhaps by changing the image format that was loaded before.

PGETFRAME pgf; pgf = AVIStreamGetFrameOpen(pStream, NULL); if(!pgf) // error

Now that the decompression system has been initialization, we can enter the loop that plucks and displays each frame for this video stream. AVIFile is organized so you only need one frame in memory at a time, allowing you to quickly play large files, but you can copy or buffer the frames as needed.

Next we’ll determine which frame we need to pluck from the stream. Usually that’s accomplished by incrementing the value lTime each millisecond via a multimedia timer, or calculating it via the difference in time between frame renderings. The API functions are then used to calculate a frame value based on the amount of time elapsed since the beginning of play. This allows accurate playback for whatever the file specifies as its playback speed, regardless of the time it takes us to render a frame. With this code you’ll be able to synchronize the video with speech or game events. Alternatively you can calculate the lFrame variable through any means depending on what effect you’re accomplishing.

// Precalculated: When stream is opened lEndTime = AVIStreamEndTime(pStream); // Calculated just before next frame is blitted if(lTime <= lEndTime) lFrame = AVIStreamTimeToSample(pStream, lTime); else // the video is done

With that information, it’s easy to pluck a packed DIB from the video stream.

LPBITMAPINFOHEADER lpbi; lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, lFrame);

The packed DIB is comprised of a BITMAPINFOHEADER structure, followed by the palette information if needed, and then followed by the bitmap data. All of this is just one sequential block of memory, so it’s possible to calculate the palette and bitmap pointers using pointer arithmetic.

// For 16, 24, or 32bit image formats LPBYTE pData = lpbi + lpbi->biSize; // For 8bit image formats LPBYTE pData = lpbi + lpbi->biSize + 256 * sizeof(RGBQUAD);

The image data that has been extracted is only good until the next time we call AVIStreamGetFrame, so it’s important to display it to screen, copy it to a texture or bmp file, or whatever you want to do with it. I don’t go into such details here, but you’ll see how in the provided sample code.

When all of the frames have been processed, it’s important to close down the decompression system as follows.

if(AVIStreamGetFrameClose(pgf)) // error




Next : Cleaning Up