Microsoft DirectX 8.1 (C++) |
This article describes how to write a video editing project to a file. First it describes how to write a file with the basic render engine. Then it describes smart recompression with the smart render engine.
For an overview of how Microsoft® DirectShow® Editing Services renders projects, see About the Render Engines.
Using the Basic Render Engine
Start by building the front end of the graph, as follows:
The following code example shows these steps.
IRenderEngine *pRender = NULL;
hr = CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC,
IID_IRenderEngine, (void**) &pRender);
hr = pRender->SetTimelineObject(pTL);
hr = pRender->ConnectFrontEnd( );
Next, add multiplexer and file-writing filters to the filter graph. The easiest way to do this is with the Capture Graph Builder, a DirectShow component for building capture graphs. The capture graph builder exposes the ICaptureGraphBuilder2 interface. Perform the following steps:
The following code example shows these steps.
CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **)&pBuilder);
// Get a pointer to the graph front end.
IGraphBuilder *pGraph;
pRender->GetFilterGraph(&pGraph);
pBuilder->SetFiltergraph(pGraph);
// Create the file-writing section.
IBaseFilter *pMux;
pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi,
OLESTR("Output.avi"), &pMux, NULL);
Finally, connect the output pins on the front end to the mux filter.
The following code example shows how to connect the output pins.
long NumGroups;
pTimeline->GetGroupCount(&NumGroups);
// Loop through the groups and get the output pins.
for (i = 0; i < NumGroups; i++)
{
IPin *pPin;
if (pRender->GetGroupOutputPin(i, &pPin) == S_OK)
{
IBaseFilter *pCompressor;
// Create a compressor filter. (Not shown.)
// Set compression parameters. (Not shown.)
// Connect the pin.
pBuilder->RenderStream(NULL, NULL, pPin, pCompressor, pMux);
pCompressor->Release();
pPin->Release();
}
}
To set compression parameters (step 4, previously), use the IAMVideoCompression interface. This interface is exposed on the output pins of compression filters. Enumerate the compression filter's pins, and query each output pin for IAMVideoCompression. (For information about enumerating pins, see Enumerating Pins.) Be sure to release all the interface pointers that you obtained during this step.
After you build the filter graph, call the IMediaControl::Run method on the filter graph manager. As the filter graph runs, it writes the data to a file. Use event notification to wait for playback to complete. (See Responding to Events.) When playback finishes, you must explicitly call IMediaControl::Stop to stop the filter graph. Otherwise, the file is not written correctly.
Using the Smart Render Engine
To get the benefits of smart recompression, use the smart render engine in place of the basic render engine. The steps in building the graph are almost the same. The major difference is that compression is handled in the front end of the graph, not in the file-writing section.
Each video group has a property that specifies the compression format for that group. The compression format must exactly match the group's uncompressed format in height, width, bit depth, and frame rate. The smart render engine uses the compression format when it constructs the graph. Before you set the compression format, make sure to set the uncompressed format for that group by calling IAMTimelineGroup::SetMediaType.
To set a group's compression format, call the IAMTimelineGroup::SetSmartRecompressFormat method. This method takes a pointer to an SCompFmt0 structure. The SCompFmt0 structure has two members: nFormatId, which must be zero, and MediaType, which is an AM_MEDIA_TYPE structure. Initialize the AM_MEDIA_TYPE structure with the format information.
Note If you want the final project to have the same format as one of your source files, you can get the AM_MEDIA_TYPE structure directly from the source file, using the media detector. See IMediaDet::get_StreamMediaType.
Cast the SCompFmt0 variable to a pointer of type long, as shown in the following example.
SCompFmt0 *pFormat = new SCompFmt0;
memset(pFormat, 0, sizeof(SCompFmt0));
pFormat->nFormatId = 0;
// Initialize pFormat->MediaType. (Not shown.)
pGroup->SetSmartRecompressFormat( (long*) pFormat );
The smart render engine automatically searches for a compatible compression filter. You can also specify a compression filter for a group by calling ISmartRenderEngine::SetGroupCompressor.
To build the graph, use the same steps that were described for the Basic Render Enginer in the previous section. The only differences are the following: