当前位置: 首页> 娱乐> 明星 > 营销型企业网站有哪些类型_室内效果图制作流程_域名站长工具_百度教育

营销型企业网站有哪些类型_室内效果图制作流程_域名站长工具_百度教育

时间:2025/7/14 18:48:18来源:https://blog.csdn.net/Cmatrix204/article/details/142610052 浏览次数:0次
营销型企业网站有哪些类型_室内效果图制作流程_域名站长工具_百度教育

一、Camx内存池架构简介

1.1内存池使用的好处

        首先,在项目中如果频繁的使用malloc申请内存空间,堆上分配和释放内存,会导致性能的损失。由于堆空间申请的存储地址是不连续的,也会使系统中出现的大量的内存碎片,降低内存的利用率,而内存池的使用就很好的解决了这些性能和内存上的问题。

        其次,内存池使用映射到连续物理地址的Ion Buffer(本质是linux的file文件),通过文件描述符可以实现各个进程间数据的共享,比堆空间的使用范围大多了,能更好的link上下路各个模块间的链路。

1.2Camx内存池架构总览

        高通Camx架构中的imageBuffer在pipeline的流转中扮演着重要的作用,而管理imagerBuffer的ImageBufferManager与MemPool Manager共同承担起高通Camx架构中的内存池的调度角色,下图简单绘制了一下相互的调用关系。

二、Camx ImageBufferManager

代码路径:vendor\qcom\proprietary\camx\src\core\camximagebuffermanager.cpp

                  vendor\qcom\proprietary\camx\src\core\camximagebuffer.cpp


2.1 ImageBufferManager相关函数解析

2.1.1 ImageBufferManager::Create函数实现如下

CamxResult ImageBufferManager::Create(const CHAR*              pBufferManagerName,BufferManagerCreateData* pCreateData,ImageBufferManager**     ppImageBufferManager){CamxResult          result              = CamxResultSuccess;ImageBufferManager* pImageBufferManager = NULL;if (CamxResultSuccess == result){*ppImageBufferManager = NULL;pImageBufferManager = CAMX_NEW ImageBufferManager();}if (CamxResultSuccess == result){// 从内存池中为ImageBufferManager分配内存result = pImageBufferManager->Initialize(pBufferManagerName, pCreateData);if (CamxResultSuccess == result){CAMX_LOG_INFO(CamxLogGroupMemMgr, "[%s] : allocRequired=%d, immediateAllocBufferCount=%d, maxBufferCount=%d", pBufferManagerName, pCreateData->allocateBufferMemory, pCreateData->immediateAllocBufferCount, pCreateData->maxBufferCount);// 初始化ImageBufferManager中的buffers,这里是重点result = pImageBufferManager->InitializeBuffers(pCreateData);}}if (CamxResultSuccess == result){*ppImageBufferManager = pImageBufferManager;}return result;

2.1.2 ImageBufferManager::InitializeBuffer实现如下

CamxResult ImageBufferManager::InitializeBuffers(
BufferManagerCreateData* pCreateData) {m_createData                = *pCreateData;m_currentFormat             = pCreateData->bufferProperties.imageFormat;m_maxBufferCount            = pCreateData->maxBufferCount;m_immediateAllocBufferCount = pCreateData->immediateAllocBufferCount;// Allocate the minimum number of buffers needed immediately seriallyfor (UINT i = 0; i < m_immediateAllocBufferCount; i++){// ①new bufferImageBuffer* pBuffer = CAMX_NEW ImageBuffer();if (NULL != pBuffer){// ②buffer初始化,buffer相关信息放在全局变量m_createData中result = pBuffer->Initialize(m_pBufferManagerName, &m_createData, &m_currentFormat, this,m_hMemPoolBufMgrHandle);// ③Allocate the bufferresult = pBuffer->Allocate();LDLLNode* pNode = static_cast<LDLLNode*>(CAMX_CALLOC(sizeof(LDLLNode)));if (NULL != pNode){pNode->pData = pBuffer;// ④Add the buffer to the free buffer listm_freeBufferList.InsertToTail(pNode);}}

2.1.3 ImageBufferManager::GetImageBuffer函数实现如下

①从free-list中找buffer;如果没有
②再去busy-list中找引用计数为0的buffer;还是没有
③看看能不能自己创建buffer;如果不能创建
④超时等待n次去获取busy-list中引用计数为0的buffer
经过上述操作,如果能获取到buffer,先添加buffer的引用计数,然后封装成node,放到busy-list链表尾


ImageBuffer* ImageBufferManager::GetImageBuffer(){// first:先从free_list的头部取出buffer节点LDLLNode*    pNode       = m_freeBufferList.RemoveFromHead();   ImageBuffer* pBuffer     = NULL;// Check the free List for an available bufferif (NULL != pNode){// 取出buffer节点中的bufferpBuffer = static_cast<ImageBuffer*>(pNode->pData);  CAMX_FREE(pNode); // 释放该节点所占用的内存pNode = NULL;}// second:如果free_list中没有可用buffer,就去busy_list中去取if (NULL == pBuffer) { // 从头遍历busy_list中的节点pNode = m_busyBufferList.Head();while (NULL != pNode){ImageBuffer* pBusyBuffer = static_cast<ImageBuffer*>(pNode->pData);  LDLLNode*    pNext       = LightweightDoublyLinkedList::NextNode(pNode); if (0 == pBusyBuffer->GetReferenceCount()) { // 如果该busy-buffer的引用计数为0,说明该buffer可以被使用m_busyBufferList.RemoveNode(pNode);// 就从busy_list中取出node,这里会先移出,然后后面会再次添加到busy-list的尾部if (NULL == pBuffer) {// We will keep this bufferpBuffer = pBusyBuffer;   // 将上述busy-buffer赋值给pBufferCAMX_FREE(pNode);        // 释放该节点所占用的内存pNode = NULL;}else{// 如果从busy-list取节点时刚好发现pBuffer不为空了,而pNode都从busy-list中取出来了,这次不用就下次再用吧,将其放到free-list中m_freeBufferList.InsertToTail(pNode);}}pNode = pNext; }}// third:如果free-list和busy-list中没有找到引用计数为0的buffer,看看能不能创建bufferif (NULL == pBuffer) { UINT numOfFreeBuffers = m_freeBufferList.NumNodes();UINT numOfBusyBuffers = m_busyBufferList.NumNodes();// If no free buffers were found either in the free list or the busy list, we check to see if an additional buffer// can be allocated immediatelyif ((numOfFreeBuffers + numOfBusyBuffers) < m_maxBufferCount){  // 只要没有达到创建buffer的max值,就能额外创建bufferCamxResult result = CamxResultSuccess;// 下面就是buffer创建三部曲pBuffer = CAMX_NEW ImageBuffer();if (NULL != pBuffer){result = pBuffer->Initialize(m_pBufferManagerName, &m_createData, &m_currentFormat, this, m_hMemPoolBufMgrHandle);  } else {CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] Ran out of memory to allocate", GetBufferManagerName());result = CamxResultENoMemory;}if (CamxResultSuccess == result){if ((TRUE == m_createData.allocateBufferMemory) &&(FALSE == m_createData.bEnableLateBinding)){// Allocate the bufferresult = pBuffer->Allocate();}}}}// four:如果上面三种情况都不满足,那么就只能等待busy-list中的buffer释放了if (NULL == pBuffer){    pNode = NULL;while (NULL == pNode){ // 设置超时等待,接收busy-list中的buffer释放信号         result = m_pWaitFreeBuffer->TimedWait(m_pLock->GetNativeHandle(), BufferTimeoutMilliseconds);pNode = m_freeBufferList.RemoveFromHead();if (timeoutCount >= MaxTimeoutCount){  // 这里会进行几次超时等待,如果超过最大等待次数就退出循环,等不下去了,累了!!CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] Waited %ux%u times and failed to get buffer, returning a null buffer", GetBufferManagerName(), timeoutCount, BufferTimeoutMilliseconds);break;}else if (CamxResultETimeout == result){ // 继续超时等待,死等,还挺执着!!// timeout happened, print an error log and continue waitingtimeoutCount++;CAMX_LOG_WARN(CamxLogGroupMemMgr, "[%s] Waiting %ux%d ms timedout, there might be a leak or performance issue", GetBufferManagerName(), timeoutCount, BufferTimeoutMilliseconds);}else if (CamxResultSuccess != result){ // 函数执行期间遇到错误,退出循环timeoutCount++;CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] Waiting %dx%d ms failed for unknown reason, result=%s",GetBufferManagerName(), timeoutCount,BufferTimeoutMilliseconds,Utils::CamxResultToString(result));break;}}// 如果free-list中取到节点了,万事大吉,取其buffer。念念不忘,必有回响!if (NULL != pNode){pBuffer = static_cast<ImageBuffer*>(pNode->pData);CAMX_FREE(pNode);pNode   = NULL;CAMX_LOG_INFO(CamxLogGroupMemMgr, "[%s] Returning a buffer [%p] from the free list after wait ended",GetBufferManagerName(), pBuffer);}}// 几经波折,如果能取到buffer,会进一步处理if (NULL != pBuffer){m_pLock->Unlock();pBuffer->AddImageReference();  // 添加buffer的引用计数m_pLock->Lock();pBuffer->SetBusyState(TRUE);   // 我很忙pBuffer->ClearReferenceHolderData();pNode = static_cast<LDLLNode*>(CAMX_CALLOC(sizeof(LDLLNode)));if (NULL != pNode){pNode->pData = pBuffer;m_busyBufferList.InsertToTail(pNode); // 将节点插入到busy-list的尾部m_peakBufferHolders = Utils::MaxUINT(m_peakBufferHolders, m_busyBufferList.NumNodes());}} return pBuffer;
}

2.1.4 ImageBufferManager::AddReference函数实现如下

①查看该buffer是否在free-list中,如果在则将其从free-list中移到busy-list中,并添加该buffer的引用计数;如果不在
②查看该buffer是否在busy-list中,如果在则增加该buffer的引用计数。

UINT ImageBufferManager::AddReference(
ImageBuffer* pImageBuffer) {BOOL      doneFlag = FALSE;UINT      count    = 0;    LDLLNode* pNode;// 看看该buffer是不是在free-list中,如果是,则将其从中移除并添加到busy-list中pNode = m_freeBufferList.Head();while (NULL != pNode){if (pImageBuffer == static_cast<ImageBuffer*>(pNode->pData)){// Add reference to the image buffercount = pImageBuffer->AddImageReference();// Move if from free list to busy listm_freeBufferList.RemoveNode(pNode);pImageBuffer->SetBusyState(TRUE);m_busyBufferList.InsertToTail(pNode);CAMX_LOG_VERBOSE(CamxLogGroupMemMgr, "[%s] Image buffer %p in free list, reference count after adding = %d",GetBufferManagerName(), pImageBuffer, pImageBuffer->GetReferenceCount());doneFlag = TRUE;break;}pNode = LightweightDoublyLinkedList::NextNode(pNode);}// 添加引用的buffer不在freelist中if (FALSE == doneFlag){pNode = m_busyBufferList.Head();// Didn't find the image buffer in free list, then search busy listwhile (NULL != pNode){// Found the image buffer in busy listif (pImageBuffer == static_cast<ImageBuffer*>(pNode->pData)){// Add reference to the image buffercount = pImageBuffer->AddImageReference();CAMX_LOG_VERBOSE(CamxLogGroupMemMgr, "[%s] Image buffer %p in busy list, reference count after adding = %d",GetBufferManagerName(), pImageBuffer, pImageBuffer->GetReferenceCount());doneFlag = TRUE;break;}pNode = LightweightDoublyLinkedList::NextNode(pNode);}}if (FALSE == doneFlag){CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] Add reference to image buffer %p failed.",GetBufferManagerName(), pImageBuffer);}m_pLock->Unlock();return count;
}CAMX_INLINE UINT AddImageReference()
{UINT count = CamxAtomicIncU(&m_aReferenceCount); // 引用计数+1return count; // 返回添加引用计数后的数值
}

2.1.5 ImageBufferManager::ReleaseReference函数实现如下

①查看该buffer是否在busy-list中;如果在

②查看将该buffer引用计数-1后的引用计数值;如果为0

③将其从busy-list移动到free-list链表中,并发送信号通知那些等待buffer的线程去取buffer(GetImageBuffer中如果取不到buffer,会设置超时等待)

UINT ImageBufferManager::ReleaseReference(
ImageBuffer* pImageBuffer){BOOL doneFlag = FALSE;UINT count    = 0;LDLLNode* pNode = m_busyBufferList.Head();while (NULL != pNode){// Found the image buffer in busy list,if (pImageBuffer == static_cast<ImageBuffer*>(pNode->pData)){if (0 < pImageBuffer->GetReferenceCount()) {// count为该buffer引用计数-1后的结果count = pImageBuffer->ReleaseImageReference();if (0 == count){// Move the buffer to the free listm_busyBufferList.RemoveNode(pNode);if ((TRUE == m_createData.bEnableLateBinding)   &&(TRUE == m_createData.allocateBufferMemory) &&(TRUE == pImageBuffer->HasBackingBuffer())){// If late binding is enabled, release the buffer and just add the holder ImageBuffer object into// free list. When this ImageBuffer is acquired, explicit BindBuffer on this ImageBuffer object will be// called to allocate or bind the buffer back to this ImageBufferpImageBuffer->Release(FALSE);}pImageBuffer->SetBusyState(FALSE);// 为即将插入到free-list中的buffer设置状态时传参false,为busy-list时传参truem_freeBufferList.InsertToTail(pNode); // 发送信号通知等待此buffer的线程,有buffer用了,不用等了m_pWaitFreeBuffer->Signal(); }}doneFlag = TRUE;break;}pNode = LightweightDoublyLinkedList::NextNode(pNode);}if (FALSE == doneFlag){CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] Didn't find the image buffer %p in busy list.",GetBufferManagerName(), pImageBuffer);}return count;
}

三、Camx MemPoolManager

        在对ImageBufferManager接口进行详细说明后,对MemPoolMgr中如何获取ImagerBufferManager所需的ImageBuffer进行了下图的关系说明。

四、Camx ImageBuffer

         imageBuffer在pipeline中扮演着非常重要的决策,负责图像数据在node之间的流转。在pipeline中node之间的连接是靠port来链接的,而port的连接正是通过共享内存(一组imageBuffer)来实现的

        高通Camx架构通过一个 Import 操作,把MemPoolBufferbufferInfo,传递给 imagebufferbufferInfo ImageBuffer pipeline node port口 之间是通过传递这个bufferInfo,把一个node outputport 传递给 inputport的。

        以下是简单的ImageBuffer在pipeline里面的流转示意图:

五、Ending

        本博文主要对一些文章中高通内存池架构/ImageBuffer进行拆分进行框架上的梳理,很多具体的各个模块细节可参考以下博文:

        1.ImageBufferManager具体在整个流程中的调用以及ImgeBuffer在pipeline之间的流转:ImageBufferManager介绍-CSDN博客

DMABuffer剖析_dma buffer-CSDN博客

        2.MemPoolMgr与ImageBufferManager之间更详细的link以及更深层次的涉及理解:DMABuffer剖析_dma buffer-CSDN博客

        3.关于ION buffer本质与mmap映射使用更详细的说明:

Android ION 相关信息查看方法_kernel查看ion-CSDN博客

ION基本概念介绍和原理分析_ion buffer-CSDN博客

关键字:营销型企业网站有哪些类型_室内效果图制作流程_域名站长工具_百度教育

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: