OpenNI2中主要涉及到内存管理部分的主要是(Depth, IR, Color)Frame buffer 部分,应用层通过OpenNI API可以获取到底层硬件传感器的各种数据,主要还是深度数据,红外图像数据,彩色图像数据。这其中就涉及到内存分配,引用,销毁一个完整的内存操作闭环。
以下从获取一帧深度数据的完整流程来具体分析Openni是如果管理内存的。
1.驱动层
驱动数据接口一般是USB,收到一帧数据后驱动层会去分配内存存放数据,调用的函数接口为:getServices().acquireFrame()
-->
OniFrame* Sensor::acquireFrame()
{
OniFrameInternal* pResult = m_frameManager.acquireFrame();
if (pResult == NULL)
{
return NULL;
}
{
OniFrameInternal* pResult = m_frameManager.acquireFrame();
if (pResult == NULL)
{
return NULL;
}
pResult->data = m_allocFrameBufferCallback(m_requiredFrameSize, m_frameBufferAllocatorCookie);
if (pResult->data == NULL)
{
m_frameManager.release(pResult);
return NULL;
}
if (pResult->data == NULL)
{
m_frameManager.release(pResult);
return NULL;
}
pResult->dataSize = m_requiredFrameSize;
pResult->backToPoolFunc = frameBackToPoolCallback;
pResult->backToPoolFuncCookie = this;
pResult->freeBufferFunc = m_freeFrameBufferCallback;
pResult->freeBufferFuncCookie = m_frameBufferAllocatorCookie;
pResult->backToPoolFunc = frameBackToPoolCallback;
pResult->backToPoolFuncCookie = this;
pResult->freeBufferFunc = m_freeFrameBufferCallback;
pResult->freeBufferFuncCookie = m_frameBufferAllocatorCookie;
xnl::AutoCSLocker lock(m_framesCS);
m_currentStreamFrames.AddLast(pResult);
m_currentStreamFrames.AddLast(pResult);
return pResult;
}
}
首先调用到了frameManager 里面的acquireFrame()
OniFrameInternal* FrameManager::acquireFrame()
{
OniFrameInternal* pFrame = m_frames.Acquire();
{
OniFrameInternal* pFrame = m_frames.Acquire();
// reset all fields
pFrame->dataSize = 0;
pFrame->data = NULL; //此时的内存还没有分配
pFrame->sensorType = (OniSensorType)0;
pFrame->timestamp = 0;
pFrame->frameIndex = 0;
pFrame->width = 0;
pFrame->height = 0;
pFrame->videoMode.pixelFormat = (OniPixelFormat)0;
pFrame->videoMode.resolutionX = 0;
pFrame->videoMode.resolutionY = 0;
pFrame->videoMode.fps = 0;
pFrame->croppingEnabled = FALSE;
pFrame->cropOriginX = 0;
pFrame->cropOriginY = 0;
pFrame->stride = 0;
pFrame->backToPoolFunc = NULL;
pFrame->backToPoolFuncCookie = NULL;
pFrame->refCount = 1; // this is the only reference
pFrame->freeBufferFunc = NULL;
pFrame->freeBufferFuncCookie = NULL;
pFrame->dataSize = 0;
pFrame->data = NULL; //此时的内存还没有分配
pFrame->sensorType = (OniSensorType)0;
pFrame->timestamp = 0;
pFrame->frameIndex = 0;
pFrame->width = 0;
pFrame->height = 0;
pFrame->videoMode.pixelFormat = (OniPixelFormat)0;
pFrame->videoMode.resolutionX = 0;
pFrame->videoMode.resolutionY = 0;
pFrame->videoMode.fps = 0;
pFrame->croppingEnabled = FALSE;
pFrame->cropOriginX = 0;
pFrame->cropOriginY = 0;
pFrame->stride = 0;
pFrame->backToPoolFunc = NULL;
pFrame->backToPoolFuncCookie = NULL;
pFrame->refCount = 1; // this is the only reference
pFrame->freeBufferFunc = NULL;
pFrame->freeBufferFuncCookie = NULL;
return pFrame;
}
}
该函数创建了一个空的OniFrameInternal结构,里面的参数需要在接下来填充。紧接着要去做真正的内存分配: m_allocFrameBufferCallback(),该函数是需要用户配置的回调函数,默认采用系统设置的:
Sensor::Sensor(xnl::ErrorLogger& errorLogger, FrameManager& frameManager, const DriverHandler& driverHandler) :
m_streamCount(0),
m_startedStreamCount(0),
m_errorLogger(errorLogger),
m_frameManager(frameManager),
m_driverHandler(driverHandler),
m_streamHandle(NULL),
m_requiredFrameSize(0)
{
resetFrameAllocator();
m_streamCount(0),
m_startedStreamCount(0),
m_errorLogger(errorLogger),
m_frameManager(frameManager),
m_driverHandler(driverHandler),
m_streamHandle(NULL),
m_requiredFrameSize(0)
{
resetFrameAllocator();
OniStreamServices::streamServices = this;
OniStreamServices::getDefaultRequiredFrameSize = getDefaultRequiredFrameSizeCallback;
OniStreamServices::acquireFrame = acquireFrameCallback;
OniStreamServices::addFrameRef = addFrameRefCallback;
OniStreamServices::releaseFrame = releaseFrameCallback;
}
OniStreamServices::getDefaultRequiredFrameSize = getDefaultRequiredFrameSizeCallback;
OniStreamServices::acquireFrame = acquireFrameCallback;
OniStreamServices::addFrameRef = addFrameRefCallback;
OniStreamServices::releaseFrame = releaseFrameCallback;
}
如果在回调函数中没有设置分配函数,引用函数,销毁函数(acquireFrame,addFrameRef , releaseFrame)那么 系统将采用默认配置:void Sensor::resetFrameAllocator()
{
m_allocFrameBufferCallback = allocFrameBufferFromPoolCallback;
m_freeFrameBufferCallback = releaseFrameBufferToPoolCallback;
m_frameBufferAllocatorCookie = this;
}
{
m_allocFrameBufferCallback = allocFrameBufferFromPoolCallback;
m_freeFrameBufferCallback = releaseFrameBufferToPoolCallback;
m_frameBufferAllocatorCookie = this;
}
void* Sensor::allocFrameBufferFromPool(int size)
{
XN_ASSERT(size == m_requiredFrameSize);
void* pResult = NULL;
xnl::AutoCSLocker lock(m_framesCS);
if (m_availableFrameBuffers.IsEmpty())
{
// create a new one
pResult = xnOSMallocAligned(size, XN_DEFAULT_MEM_ALIGN);
m_allFrameBuffers.AddLast(pResult);
}
else
{
xnl::List<void*>::Iterator it = m_availableFrameBuffers.Begin();
pResult = *it;
m_availableFrameBuffers.Remove(it);
}
return pResult;
}
{
XN_ASSERT(size == m_requiredFrameSize);
void* pResult = NULL;
xnl::AutoCSLocker lock(m_framesCS);
if (m_availableFrameBuffers.IsEmpty())
{
// create a new one
pResult = xnOSMallocAligned(size, XN_DEFAULT_MEM_ALIGN);
m_allFrameBuffers.AddLast(pResult);
}
else
{
xnl::List<void*>::Iterator it = m_availableFrameBuffers.Begin();
pResult = *it;
m_availableFrameBuffers.Remove(it);
}
return pResult;
}
在allocFrameBufferFromPool()函数中开始真正分配内存xnOSMallocAligned(),前提是在当前可用Frame list上没有可用内存。当然提一次分配时list肯定为空,接下来会分析不为空的情况。分配成功后会把该内存放到m_allFrameBuffers 链表上。