Decompressing Directly to Video Hardware

Drivers that can render video directly to hardware should support the ICM_DRAW messages in addition to the ICM_DECOMPRESS messages. The ICM_DRAW messages decompress data directly to hardware rather than into a data buffer returned to the client-application by the decompression driver.

Your driver will receive a series of messages from the client-application to coordinate the following activities to decompress a video sequence:

The following ICM_DRAW messages are used by video decompression drivers for these decompression activities:

Message

Description

ICM_DRAW

Decompresses a frame of data and draws it.

ICM_DRAW_BEGIN

Prepares to draw data.

ICM_DRAW_END

Clean up after decompressing an image to the screen.

ICM_DRAW_REALIZE

Realizes a palette.

ICM_DRAW_QUERY

Determines if the driver can render data in a specific format.

ICM_DRAW_SUGGESTFORMAT

Has the driver suggest and output format.


The video decompressed with the ICM_DRAW messages is retained by your driver and it handles the display of data. These messages control only the decompression process. The messages used to control the drawing are described separately. Your driver will receive the ICM_DRAW messages only if it sets the VIDCF_DRAW flag when it responds to the ICM_GETINFO message.

Setting the Driver State

The client-application restores the driver state by sending ICM_SETSTATE. The process for handling this message is the same as for the ICM_DECOMPRESS messages.

Specifying the Input and Output Formats

Because your driver handles the drawing of video, the client-application does not need to determine the output format. The client-application needs to know only if your driver can handle the input format. It sends ICM_DRAW_QUERY to determine if your driver supports the input format. The input format is specified with a pointer to a BITMAPINFO data structure in dwParam1. The dwParam2 parameter is not used.

If your driver supports the specified input format, return ICERR_OK to indicate the driver accepts the formats. If your driver does not support the format, return ICERR_BADFORMAT.

Your driver might also receive the ICM_DRAW_SUGGESTFORMAT message. Typically, this message is sent by the decompression portion of the driver to the drawing portion of the driver to obtain the best decompressed format for the data when the drawing portion can handle several formats. The dwParam1 parameter of ICM_DRAW_SUGGESTFORMAT points to a ICDRAWSUGGEST structure and the dwParam2 parameter specifies its size.

If returning format information, return ICERR_OK. If the lpbiSuggest member is NULL, return the amount of memory required for the suggested output format structure.

Preparing to Decompress Video

When the client-application is ready, it sends the ICM_DRAW_BEGIN message to the driver to prepare the driver for decompressing the video stream. Your driver should create any tables and allocate any memory that it needs to decompress data efficiently.

The client-application sets dwParam1 to the ICDRAWBEGIN data structure. The size of this structure is contained in dwParam2.

If the ICDRAW_QUERY flag is set in the dwFlags member, the client-application is interrogating your driver to determine if can decompress the data with the parameters specified in the ICDRAWBEGIN data structure. Your driver should return ICM_ERR_OK if it can accept the parameters. It should return ICM_ERR_NOTSUPPORTED if it does not accept them.

When the ICDRAW_QUERY flag is set, ICM_DRAW_BEGIN will not be paired with ICM_DRAW_END. Your driver will receive another ICM_DRAW_BEGIN without this flag to start the actual decompression sequence.

Your driver can ignore the palette handle specified in the hpal member.

The hwnd and hdc member specifies the handle of the window and DC used for drawing. These members are valid only if the ICDRAW_HDC flag is set in the dwFlags member.

The xDst and yDst members specify the x- and y-position of the upper-right corner of the destination rectangle. (This is relative to the current window or display context.) The dxDst and dyDst members specifies the width and height of the destination rectangle. These members are valid only if ICDRAW_HDC flag is set. The ICDRAW_FULLSCREEN flag indicates the entire screen should be used for display and overrides any values specified for these members.

The xSrc, ySrc, dxSrc, and dySrc members specify a source rectangle used to clip the frames of the video sequence. The source rectangle is stretched to fill the destination rectangle. The xSrc and ySrc members specify x- and y-position of the upper-right corner of the source rectangle. (This is relative to a full frame image of the video.) The dxSrc and dySrc members specify the width and height of the source rectangle.

Your driver should stretch the image from the source rectangle to fit the destination rectangle. If the client-application changes the size of the source and destination rectangles, it will send the ICM_DRAW_END message and specify new rectangles with a new ICM_DRAW_BEGIN message. For more information on handling the source and destination rectangles, see the Microsoft(r) Win32(tm) Programmer's Reference.

The lpbi member specifies a pointer to a BITMAPINFOHEADER data structure containing the input format.

The dwRate member specifies the decompression rate in an integer format. To obtain the rate in frames-per-second divide this value by the value in dwScale. Your driver will use these values when it handles the ICM_DRAW_START message.

If your driver can decompress the data with the parameters specified in the ICDRAWBEGIN data structure, your driver should return ICERR_OK and allocate any resources it needs to efficiently decompress the data. If your driver cannot decompress the data with the parameters specified, your driver should fail the message by returning ICERR_NOTSUPPORTED. When this message fails, your driver will not get an ICM_DRAW_END message so it should not prepare its resources for other ICM_DRAW messages.

Decompressing the Video

The client-application sends ICM_DRAW each time it has an image to decompress. (Your driver should use this message to decompress images. It should wait for the ICM_DRAW_START message before it begins to render them.) The client-application uses the flags in the file index to ensure the first frame in a series of frames decompressed starts with a key frame boundary. Your driver must allocate the memory it needs for the decompressed image.

The ICDRAW data structure specified in dwParam1 contains the decompression parameters. The value specified in dwParam2 specifies the size of the structure.

The format of the input data is specified in a BITMAPINFOHEADER structure pointed to by lpFormat member. The input data is in a buffer specified by the lpData member. The number of bytes in the input buffer is specified by the cbData member.

The client-application sets the ICDRAW_HURRYUP flag in the dwFlags member when it wants your driver to try to decompress data at a faster rate. For example, the client-application might use this flag when the video is starting to lag behind the audio. If your driver cannot speed up its decompression and rendering performance, it might be necessary to avoid rendering a frame of data. The client-application sets the ICDRAW_UPDATE flag and sets lpData to NULL if it wants your driver to update the screen based on data previously received.

When your driver has finished decompressing the data, it returns ICERR_OK. After the driver returns from this message, the client-application deallocates or reuses the memory containing the format and image data. If your driver needs the format or image data for future use, it should copy the data it needs before it returns from the message.

Ending Decompression

Your driver receives ICM_DRAW_END when the client-application no longer needs data decompressed or rendered. For this message, your driver should free the resources it allocated for the ICM_DRAW_BEGIN message. Your driver should also leave the display in the full screen mode.

After sending ICM_DRAW_END, the client-application must send ICM_DRAW_BEGIN to continue decompressing data. Your driver should not expect the client-application to send a ICM_DRAW_END message for each ICM_DRAW_BEGIN message. The client-application can use ICM_DRAW_BEGIN to restart decompression without sending ICM_DRAW_END.

Rendering the Data

The client-application sends the following messages to control the driver's internal clock for rendering the decompressed data:

Message

Description

ICM_DRAW_GETTIME

Obtains the value of the driver's internal clock if it is handling the timing of drawing frames.

ICM_DRAW_SETTIME

Sets the driver's internal clock if it is handling the timing of drawing frames.

ICM_DRAW_START

Starts the internal clock of a driver if it handles the timing of drawing frames.

ICM_DRAW_STOP

Stop the internal clock of a driver if it handles the timing of drawing frames.

ICM_DRAW_WINDOW

Informs the driver the display window has been moved, hidden, or displayed.

ICM_DRAW_FLUSH

Flushes any frames that are waiting to be drawn.

ICM_DRAW_RENDERBUFFER

Draws a frame waiting to be drawn.

ICM_DRAW_UPDATE

Redraws the image currently displayed.

ICM_DRAW_CHANGEPALETTE

Changes the palette.


The client-application sends ICM_DRAW_START to have your driver start (or continue) rendering data at the rate specified by the ICM_DRAW_BEGIN message. The ICM_DRAW_STOP message pauses the internal clock. Neither of these messages use dwParam1, dwParam2, or a return value.

The client-application uses ICM_DRAW_GETTIME to obtain the value of the internal clock. Your driver returns the current time value (this is normally frame numbers for video) in the DWORD indicated by the pointer specified by dwParam1. The current time is relative to the start of drawing.

The client-application uses ICM_DRAW_SETTIME to set the value of the internal clock. Typically, the client-application uses this message to synchronize the driver's clock to an external clock. Your driver should set its clock to the value (this is normally frame numbers for video) specified in the DWORD pointed to by dwParam1.

The client-application sends ICM_DRAW_FLUSH to have your driver discard any frames that have not been drawn.

The client-application sends ICM_DRAW_RENDERBUFFER to have your driver draw the image currently buffered.

The client-application sends ICM_DRAW_UPDATE to have your driver redraw an image.

The client-application sends ICM_DRAW_CHANGEPALETTE when the palette changes in the movie.