Microsoft DirectX 9.0

Find an Interface on a Filter or Pin

For many operations in DirectShow, the application calls methods on the Filter Graph Manager. In some situations, however, the application must call a method directly on a filter or pin. For example, many filters expose specialized interfaces that are used to configure the filter.

In the case of a filter interface, you might already have a pointer to the filter's IBaseFilter interface. In that case, simply use QueryInterface to get the other interface. But some filters might be added to the graph by the Filter Graph Manager. (For details, see Intelligent Connect.) In that case, use the IEnumFilters interface to loop through all the filters in the graph, and query each one in turn. The following function demonstrates this:

HRESULT FindFilterInterface(
    IGraphBuilder *pGraph, // Pointer to the Filter Graph Manager.
    REFGUID iid,           // IID of the interface to retrieve.
    void **ppUnk)          // Receives the interface pointer.
{
    if (!pGraph || !ppUnk) return E_POINTER;

    HRESULT hr = E_FAIL;
    IEnumFilters *pEnum = NULL;
    IBaseFilter *pF = NULL;
    if (FAILED(pGraph->EnumFilters(&pEnum)))
    {
        return E_FAIL;
    }
    // Query every filter for the interface.
    while (S_OK == pEnum->Next(1, &pF, 0))
    {
        hr = pF->QueryInterface(iid, ppUnk);
        pF->Release();
        if (SUCCEEDED(hr))
        {
            break;
        }
    }
    pEnum->Release();
    return hr;
}

The following example uses this function:

hr = pGraph->RenderFile(L"C:\\Example.avi", 0);
if (SUCCEEDED(hr))
{
    IIPDVDec *pDvDec;
    hr = FindFilterInterface(pGraph, IID_IIPDVDec, (void**)&pDvDec);
    if (SUCCEEDED(hr))
    {
        pDvDec->put_IPDisplay(DVRESOLUTION_QUARTER);
        pDvDec->Release();
    }
    else if (hr == E_NOINTERFACE)
    {
        // This file does not contain DV video.
    }
    else
    {
        // Some other error occurred.
    }
}

First, the example renders an AVI file for playback. Then, if the file contains DV-encoded video, the example sets the output resolution to one-quarter size. The interface for setting the output resolution is the IIPDVDec interface, which is exposed by the DV Video Decoder filter. If the AVI file contains DV-encoded video, the RenderFile method automatically puts the DV Video Decoder in the filter graph. If so, the FindFilterInterface function succeeds and returns a pointer to the IIPDVDec interface. Otherwise, the function returns E_NOINTERFACE, which simply means the AVI file does not contain DV video.

To find an interface on a pin, use the IEnumPins interface to loop through the pins on a filter. The following function shows how to do this:

HRESULT FindPinInterface(
    IBaseFilter *pFilter,  // Pointer to the filter to search.
    REFGUID iid,           // IID of the interface.
    void **ppUnk)          // Receives the interface pointer.
{
    if (!pFilter || !ppUnk) return E_POINTER;

    HRESULT hr = E_FAIL;
    IEnumPins *pEnum = 0;
    if (FAILED(pFilter->EnumPins(&pEnum)))
    {
        return E_FAIL;
    }
    // Query every pin for the interface.
    IPin *pPin = 0;
    while (S_OK == pEnum->Next(1, &pPin, 0))
    {
        hr = pPin->QueryInterface(iid, ppUnk);
        pPin->Release();
        if (SUCCEEDED(hr))
        {
            break;
        }
    }
    pEnum->Release();
    return hr;
}

The next function searches for an interface on a filter or a pin:

HRESULT FindInterfaceAnywhere(
    IGraphBuilder *pGraph, 
    REFGUID iid, 
    void **ppUnk)
{
    if (!pGraph || !ppUnk) return E_POINTER;
    HRESULT hr = E_FAIL;
    IEnumFilters *pEnum = 0;
    if (FAILED(pGraph->EnumFilters(&pEnum)))
    {
        return E_FAIL;
    }
    // Loop through every filter in the graph.
    IBaseFilter *pF = 0;
    while (S_OK == pEnum->Next(1, &pF, 0))
    {
        hr = pF->QueryInterface(iid, ppUnk);
        if (FAILED(hr))
        {
            // The filter does not expose the interface, but maybe
            // one of its pins does.
            hr = FindPinInterface(pF, iid, ppUnk);
        }
        pF->Release();
        if (SUCCEEDED(hr))
        {
            break;
        }
    }
    pEnum->Release();
    return hr;
}

Note that all of the functions shown here stop at the first successful QueryInterface.

See Also