我正在编写directshow应用程序。下面的代码工作正常,但崩溃时出现错误消息“App.exe已停止工作”。整个代码写在下面。请注意,我使用的是没有atlbase.h
的Windows SDK 7.0,因此我不能使用CComPtr<IBaseFilter> myFilter;
类型的指针声明,它应该在退出时清除内存。
编辑:只有在我明确连接所有过滤器时,应用程序才会崩溃。在这种情况下,我的过滤器的析构函数不会被调用。如果我只是将源过滤器连接到渲染器(它将在内部连接我的过滤器和解复用过滤器),我的过滤器的析构函数被调用,并且没有崩溃。我已将宏MANUAL_CONNECT
放在导致崩溃的代码上。我已移除RemoveFilter
来电并将其替换为Release
来电。
我在这里编写应用程序代码:
void main(WORD32 argc, CHAR *argv[])
{
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
{
IGraphBuilder *pGraph = NULL;
IFileSourceFilter *pFileSourceFilter = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
IBaseFilter *pSource = NULL;
IBaseFilter *pVideoDecode = NULL;
IBaseFilter *pVideoRenderer = NULL;
IEnumPins *pEnumPins = NULL;
IPin *pPinIn = NULL;
IPin *pPinOut = NULL;
ULONG fetched;
PIN_INFO PinInfo;
IEnumFilters *pEnum = NULL;
BOOL stop = FALSE;
int i;
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pSource);
hr = pGraph->AddFilter(pSource, NULL);
hr = pSource->QueryInterface(IID_IFileSourceFilter, (void**)&pFileSourceFilter);
hr = pFileSourceFilter->Load(L"input.mp4", NULL);
// Create Ittiam HEVC Decoder instance
hr = CoCreateInstance(CLSID_ivdec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoDecode);
// Create Video Renderer instance. We have used default video renderer
hr = CoCreateInstance(CLSID_VideoRendererDefault, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);
// Add decoder filter to the filter graph
hr = pGraph->AddFilter(pVideoDecode, NULL);
// Add renderer filter to the filter graph
hr = pGraph->AddFilter(pVideoRenderer, NULL);
/**************************************************************/
/* -- Connecting source filter to demux filter starts here -- */
/**************************************************************/
// Enumerate pins of the source filter
hr = pSource->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of source filter. Source filter has only output pin, so no check required
hr = pEnumPins->Next(1, &pPinOut, &fetched);
hr = pEnumPins->Release();
#if MANUAL_CONNECT
// Enumerate pins of the decoder filter
hr = pVideoDecode->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of decoder filter. Decoder filter has 2 pins, so ensure the selected pin is input pin.
// If not, get another pin
hr = pEnumPins->Next(1, &pPinIn, &fetched);
hr = pPinIn->QueryPinInfo(&PinInfo);
if(PINDIR_OUTPUT == PinInfo.dir)
{
hr = pPinIn->Release();
hr = pEnumPins->Next(1, &pPinIn, &fetched);
}
// Connect output pin of demux filter to input pin of decoder filter
hr = pGraph->Connect(pPinOut, pPinIn);
/*************************************************************/
/* -- Connecting demux filter to decoder filter ends here -- */
/*************************************************************/
/******************************************************************/
/* -- Connecting decoder filter to renderer filter starts here -- */
/******************************************************************/
// Enumerate pins of the decoder filter
hr = pVideoDecode->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of decoder filter. Decoder filter has 2 pins, so ensure the selected pin is output pin.
// If not, get another pin
hr = pEnumPins->Next(1, &pPinOut, &fetched);
hr = pPinOut->QueryPinInfo(&PinInfo);
if(PINDIR_INPUT == PinInfo.dir)
{
hr = pPinOut->Release();
hr = pEnumPins->Next(1, &pPinOut, &fetched);
}
hr = pEnumPins->Release();
#endif
// Enumerate pins of the renderer filter
hr = pVideoRenderer->EnumPins(&pEnumPins);
hr = pEnumPins->Reset();
// Get pin of renderer filter. Renderer filter has only input pin, so no check required
hr = pEnumPins->Next(1, &pPinIn, &fetched);
hr = pPinIn->QueryPinInfo(&PinInfo);
// Connect output pin of decoder filter to input pin of renderer filter
hr = pGraph->Connect(pPinOut, pPinIn);
/****************************************************************/
/* -- Connecting decoder filter to renderer filter ends here -- */
/****************************************************************/
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
hr = pControl->Stop();
hr = pSource->Release();
hr = pVideoDecode->Release();
hr = pControl->Release();
hr = pEvent->Release();
hr = pGraph->Release();
}
CoUninitialize();
printf("Exiting main!!\n");
}
我已从帖子中删除了错误检查,但我在代码中进行了所有错误检查。我可以看到Exiting main!!
打印但是应用程序崩溃了。关于如何调试这个的任何建议?如果缺少任何信息,请告诉我。我正在使用Microsoft Visual C ++ 2010 Express进行开发。
答案 0 :(得分:2)
您必须在调用CoUninitialize
之前终止线程上的所有COM活动(具体是:释放所有COM接口指针),否则不要这样做。
例如,在Release
底部查看this code及其_tmain
来电。
使用更新版本的Visual Studio(2013,2015)是有意义的,其中免费社区版已包含ATL,您可以使用CComPtr
和朋友享受自动COM界面参考管理。这是对使用原始COM接口指针的人的第一个建议,并且遇到管理错误的问题。
另见:
UPDATE :使用原始指针不准确,您一直在泄密:
hr = pGraph->Connect(pPinOut, pPinIn);
// ...
hr = pEnumPins->Next(1, &pPinOut, &fetched);
IEnumPin::Next
调用覆盖pPinOut
指针并泄漏引用。