2016-03-01 87 views
-1

我正在写directshow应用程序。下面的代码工作正常,但崩溃的错误消息“App.exe已停止工作”。整个代码写在下面。请注意,我使用Windows SDK 7.0,它没有atlbase.h,因此我不能使用CComPtr<IBaseFilter> myFilter;类型的指针声明,它应该在退出时清除内存。DirectShow应用程序崩溃后退出main()

编辑:只有我明确连接所有过滤器,应用程序才会崩溃。在这种情况下,我的过滤器的析构函数不会被调用。如果我只是将源代码过滤器连接到渲染器(它将在内部连接我的过滤器和解复用过滤器),我的过滤器的析构函数将被调用并且不会崩溃。我已将宏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

你只在类似的*两个地方检查错误。如果您不打算查看它是否表示成功或失败,那么保存从该函数返回的HRESULT值是没用的。 –

回答

2

在调用CoUninitialize之前,您必须终止线程上的所有COM活动(特别是:释放所有COM接口指针),您不这样做。

例如,请参见this code及其Release调用底部的_tmain

使用更新版本的Visual Studio(2013,2015),其中免费社区版已包含ATL,您可以使用CComPtr和朋友享受自动COM接口参考管理。对于那些使用原始COM接口指针的用户来说,这是第一个建议,并且遇到了错误管理它们的问题。

参见:

UPDATE:使用原始指针不准确,你一直有泄漏:

hr = pGraph->Connect(pPinOut, pPinIn); 
    // ... 
    hr = pEnumPins->Next(1, &pPinOut, &fetched); 

IEnumPin::Next调用覆盖pPinOut指针并泄漏一个引用。

+0

当我简单地调用'hr = pGraph-> RenderFile(L“input.mp4”,NULL);'时,没有崩溃。我注意到当我手动添加过滤器时,我的过滤器的析构函数没有被调用。任何建议可能会出错?直接调用RenderFile时,我的过滤器的析构函数被调用。 – Saurabh

+0

发现问题但解决方案不确定。当我手动将我的过滤器的输入引脚连接到文件源并将输出引脚连接到渲染器时,释放我的过滤器时发生崩溃。如果我直接将文件源连接到渲染器(它将在内部连接我的过滤器),则不会崩溃,并且存在干净的退出。我如何手动连接引脚并仍然确保干净退出? – Saurabh

+0

在问题中更新源代码以反映您在COM接口管理中的进度将是一个好主意。您尚未解决原始问题。 –