分享

directshow 中 x Objects left active 问题的解决(转载)

 lzp20 2012-11-05

“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 : %10ws ",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 : %10ws ",PinInfo.achName);
            
//printf("..filter pin : %10ws ",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 : %10ws ",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 : %10ws ",PinInfo.achName);
            
//printf("..filter pin : %10ws ",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();
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多