退出main()

时间:2016-03-01 10:06:49

标签: c++ com directshow

我正在编写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进行开发。

1 个答案:

答案 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指针并泄漏引用。