[INTEL NAVIGATION HEADER]

Programming Indeo® Video Interactive With ActiveMovie*: Decompressing

If you are a multimedia application developer who wishes to include the advanced features of the Indeo® video interactive codec into your 32­bit application, read this document. It explains what you need to know in order to control the playback parameters of the Indeo video interactive codec programmatically from the ActiveMovie* interface, so that you can integrate features such as access key protection or local decode. This document assumes you are familiar with ActiveMovie.

Indeo video interactive is Intel's latest digital video capture, compression, and decompression software. The technology is based on a compressor-decompressor, or codec, a software driver used to compress digital video data for storage, and decompress it for playback on a multimedia PC. Indeo video interactive uses an efficient encoding algorithm and yields high quality images. It includes a wide variety of features designed for interactive multimedia applications, such as real-time video effects, access key file protection, local decode, and the ability to specify transparency for portions of a video frame.

This document consists of four sections:

The ActiveMovie Interface to Indeo Video Interactive
Introduces ActiveMovie and outlines the process whereby your multimedia application can access the Indeo video interactive codec in the ActiveMovie environment.

Codec States and Data Structures
Introduces the state structures used to pass information to and from the codec, and describes how to initialize them.

Changing Playback Parameters
Provides specific details and C source code examples for accessing and modifying individual decode parameters.

References
Points you to other documents that provide information on related topics.


The ActiveMovie Interface to Indeo Video Interactive
ActiveMovie is Microsoft's multimedia architecture for controlling and processing streams of digital audio and video. It is intended to supersede Video for Windows.* ActiveMovie uses Microsoft's COM architecture to build and control interfaces between filters, or between applications and filters.

In the ActiveMovie environment, an application uses the ActiveMovie COM interface to build a graph containing various filters--known as a filter graph. Each filter performs one service for the application, for example, getting the data from the source file, transforming the data, or rendering the data in some manner. The Indeo video codec is represented in this environment by an Indeo video filter; in the context of ActiveMovie, therefore, the expressions Indeo video codec and Indeo video filter are synonyms.

Every filter has one or more interfaces, and each interface serves a specific purpose. The Indeo video filter has an encode interface and a decode interface. Both are customized to allow applications to access the special features of Indeo video interactive.

To use the Indeo video codec in the ActiveMovie environment, an application takes the following basic steps:

  1. Initialize the Indeo video interactive data structures as described below.
  2. Invoke the IGraphBuilder's method RenderFile to create an instance of a filter graph for a specified file.
  3. If the file was encoded with Indeo video interactive, one of the filters in the resulting graph is the Indeo video codec. Query the filters to determine if one exposes the Indeo video decode interface, and if so, get a pointer to it. This pointer is necessary to access the special features of Indeo video interactive.

The following code shows how to get a pointer to the decode interface of the Indeo video filter (the IIndeoDecode interface) after a movie file has been opened. This interface is then used in subsequent calls to get and set the Indeo video interactive decode parameters.


// IFilterGraph *pGraph is a graph populated with filters to render
// a particular media file.  See the ActiveMovie SDK Help reference
// for the IGraphBuilder interface and its RenderFile method.
// See if the Indeo codec filter is in the graph.

pGraph->EnumFilters(&pEnum);

// While there are more filters, get the next filter in the graph.
while ((hr = pEnum->Next(1, &pFilter, &pcFetched))== S_OK)
{
        // Does this filter expose the IIndeoDecode interface?
        hr = pFilter->QueryInterface(IID_IIndeoDecode, &pIndeo);
        pFilter->Release();
        // If the interface is exposed, break out of the loop.
                if (hr == S_OK)
                        break;
}
//This interface must be released even though it was not obtained in the
usual way with QueryInterface.

pEnum->Release();

NOTE: For a complete application example, see the source code for IPlay, an example application that plays back video files, taking advantage of most of the special features provided by Indeo video interactive. The executable application is available in the file iplay.exe, and the C++ source code is available in the file iplaysrc.exe.


Codec States and Data Structures
The Indeo video interactive codec maintains two states while decoding: sequence state and frame state. Sequence state is the state of the codec between the time you tell the filter graph to run and the time you tell it to pause or stop, and frame state is the state of the codec while the filter graph is running, decoding video frame by frame.

In one respect, ActiveMovie is a significant departure from the Video for Windows model: while Video for Windows is frame-based, ActiveMovie is time-based. While it remains straightforward to access sequence state in the ActiveMovie environment, accessing frame state is less straightforward. A COM filter graph is intended to encapsulate the service it provides, thus, certain features that depend on accessing frame state, such as transparency, are more difficult to implement.

Two predefined data structures represent these states: R4_DEC_SEQ_DATA represents sequence state and R4_DEC_FRAME_DATA represents frame state. They are defined in the file ax_spec.h.

While decoding, you can examine or change the codec state by using one of the methods getDecodeFrame or setDecodeFrame, getDecodeSequence or setDecodeSequence, passing as the parameter the address of one of these two predefined state structures. See ax_spec.h for methods on the interface IIndeoDecode.

Both data structures contain header members that your application initializes in the same way regardless of the operation to be performed, as well as other members whose initialization and use is operation-specific.

The Decode Sequence Data Structure
The R4_DEC_SEQ_DATA data structure contains members that describe the state of the codec for sequences of decode operations. A sequence starts when the IMediaControl interface invokes the method Run and continues until it invokes the method Pause or Stop. You can change the sequence state of the codec at any point in a sequence, but the change has no effect until the next sequence begins.

The following C code example demonstrates how to initialize the header members of the R4_DEC_SEQ_DATA structure before sending either setDecodeSequence or getDecodeSequence. (Initialize other members of this structure according to the type of action required, as detailed in the next section.)

R4_DEC_SEQ_DATA         r4SeqData;

r4SeqData.dwSize        = sizeof(R4_DEC_SEQ_DATA);
r4SeqData.dwFourCC      = FOURCC_IV41;
r4SeqData.dwVersion     = SPECIFIC_INTERFACE_VERSION;
r4SeqData.mtType        = MT_DECODE_SEQ_VALUE;
r4SeqData.oeEnvironment = OE_32;
r4SeqData.dwFlags       = 0;

The Decode Frame Data Structure
The R4_DEC_FRAME_DATA data structure contains members that describe the state of the codec for decode operations. The codec incorporates changes to its frame state as the Indeo video codec/filter decodes.

The following C code example demonstrates how to initialize the header members of the R4_DEC_FRAME_DATA structure before sending either setDecodeFrame or getDecodeFrame. (Initialize other members of this structure according to the type of action required, as detailed in the next section.)

R4_DEC_FRAME_DATA       r4FrmData;

r4FrmData.dwSize        = sizeof(R4_DEC_FRAME_DATA);
r4FrmData.dwFourCC      = FOURCC_IV41;
r4FrmData.dwVersion     = SPECIFIC_INTERFACE_VERSION;
r4FrmData.mtType        = MT_DECODE_FRAME_VALUE;
r4FrmData.oeEnvironment = OE_32;
r4FrmData.dwFlags       = 0;

The Current and Default Codec States
In both the R4_DEC_SEQ_DATA and R4_DEC_FRAME_DATA structures, the member mtType indicates whether action is taken on the current or the default state of the codec. Values of MT_DECODE_FRAME_VALUE or MT_DECODE_SEQ_VALUE specify actions taken on the current codec state. The other defined values, MT_DECODE_FRAME_DEFAULT or MT_DECODE_SEQ_DEFAULT, specify that actions are taken on the default codec state. When you act on the default codec state it becomes the current state.


Changing Playback Parameters
Before any operations such as those exemplified in the following code samples, you must initialize the header members of the decode data structures as shown in Codec States and Data Structures, above. All of the following examples assume operations are done on the current codec state.

The examples below demonstrate how to use the methods getDecodeFrame, setDecodeFrame, getDecodeSequence, or setDecodeSequence to get and set sequence or frame parameters. These examples all follow the same general pattern:

  1. Set dwFlags to specify the valid members of the structure.
  2. Assign a value to the variable or flag corresponding to the member or members in which you are interested.
  3. Call the appropriate method to retrieve or modify the state of that member.

Modifying the Decode Sequence Parameters
The following examples demonstrate how to use the setDecodeSequence message to modify selected decode parameters. These examples all assume that the r4State variable was initialized prior to sending the message to the codec, as shown in the section above entitled "Codec States and Data Structures."

NOTE: For the sake of clarity, the examples below do not check return values for errors. Your application, however, needs to check all return values for errors.

Transparent Pixel Fill Method
Setting the fill method for transparent pixels determines whether the codec writes only the nontransparent pixels to the output buffer, or writes the transparent pixels also. This determines whether the user sees the nontransparent shape against a solid background written by the codec, as illustrated in Figure 1, or against no background at all. If the codec does not write the background pixels, they are not updated, leaving visible those pixels that represented the foreground objects in previous frames.

Figure 1. Transparent Pixel Fill Method: Codec Writes Background

If the codec writes the transparent pixels, the color it uses to represent them is based on the method of encoding: black if encoded with the TM_BITMASK option, or one of the transparent colors if encoded with any other option.

If the codec does not write the transparent pixels, your application is responsible for the state of the buffer before the frame is decoded. If you wish your application to supply its own background, such as a bitmap, then you must either write your own filter to replace the Indeo video codec, or else write an additional filter that can mix the pixels appropriately after the video data is decoded by the Indeo video filter.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_SEQ_DATA r4SeqData is an initialized decode sequence structure
*/
/* Set the valid field flags*/
r4SeqData.dwFlags = DECSEQ_FILL_TRANSPARENT | DECSEQ_VALID;

/* Set the transparency fill field */
r4State.fFillTransparentPixels = 1;   /*  1 = fill, 0 = don't fill */

pIndeo->set_DecodeSequence(&r4SeqData);

Decode Scalability
The decode scalability parameter allows the application to turn on or off the quality scalability feature of the codec. Quality scalability allows Indeo video interactive to reduce image quality rather than drop frames if insufficient processor resource is available to decode all the compressed frame data within the time limit.

By default, the time limit is determined by the frame rate with which the video was encoded. If your application requires faster decoding, you can set a more stringent time limit as discussed in the section entitled "Setting the decode time limit," below.

Turn decode scalability on with the fScalability variable.

NOTE: Turning decode scalability on affects only playback of those video clips that were encoded with scalability on.

/*  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder
interface  R4_DEC_SEQ_DATA r4SeqData is an initialized decode
sequence structure
*/
/* Set the valid field flags  */
r4SeqData.dwFlags = DECSEQ_SCALABILITY | DECSEQ_VALID;

/* Set the scalability field */
r4SeqData.fScalability = 1;  /*  0 = disable, 1 = enable */

pIndeo->set_DecodeSequence(&r4SeqData);

Access Key Protection
This feature allows an application to supply an access key for video clips that have been encoded with access key protection enabled. It has no effect on clips not encoded with the access key feature.

An access key must have a numeric value only. Valid values are in the range of 0 through (232-1). If a clip has been encoded with access key protection enabled and the proper access key is not supplied when decoding, the codec returns the error ICERR_INTERNAL as soon as it receives the next decompression message.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_SEQ_DATA r4SeqData is an initialized decode sequence structure
*/
/* Set the valid field flags */
r4SeqData.dwFlags = DECSEQ_KEY | DECSEQ_VALID;

/* Set the enable key field and the key itself */
r4SeqData.fEnabledKey = 1;     /*  0 = disable, 1 = enable  */
r4SeqData.dwKey       = 032455;

pIndeo->set_DecodeSequence(&r4SeqData);

Alternate Line Zoom-by-two

NOTE: Alternate line zoom-by-two is not implemented in this release.

Modifying the Decode Frame Parameters

Setting the address of the transparency bounding rectangle
As shown in Figure 2, the bounding rectangle is the smallest rectangle that can contain the nontransparent pixels.

Figure 2. Bounding Rectangle of Nontransparent Figure

The application must specify the address of an R4_RECT structure to which the codec can return the origin, width, and height of the bounding rectangle in the last frame decoded: that is, which rectangular region of the frame was written over. This allows the application to repaint the background after the nontransparent shape has moved.

Once you have set the address of the bounding rectangle, the codec updates the bounding rectangle's position after each frame is decoded so that the application can continue to clean up the background as necessary.

If the codec returns all zeroes, no pixels were written in the last frame because the nontransparent shape did not appear.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

R4_RECT r4Rect;

/* Set the valid field flags  */
r4FrmData.dwFlags = DECFRAME_BOUNDING_RECT | DECFRAME_VALID;

/* Set the bounding rect field */
r4FrmData.pr4BoundingRect = &r4Rect;

pIndeo->set_DecodeFrame(&r4FrmData);

Setting the Address of the Transparency Bitmask
The Indeo video interactive codec can handle transparency while decoding frames, or the application can handle the transparency itself after frames have been decoded; in either case, however, you must specify how the transparency is to be handled. The Indeo video interactive codec can decode only transparent video that was encoded using the Indeo video interactive codec with the transparency option enabled. It cannot decode transparent video generated by any other means.

If you decide to handle the transparency in your application, this message provides the codec with the address of memory in which to write a one­bit bitmask for the last frame decoded, and the address of a flag to be set if bitmask information is available. Enough memory must be allocated for one bit to represent each pixel of a frame. The bitmask specifies which areas of the frame have nontransparent video information: a value of zero means a pixel is transparent and a value of one means that it is not.

Each row must begin on a DWORD boundary, and the total number of bytes must be a multiple of four. If it isn't, round up to the nearest multiple of four.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/*  Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_TRANS_BITMASK | DECFRAME_VALID;

/* Set the transparency bitmask  and updated bitmask fields */
r4FrmData.pfUpdatedTransparencyBitmask = &fBitmask;
r4FrmData.pbmTransparencyBitmask       = pbmBitmask;

pIndeo->set_DecodeFrame(&r4FrmData);

Setting the Decode Time Limit
An application can specify the number of milliseconds in which the codec must decompress and color-convert each frame. If scalability was not enabled during compression, the codec ignores the time limit. If a frame cannot be decoded in the time specified and quality scalability is on, image quality is reduced.

The milliseconds specified are wall clock milliseconds, not CPU cycles. The codec consults the system clock to determine the elapsed time.

If you set the time limit to zero, the codec uses the frame rate with which the video was encoded to determine the time limit. This is the default. For example, a frame rate of ten frames per second indicates a time limit of one hundred milliseconds.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/* Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_TIME_LIMIT | DECFRAME_VALID;

/* Set the time limit field (milliseconds) */
r4FrmData.dwTimeLimit = dwTimeLimit;

pIndeo->set_DecodeFrame(&r4FrmData);
Setting the Position and Dimensions of the Decode Rectangle for Local Decode
Indeo video interactive can decode a specified rectangular region of the original image, called a decode rectangle, rather than the entire image. The decode rectangle specifies the upper left corner, width, and height of the decode rectangle relative to the original image.

A decode rectangle cannot be smaller than the minimum size specified during encoding. It can be changed only immediately before a key frame; if you try to change it before any other frame, the codec queues your request, which takes effect at the next key frame. The decode rectangle cannot extend outside the image and must wholly enclose the view rectangle, which is discussed below. If all fields are zero, the entire image is decoded.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
  R4_RECT r4DecodeRect is the decode rectangle
*/

/* Initialize the decode rectangle */
r4DecodeRect.dwX      = x;   /* X of upper left corner*/
r4DecodeRect.dwY      = y;   /* Y of upper left corner */
r4DecodeRect.dwWidth  = dx;  /* Width */
r4DecodeRect.dwHeight = dy;  /* Height */

/* Set the valid field flags  */
r4FrmData.dwFlags = DECFRAME_DECODE_RECT | DECFRAME_VALID;

/* Set the decode rect field */
r4FrmData.rDecodeRect = &r4DecodeRect;

pIndeo->set_DecodeFrame(&r4FrmData);

Setting the Position and Dimensions of the View Rectangle for Local Decode
Within a decode rectangle, Indeo video interactive can further limit the pixels it writes to the output buffer. This smaller area is called the view rectangle. Specify the origin, width and height of the view rectangle relative to the original image. The view rectangle cannot extend outside the decode rectangle; if it does, the codec returns the error ICERR_BADPARAM when the next decompression message is received. If all fields are zero, the view rectangle defaults to the entire decode rectangle.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
  R4_RECT r4ViewRect is the view rectangle
*/

/* Initialize the view rectangle */
r4ViewRect.dwX      = x;   /* X of upper left corner*/
r4ViewRect.dwY      = y;   /* Y of upper left corner */
r4ViewRect.dwWidth  = dx;  /* Width */
r4ViewRect.dwHeight = dy;  /* Height */

/*  Set the valid field flags  */
r4FrmData.dwFlags  = DECFRAME_VIEW_RECT | DECFRAME_VALID;

/* Set the view rect field */
r4FrmData.rViewRect = &r4ViewRect;

pIndeo->set_DecodeFrame(&r4FrmData);

Setting the Brightness, Saturation, and Contrast Levels
Indeo video interactive supports changing the brightness, contrast, and saturation of the video clip during playback. Valid values for all three parameters range from -255 to 255.

Brightness is an additive adjustment to luminance. Contrast and saturation are nonlinear adjustments.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
  b, s, c are long in the range -255 to 255
*/

/*  Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_BRIGHTNESS | DECFRAME_SATURATION |
                    DECFRAME_CONTRAST | DECFRAME_VALID;

/* Set the brightness, saturation, and contrast fields */
r4FrmData.lBrightness = b;
r4FrmData.lSaturation = s;
r4FrmData.lContrast   = c;

pIndeo->set_DecodeFrame(&r4FrmData);

Retrieving the Decode Sequence Parameters
The following examples show how to use the getDecodeSequence method to retrieve the current decode sequence parameters.

NOTE: The access key parameters cannot be retrieved.

Transparent Pixel Fill Method
To retrieve the current fill mode, set the appropriate flag in the dwFlags field and send the getDecodeSequence message. On successful return, the fFillTransparentPixels member of the r4State structure indicates the current mode.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_SEQ_DATA r4SeqData is an initialized decode sequence structure
*/

/* Set the valid field flags  */
r4SeqData.dwFlags = DECSEQ_FILL_TRANSPARENT |DECSEQ_VALID;

pIndeo->get_DecodeSequence(&r4SeqData);

Decode Scalability
To retrieve the current decode scalability mode, set the appropriate flag in the dwFlags field and send the getDecodeSequence message. On successful return, the fScalability member of the r4State structure indicates the current mode.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_SEQ_DATA r4SeqData is an initialized decode sequence structure
*/

/* Set the valid field flags */
r4SeqData.dwFlags  = DECSEQ_SCALABILITY | DECSEQ_VALID;

pIndeo->get_DecodeSequence(&r4SeqData);

Alternate Line Zoom-by-two

NOTE: Alternate line zoom-by-two is not implemented in this release.

Retrieving the Decode Frame Parameters
The following examples show how to use the getDecodeFrame message to retrieve the current decode frame parameters.

NOTE: The address of the transparency bounding rectangle and the transparency bitmask cannot be retrieved. These parameters were originally furnished by the application.

Retrieving the Decode Time Limit
To retrieve the current decode time limit, set the appropriate flag in the dwFlags field and call the getDecodeFrame method. On successful return, the lTimeLimit member of the r4State structure contains the current value.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/* Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_TIME_LIMIT | DECFRAME_VALID;

pIndeo->get_DecodeFrame(&r4FrmData);

Retrieving the Position and Dimensions of the Decode Rectangle for Local Decode
To retrieve the current origin, width, and height of the decode rectangle, set the corresponding flag in the dwFlags field, supply the address of R4_RECT in which to place the values, and call the getDecodeFrame method. On successful return, the R4_RECT contains the current position and dimensions of the decode rectangle.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/* Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_DECODE_RECT | DECFRAME_VALID;

pIndeo->get_DecodeFrame(&r4FrmData);

Retrieving the Position and Dimensions of the View Rectangle for Local Decode
To retrieve the current position and dimensions of the view rectangle, set the corresponding flag in the dwFlags field, supply the address of R4_RECT in which to place the values, and call the getDecodeFrame method. On successful return, the R4_RECT contains the current position and dimensions of the view rectangle.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/*  Set the valid field flags */
r4FrmData.dwFlags  = DECFRAME_VIEW_RECT | DECFRAME_VALID;

pIndeo->get_DecodeFrame(&r4FrmData);

Retrieving the Brightness, Saturation, and Contrast Levels
To retrieve the current values for brightness, saturation, and contrast, set the corresponding flags in the dwFlags field and call the getDecodeFrame method. On successful return, the lBrightness, lSaturation, and lContrast members of the r4State structure contain the current values.

/*
  IIndeoDecode *pIndeo is a valid pointer to an IVI decoder interface
  R4_DEC_FRAME_DATA r4FrmData is an initialized decode frame structure
*/

/*  Set the valid field flags */
r4FrmData.dwFlags = DECFRAME_BRIGHTNESS | DECFRAME_SATURATION  |
                    DECFRAME_CONTRAST | DECFRAME_VALID;

pIndeo->get_DecodeFrame(&r4FrmData);



References

For latest information, also see:

For more information on COM, see:


* Legal Stuff © 1997 Intel Corporation

Free Web Hosting