locked
Rebuilding a filter graph RRS feed

  • Question

  • Hi folks,

    My application that allows the user to capture from up to eight cameras works just fine, but it must be possible for the user to change the cameras, add some, remove some. My strategy when the user wants to switch cameras, is just to remove all filters in the graph and rebuild the graph when the new selection is made.
    To remove all filters I use the EnumFilters method, calling RemoveFilter() for each found filter. Till now I have been able to successfully change the camera set up but when I look in the task manager, each time I rebuild the filter graph a number of threads is added (off course), but when I remove all filters, less threads are removed than where added first. Each time I do this the thread count gets larger and larger.
    Should I be concerned about this? I'm not noticing any performance issues. Maybe I'm forgetting about something.

    Here's my code for removing the filters:

    IEnumFilters    *pfEnum = NULL
        IBaseFilter     *pfFilter; 
        int Count = 0
        int Failed = 0
        AnsiString Msg; 
        HRESULT hr; 
     
        //Return if graph was not build 
        if(!GraphLiveIsBuild) return; 
     
        //Enumerate all filters 
        hr = plGraph->EnumFilters(&pfEnum); 
        if(FAILED(hr)) 
        { 
            MessageBox(Handle, "Could not enumerate DirectShow filters. Capture graph is not cleared.", 
                "Clearing capture graph", MB_ICONINFORMATION); 
            return; 
        } 
     
        //Remove each filter 
        while(pfEnum->Next(1, &pfFilter, NULL) == S_OK) 
        { 
            Count++; 
            hr = plGraph->RemoveFilter(pfFilter); 
            if(FAILED(hr)) Failed++; 
            pfEnum->Reset(); 
        } 
        pfEnum->Release(); 
     
        if(Failed > 0) 
        { 
            Msg = "Not all components from the capture graph could be cleared. " + IntToStr(Count - Failed) + 
                " out of " + IntToStr(Count) + " components where removed."; 
            MessageBox(Handle, Msg.c_str(), "Clearing capture graph", MB_ICONINFORMATION); 
        } 
        GraphLiveIsBuild = false

    And one more thing, should I be using IGraphConfig::RemoveFilterFromCache as well?

    Thanks
    Tuesday, December 23, 2008 8:28 PM

Answers

  • Perhaps you are losing a reference somewhere and filters are still alive orphaned and leaked.

    While enumerating filters you are using the same pfFilter local variable and you are not releasing the pointer on each iteration. You should have done this.

    BTW if you used smart pointers you would immediately get an assertion in debug build.


    http://alax.info/blog/tag/directshow
    • Marked as answer by Luukje Wednesday, December 24, 2008 7:45 PM
    Tuesday, December 23, 2008 9:10 PM

All replies

  • Perhaps you are losing a reference somewhere and filters are still alive orphaned and leaked.

    While enumerating filters you are using the same pfFilter local variable and you are not releasing the pointer on each iteration. You should have done this.

    BTW if you used smart pointers you would immediately get an assertion in debug build.


    http://alax.info/blog/tag/directshow
    • Marked as answer by Luukje Wednesday, December 24, 2008 7:45 PM
    Tuesday, December 23, 2008 9:10 PM
  • I did forget about this. I have a separate function that releases the pointers to the filters I have manually added, but I forgot about the ones added by RenderStream(). I just tried pfFilter->Release after removing each filter, but that still leaves the same amount of threads open...
    Tuesday, December 23, 2008 9:49 PM
  • To release filters properly, I recommend that you use CComPtr.
    You might want to remove graph builder after removing filters if it is recycled.

    You don't need to use IGraphConfig::RemoveFilterFromCache if you use dynamic reconnection.


    Was this post helpful?
    Wednesday, December 24, 2008 2:33 AM
  • I'm not using CComPtr, although I know it's the preferred method for most people. I keep track of all filters that are being created and set the pointers to NULL when released. My separate cleanup function releases all components that are non zero, including the graph builder.
    I have reproduced my set up in GraphEdit to see what happens if I stop the graph and remove all filters and I see that GraphEdit also leaves more threads running. I think I should not worry about this too much. I guess the users will not change the camera setup a 100 times in one execution of the application...

    Thanks
    Wednesday, December 24, 2008 7:45 PM
  • As a hint, to find the filter which has a leak on references you can check result of IUnknown::Release call. When you removed the filter from the graph and it is disconnected from peers, your last release on the filter should have a zero returned, e.g.

    IBaseFilter* pBaseFilter;
    // ...
    // Remove filter from the graph
    ULONG nFilterReferenceCount = pBaseFilter->Release();
    ASSERT(nFilterReferenceCount == 0);
    pBaseFilter = NULL;
    or a version with templates:

    CComPtr<IBaseFilter> pBaseFilter;
    // ...
    ULONG nFilterReferenceCount = pBaseFilter.Detach()->Release();
    ATLASSERT(nFilterReferenceCount == 0);

    http://alax.info/blog/tag/directshow
    Wednesday, December 24, 2008 8:26 PM