Microsoft RIFF

Also Known As: RIFF, Resource Interchange File Format, RIFX, .WAV, .AVI, .BND, .RMI, .RDI


Type Multimedia
Colors 24-bit
Compression RLE, uncompressed, audio, video
Maximum Image Size Varies
Multiple Images Per File No
Numerical Format Little- and big-endian
Originator Microsoft Corporation
Platform Microsoft Windows 3.x, Windows NT
Supporting Applications Microsoft Windows and OS/2 multimedia applications
See Also IFF, Chapter 10, Multimedia

Usage
RIFF is a device control interface and common file format native to the Microsoft Windows system. It is used to store audio, video, and graphics information used in multimedia applications.

Comments
A complex format designed to accommodate various types of data for multimedia applications. Because it is quite new and vendor-controlled, the specification is likely to change in the future.

Vendor specifications are available for this format.


Microsoft RIFF (Resource Interchange File Format) is a multimedia file format created by Microsoft for use with the Windows GUI. RIFF itself does not define any new methods of storing data, as many of the bitmap formats described in this book do. Instead, RIFF defines a structured framework, which may contain existing data formats. Using this concept, you can create new, composite formats consisting of two or more existing file formats.

Contents:
File Organization
File Details
For Further Information

Multimedia applications require the storage and management of a wide variety of data, including bitmaps, audio data, video data, and peripheral device control information. RIFF provides an excellent way to store all these varied types of data. The type of data a RIFF file contains is indicated by the file extension. Examples of data that may be stored in RIFF files are:

NOTE:

At this point, AVI files are the only type of RIFF files that have been fully implemented using the current RIFF specification. Although WAV files have been implemented, these files are very simple, and their developers typically use an older specification in constructing them.

Because RIFF is an umbrella name for a variety of multimedia files, RIFF files are referred to by the type of data they contain, rather than by the actual format name of RIFF. For this reason, you may find RIFF files rather confusing when you start to use them. For example, a RIFF file containing Audio/Visual Interleaved data is normally referred to simply as an "AVI file" and not as a "RIFF Audio/Visual Interleaved Format File." Only a programmer might ever realize that all of these different files are the same format, or even care.

There is another area of potential confusion. Some people think that RIFF files are somehow similar in design to TIFF (Tag Image File Format) files. While it is true that both formats contain data structures that may be added or deleted to a file ("tags" in TIFF and "chunks" in RIFF), the internal concept and design of these structures within RIFF and TIFF differ greatly. Unlike TIFF, the RIFF file format is based on the Electronic Arts Interchange File Format (IFF) structure (see the article describing this format). And, although both formats use the same concept of data storage, they are not compatible in their design.

File Organization

RIFF is a binary file format containing multiple nested data structures. Each data structure within a RIFF file is called a chunk. Chunks do not have fixed positions within a RIFF file, and therefore standard offset values cannot be used to locate their fields. A chunk contains data such as a data structure, a data stream, or another chunk called a subchunk. Every RIFF chunk has the following basic structure:

typedef struct _Chunk
{
    DWORD ChunkId;              /* Chunk ID marker */
    DWORD ChunkSize;            /* Size of the chunk data in bytes */
    BYTE ChunkData[ChunkSize];  /* The chunk data */
} CHUNK;

ChunkId contains four ASCII characters that identify the data the chunk contains. For example, the characters RIFF are used to identify chunks containing RIFF data. If an ID is smaller than four characters, it is padded on the right using spaces (ASCII 32). Note that RIFF files are written in little-endian byte order. Files written using the big-endian byte ordering scheme have the identifier RIFX.

ChunkSize is the length of the data stored in the ChunkData field, not including any padding added to the data. The size of the ChunkId and ChunkSize fields are not themselves included in this value.

ChunkData contains data that is WORD-aligned within the RIFF file. If the data is an odd length in size, an extra byte of NULL padding is added to the end of the data. The ChunkSize value does not include the length of the padding.

Subchunks also have the same structure as chunks. A subchunk is simply any chunk that is contained within another chunk. The only chunks that may contain subchunks are the RIFF file chunk RIFF and the list chunk, LIST (explained in the next section). All other chunks may contain only data.

A RIFF file itself is one entire RIFF chunk. All other chunks and subchunks in the file are contained within this chunk. If you are decoding, your RIFF reader should ignore any chunks that the reader does not recognize or it cannot use. If you are encoding, your RIFF writer will write out all unknown and unused chunks that were read. Do not discard them.

File Details

RIFF files that are used to store audio and video information are called AVI files. The RIFF AVI file format normally contains only a single AVI chunk; however, other types of chunks may also appear. An AVI reader should ignore all chunks it does not need or recognize that are stored within a RIFF AVI file.

Although Microsoft uses a standard notation to describe the internal arrangement of data structures within RIFF files, we believe it is clearer to use our own C-like syntax to illustrate the placement of chunks and subchunks within a RIFF AVI file. The ChunkId for each chunk is listed in the comments:

struct _RIFF   /* "RIFF" */
{
    struct _AVICHUNK   /* "AVI " */
    {
        struct _LISTHEADERCHUNK   /* "hdrl" */
        {
            AVIHEADER AviHeader;     /* "avih" */
            struct _LISTHEADERCHUNK  /* "strl" */
            {
                AVISTREAMHEADER	StreamHeader; /* "strh" */
                AVISTREAMFORMAT	StreamFormat; /* "strf" */
                AVISTREAMDATA	StreamData;   /* "strd" */
            }
        }
        struct _LISTMOVIECHUNK  /* "movi" */
        {
            struct _LISTRECORDCHUNK  /* "rec " */
            {
                /* Subchunk 1 */
                /* Subchunk 2 */
                /* Subchunk N */
            }
        }
        struct _AVIINDEXCHUNK  /* "idx1" */
        {
            /* Index data */
        }
    }
}

The above structure represents the internal data layout of a RIFF file containing only one AVI chunk. This chunk follows the format of the chunk data structure previously described. The AVI chunk is identified by the 4-character chunk identifier "AVI " (note the final blank character). The AVI chunk contains two mandatory LIST subchunks, which indicate the format of the data stream(s) stored in the file.

AVI Header Subchunk

The first mandatory LIST chunk contains the main AVI header subchunk and has the identifier hdrl. The information in the header subchunk defines the format of the entire AVI chunk. The hdrl chunk must appear as the first chunk within the AVI chunk. The format of the header subchunk is the following:

typedef struct _AVIHeader
{
    DWORD TimeBetweenFrames;     /* Time delay between frames */
    DWORD MaximumDataRate;       /* Data rate of AVI data */
    DWORD PaddingGranularity;    /* Size of single unit of padding */
    DWORD Flags;                 /* Data parameters */
    DWORD TotalNumberOfFrames;   /* Number of video frame stored */
    DWORD NumberOfInitialFrames; /* Number of preview frames */
    DWORD NumberOfStreams;       /* Number of data streams in chunk*/
    DWORD SuggestedBufferSize;   /* Minimum playback buffer size */
    DWORD Width;                 /* Width of video frame in pixels */
    DWORD Height;                /* Height of video frame in pixels*/
    DWORD TimeScale;             /* Unit used to measure time */
    DWORD DataRate;              /* Data rate of playback */
    DWORD StartTime;             /* Starting time of AVI data */
    DWORD DataLength;            /* Size of AVI data chunk */
} AVIHEADER;

TimeBetweenFrames contains a value indicating the amount of delay between frames in microseconds.

MaximumDataRate value indicates the data rate of the AVI data in bytes per second.

PaddingGranularity specifies the multiple size of padding used in the data in bytes. When used, the value of this field is typically 2048.

Flags contains parameter settings specific to the AVI file and its data. The parameters correspond to the bit values of the Flags field as follows:

Bit 4

AVI chunk contains an index subchunk (idx1).

Bit 5

Use the index data to determine how to read the AVI data, rather than the physical order of the chunks with the RIFF file.

Bit 8

AVI file is interleaved.

Bit 16

AVI file is optimized for live video capture.

Bit 17

AVI file contains copyrighted data.

TotalNumberOfFrames indicates the total number of frames of video data stored in the movi subchunk.

NumberOfInitialFrames specifies the number of frames in the file before the actual AVI data. For non-interleaved data this value is 0.

NumberOfStreams holds the number of data streams in the chunk. A file with an audio and video stream contains a value of 2 in this field, while an AVI file containing only video data has 1. In the current version of the RIFF format, one audio and one video stream are allowed.

SuggestedBufferSize is the minimum size of the buffer to allocate for playback of the AVI data. For non-interleaved AVI data, this value is at least the size of the largest chunk in the file. For interleaved AVI files, this value should be the size of an entire AVI record.

Width and Height values indicate the size of the video image in pixels.

TimeScale is the unit used to measure time in this chunk. It is used with DataRate to specify the time scale that the stream will use. For video streams, this value should be the frame rate and typically has a value of 30. For audio streams, this value is typically the audio sample rate.

DataRate is divided by the TimeScale value to calculate the number of samples per second.

StartTime is the starting time of the AVI data and is usually 0.

DataLength is the size of the AVI chunk in the units specified by the TimeScale value.

The hdrl subchunk also contains one or more LIST chunks with the identifier strl. There will be one of these LIST chunks per data stream stored in the AVI chunk.

Three subchunks are stored within the strl LIST chunk. The first is the Stream Header subchunk, which has the identifier strh. This header contains information specific to the data stream stored in the strl LIST chunk. A stream header is required and has the following format:

typedef struct _StreamHeader
{
    char  DataType[4];           /* Chunk identifier ("strl") */
    char  DataHandler[4];        /* Device handler identifier */
    DWORD Flags;                 /* Data parameters */
    DWORD Priority;              /* Set to 0 */
    DWORD InitialFrames;         /* Number of initial audio frames */
    DWORD TimeScale;             /* Unit used to measure time */
    DWORD DataRate;              /* Data rate of playback */
    DWORD StartTime;             /* Starting time of AVI data */
    DWORD DataLength;            /* Size of AVI data chunk */
    DWORD SuggestedBufferSize;   /* Minimum playback buffer size */
    DWORD Quality;               /* Sample quailty factor */
    DWORD SampleSize;            /* Size of the sample in bytes */
} STREAMHEADER;

DataType contains a 4-character identifier indicating the type of data the stream header refers to. Identifiers supported by the current version of the RIFF format are: vids for video data and auds for audio data.

DataHandler may contain a 4-character identifier specifying the preferred type of device to handle the data stream.

Flags contains a set of bit flags use to indicate parameter settings related to the data.

Priority is set to 0.

InitialFrames indicates in seconds how far the audio is placed ahead of the video in interleaved data.

TimeScale, DataRate, StartTime, DataLength, and SuggestedBufferSize all have the same function as the fields of the same names in the hdr1 chunk.

Quality is an integer in the range of 0 to 10,000, indicating the quality factor used to encode the sample.

SampleSize is the size of a single sample of data. If this value is 0, the sample varies in size and each sample is stored in a separate subchunk. If this value is non-zero, then all the samples are the same size and are stored in a single subchunk.

Immediately following the stream header is a stream format subchunk with the identifier strf. This header describes the format of the stream data. Its format varies depending on the type of data that is stored (audio or video). This subchunk is also required.

Another stream data subchunk with the identifier strd can optionally follow the stream format subchunk. The data in this chunk is used to configure the drivers required to interpret the data. The format of this chunk also varies depending upon the type of compression used on the stream data.

AVI Data Subchunk

The second mandatory LIST chunk contains the actual AVI data, has the identifier movi, and must appear as the second chunk within the AVI chunk.

The data in the movi chunk may be grouped in the form of LIST records (a LIST chunk containing one or more subchunks each with the identifier "rec "). Only data that is interleaved to be read from a CD-ROM is stored as a series of LIST records (data is read more efficiently from a CD-ROM when it is interleaved). If the data is not interleaved, it is stored as a single block of data within the movi chunk itself.

Index Chunk

The AVI chunk may also contain a third chunk, called an index chunk. An index chunk has the identifier idx1 and must appear after the hdrl and movi chunks. This chunk contains a list of all chunks within the AVI chunk, along with their locations, and is used for random access of audio and video data. The index chunk has the following format:

typedef struct _AviIndex
{
    DWORD Identifier;    /* Chunk identifier reference */
    DWORD Flags;         /* Type of chunk referenced */
    DWORD Offset;        /* Position of chunk in file */
    DWORD Length;        /* Length of chunk in bytes */
} AVIINDEX;

Identifier contains the 4-byte identifier of the chunk it references (strh, strf, strd, and so on).

Flags bits are used to indicate the type of frame the chunk contains or to identify the index structure as pointing to a LIST chunk.

Offset indicates the start of the chunk in bytes relative to the movi list chunk.

Length is the size of the chunk in bytes.

The idx1 chunk contains one of these structures for every chunk and subchunk in the AVI chunk. The structures need not index each chunk in the order in which they occur within the AVI chunk. The order of the index structures in the idx1 may also be used to control the presentation order of the data stored in the AVI chunk. If an index is included in an AVI chunk, the appropriate indication bit must be set in the Flags field of the AVI header chunk. If an application reading a RIFF file decides to use the information in the index chunk, it must first find the hdrl chunk and determine if an index chunk exists by examining the Flags field value in the AVI header. If it does exist, the reader will skip past all the chunks in the AVI chunk until it encounters the idx1 chunk.

JUNK Chunk

One other type of chunk that is commonly encountered in an AVI chunk is the padding or JUNK chunk (so named because its chunk identifier is JUNK). This chunk is used to pad data out to specific boundaries (for example, CD-ROMs use 2048-byte boundaries). The size of the chunk is the number of bytes of padding it contains. If you are reading AVI data, do not use use the data in the JUNK chunk. Skip it when reading and preserve it when writing. The JUNK chunk uses the standard chunk structure:

typedef struct _JunkChunk
{
    DWORD ChunkId;             /* Chunk ID marker (JUNK)*/
    DWORD PaggingSize;         /* Size of the padding in bytes */
    BYTE Padding[ChunkSize];   /* Padding */
} JUNKCHUNK;

For Further Information

For further information about the Microsoft RIFF format, see the specification included on the CD-ROM.

If you write an application that recognizes the RIFF file format, you will need to get a copy of the Microsoft Multimedia Development Kit (MDK). The MDK contains all the tools and documentation necessary to work with RIFF files, as well as with the other details of Microsoft Windows multimedia.

For information about Microsoft multimedia products, including the MDK, contact Microsoft:

Microsoft Corporation
Attn: Multimedia Systems Group
Product Marketing
One Microsoft Way
Redmond, WA 98052-6399
WWW: http://www.microsoft.com/

For specific information about Microsoft AVI and the RIFF file formats, see the following Microsoft documents:

Microsoft Corporation. Microsoft Windows Multimedia Programmer's Guide, Microsoft Press, Redmond, WA.

Microsoft Corporation. Microsoft Windows Multimedia Programmer's Reference, Microsoft Press, Redmond, WA.

See also the discussion and additional references in Chapter 10, in this book.

You may also be able to get information via FTP through the Developer Relations Group at:

ftp://ftp.microsoft.com/developer/drg/



Copyright © 1996, 1994 O'Reilly & Associates, Inc. All Rights Reserved.