none
关于Directshow轮换播放不同视频文件内存泄漏问题 RRS feed

  • 问题

  • 我的情况是这样的,我要弄一个播放窗口,轮换播放节目列表的不同视频文件,我的程序使用VMR的windowless模式来循环的播放视频文件,但每播放一次,内存就会增加,代码是根据DX文档哪里的windowless代码来修改的.程序是这样的我弄一个定时器,一到时间我就转换播放文件,而不管文件播放没有.就这样循环下来,内存不断的增加,我也试过自己析放Com对象或者用了智能指针,但还是内存泄漏.请教解决办法或者测试在那里内存泄漏的办法.大概代码如下,其中CComPtr<IGraphBuilder> m_pGraph;
    CComPtr<IMediaEventEx> m_pEvent;CComPtr<IMediaSeeking>m_pMediaSeeking; CComPtr<IMediaControl> m_pMediaControl;

    CMyPlayer::CMyPlayer(void)
    {
    m_nPlayStatus = 0;
    m_pGraph = NULL;
    m_pMediaControl = NULL;
    m_pEvent = NULL;
    m_pMediaSeeking = NULL;
    }

    CMyPlayer::~CMyPlayer(void)
    {
    m_nPlayStatus = 0;
    CoUninitialize();
    }

    BEGIN_MESSAGE_MAP(CMyPlayer, CPlayer)
    ON_WM_CREATE()
    ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
    END_MESSAGE_MAP()

    int CMyPlayer::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
    return 0;
    }

    BOOL CMyPlayer::Create(const RECT& rect, CWnd* pParent)
    {
    CString strClassName = AfxRegisterWndClass(CS_DBLCLKS);
    return CreateEx(0, strClassName, _T("Media Player"), WS_EX_TRANSPARENT|WS_CHILD|WS_VISIBLE|WS_TABSTOP, rect, pParent, 0, 0);
    }
    bool CMyPlayer::CreatePlayer(const CRect& rect, CWnd* pParent, HWND hWnd)
    {
    if (!Create(rect, pParent))
    return false;

    MoveWindow(rect);
    m_hParent = pParent->m_hWnd;
    m_hBasePlayer = hWnd;
    if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
    {
    AfxMessageBox(_T("CoInitialize Failed!\r\n"));
    return false;
    }
    return true;
    }
    bool CMyPlayer::CommonPlay(LPCTSTR lpFileName)
    {
    m_strFileName = lpFileName;
    if (m_nPlayStatus == 0)
    {
    InitPlay();
    }
    else if (m_nPlayStatus == 2)
    return true;
    BOOL bRet = Play();
    if (bRet)
    m_nPlayStatus = 2;
    else
    {
    m_nPlayStatus = 0;
    return false;
    }
    return true;
    }
    BOOL CMyPlayer::Play(void)
    {
    if (m_pGraph)
    {
    if (m_pMediaControl == NULL)
    m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl);
    if (m_pMediaControl)
    m_pMediaControl->Run();
    return TRUE;
    }
    return FALSE;
    }
    HRESULT CMyPlayer::InitWindowlessVMR( 
      HWND hwndApp, // Window to hold the video. 
      IGraphBuilder* pGraph, // Pointer to the Filter Graph Manager. 
      IVMRWindowlessControl** ppWc // Receives a pointer to the VMR.
      ) 
    {
    if (pGraph == NULL || ppWc == NULL)
    {
    return E_POINTER;
    }
    CComPtr<IBaseFilter> pVmr = NULL;
    CComPtr<IVMRWindowlessControl> pWc = NULL;
    // Create the VMR. 
    HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
    if (FAILED(hr))
    {
    return hr;
    }
    // Add the VMR to the filter graph.
    hr = pGraph->AddFilter(pVmr, L"Video Mixing Renderer");
    if (FAILED(hr))
    {
    return hr;
    }
    CComPtr<IVMRFilterConfig> pConfig = NULL;
    hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
    if (SUCCEEDED(hr))
    {
    hr = pConfig->SetRenderingMode(VMRMode_Windowless);
    }
    if (SUCCEEDED(hr))
    {
    hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
    if (SUCCEEDED(hr))
    {
    hr = pWc->SetVideoClippingWindow(hwndApp);
    if (SUCCEEDED(hr))
    {
    *ppWc = pWc;
    (*ppWc)->AddRef();
    }
    else
    {
    ;
    }
    }
    }
    return hr;
    }
    int CMyPlayer::CleanUp(void)
    {
    CComPtr<IVideoWindow> pVidWin = NULL;
    if (m_pGraph)
    {
    m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
    pVidWin->put_Visible(OAFALSE);
    }
    return 0;
    }
    void CMyPlayer::InitPlay()
    {
    HRESULT hr;
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void**)&m_pGraph);
    CComPtr<IVMRWindowlessControl> g_pWC = NULL;
    if (m_pGraph != NULL)
    {
    hr = InitWindowlessVMR(m_hWnd, m_pGraph, &g_pWC);
    }
    if (SUCCEEDED(hr))
    {
    USES_CONVERSION;
    m_pGraph->RenderFile(m_strFileName, 0);
    long lWidth, lHeight;
    hr = g_pWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
    if (SUCCEEDED(hr))
    {
    RECT rcSrc, rcDest;
    // Set the source rectangle.
    SetRect(&rcSrc, 0, 0, lWidth, lHeight);
    // Get the window client area
    GetClientRect(&rcDest);
    // Set the destination rectangle.
    SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom);

    g_pWC->SetAspectRatioMode(VMR_ARMODE_NONE);
    hr = g_pWC->SetVideoPosition(&rcSrc, &rcDest);
    }
    }
    if (m_pGraph != NULL)
    {
    m_pGraph->QueryInterface(IID_IMediaEventEx, (void**)&m_pEvent);// 注意此处Filter Graph Manager的事件以WM_GRAPHNOTIFY发出(用户定义的消息).
    m_pEvent->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);
    m_pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_pMediaSeeking);//设置Seeking
    }
    }
    bool CMyPlayer::CommonPlay()
    {
    return CommonPlay(m_strFileName);
    }

    bool CMyPlayer::CommonPause()
    {
    if (m_pMediaControl)
    m_pMediaControl->Pause();
    m_nPlayStatus = 1;
    return true;
    }

    bool CMyPlayer::CommonStop()
    {
    CComPtr<IVideoWindow> pVidWin = NULL;
    HRESULT hr;
    if (m_pMediaControl)
    {
    LONGLONG lPos = 0;
    if (m_pMediaControl)
    hr = m_pMediaControl->Stop();
    if (m_pMediaSeeking)
    hr = m_pMediaSeeking->SetPositions(&lPos, AM_SEEKING_AbsolutePositioning, &lPos, AM_SEEKING_NoPositioning);
    if (m_pGraph)
    {
    m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
    pVidWin->put_Visible(OAFALSE);
    }
    long lLevCode;
    if (m_pEvent)
    m_pEvent->WaitForCompletion(INFINITE, &lLevCode);
    }
    m_nPlayStatus = 0;
    m_bPlayEnd = true;
    CleanUp();
    return true;
    }
    int CMyPlayer::GetPlayStatus()
    {
    return m_nPlayStatus;
    }

    HRESULT CMyPlayer::OnGraphNotify(WPARAM wParam, LPARAM lParam)
    {
    long lLevCode, lParam1, lParam2;
    HRESULT hr;
    while (m_pEvent, hr = m_pEvent->GetEvent(&lLevCode, &lParam1, &lParam2, 0), SUCCEEDED(hr))
    {
    hr = m_pEvent->FreeEventParams(lLevCode, lParam1, lParam2);
    if ((EC_COMPLETE == lLevCode) || (EC_USERABORT == lLevCode) || (EC_ERRORABORT == lLevCode))
    {
    CommonStop();
    m_nPlayStatus = 0;
    break;
    }
    }
    return hr;
    }
    2010年9月26日 5:06

答案