【问题标题】:DirectShow manual graph memory leaksDirectShow 手动图形内存泄漏
【发布时间】:2018-09-28 11:00:01
【问题描述】:

这里是简单的手动捕获和渲染图构建。
CaptureFilter->SmartTee->(预览)->AviDecompressor->渲染
一切正常,工作时获得 140Mb。
在我停止渲染并释放所有过滤器和 IGraphBuilder 后剩余 50Mb!
再次构建相同的过滤器 - 除了内存中的 140+50=190Mb 之外,所有工作都有效。
释放后剩余 100Mb。
一次又一次。
我以任何可以想象的组合尝试了 SmartPtr、ComPtr、Release(),但没有任何效果。
似乎我做错了什么:(

#include <windows.h>
#include <dshow.h>
#include <iostream>
#include <string>

#pragma comment(lib, "strmiids")

#define SafeRelease(Com) {if (Com!=nullptr){Com->Release(); Com=nullptr;};};

void GetCaptureSource(std::wstring friendly_name, IBaseFilter** ppCaptureFilter);

void GetPin(IPin** ppPin, IBaseFilter* pFilter, std::string direction_str, std::wstring name_wstr = L"");


int  main()
{

    HRESULT hr = CoInitialize(0);

    //Get Capture Filter
    IBaseFilter* p_CaptureFilter;
    GetCaptureSource(L"USB3.0 Capture Video", &p_CaptureFilter);

    //Get Capture Pin
    IPin* p_CaptureOutPin;
    GetPin(&p_CaptureOutPin, p_CaptureFilter, "out");

    //Get Smart Tee Filter
    IBaseFilter* p_SmartTee;
    hr = CoCreateInstance(CLSID_SmartTee, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_SmartTee));

    //Get Smart Tee Pins
    IPin* p_SmartInputPin;
    GetPin(&p_SmartInputPin, p_SmartTee, "in");
    IPin* p_SmartOutputPin;
    GetPin(&p_SmartOutputPin, p_SmartTee, "out", L"Preview");

    //Get AviDecompressorFilter
    IBaseFilter* p_AviDecompressor;
    hr = CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_AviDecompressor));

    //Get Avi Decompressor Pins
    IPin* p_AviInputPin;
    GetPin(&p_AviInputPin, p_AviDecompressor, "in");
    IPin* p_AviOutputPin;
    GetPin(&p_AviOutputPin, p_AviDecompressor, "out");

    //Get Video Render Filter
    IBaseFilter* p_VideoRender;
    hr = CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_VideoRender));

    //Get Video Render Pin
    IPin* p_RenderPin;
    GetPin(&p_RenderPin, p_VideoRender, "in");

    // Create the Filter Graph Manager.
    IGraphBuilder* p_GraphBuilder;
    hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&p_GraphBuilder);

    //Add Capture Filter
    hr = p_GraphBuilder->AddFilter(p_CaptureFilter, L"CaptureFilter");

    //Add Smart Tee Filter
    hr = p_GraphBuilder->AddFilter(p_SmartTee, L"SmartTee");

    //Add Decompressor Filter
    hr = p_GraphBuilder->AddFilter(p_AviDecompressor, L"Avi Decompressor");

    //Add Video Render Filter
    hr = p_GraphBuilder->AddFilter(p_VideoRender, L"Video Render");

    //Connect Pins
    hr = p_GraphBuilder->Connect(p_CaptureOutPin, p_SmartInputPin);
    hr = p_GraphBuilder->Connect(p_SmartOutputPin, p_AviInputPin);
    hr = p_GraphBuilder->Connect(p_AviOutputPin, p_RenderPin);

    //Get Interfaces
    IVideoWindow* p_VideoWindow;
    hr = p_GraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&p_VideoWindow);
    IMediaControl* p_MediaControl;
    hr = p_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&p_MediaControl);

    //Release all pins references
    SafeRelease(p_CaptureOutPin);
    SafeRelease(p_SmartInputPin);
    SafeRelease(p_SmartOutputPin);
    SafeRelease(p_AviInputPin);
    SafeRelease(p_AviOutputPin);
    SafeRelease(p_RenderPin);

    //Release all filter references
    SafeRelease(p_CaptureFilter);
    SafeRelease(p_SmartTee);
    SafeRelease(p_AviDecompressor);
    SafeRelease(p_VideoRender);

    std::cout << "Press any key to START\n";
    std::system("pause");
    hr = p_MediaControl->Run();

    p_VideoWindow->put_Caption(L"render_window");
    p_VideoWindow->SetWindowPosition(20, 20, 1920, 1080);

    LONG lStyle = GetWindowLong(0, GWL_STYLE);
    lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
    p_VideoWindow->put_WindowStyle(lStyle);

    //There Window apears and ALL GOOD
    std::cout << "Press any key to STOP\n";
    std::system("pause");


    hr = p_MediaControl->Stop();

    hr = p_VideoWindow->put_Visible(OAFALSE);
    hr = p_VideoWindow->put_Owner(NULL);

    //SafeRelease(p_MediaControl);
    //SafeRelease(p_VideoWindow);
    SafeRelease(p_GraphBuilder);

    CoUninitialize();

    std::cout << "Press any key to QUIT\n";
    std::system("pause");
    std::cout << "\n\n";
    //system("pause");
    return 0;


}



void GetCaptureSource(std::wstring friendly_name, IBaseFilter** ppCaptureFilter) {

    HRESULT hr;

    ICreateDevEnum* devs;
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&devs);

    IEnumMoniker* p_InputMonikersEnum;
    hr = devs->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &p_InputMonikersEnum, 0);
    SafeRelease(devs);


    bool is_capture_finded = false;
    do {
        IMoniker* p_CaptureMoniker;
        hr = p_InputMonikersEnum->Next(1, &p_CaptureMoniker, 0);
        if (hr != S_OK) break;
        IPropertyBag* p_PropBag;
        hr = p_CaptureMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&p_PropBag);
        VARIANT var;
        VariantInit(&var);
        VariantClear(&var);
        hr = p_PropBag->Read(L"FriendlyName", &var, 0);
        SafeRelease(p_PropBag);
        std::wstring input_moniker_friendly_name = std::wstring(var.bstrVal);
        if (input_moniker_friendly_name == friendly_name) {
            is_capture_finded = true;
            hr = p_CaptureMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppCaptureFilter);
            SafeRelease(p_CaptureMoniker);
            break;
        }
        SafeRelease(p_CaptureMoniker);
    } while (true);
    if (is_capture_finded == false) MessageBoxW(0, L"Capture NOT founded.", L"ERROR", MB_OK);

    SafeRelease(p_InputMonikersEnum);

    return;
}


void GetPin(IPin** ppPin, IBaseFilter* pFilter, std::string direction_str, std::wstring name_wstr) {

    HRESULT hr;
    IEnumPins* pEnumPins;
    hr = pFilter->EnumPins(&pEnumPins);
    do {
        IPin* pNextPin;
        hr = pEnumPins->Next(1, &pNextPin, 0);
        if (hr != S_OK) break;
        PIN_INFO pin_inf;
        hr = pNextPin->QueryPinInfo(&pin_inf);
        bool is_pin_of_interest = true;
        if ((direction_str == "in") && (pin_inf.dir == PINDIR_OUTPUT)) is_pin_of_interest = false;
        if ((direction_str == "out") && (pin_inf.dir == PINDIR_INPUT)) is_pin_of_interest = false;
        if ((name_wstr != L"") && (name_wstr != std::wstring(pin_inf.achName))) is_pin_of_interest = false;
        if (is_pin_of_interest) {
            *ppPin = pNextPin;
            SafeRelease(pNextPin);
            break;
        }
        SafeRelease(pNextPin);
    } while (true);
    SafeRelease(pEnumPins);
    return;
}

【问题讨论】:

  • 但是您没有释放p_MediaControlp_VideoWindow...?这些也指向图表。枚举图中所有剩余的过滤器并删除它们可能也是一个好主意。 (EnumFiltersRemoveFilter
  • 如果在那之后您仍然有参考泄漏,请在关机时开始调查所有-&gt;Release 调用的输出。如果返回 0,则该对象已被删除。
  • Release() 引脚上的函数从 4 到 8 返回。在过滤器上从 4 到 6 如果做 pMediaContrtol->Release(); pVideoWindow->Release(); pGraphBuilder->Relise()
  • PIN_INFO 填写的GetPin 包含对您还需要释放的过滤器的引用。
  • @nefton - 如果您能花时间实际发布您的问题的答案,而不仅仅是这里的 cmets,这样其他人可以受益,那就太好了。人们并不总是阅读 cmets..

标签: c++ directshow


【解决方案1】:

这是工作代码
1. 你应该释放你创建的所有 I* 实例,但不能只释放 IPIns
2. 看代码,还有一些细微差别

#include <windows.h>
#include <dshow.h>
#include <iostream>
#include <string>

#pragma comment(lib, "strmiids")

#define SafeRelease(Com) {if (Com!=nullptr){Com->Release(); Com=nullptr;};};

void GetCaptureSource(std::wstring friendly_name, IBaseFilter** ppCaptureFilter);

void GetPin(IPin** ppPin, IBaseFilter* pFilter, std::string direction_str, std::wstring name_wstr = L"");


int  main()
{

    HRESULT hr = CoInitialize(0);

    //Get Capture Filter
    IBaseFilter* p_CaptureFilter;
    GetCaptureSource(L"USB3.0 Capture Video", &p_CaptureFilter);

    //Get Capture Pin
    IPin* p_CaptureOutPin;
    GetPin(&p_CaptureOutPin, p_CaptureFilter, "out");

    //Get Smart Tee Filter
    IBaseFilter* p_SmartTee;
    hr = CoCreateInstance(CLSID_SmartTee, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_SmartTee));

    //Get Smart Tee Pins
    IPin* p_SmartInputPin;
    GetPin(&p_SmartInputPin, p_SmartTee, "in");
    IPin* p_SmartOutputPin;
    GetPin(&p_SmartOutputPin, p_SmartTee, "out", L"Preview");

    //Get AviDecompressorFilter
    IBaseFilter* p_AviDecompressor;
    hr = CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_AviDecompressor));

    //Get Avi Decompressor Pins
    IPin* p_AviInputPin;
    GetPin(&p_AviInputPin, p_AviDecompressor, "in");
    IPin* p_AviOutputPin;
    GetPin(&p_AviOutputPin, p_AviDecompressor, "out");

    //Get Video Render Filter
    IBaseFilter* p_VideoRender;
    hr = CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&p_VideoRender));

    //Get Video Render Pin
    IPin* p_RenderPin;
    GetPin(&p_RenderPin, p_VideoRender, "in");

    // Create the Filter Graph Manager.
    IGraphBuilder* p_GraphBuilder;
    hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&p_GraphBuilder);

    //Add Capture Filter
    hr = p_GraphBuilder->AddFilter(p_CaptureFilter, L"CaptureFilter");

    //Add Smart Tee Filter
    hr = p_GraphBuilder->AddFilter(p_SmartTee, L"SmartTee");

    //Add Decompressor Filter
    hr = p_GraphBuilder->AddFilter(p_AviDecompressor, L"Avi Decompressor");

    //Add Video Render Filter
    hr = p_GraphBuilder->AddFilter(p_VideoRender, L"Video Render");

    //Connect Pins
    hr = p_GraphBuilder->Connect(p_CaptureOutPin, p_SmartInputPin);
    hr = p_GraphBuilder->Connect(p_SmartOutputPin, p_AviInputPin);
    hr = p_GraphBuilder->Connect(p_AviOutputPin, p_RenderPin);

    //Get Interfaces
    IVideoWindow* p_VideoWindow;
    hr = p_GraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&p_VideoWindow);
    IMediaControl* p_MediaControl;
    hr = p_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&p_MediaControl);

    //DONT RELEASE IPINS REFERENSES!!!!!!!!
    //IT CAUSE ERROR WHEN YOU TRY TO RELEASE FILTERS OR GRAPH WERY LATER
    //AND WILL BE WERY HARD TO FIND IT

    //p_CaptureOutPin->Release();
    //p_SmartInputPin->Release();
    //p_SmartOutputPin->Release();
    //p_AviInputPin->Release(); 
    //p_AviOutputPin->Release();
    //p_RenderPin->Release(); 

    //Release all filter references
    p_CaptureFilter->Release();
    p_SmartTee->Release();
    p_AviDecompressor->Release();
    p_VideoRender->Release();

    std::cout << "Press any key to START\n";
    std::system("pause");
    hr = p_MediaControl->Run();

    p_VideoWindow->put_Caption(L"render_window");
    p_VideoWindow->SetWindowPosition(20, 20, 1920, 1080);

    LONG lStyle = GetWindowLong(0, GWL_STYLE);
    lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
    p_VideoWindow->put_WindowStyle(lStyle);

    //There Window apears and ALL GOOD
    std::cout << "Press any key to STOP\n";
    std::system("pause");


    hr = p_MediaControl->Stop();

    hr = p_VideoWindow->put_Visible(OAFALSE);
    hr = p_VideoWindow->put_Owner(NULL);

    // Enumerate the filters in the graph.
    IEnumFilters *pEnum = NULL;
    hr = p_GraphBuilder->EnumFilters(&pEnum);
    do {
        IBaseFilter *pFilter = NULL;
        hr = pEnum->Next(1, &pFilter, NULL);
        if (hr != S_OK) break;
        // Remove the filter.
        p_GraphBuilder->RemoveFilter(pFilter);
        // RESET THE ENUMERATOR IN CYCLE (WERY STRANGE CODE BUT ELSEWERE NOTHING WORKS)
        pEnum->Reset();
        pFilter->Release();
    } while (true);
    pEnum->Release();


    std::cout << "Press any key to QUIT\n";
    std::system("pause");
    std::cout << "\n\n";
    //system("pause");
    return 0;


}



void GetCaptureSource(std::wstring friendly_name, IBaseFilter** ppCaptureFilter) {

    HRESULT hr;

    ICreateDevEnum* devs;
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&devs);

    IEnumMoniker* p_InputMonikersEnum;
    hr = devs->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &p_InputMonikersEnum, 0);
    SafeRelease(devs);


    bool is_capture_finded = false;
    do {
        IMoniker* p_CaptureMoniker;
        hr = p_InputMonikersEnum->Next(1, &p_CaptureMoniker, 0);
        if (hr != S_OK) break;
        IPropertyBag* p_PropBag;
        hr = p_CaptureMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&p_PropBag);
        VARIANT var;
        VariantInit(&var);
        VariantClear(&var);
        hr = p_PropBag->Read(L"FriendlyName", &var, 0);
        SafeRelease(p_PropBag);
        std::wstring input_moniker_friendly_name = std::wstring(var.bstrVal);
        if (input_moniker_friendly_name == friendly_name) {
            is_capture_finded = true;
            hr = p_CaptureMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppCaptureFilter);
            SafeRelease(p_CaptureMoniker);
            break;
        }
        SafeRelease(p_CaptureMoniker);
    } while (true);
    if (is_capture_finded == false) MessageBoxW(0, L"Capture NOT founded.", L"ERROR", MB_OK);

    SafeRelease(p_InputMonikersEnum);

    return;
}


void GetPin(IPin** ppPin, IBaseFilter* pFilter, std::string direction_str, std::wstring name_wstr) {

    HRESULT hr;
    IEnumPins* pEnumPins;
    hr = pFilter->EnumPins(&pEnumPins);
    do {
        IPin* pNextPin;
        hr = pEnumPins->Next(1, &pNextPin, 0);
        if (hr != S_OK) break;
        PIN_INFO pin_inf;
        hr = pNextPin->QueryPinInfo(&pin_inf);
        bool is_pin_of_interest = true;
        if ((direction_str == "in") && (pin_inf.dir == PINDIR_OUTPUT)) is_pin_of_interest = false;
        if ((direction_str == "out") && (pin_inf.dir == PINDIR_INPUT)) is_pin_of_interest = false;
        if ((name_wstr != L"") && (name_wstr != std::wstring(pin_inf.achName))) is_pin_of_interest = false;
        pin_inf.pFilter->Release();
        if (is_pin_of_interest) {
            *ppPin = pNextPin;
            SafeRelease(pNextPin);
            break;
        }
        SafeRelease(pNextPin);
    } while (true);
    SafeRelease(pEnumPins);
    return;
}

【讨论】:

  • 还需要释放p_VideoWindow。但无论如何还是有一些泄漏,至少处理泄漏。我循环运行代码 100 次,任务管理器显示句柄数正在增长。 Deleaker 显示了互斥锁、事件等的泄漏,这里是截图i.snag.gy/OIhCub.jpg
猜你喜欢
  • 2021-01-27
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
相关资源
最近更新 更多