[Fixed in the latest version]A memory leak issue in Media extensions sample (Windows 8.1)

Media extensions sample demonstrates how to write and use media foundation filter in windows store applications. But you may find that the destructor of CMPEG1Source isn’t called when video playback is stopped which causes a native memory leak issue.

Actually this issue is caused by the unmatched reference count of the COM objects. When the source of media element set to null, the ref count of CMPEG1Source isn’t 0. So the CMPEG1Source object can’t get released.

When I check the ref count of CMPEG1Source object, I find that the constructor of CMPEG1Stream adds a ref count of CMPEG1Source object as following:

CMPEG1Stream::CMPEG1Stream(CMPEG1Source *pSource, IMFStreamDescriptor *pSD, HRESULT& hr) :

    m_cRef(1),

    m_pEventQueue(NULL),

    m_state(STATE_STOPPED),

    m_bActive(FALSE),

    m_bEOS(FALSE),

    m_flRate(1.0f)

{

    … 

    m_pSource = pSource;

    m_pSource->AddRef();

     …

}

It should be decreased when the destructor of CMPEG1Stream is called:

CMPEG1Stream::~CMPEG1Stream()

{

    assert(m_state == STATE_SHUTDOWN);

    SafeRelease(&m_pSource);

 

    auto module = ::Microsoft::WRL::GetModuleBase();

    if (module != nullptr)

    {

        module->DecrementObjectCount();

    }

}

But the destructor of CMPEG1Stream neither gets called. So actually there is CMPEG1Stream objects leak too.

Then we should also check the ref count of CMPEG1Stream object. The ref count of CMPEG1Stream is added when we add the stream to a StreamList object in AddStream function:

HRESULT AddStream(BYTE id, CMPEG1Stream *pStream)

{

    … 

    m_streams[m_count] = pStream;

    pStream->AddRef();

     …

}

It decreases the ref count of CMPEG1Stream object in StreamList’s Clear function:

void Clear()

{

    for (UINT32 i = 0; i < MAX_STREAMS; i++)

    {

        SafeRelease(&m_streams[i]);

    }

    m_count = 0;

}

Unfortunately Clear function is never called when the CMPEG1Source object is shut down. The solution is that we should add this function call in CMPEG1Source::Shutdown function as following:

HRESULT CMPEG1Source::Shutdown()

{

    …

    if (SUCCEEDED(hr))

    {

        // Shut down the stream objects.

 

        for (DWORD i = 0; i < m_streams.GetCount(); i++)

        {

            (void)m_streams[i]->Shutdown();

        }

        m_streams.Clear();

        …

    }

     …

}

After the line m_streams.Clear() in Shutdown function is added, the sample can work well without the memory leak.