Microsoft DirectX 9.0

Selecting a Decoder in DirectShow Editing Services

When DirectShow Editing Services (DES) renders a video editing project, the Rendering Engine automatically selects the necessary decoders. This may happen inside the IRenderEngine::ConnectFrontEnd method, or else dynamically during rendering.

A user might install several decoders that are capable of decoding a particular file. This is particularly true for MPEG-2 content, because DirectShow does not provide an MPEG-2 decoder, so users often install third-party decoders. When multiple decoders are available, DES uses the Intelligent Connect algorithm to select the decoder.

There is no way for the application to specify directly which decoder to use. However, you can choose the decoder indirectly through the IAMGraphBuilderCallback callback interface. By implementing this interface in your application, you can receive notifications during the graph-building process and reject certain filters from the graph.

Start by implementing a class that exposes the IAMGraphBuilderCallback interface:

class GraphBuilderCB : public IAMGraphBuilderCallback
{
public:
     // Method declarations (not shown).
};

Then create an instance of the Filter Graph Manager and register your class to receive callback notifications:

// Declare an instance of the callback object.
GraphBuilderCB GraphCB; 

// Create the Filter Graph Manager.
CComPtr<IGraphBuilder> pGraph;
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if (FAILED(hr))
{
    // Handle error (not shown).
}
// Register to receive the callbacks.
CComQIPtr<IObjectWithSite> pSite(pGraph);
if (pSite)
{
    hr = pSite->SetSite((IUnknown*)&GraphCB);
}

Next, create the Render Engine and call the IRenderEngine::SetFilterGraph method with a pointer to the Filter Graph Manager. This ensures that the Render Engine does not create its own Filter Graph Manager, but instead uses the instance that you have configured for callbacks.

CComPtr<IRenderEngine> pRender;
hr = pRender.CoCreateInstance(CLSID_RenderEngine);
if (FAILED(hr))
{
    // Handle error (not shown).
}

hr = pRender->SetFilterGraph(pGraph);

When the project is rendered, the application's IAMGraphBuilderCallback::SelectedFilter method is called immediately before the Filter Graph Manager creates a new filter. The SelectedFilter method receives a pointer to an IMoniker interface that represents a moniker for the filter. Examine the moniker, and if you decide to reject the filter, return a failure code from the SelectedFilter method.

The difficult part is to identify which monikers represent decoders — and in particular, which monikers represent decoders that you want to reject. One solution is the following: