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.
Since we already know the stream’s format, we’ll load the sound data into a byte buffer.
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. 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.
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.
With that information, it’s easy to pluck a packed DIB from the video stream.
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.
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.
|