Compressing Video Data

Similar to decompressing video data, your driver will receive a series of messages when it is used to compress data. The client-application will send messages to your driver to coordinate the following activities:

The following messages are used by video compression drivers:

Message

Description

ICM_COMPRESS

Compresses a frame of data into the buffer provided by the client-application.

ICM_COMPRESS_BEGIN

Prepares for compressing data.

ICM_COMPRESS_END

Cleans up after compressing.

ICM_COMPRESS_GET_FORMAT

Obtains the driver's suggest the output format of the compressed data.

ICM_COMPRESS_GET_SIZE

Obtains the maximum size of one frame of data when it is compressed in the output format.

ICM_COMPRESS_QUERY

Determines if a driver can compress a specific input format.


The video compressed with these messages is returned to the client-application. When compressing data, your driver can use either software or hardware to do the compression.

Note:

When MSVideo recompresses a file, each frame is decompressed to a full frame before it is passed to the compressor.

Obtaining the Driver State

The client-application obtains the driver state by sending ICM_GETSTATE. The client-application determines the size of the buffer needed for the state information by sending this message with dwParam1 set to NULL. Your driver should respond to the message by returning the size of the buffer it needs for state information.

After it determines the buffer size, the client-application resends the message with dwParam1 pointing to a block of memory it allocated. The dwParam2 parameter specifies the size of the memory block. Your driver should respond by filling the memory with its state information. If your driver uses state information, include only optional decompression parameters with the state information. State information typically includes the setup specified by user with the ICM_CONFIGURE dialog box. Any information required for decompressing the image data must be included with the format data. When done, your driver should return the size of the state information.

The client-application does not validate any data in the state information. It simply stores the state information in the 'strd' data chunk of the AVI file.

Specifying the Input Format and Determining the Compression Format

The client-application uses the ICM_COMPRESS_GET_FORMAT or ICM_COMPRESS_QUERY message to specify the input format and determine the compression (output) format. The client-application sends ICM_COMPRESS_GET_FORMAT if it wants your driver to suggest the compressed format. The client-application sends ICM_COMPRESS_QUERY to determine if your driver supports a format it is suggesting.

Both messages have a pointer to a BITMAPINFO data structure in dwParam1. This structure specifies the format of the incoming uncompressed data. The contents of dwParam2 depends on the message.

If the client-application wants your driver to suggest the format, it determines the size of the buffer needed for the compressed data format by sending ICM_COMPRESS_GET_FORMAT. When requesting the buffer size, the client-application uses dwParam1 to point to a BITMAPINFO structure and sets dwParam2 to NULL. Based on the input format, your driver should return the number of bytes needed for the format buffer. Return a buffer size at least large enough to hold a BITMAPINFOHEADER data structure and a color table.

The client-application gets the output format by sending ICM_COMPRESS_GET_FORMAT with valid pointers to BITMAPINFO structures in both dwParam1 and dwParam2. Your driver should return the output format in the buffer pointed to by dwParam2. If your driver can produce multiple formats, the format selected by your driver should be the one that preserves the greatest amount of information rather than one that compresses to the most compact size. This will preserve image quality if the video data is later edited and recompressed.

The output format data becomes the 'strf' chunk in the AVI RIFF file. The data must start out like a BITMAPINFOHEADER data structure. You can include any additional information required to decompress the file after the BITMAPINFOHEADER data structure. A color table (if used) follows this information.

If you have format data following the BITMAPINFOHEADER structure, update the biSize member to specify the number of bytes used by the structure and your additional data. If a color table is part of the BITMAPINFO information, it follows immediately after your additional information.

If your driver cannot handle the input format, it returns ICMERR_BADFORMAT to fail the message.

If your driver gets ICM_COMPRESS_QUERY, the dwParam1 parameter points to a BITMAPINFO data structure containing the input format data. The dwParam2 parameter will either be NULL or contain a pointer to a BITMAPINFO structure describing the compressed format the client-application wants to use. If dwParam2 is NULL, your compression driver can use any output format. (The client-application just wants to know if your driver can handle the input.) If dwParam2 points to a BITMAPINFO structure, the client-application is suggesting the output format.

If your driver supports the specified input and output format, or it supports the specified input with NULL specified for dwParam2, return ICERR_OK to indicate the driver accepts the formats. Your driver does not have to accept the suggested format. If you fail the message by returning ICERR_BADFORMAT, the client-application suggests alternate formats until your driver accepts one. If your driver exhausts the list of formats normally used, the client-application requests a format with ICM_COMPRESS_GET_FORMAT.

Initialization for the Compression Sequence

When the client-application is ready to start compressing data, it sends the ICM_COMPRESS_BEGIN message. The client-application uses dwParam1 to point to the format of the data being compressed, and uses dwParam2 to point to the format for the compressed data. If your driver cannot handle the formats, or if they are incorrect, your driver should return ICERR_BADFORMAT to fail the message.

Before the client-application starts compressing data, it sends ICM_COMPRESS_GET_SIZE. For this message the client-application uses dwParam1 to point to the input format and uses dwParam2 to point to the output format. Your driver should return the worst case size (in bytes) that it expects a compressed frame to occupy. The client-application uses this size value when it allocates buffers for the compressed video frame.

Compressing the Video

The client-application sends ICM_COMPRESS for each frame it wants compressed. It uses dwParam1 to point to an ICCOMPRESS structure containing the parameters used for compression. Your driver uses the buffers pointed to by the members of ICCOMPRESS for returning information about the compressed data.

Your driver returns the actual size of the compressed data in the biSizeImage member in the BITMAPINFOHEADER data structure pointed to by the lpbiOutput member of ICCOMPRESS.

The format of the input data is specified in a BITMAPINFOHEADER structure pointed to by the lpbiInput member of ICDECOMPRESS. The input data is in a buffer specified by the lpInput member. The lpbiOutput and lpOutput members contain pointers to the format data and buffer used for the output data. Your driver must indicate the size of the compressed video data in the biSizeImage member in the BITMAPINFO structure specified for lpbiOutput.

The dwFlags member specifies flags used for compression. The client-application sets ICM_COMPRESS_KEYFRAME flag if the input data should be treated as a key frame. (A key frame is one that does not require data from a previous frame for decompression.) When this flag is set, your driver should treat the image as the initial image in a sequence.

The lpckid member specifies a pointer to a buffer used to return the chunk ID for data in the AVI file. Your driver should assign a two-character code for the chunk ID only if it uses a custom chunk ID.

The lpdwFlags member specifies a pointer to a buffer used to return flags for the AVI index. The client-application will add the returned flags to the file index for this chunk. If the compressed frame is a key frame (a frame that does not require a previous frame for decompression), your driver should set the AVIIF_KEYFRAME flag in this member. Your driver can define its own flags but they must be set in the high word only.

The lFrameNum member specifies the frame number of the frame to compress. If your driver is performing fast temporal compression, check this member to see if frames are being sent out of order or if the client-application is having a frame recompressed.

The dwFrameSize member indicates the maximum size (in bytes) desired for the compressed frame. If it specifies zero, your driver determines the size of the compressed image. If it is non-zero, your driver should try to compress the frame to within the specified size. This might require your driver to sacrifice image quality (or make some other trade-off) to obtain the size goal. Your driver should support this if it sets the VIDCF_CRUNCH flag when it responds to the ICM_GETINFO message.

The dwQuality member specifies the compression quality. Your driver should support this if it sets the VIDCF_QUALITY flag when it responds to the ICM_GETINFO message.

The format of the previous data is specified in a BITMAPINFOHEADER structure pointed to by lpbiPrev. The input data is in a buffer specified by lpPrev. Your driver will use this information if it performs temporal compression (that is, it needs the previous frame to compress the current frame). If your driver supports temporal compression, it should set the VIDCF_TEMPORAL flag when it responds to the ICM_GETINFO message. If your driver supports temporal compression and does not need the information in the lpbiPrev and lpPrev members, it should set the VIDCF_FASTTEMPORALC flag when it responds to the ICM_GETINFO message. The VIDCF_FASTEMPORALC flag can decrease the processing time because your driver does not need to access data specified in lpbiPrev and lpPrev.

When your driver has finished compressing the data, it returns ICERR_OK.

Ending Compression

Your driver receives ICM_COMPRESS_END when the client-application no longer needs data compressed, or when the client-application is changing the format or palette. After sending ICM_COMPRESS_END, the client-application must send ICM_COMPRESS_BEGIN to continue compressing data. Your driver should not expect the client-application to send a ICM_COMPRESS_END message for each ICM_COMPRESS_BEGIN message. The client-application can use ICM_COMPRESS_BEGIN to restart compression without sending ICM_COMPRESS_END.

When the driver is no longer needed, the system will close it by sending DRV_CLOSE.