“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();}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。