自定义directshow中的内存分配机制

     最近一直在DM365平台上进行音视频录制的开发工作, 由于系统为wince6.0,所以采用了directshow实现。视频编码模块封装成单独的filter, 由于硬编码器的输入缓冲区要求物理地址连续(TI提供了一个叫CMEM的模块)这就需要重新实现directshow的内存管理机制。

 

一、实现自己的内存分配器

 

1.  内存管理的几个相关接口及类有:

  1).IMemAllocator
  2).CBaseAllocator
  3).CMemAllocator

 

2.  实际的内存分配相关函数是在CMemAllocator中实现,涉及3个函数:
1).HRESULT CMemAllocator::Alloc(void), 此函数进行内存分配,代码如下:

HRESULT CMemAllocator::Alloc(void) { ... m_pBuffer = (PBYTE)VirtualAlloc(NULL, m_lCount * lAlignedSize, MEM_COMMIT, PAGE_READWRITE); .... for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize) { pSample = new CMediaSample( NAME("Default memory media sample"), this, &hr, pNext + m_lPrefix, // GetPointer() value m_lSize); // not including prefix ASSERT(SUCCEEDED(hr)); if (pSample == NULL) { return E_OUTOFMEMORY; } // This CANNOT fail m_lFree.Add(pSample); ... }


2).void CMemAllocator::Free(void),此致函数体为空,有一个注释如下
// in our case, we keep the memory until we are deleted, so
// we do nothing here. The memory is deleted in the destructor by
// calling ReallyFree()
3).void CMemAllocator::ReallyFree(void),这才是真正的内存释放函

 

3. 要实现自己的MemAllocator,只需要对CMemAllocator中的,Alloc、RellyFree函数中内存分配与释放进行修改。由于RellyFree不是虚函数,不能继承CmemAllocator。我们可以从CBaseAllocator继承一个类,其实现参考CMemAllocator。

 

二、自定义内存分配器的调用

1.directshow中内存分配器的调用流程

 1.在amfilter.cpp中,定义了一个全局的函数 STDAPI CreateMemoryAllocator(IMemAllocator **ppAllocator) { return CoCreateInstance(CLSID_MemoryAllocator, 0, CLSCTX_INPROC_SERVER, IID_IMemAllocator, (void **)ppAllocator); } 2.可以发现在CBaseInputPin::GetAllocator函数中调用了该函数 STDMETHODIMP CBaseInputPin::GetAllocator( IMemAllocator **ppAllocator) { CheckPointer(ppAllocator,E_POINTER); ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *)); CAutoLock cObjectLock(m_pLock); if (m_pAllocator == NULL) { HRESULT hr = CreateMemoryAllocator(&m_pAllocator); if (FAILED(hr)) { return hr; } } ASSERT(m_pAllocator != NULL); *ppAllocator = m_pAllocator; m_pAllocator->AddRef(); return NOERROR; } HRESULT CBaseInputPin::BreakConnect() { /* We don't need our allocator any more */ if (m_pAllocator) { // Always decommit the allocator because a downstream filter may or // may not decommit the connection's allocator. A memory leak could // occur if the allocator is not decommited when a pin is disconnected. HRESULT hr = m_pAllocator->Decommit(); if( FAILED( hr ) ) { return hr; } m_pAllocator->Release(); m_pAllocator = NULL; } return S_OK; }  

2. 从上述调用过程可以发现,我们只需要重新实现CBaseInputPin::GetAllocator即可,我的实现如下:

HRESULT CAviInputPin::GetAllocator( IMemAllocator ** ppAllocator ) { CheckPointer(ppAllocator,E_POINTER); ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *)); CAutoLock cObjectLock(m_pLock); if (m_pAllocator == NULL) { HRESULT hr = NOERROR; m_pAllocator = new CCemeMemAllocator(L"CCemeMemAllocator", NULL, &hr); if (FAILED(hr)) { return hr; } } ASSERT(m_pAllocator != NULL); *ppAllocator = m_pAllocator; m_pAllocator->AddRef(); //此条语句不可缺少 return NOERROR; }

你可能感兴趣的:(server,filter,null,leak,WinCE,destructor)