A stream’s information is obtained simply through the use of this function.
Like the file’s info, this stuff isn’t essential for processing an AVI file. There are some things you can calculate from the structure members, but I’ve found an easier way to determine these values that’s described later.
Since a stream can be of numeral kinds, we need to know its format. First of all, we must know how long the format data is. The following code accomplishes that.
Audio Stream Specifics
The format data for an audio stream is based on the WAVEFORMAT structure, but it may have a few extra data members at the end and a different structure name. You can tell what structure it is by comparing the lSize variable with the sizeof(WAVEFORMATEX) or sizeof(PCMWAVEFORMAT). These structures, and most others, simply extend WAVEFORMAT with a few extra bytes.
PCMWAVEFORMAT includes the important wBitsPerSample member, and WAVEFORMATEX includes both wBitsPerSample and cbSize. The cbSize member tells how many extra bytes are stored after the WAVEFORMATEX structure. The extra bytes are for non-Pulse Code Modulation (PCM) formats, if you want to support those. Usually you’ll only find PCM formats, but the code you’re about to see supports all of them.
We’ll accomplish that by reading in a chunk and casting it to a WAVEFORMAT pointer.
LPBYTE pChunk = new BYTE[lSize];
if(!pChunk)
// allocation error
if(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), pChunk, &lSize))
// error
LPWAVEFORMAT pWaveFormat = (LPWAVEFORMAT)pChunk;
Now that we know the audio format, we are better equipped to interpret the actual sound information in order to play it back. It’s not necessary to be familiar with the structure members just yet.
Video Stream Specifics
The BITMAPINFO structure defines the format for a video stream. That structure contains one of the BITMAPINFOHEADER, BITMAPV4HEADER, or BITMAPV5HEADER structures, followed by the palette information if the image format is 8bits per pixel. Software for Windows 98 or Windows2000 should write the BITMAPV5HEADER, but for reading an AVI file we need to determine which version was stored in the file in order to be backward compatible. That’s easiest by allocating and reading it all in one chunk like we did with the sound format.
LPBYTE pChunk = new BYTE[lSize];
if(!pChunk)
// allocation error
if(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), pChunk, lSize))
// error
The reason why that’s possible, is because each structure begins with the same information as BITMAPINFO, but adds a few extra members to the previous version. If you determine that you need these extra members for a project you’re working on, it’s easy to cast the data chunk over to the appropriate structure pointer:
// Only if you need to:
LPBITMAPINFO pInfo = (LPBITMAPINFO)pChunk;
DWORD biSize = pInfo->bmiHeader.biSize;
switch(biSize)
{
case sizeof(BITMAPV5HEADER):
// ...
case sizeof(BITMAPV4HEADER):
// ...
case sizeof(BITMAPINFOHEADER):
// ...
};
The BITMAPINFO structure tells us a lot about the image format. It tells what type of compression is used, the frame size, bit depth, etc. That’s all the necessary information one needs when converting image data over to a GDI HBITMAP, MFC CBitmap, LPDIRECTDRAWSURFACE, or custom format.