directshow 中 x Objects left active 问题的解决

    技术2022-05-11  82

    directshow 中 x Objects left active 问题的解决 

    说明:这篇文章并不具有普遍性,也不涉及深入的com和directshow知识,但如果你也遇到了类似的问题,它可以起一个借鉴作用。

    “x Objects left active“这是很多人开发direct show时遇到的一个错误,我也被它困扰过很长一段时间,直到最近才找到解决的办法。假设出错的代码是这样的:

     

    #include  " stdafx.h " #include  < dshow.h > #include  < stdio.h > #include  < qedit.h > #include  < streams.h >       //  DirectShow (includes windows.h) void  runthread( void ){    IGraphBuilder  * pGraph  =  NULL;    IMediaControl  * pControl  =  NULL;    IMediaEvent    * pEvent  =  NULL;    IBaseFilter  * pSampleGrabber1  =  NULL, * pSampleGrabber2  =  NULL;     //  Initialize the COM library.     HRESULT hr  =  CoInitialize(NULL);     if  (FAILED(hr))    {        printf( " ERROR - Could not initialize COM library " );         return ;    }     //  Create the filter graph manager and query for interfaces.     hr  =  CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,                         IID_IGraphBuilder, ( void   ** ) & pGraph);     if  (FAILED(hr))    {        printf( " ERROR - Could not create the Filter Graph Manager. " );         return ;    }    hr  =  pGraph -> QueryInterface(IID_IMediaControl, ( void   ** ) & pControl);    hr  =  pGraph -> QueryInterface(IID_IMediaEvent, ( void   ** ) & pEvent);    hr  =  pGraph -> RenderFile(L " C:/DXSDK/Samples/Media/CLOCKTXT.avi " ,NULL);     //  Create Filters     hr  =  CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,                         IID_IBaseFilter, ( void   ** ) & pSampleGrabber1);    hr  =  CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,         IID_IBaseFilter, ( void   ** ) & pSampleGrabber2);     //  Add filters to Filter Graph     hr  =  pGraph -> AddFilter(pSampleGrabber1,L " filter3 " );    hr  =  pGraph -> AddFilter(pSampleGrabber2,L " filter4 " ); /// /// {    IEnumFilters  * pEnumFilter  =  NULL;    IBaseFilter  * pFilter  =  NULL;    IEnumPins  * pEnumPin  =  NULL;    IPin  * pPin  =  NULL;    FILTER_INFO FilterInfo;    PIN_INFO PinInfo;    pGraph -> EnumFilters( & pEnumFilter);     while  (pEnumFilter -> Next( 1 , & pFilter,NULL)  ==  S_OK)    {        pFilter -> QueryFilterInfo( & FilterInfo);        printf( " filter name : ws " ,FilterInfo.achName);        pFilter -> EnumPins( & pEnumPin);         int  i = 0 ,j = 0 ;         while  (pEnumPin -> Next( 1 , & pPin,NULL)  ==  S_OK)        {             //  Check pin info             pPin -> QueryPinInfo( & PinInfo);            printf( " ..filter pin : ws " ,PinInfo.achName);             // printf("..filter pin : ws ",pPin->QueryId);              if  (PinInfo.dir  ==  PINDIR_INPUT) printf( " ..Pin is Input " );                 else  printf( " ..Pin is Output " );             //  Check Connect             AM_MEDIA_TYPE pmt;            ZeroMemory( & pmt, sizeof (AM_MEDIA_TYPE));             if  (pPin -> ConnectionMediaType( & pmt)  !=  S_OK)                printf( " ..this pin is not connected. " );                                     //  Check Render              if  (PinInfo.dir  ==  PINDIR_INPUT                      &&  pmt.majortype  ==  MEDIATYPE_Video)                i  =   1 ;             if  (PinInfo.dir  ==  PINDIR_INPUT                      &&  pmt.majortype  ==  MEDIATYPE_Audio)                i  =   2 ;            j ++ ;        }         if  (j  ==   1   &&  i  == 1 ) printf( " ..this is a video render. " );         if  (j  ==   1   &&  i  == 2 ) printf( " ..this is a audio render. " );        pEnumPin -> Release();    }    pEnumFilter -> Release();} // return;*/ /// /// /*     if (SUCCEEDED(hr))    {        // Run the graph.        hr = pControl->Run();        if (SUCCEEDED(hr))        {            // Wait for completion.            long evCode;            pEvent->WaitForCompletion(INFINITE, &evCode);        }    } */     pSampleGrabber1 -> Release();    pSampleGrabber2 -> Release();    pControl -> Release();    pEvent -> Release();    pGraph -> Release();    CoUninitialize();} void  main(){    runthread();}

    这段程序先建立一个用来渲染文件的filtergraph,然后建立两个SampleGrabber Filter,并将其加入filtergraph。请注意,这两个filter只是加入了filtergraph,而没有于其中任何一个filter连接。接下来,程序例遍整个filtergraph,显示filter的名字、pin的名字、pin的连接情况,并根据filter拥有的已连接的input pin数目和pin的媒体类型来判断该filter是否是一个renderer(尽管这并非十分科学)。

    看起来程序并没有错,可我们在调试时却得到了这样的结果:Executable:***.exe Pid *** Tid ***.Module qedit.dll, 6 objects left active!这就是说,我们还有未释放的资源。当然,你可以将这条消息屏蔽掉,而且你的程序也不会出现太大的问题,至少眼前来说是如此。

    其实问题个根源在这里:

    pGraph -> EnumFilters( & pEnumFilter); while  (pEnumFilter -> Next( 1 , & pFilter,NULL)  ==  S_OK){....}pEnumFilter -> Release();

    看看DirectShow关于Enumerating Filters的说明,你会找到这样一句:“Note the places where the function calls Release on an interface to decrement the reference count.“也就是说,pEnumFilter->Next返回的pFilter指向的接口是一个新申请的接口,而系统并不自己释放它,只就需要我们来做了:

    pGraph -> EnumFilters( & pEnumFilter); while  (pEnumFilter -> Next( 1 , & pFilter,NULL)  ==  S_OK){....    pFilter -> Release();}pEnumFilter -> Release();

    类似情况也出现在pFilter->QueryFilterInfo和pEnumPin->Next(1,&pPin,NULL)中。所以我们必须手动释放其中接口指针指向的接口。修改之后的代码:

     

    #include  " stdafx.h " #include  < dshow.h > #include  < stdio.h > #include  < qedit.h > #include  < streams.h >       //  DirectShow (includes windows.h) void  runthread( void ){    IGraphBuilder  * pGraph  =  NULL;    IMediaControl  * pControl  =  NULL;    IMediaEvent    * pEvent  =  NULL;    IBaseFilter  * pSampleGrabber1  =  NULL, * pSampleGrabber2  =  NULL;     //  Initialize the COM library.     HRESULT hr  =  CoInitialize(NULL);     if  (FAILED(hr))    {        printf( " ERROR - Could not initialize COM library " );         return ;    }     //  Create the filter graph manager and query for interfaces.     hr  =  CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,                         IID_IGraphBuilder, ( void   ** ) & pGraph);     if  (FAILED(hr))    {        printf( " ERROR - Could not create the Filter Graph Manager. " );         return ;    }    hr  =  pGraph -> QueryInterface(IID_IMediaControl, ( void   ** ) & pControl);    hr  =  pGraph -> QueryInterface(IID_IMediaEvent, ( void   ** ) & pEvent);    hr  =  pGraph -> RenderFile(L " C:/DXSDK/Samples/Media/CLOCKTXT.avi " ,NULL);     //  Create Filters     hr  =  CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,                         IID_IBaseFilter, ( void   ** ) & pSampleGrabber1);    hr  =  CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,         IID_IBaseFilter, ( void   ** ) & pSampleGrabber2);     //  Add filters to Filter Graph     hr  =  pGraph -> AddFilter(pSampleGrabber1,L " filter3 " );    hr  =  pGraph -> AddFilter(pSampleGrabber2,L " filter4 " ); /// /// {    IEnumFilters  * pEnumFilter  =  NULL;    IBaseFilter  * pFilter  =  NULL;    IEnumPins  * pEnumPin  =  NULL;    IPin  * pPin  =  NULL;    FILTER_INFO FilterInfo;    PIN_INFO PinInfo;    pGraph -> EnumFilters( & pEnumFilter);     while  (pEnumFilter -> Next( 1 , & pFilter,NULL)  ==  S_OK)    {        pFilter -> QueryFilterInfo( & FilterInfo);        printf( " filter name : ws " ,FilterInfo.achName);        pFilter -> EnumPins( & pEnumPin);         int  i = 0 ,j = 0 ;         while  (pEnumPin -> Next( 1 , & pPin,NULL)  ==  S_OK)        {             //  Check pin info             pPin -> QueryPinInfo( & PinInfo);            printf( " ..filter pin : ws " ,PinInfo.achName);             // printf("..filter pin : ws ",pPin->QueryId);              if  (PinInfo.dir  ==  PINDIR_INPUT) printf( " ..Pin is Input " );                 else  printf( " ..Pin is Output " );             //  Check Connect             AM_MEDIA_TYPE pmt;            ZeroMemory( & pmt, sizeof (AM_MEDIA_TYPE));             if  (pPin -> ConnectionMediaType( & pmt)  !=  S_OK)                printf( " ..this pin is not connected. " );                                     //  Check Render              if  (PinInfo.dir  ==  PINDIR_INPUT                      &&  pmt.majortype  ==  MEDIATYPE_Video)                i  =   1 ;             if  (PinInfo.dir  ==  PINDIR_INPUT                      &&  pmt.majortype  ==  MEDIATYPE_Audio)                i  =   2 ;            j ++ ;            pPin -> Release();        }         if  (j  ==   1   &&  i  == 1 ) printf( " ..this is a video render. " );         if  (j  ==   1   &&  i  == 2 ) printf( " ..this is a audio render. " );        pEnumPin -> Release();         if  (FilterInfo.pGraph != NULL)         {             int  k = FilterInfo.pGraph -> Release();            printf( " %d " ,k);        }        pFilter -> Release();    }    pEnumFilter -> Release();} // return;*/ /// /// /*     if (SUCCEEDED(hr))    {        // Run the graph.        hr = pControl->Run();        if (SUCCEEDED(hr))        {            // Wait for completion.            long evCode;            pEvent->WaitForCompletion(INFINITE, &evCode);        }    } */     pSampleGrabber1 -> Release();    pSampleGrabber2 -> Release();    pControl -> Release();    pEvent -> Release();    pGraph -> Release();    CoUninitialize();} void  main(){    runthread();}

    转载请注明 “刘佳鹏原创“ 2007-2-6


    最新回复(0)