tanvon++

September 27, 2008

Inserting a DMO in the DirectShow Filter Graph

Filed under: DMO, DirectShow, System Device Enumerator — Tags: — tanvon malik @ 10:30 am

DirectX Media Objects (DMO) can be thought as light weight DirectShow filter with limited functionality, But are easier to develop, mostly used for audio video effects.

DMOs can be inserted in a filter graph through a wrapper filter, after DMOs insertion in the filter graph it is treated like a normal filter.

A DMO is a COM object. So wrapping means it is aggregated by the DMO Wrapper Filter.

DMO creation sequence is,

  1. Call CoCreateInstance to create DMO Wrapper Filter.
  2. Query the DMO Wrapper Filter for the IDMOWrapperFilter interface.
  3. Initialize the required DMO with IDMOWrapperFilter::Init.
// Create the DMO Wrapper filter.
IBaseFilter *pFilter;
HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL,
    CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pFilter);

if (SUCCEEDED(hr))
{
    // Query for IDMOWrapperFilter.
    IDMOWrapperFilter *pDmoWrapper;
    hr = pFilter->QueryInterface(IID_IDMOWrapperFilter,
                                                (void**)&pDmoWrapper);

    if (SUCCEEDED(hr))
    {
        // Initialize the filter.
        hr = pDmoWrapper->Init(CLSID_MyDMO, DMOCATEGORY_VIDEO_EFFECT);
        pDmoWrapper->Release();

        if (SUCCEEDED(hr))
        {
            // Add the filter to the graph.
            hr = pGraph->AddFilter(pFilter, L"My DMO");
        }
    }
    pFilter->Release();
}

Inserting DMO in filter graph through System Device Enumerator

The other way to add a DMO in the filter graph is through System Device Enumerator. The System Device Enumerator can be used to enumerate the DMOs in various categories, and through System Device Enumerator it is easy to instantiate a DMO through IMoniker::BindToObject which automatically creates the DMO Wrapper filter and initializes it with the DMO.

Enumerating Filters in the Filter Graph

Filed under: DirectShow, DirectShow Filters, Enum, Filters, Filters Enumeration — Tags: — tanvon malik @ 10:17 am

I have posted earlier about enumerating the DirectShow filters registered on a client computer.

And another post a enumerating the Pins a DirectShow Filter have.

But this time I am posting about enumerating the DirectShow filters in a specific Filter Graph. A DirectShow filter graph can be created in a number of ways, the easiest is through intelligent connect way, just call IGraphBuilder::RenderFile on a media file and all the graph will be built for you.

Now after the filter graph built it is not known which filters are inserted in the filter graph by the Filter Graph Manager, the filters in a filter graph can be easily seen through the GraphEdit if you register the filter graph in the Running Object Table (ROT). At the time let us explore the filter graph through the code.

HRESULT EnumFilters (IFilterGraph *pGraph)
{
    IEnumFilters *pEnum = NULL;
    IBaseFilter *pFilter;
    ULONG cFetched;

    HRESULT hr = pGraph->EnumFilters(&pEnum);
    if (FAILED(hr)) return hr;

    while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
    {
        FILTER_INFO FilterInfo;
        hr = pFilter->QueryFilterInfo(&FilterInfo);
        if (FAILED(hr))
        {
            MessageBox(NULL, TEXT("Could not get the filter info"),
                TEXT("Error"), MB_OK | MB_ICONERROR);
            continue;  // Maybe the next one will work.
        }

        MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
        // The FILTER_INFO structure holds a pointer to the Filter Graph
        // Manager, with a reference count that must be released.
        if (FilterInfo.pGraph != NULL)
        {
            FilterInfo.pGraph->Release();
        }
        pFilter->Release();
    }

    pEnum->Release();
    return S_OK;
}

 

If you have read few previous posts of this blog then it will not be  difficult to understand the code.

The IFilterGraph::EnumFilters gives us a enumerator which can be used to enumerate all the filters in the filter graph. The IBaseFilter::QueryFilterInfo helps us to know the filter name and wether it is the member of a filter graph or not.

September 7, 2008

Enum the backbone of DirectShow Graph Building

Filed under: DirectShow, DirectShow Filters, Enum, Filters, Filters Enumeration — Tags: , — tanvon malik @ 4:32 pm

As a few last post are about enumeration, wether enumerating the Filter Categories or enumerating the filters in those categories or enumerating the filters pins.

Now comes another enumeration related post but this time we will enumerate all the filters in a given graph, this can be useful.

  • if you want to find some kind of info about all the filters.
  • want to find a specific interface but don’t know which filter implements that interface.
  • want to release all the filters in the filter graph.
here is the code about finding info about filter
HRESULT EnumFilters (IFilterGraph *pGraph)
{
    IEnumFilters *pEnum = NULL;
    IBaseFilter *pFilter;
    ULONG cFetched;

    HRESULT hr = pGraph->EnumFilters(&pEnum);
    if (FAILED(hr)) return hr;

    while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
    {
        FILTER_INFO FilterInfo;
        hr = pFilter->QueryFilterInfo(&FilterInfo);
        if (FAILED(hr))
        {
            MessageBox(NULL, TEXT("Could not get the filter info"),
                TEXT("Error"), MB_OK | MB_ICONERROR);
            continue;  // Maybe the next one will work.
        }

#ifdef UNICODE
        MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
#else
        char szName[MAX_FILTER_NAME];
        int cch = WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
            MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);
        if (chh > 0)
            MessageBox(NULL, szName, TEXT("Filter Name"), MB_OK);
#endif

        // The FILTER_INFO structure holds a pointer to the Filter Graph
        // Manager, with a reference count that must be released.
        if (FilterInfo.pGraph != NULL)
        {
            FilterInfo.pGraph->Release();
        }
        pFilter->Release();
    }

    pEnum->Release();
    return S_OK;
}

here is the code to find a specific interface on a filter
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;
}

here is the code which releases all the filters in the DirectShow Filter
Graph
// Stop the graph.
pControl->Stop();

// Enumerate the filters in the graph.
IEnumFilters *pEnum = NULL;
HRESULT hr = pGraph->EnumFilters(&pEnum);
if (SUCCEEDED(hr))
{
    IBaseFilter *pFilter = NULL;
    while (S_OK == pEnum->Next(1, &pFilter, NULL))
     {
         // Remove the filter.
         pGraph->RemoveFilter(pFilter);
         // Reset the enumerator.
         pEnum->Reset();
         pFilter->Release();
    }
    pEnum->Release();
}

Enumerating the DirectShow Filter Pin

When it comes the time of connecting the DirectShow filters manually in DirectShow Filter Graph, at that time we admire the benefits of the Intelligent Connect. To connect a filter manually we have to built the entire filter graph with coding.

First of all a source filer have to be created the filter graph

IGraphBuilder *  pGB;
CoCreateInstance(CLSID_FilterGraph,NULL,
               CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGB);

then a Source Filter have to be added the filter graph, wether with CoCreateInstance() or with System Device Enumerator, All filters can’t be created with CoCreateInstance, Normally the filters which are wrapper to devices have to be created with the System Device Enumerator. But here a source filter is being added that will read the media data from a file from the disk.

IBaseFilter * pSF;
    pGB->AddSourceFilter(L"c:\\media\\video\\ruby.avi", L"Source Filter",
                                                                  &pSF);
    IEnumPins * pEP;
    pSF->EnumPins(&pEP);
    IPin * pOutPin;
    while(pEP->Next(1,&pOutPin,0) == S_OK)
    {
        PIN_DIRECTION pDir;
        pOutPin->QueryDirection(&pDir);
        if(pDir == PINDIR_OUTPUT)
            break;// success
        pOutPin->Release();
    }
    pEP->Release();

Now how to enumerate the pins, IBaseFilter has a method which makes it easy to enumerate the pins a filter have.

HRESULT EnumPins(
  IEnumPins **ppEnum
);

which gives us IEnumPins interface, with this interface you can easily enumerate the pins a filter have wether these are input pins or output pins. you first call Next then check for the pin direction.

HRESULT QueryDirection(
  PIN_DIRECTION *pPinDir
);

For direction checking  QueryDirection is called this method tells us the pin direction.

Now you can call IGraphBuilder::Render to built the entire graph.

HRESULT Render(
  IPin *ppinOut
);
this method takes the output pin to be rendered.
or you can call IGraphBuilder::Connect to directly connect the 
output pin to a downstream filters input pin.
HRESULT Connect(
  IPin *ppinOut,
  IPin *ppinIn
);

Blog at WordPress.com.