2445
- 收藏
- 点赞
- 分享
- 举报
内存管理
[i=s] 本帖最后由 anwafs 于 2019-10-29 11:47 编辑 [/i]
[password]254431[/password]
/////////////////////////////////////////////////////////////////////////////////////
伙伴:
#ifndef BUDDYSYSTEM_H
#define BUDDYSYSTEM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <osal.h>
typedef enum
{
BUDDY_MEM_TYPE_MMZ = 0,
BUDDY_MEM_TYPE_OS,
BUDDY_MEM_TYPE_MAX
} BuddyMemType;
/* Buddy System 分配的内存地址 */
typedef struct BuddyMem
{
Int8 *pVirMem; /* 伙伴系统返回的虚拟地址 */
Sizet pPhyAddr; /* 伙伴系统返回的物理地址,os内存无效 ,mmz有效 */
Int8 memType;
Int8 res[3];
Uint32 res1[32];
} BuddyMem;
typedef struct BuddyNode
{
struct BuddyNode *prelink; /* 指向前驱节点 */
Int32 tag; /* 块标志,0空闲,1占用 */
Int32 kval; /* 块大小,值为2的kval次幂 */
struct BuddyNode *nextlink; /* 头部域,指向后继节点 */
Sizet phyAddr; /* userSpace的物理地址 */
Int8 *userSpace; /* 用户可用地址 */
} BuddyNode;
typedef struct BuddySets
{
Uint32 memSize; /* 伙伴系统总内存大小, memSize = blockSize * 2~blockNum */
Uint32 blockSize; /* 每块内存大小 */
Int16 memType; /* 内存类型,mmz or os,参考 BuddyMemType */
Int16 blockNum; /* 此值描述内存块个数,总个数为2的blockNum次幂,例 num = 7,则总个数为2的7次方 */
Sizet pBasePhyAddr; /* 待管理地址的物理地址 */
Int8 *pUserMem; /* 待管理内存的虚拟地址 */
Int8 beCache; /* 只对mmz内存有效,内存是否为cache,0:否 1:是 */
Int8 res0[3];
Int32 res[32];
} BuddySets;
typedef struct
{
BuddyNode *pNodeStart; /* 内存模块的起点 */
BuddyNode *pNodeEnd; /* 内存模块的终点 */
BuddySets params; /* 内存模块参数 */
OSAL_MutexHandle lock;
} BuddySys;
typedef struct BuddyHeadNode
{
Int32 nodesize; /* 该链表的空闲块大小 */
BuddyNode *first; /* 该链表的表头指针 */
BuddySys vdsBuddySys; /* 存放该内存模块的整体信息 */
} BuddyHeadNode;
Int32 buddyInit( BuddySets *pSets, BuddyHeadNode **pBuddyHeadNode);
Int32 buddyDeinit( BuddyHeadNode *pBuddyHeadNode);
Int32 buddyAlloc( BuddyHeadNode *pBuddyHeadNode, Uint32 size, BuddyMem *pBuddyMem);
Int32 buddyReclaim( BuddyHeadNode *pBuddyHeadNode, BuddyMem *pBuddyMem);
void buddyPrintLayout( BuddyHeadNode *pBuddyHeadNode);
Int32 buddyGetMmzPoolId( BuddyHeadNode *pBuddyHeadNode, Int32 *pPoolId);
Int32 buddyFlushMem( BuddyHeadNode *pBuddyHeadNode, BuddyMem *pBuddyMem);
#endif
#ifndef BUDDYSYSTEM_C
#define BUDDYSYSTEM_C
#include " buddySys.h"
/* 返回p处内存块的伙伴内存地址 */
static BuddyNode * buddy( BuddyNode *p, BuddyHeadNode *pBuddyHeadNode)
{
int s = 0, m = 0, n = 0;
s = p - pBuddyHeadNode[0].vdsBuddySys.pNodeStart;
m = (int)pow(2, p->kval);
n = (int)pow(2, p->kval + 1);
if (0 == s % n)
{
return p + m;
}
if (m == s % n)
{
return p - m;
}
return NULL;
}
Int32 buddyInit( BuddySets *pSets, BuddyHeadNode **ppBuddyHeadNode)
{
Int32 k = 0;
Int32 i = 0;
Int32 status = OSAL_OK;
Sizet pBasePhyAddr = 0;
Int8 *pUserMem = NULL;
BuddyNode *pBuddyNode = NULL;
BuddyHeadNode *pBuddyHeadNode = NULL;
if (OSAL_isNull(ppBuddyHeadNode) || OSAL_isNull(pSets))
{
OSAL_ERROR("%s params err\n", __func__);
return OSAL_FAIL;
}
if (pSets->blockNum <= 0 || pSets->memSize != pSets->blockSize * (Int32)pow(2, pSets->blockNum))
{
OSAL_ERROR("param err, blockNum:%d memSize:%d, and memSize should be equal to blockSize * 2~blockNum\n");
return OSAL_FAIL;
}
pBuddyHeadNode = OSAL_memAlloc(sizeof( BuddyHeadNode) * (pSets->blockNum + 1));
if (!pBuddyHeadNode)
{
OSAL_ERROR("mem over flow\n");
return OSAL_FAIL;
}
for (k = 0; k <= pSets->blockNum; k++)
{
pBuddyHeadNode[k].nodesize = (int)pow(2, k) * pSets->blockSize;
pBuddyHeadNode[k].first = NULL;
}
pBuddyNode = ( BuddyNode *)OSAL_memAlloc((int)pow(2, pSets->blockNum) * sizeof( BuddyNode));
if (!pBuddyNode)
{
OSAL_ERROR("over flow\n");
status = OSAL_FAIL;
goto exit;
}
else
{
pBuddyHeadNode[0].vdsBuddySys.pNodeStart = pBuddyNode;
pBuddyHeadNode[0].vdsBuddySys.pNodeEnd = pBuddyNode + pBuddyHeadNode[pSets->blockNum].nodesize / pSets->blockSize - 1;
}
pBuddyNode->prelink = pBuddyNode;
pBuddyNode->nextlink = pBuddyNode;
pBuddyNode->tag = 0;
pBuddyNode->kval = pSets->blockNum;
/* 所有内存先挂到最大的内存管理链表上 */
pBuddyHeadNode[pSets->blockNum].first = pBuddyNode;
pUserMem = pSets->pUserMem;
pBasePhyAddr = pSets->pBasePhyAddr;
for (i = 0; i < (int)pow(2, pSets->blockNum); i++, pBuddyNode++)
{
pBuddyNode->userSpace = pUserMem;
pBuddyNode->phyAddr = pBasePhyAddr;
pUserMem += pSets->blockSize;
pBasePhyAddr += pSets->blockSize;
}
status = OSAL_mutexCreate(OSAL_MUTEX_NORMAL, &pBuddyHeadNode[0].vdsBuddySys.lock);
if (OSAL_isFail(status))
{
OSAL_ERROR("OSAL_mutexCreate err\n");
goto exit;
}
OSAL_memCpySize(&pBuddyHeadNode[0].vdsBuddySys.params, pSets, sizeof(pBuddyHeadNode[0].vdsBuddySys.params));
*ppBuddyHeadNode = pBuddyHeadNode;
return status;
exit:
if (pBuddyHeadNode)
{
OSAL_memFree(pBuddyHeadNode);
pBuddyHeadNode = NULL;
}
if (pBuddyNode)
{
OSAL_memFree(pBuddyNode);
pBuddyNode = NULL;
}
return status;
}
Int32 buddyDeinit( BuddyHeadNode *pBuddyHeadNode)
{
if (OSAL_isNull(pBuddyHeadNode))
{
OSAL_ERROR(" buddyDeinit param err\n");
return OSAL_FAIL;
}
OSAL_mutexDelete(pBuddyHeadNode[0].vdsBuddySys.lock);
// 释放管理节点
OSAL_memFree(pBuddyHeadNode[0].vdsBuddySys.pNodeStart);
pBuddyHeadNode[0].vdsBuddySys.pNodeStart = NULL;
OSAL_memFree(pBuddyHeadNode);
pBuddyHeadNode = NULL;
return OSAL_OK;
}
Int32 buddyAlloc( BuddyHeadNode *pBuddyHeadNode, Uint32 size, BuddyMem *pBuddyMem)
{
int k = 0;
int i = 0;
BuddySys *pObj = NULL;
BuddyNode *pa = NULL, *pre = NULL, *suc = NULL, *pi = NULL;
OSAL_assertNotNull(pBuddyHeadNode);
OSAL_assertNotNull(pBuddyMem);
pObj = &(pBuddyHeadNode[0].vdsBuddySys);
OSAL_mutexLock(pObj->lock);
for (k = 0; k <= pObj->params.blockNum && (pBuddyHeadNode[k].nodesize < size || !pBuddyHeadNode[k].first); k++)
; // 查找满足分配
if (k > pObj->params.blockNum)
{
OSAL_ERROR("malloc err\n");
OSAL_mutexUnlock(pObj->lock);
return OSAL_FAIL;
}
else
{
pa = pBuddyHeadNode[k].first; // 指向可分配子表的第一个节点
pre = pa->prelink; // 分别指向前驱和后继
suc = pa->nextlink;
if(pa == suc)
{
/* k上就一个节点,k节点要被拆开,此节点不复存在 */
pBuddyHeadNode[k].first = NULL;
}
else
{
/* 删除pa,修改双向指针关系 */
pre->nextlink = suc;
suc->prelink = pre;
pBuddyHeadNode[k].first = suc;
}
/* 处理伙伴拆分后的节点 */
for (i = 1; k - i >= 0 && pBuddyHeadNode[k - i].nodesize >= size; i++)
{
pi = pa + (int)pow(2, k - i);
pi->nextlink = pi;
pi->prelink = pi;
pi->tag = 0;
pi->kval = k - i;
pBuddyHeadNode[k - i].first = pi;
}
pa->tag = 1;
pa->kval = k - (--i);
}
pBuddyMem->pVirMem = pa->userSpace;
pBuddyMem->pPhyAddr = pa->phyAddr;
pBuddyMem->memType = pObj->params.memType;
OSAL_mutexUnlock(pObj->lock);
return OSAL_OK;
}
Int32 buddyReclaim( BuddyHeadNode *pBuddyHeadNode, BuddyMem *pBuddyMem)
{
Int32 i = 0;
BuddyNode *pTmp = NULL;
BuddyNode *s = NULL;
BuddySys *pObj = NULL;
pObj = &(pBuddyHeadNode[0].vdsBuddySys);
pTmp = pObj->pNodeStart;
/* check p 合法性 */
for (i = 0; i < (int)pow(2, pObj->params.blockNum); i++)
{
if (pTmp->userSpace == pBuddyMem->pVirMem)
{
break;
}
pTmp++;
}
if (i >= (int)pow(2, pObj->params.blockNum))
{
OSAL_ERROR("%p err, not in the buddy system\n", pBuddyMem->pVirMem);
return OSAL_FAIL;
}
OSAL_mutexLock(pObj->lock);
s = buddy(pTmp, pBuddyHeadNode); // s指向p的伙伴的地址
while(s >= pObj->pNodeStart && s <= pObj->pNodeEnd && (!s->tag) && s->kval == pTmp->kval)
{
if (s->prelink == s && s->nextlink == s) // 链表上仅一个节点
{
pBuddyHeadNode[s->kval].first = NULL;
}
else
{
s->prelink->nextlink = s->nextlink;
s->nextlink->prelink = s->prelink;
if (pBuddyHeadNode[s->kval].first == s) // s是链表的首节点
{
pBuddyHeadNode[s->kval].first = s->nextlink;
}
}
if ((int)(pTmp - pObj->pNodeStart) % (int)pow(2, pTmp->kval + 1) == 0) // pTmp为前块
{
pTmp->kval++;
}
else
{
s->kval = pTmp->kval + 1;
pTmp = s;
}
s = buddy(pTmp, pBuddyHeadNode);
}
pTmp->tag = 0;
if (!pBuddyHeadNode[pTmp->kval].first)
{
pBuddyHeadNode[pTmp->kval].first = pTmp->prelink = pTmp->nextlink = pTmp;
}
else
{
pTmp->nextlink = pBuddyHeadNode[pTmp->kval].first;
pTmp->prelink = pTmp->nextlink->prelink;
pTmp->nextlink->prelink = pTmp;
pTmp->prelink->nextlink = pTmp;
pBuddyHeadNode[pTmp->kval].first = pTmp;
}
OSAL_mutexUnlock(pObj->lock);
return OSAL_OK;
}
void buddyPrintLayout( BuddyHeadNode *pBuddyHeadNode)
{
Int32 k = 0;
Int32 mark = 0;
BuddyNode *r = NULL;
BuddySys *pObj = NULL;
pObj = &(pBuddyHeadNode[0].vdsBuddySys);
for (k = 0, mark = 0; k <= pObj->params.blockNum; k++) //判断内存是否被沾满
{
if (pBuddyHeadNode[k].first)
{
mark = 1;
break;
}
}
if (!mark)
{
OSAL_INFO("buddy system is full\n");
}
else
{
OSAL_INFO("empty mem:\n");
for (k = 0; k <= pObj->params.blockNum; k++)
{
r = pBuddyHeadNode[k].first;
if (r)
{
OSAL_INFO("|%d <-->%d", r - pObj->pNodeStart + 1, r + (int)pow(2, r->kval) - pObj->pNodeStart);
while (r->nextlink != pBuddyHeadNode[k].first)
{
r = r->nextlink;
OSAL_INFO("|%d <-->%d", r - pObj->pNodeStart + 1, r + (int)pow(2, r->kval) - pObj->pNodeStart);
}
}
}
}
OSAL_INFO("\n");
}
Int32 buddyGetMmzPoolId( BuddyHeadNode *pBuddyHeadNode, Int32 *pPoolId)
{
OSAL_assertNotNull(pBuddyHeadNode);
OSAL_assertNotNull(pPoolId);
BuddySys *pObj = NULL;
pObj = &(pBuddyHeadNode[0].vdsBuddySys);
if ( BUDDY_MEM_TYPE_MMZ == pObj->params.memType)
{
//*pPoolId = pObj->poolBaseInfo.poolId;
}
else
{
OSAL_ERROR("memType :%d, don't have poolId\n", pObj->params.memType);
return OSAL_FAIL;
}
return OSAL_OK;
}
#endif
///////////////////////////////////////////////////////////////////////////////
预分配:
#ifndef __VDS_PBMM_H__
#define __VDS_PBMM_H__
#include <osal.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef Handle VDS_pbmmHndl;
typedef struct
{
Uint32 virtAddr;
Uint32 bufSize;
}VDS_pbmmInfo;
//每个图片比特流的缓冲区描述
typedef struct
{
Uint32 virtAddr;
Uint32 phyAddr;
Uint32 bufSize;
Uint32 usedSize;
Uint32 offset;
Uint32 privData;
}VDS_picBitBuf;
//创建图片比特流缓冲区管理的创建参数
typedef struct
{
Uint32 align;
Uint32 bitStartAddr; ///< 图片比特流区域首地址
Uint32 bitEndAddr; ///< 图片比特流区域首地址
Uint32 bitSz; ///< 图片比特流区域首地址
} VDS_pbmmCreate;
/*******************************************************************************
* 函数名 : VDS_pbmmDumpInfo
*******************************************************************************/
void VDS_pbmmDumpInfo(void);
/*******************************************************************************
* 函数名 : VDS_pbmmPreAlloc
* 描 述 : 不用的内存还到总的缓冲池
*******************************************************************************/
Int32 VDS_pbmmPreAlloc(VDS_pbmmHndl hEfmCmb, Uint32 length, VDS_picBitBuf *pBuf);
/*******************************************************************************
* 函数名 : VDS_pbmmReportLength
* 描 述 : 不用的内存还到总的缓冲池
*******************************************************************************/
Int32 VDS_pbmmReportLength(VDS_pbmmHndl hEfmCmb, Uint32 length);
/*******************************************************************************
* 函数名 : VDS_pbmmFree
* 描 述 : 释放缓冲区接口
*******************************************************************************/
Int32 VDS_pbmmFree(VDS_pbmmHndl hEfmCmb, Uint32 privData);
/*******************************************************************************
* 函数名 : VDS_pbmmInit
*******************************************************************************/
Int32 VDS_pbmmInit(VDS_pbmmCreate *pCreate, VDS_pbmmHndl *phEfmCmb);
Int32 VDS_pbmmDeInit(VDS_pbmmHndl phEfmCmb);
/*******************************************************************************
* 函数名 : VDS_pbmmGetInfo
* 描 述 : 得到图片比特流缓冲区的物理地址信息
*******************************************************************************/
Int32 VDS_pbmmGetInfo(VDS_pbmmInfo *pInfo);
#ifdef __cplusplus
}
#endif
#endif /* __VDS_PBMM_H__ */
/// .c
//////////////////// .c
#include <vds_pbmm.h>
#include <vds_pymm.h>
#include <vds_comapi.h>
#include <vds_frmShare.h>
#define VDS_PBMM_MAX_BLOCK (16)
typedef enum
{
VDS_PBMM_BUF_EMPTY = 0,
VDS_PBMM_BUF_ALLOCED,
VDS_PBMM_BUF_RELEASED,
VDS_PBMM_BUF_RECLAIMED = VDS_PBMM_BUF_EMPTY
}Vds_pbmmtatus;
typedef struct
{
Uint32 virtAddr;
Uint32 phyAddr;
Uint32 bufLen;
Uint32 index;
Uint32 status; ///<参考 IVS_CMB_STATUS
}Vds_pbmmPrivBlock;
typedef struct
{
Uint32 init;
Uint32 virtAddr; //连续内存的虚拟起始地址
Uint32 phyAddr; //连续内存的物理地址
Uint32 bufSize; //连续内存的长度
Uint32 align;
Uint32 usedEndOffset;
Uint32 usedStartOffset;
Uint32 lastAllocOffset;
Int32 fd;
Uint32 lastAllocIndex;
Vds_pbmmPrivBlock blockArray[VDS_PBMM_MAX_BLOCK];
Uint32 lastReclaimIndex;
}Vds_pbmmObj;
static Vds_pbmmObj gPbmmObj;
Int32 VDS_pbmmPreAlloc(VDS_pbmmHndl hEfmCmb, Uint32 length, VDS_picBitBuf *pBuf)
{
Int32 status = OSAL_FAIL;
Vds_pbmmObj *pObj = hEfmCmb;
Vds_pbmmPrivBlock *pBlock = NULL;
Uint32 bufLeft = 0;
if (pObj == NULL)
{
OSAL_ERROR("hEfmCmb is null\n");
return OSAL_FAIL;
}
do
{
if(pObj->usedEndOffset >= pObj->usedStartOffset)
{
bufLeft = pObj->bufSize - pObj->usedEndOffset;
if(bufLeft >= length)
{
pBuf->bufSize = length;
pBuf->usedSize = 0;
pBuf->phyAddr = pObj->phyAddr + pObj->usedEndOffset;
pBuf->virtAddr = pObj->virtAddr + pObj->usedEndOffset;
pBuf->offset = pObj->usedEndOffset;
pObj->lastAllocOffset = pObj->usedEndOffset;
status = OSAL_OK;
break;
}
else
{
bufLeft = pObj->usedStartOffset;
if(bufLeft > length)
{
pBuf->bufSize = length;
pBuf->usedSize = 0;
pBuf->phyAddr = pObj->phyAddr ;
pBuf->virtAddr = pObj->virtAddr ;
pBuf->offset = 0;
pObj->lastAllocOffset = 0;
status = OSAL_OK;
break;
}
}
}
else
{
bufLeft = pObj->usedStartOffset - pObj->usedEndOffset;
if(bufLeft >= length)
{
pBuf->bufSize = length;
pBuf->usedSize = 0;
pBuf->phyAddr = pObj->phyAddr + pObj->usedEndOffset;
pBuf->virtAddr = pObj->virtAddr + pObj->usedEndOffset;
pBuf->offset = pObj->usedEndOffset;
pObj->lastAllocOffset = pObj->usedEndOffset;
status = OSAL_OK;
break;
}
}
} while(0);
if (status == OSAL_OK)
{
pBlock = &pObj->blockArray[pObj->lastAllocIndex];
if (pBlock->status != VDS_PBMM_BUF_EMPTY)
{
OSAL_ERROR("block's status=%d,allocIndex=%d\n",
pBlock->status,
pObj->lastAllocIndex);
status = OSAL_FAIL;
}
else
{
pBlock->phyAddr = pBuf->phyAddr;
pBlock->virtAddr = pBuf->virtAddr;
pBuf->privData = pObj->lastAllocIndex;
#ifdef VDS_PBMM_DEBUG
OSAL_INFOCYAN("privData=%d is Malloc!\n", pBuf->privData);
#endif
}
}
return status;
}
Int32 VDS_pbmmReportLength(VDS_pbmmHndl hEfmCmb, Uint32 length)
{
Vds_pbmmObj *pObj = hEfmCmb;
length = OSAL_align(length, pObj->align);
pObj->usedEndOffset = pObj->lastAllocOffset + length;
pObj->blockArray[pObj->lastAllocIndex].bufLen = length;
pObj->blockArray[pObj->lastAllocIndex].status = VDS_PBMM_BUF_ALLOCED;
pObj->lastAllocIndex = (pObj->lastAllocIndex + 1 ) & (VDS_PBMM_MAX_BLOCK - 1);
return OSAL_OK;
}
Int32 VDS_pbmmFree(VDS_pbmmHndl hEfmCmb, Uint32 privData)
{
Vds_pbmmObj *pObj = hEfmCmb;
Uint32 index = 0;
Uint32 i = 0;
if (privData >= VDS_PBMM_MAX_BLOCK)
{
OSAL_ERROR("privData=%d,out of range\n",privData);
return OSAL_FAIL;
}
Vds_pbmmPrivBlock *pBlock = &pObj->blockArray[privData];
if (pBlock->status != VDS_PBMM_BUF_ALLOCED)
{
OSAL_ERROR("pBlock->status =%d\n",pBlock->status);
return OSAL_FAIL;
}
pBlock->status = VDS_PBMM_BUF_RELEASED;
index = pObj->lastReclaimIndex;
#ifdef VDS_PBMM_DEBUG
OSAL_INFOCYAN("privData=%d is Free, lastReclaimIndex %u\n"
, privData
, pObj->lastReclaimIndex);
#endif
for (i = 0; i < VDS_PBMM_MAX_BLOCK; i++)
{
pBlock = &pObj->blockArray[index];
if (pBlock->status != VDS_PBMM_BUF_RELEASED)
{
break;
}
else //reclaim
{
pObj->usedStartOffset =
(pBlock->virtAddr - pObj->virtAddr) + pBlock->bufLen;
pBlock->virtAddr = 0;
pBlock->phyAddr = 0;
pBlock->bufLen = 0;
pBlock->index = 0;
pBlock->status = VDS_PBMM_BUF_RECLAIMED;
pObj->lastReclaimIndex =
(pObj->lastReclaimIndex + 1 ) & (VDS_PBMM_MAX_BLOCK - 1);
}
index = (index + 1) & (VDS_PBMM_MAX_BLOCK - 1);
}
#ifdef VDS_PBMM_DEBUG
OSAL_INFOCYAN("lastReclaimIndex %u\n"
, pObj->lastReclaimIndex);
#endif
return OSAL_OK;
}
Int32 VDS_pbmmInit(VDS_pbmmCreate *pCreate, VDS_pbmmHndl *phEfmCmb)
{
Int32 status = OSAL_FAIL;
Vds_pbmmObj *pObj = &gPbmmObj;
Uint32 *mapVirAddr = OSAL_NULL;
if(pCreate == NULL)
{
OSAL_ERROR("pCreate is null\n");
return OSAL_FAIL;
}
OSAL_clear(pObj);
pObj->fd = open(PICMEM_DEV_NAME, O_RDWR);
if (pObj->fd < 0)
{
OSAL_ERROR("open()\n");
return status;
}
pObj->phyAddr = pCreate->bitStartAddr;
pObj->bufSize = pCreate->bitSz;
OSAL_INFO("mmap: baseaddr %p, size %x\n", pObj->phyAddr, pObj->bufSize);
mapVirAddr = (Uint32 *)mmap(OSAL_NULL, pObj->bufSize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
pObj->fd,
pObj->phyAddr);
if (mapVirAddr == MAP_FAILED)
{
OSAL_ERROR("Failed to mmap buffer (%s)\n", strerror(errno));
close(pObj->fd);
return OSAL_FAIL;
}
OSAL_clearSize(mapVirAddr, pObj->bufSize);
pObj->align = pCreate->align !=0 ? pCreate->align : 1;
pObj->virtAddr = OSAL_align((Uint32)mapVirAddr, pObj->align);
pObj->phyAddr = pObj->phyAddr + ((Uint32)mapVirAddr - pObj->virtAddr);
pObj->bufSize = pObj->bufSize - ((Uint32)mapVirAddr - pObj->virtAddr);
OSAL_INFO("[PicBmm] Init Ok! mapVirAddr %p, pObj->virtAddr %p, size %x\n"
, mapVirAddr, pObj->virtAddr, pObj->bufSize);
pObj->init = OSAL_TRUE;
*phEfmCmb = pObj;
return OSAL_OK;
}
Int32 VDS_pbmmDeInit(VDS_pbmmHndl phEfmCmb)
{
Vds_pbmmObj *pObj = phEfmCmb;
munmap((void *)pObj->virtAddr, pObj->bufSize);
return OSAL_OK;
}
Int32 VDS_pbmmGetInfo(VDS_pbmmInfo *pInfo)
{
Int32 status = OSAL_FAIL;
Vds_pbmmObj *pObj = &gPbmmObj;
if (OSAL_TRUE == pObj->init)
{
pInfo->virtAddr = pObj->virtAddr;
pInfo->bufSize = pObj->bufSize;
status = OSAL_OK;
}
return status;
}
void VDS_pbmmDumpInfo(void)
{
Int32 i = 0;
Vds_pbmmObj *pObj = &gPbmmObj;
Vds_pbmmPrivBlock *pBlock = NULL;
OSAL_INFO("usedStartOffset=%u,usedEndOffset=%u,"
"lastAllocOffset=%u,lastAllocIndex=%u,lastReclaimIndex=%u\n",
pObj->usedStartOffset, pObj->usedEndOffset,
pObj->lastAllocOffset, pObj->lastAllocIndex, pObj->lastReclaimIndex);
for(i = 0; i< VDS_PBMM_MAX_BLOCK; i++)
{
pBlock = &pObj->blockArray[i];
OSAL_INFO("index=%d, virtAddr=%x,phyAddr=%x,bufLen=%u,index=%u,status=%u\n",
i, pBlock->virtAddr, pBlock->phyAddr,
pBlock->bufLen, pBlock->index, pBlock->status);
}
}
///////////////////////////////////////////////////////////////////////////
ruffer buf:
#ifndef _VDS_RINGBUFFER_H_
#define _VDS_RINGBUFFER_H_
#include <osal.h>
#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */
#define MAXRINGCHN 4
#define BF_CHANNEL 0
#define MERGE_CHANNEL 1
#define IVS_CHANNEL 2
#define DEC_CHANNEL 3
typedef struct tagVDS_ringBufSets
{
Uint32 size; /* ringBuf 申请大小 */
Uint8 alignValue; /* 若需要对齐,对齐字节数,采用向上对齐 */
Uint8 res[3];
}VDS_ringBufSets;
typedef struct VDS_ringBuffer
{
Ptr basePhyAddr;
Ptr baseVirtAddr;
Uint32 totalSize;
Uint32 wrOfst;
Uint32 rdOfst;
Int32 encodedStreamCount;
OSAL_MutexHandle bufferLock;
Uint32 getCnt;
Uint32 rlsCnt;
VDS_ringBufSets sets;
} VDS_ringBuffer;
typedef VDS_ringBuffer* VDS_ringBufferHndl;
Int32 VDS_ringBufferInit(VDS_ringBufferHndl ringBufferHnl, VDS_ringBufSets *pSets);
Bool VDS_ringBufferiIsFull(VDS_ringBufferHndl ringBufferHnl);
Bool VDS_ringBufferIsEmpty(VDS_ringBufferHndl ringBufferHnl);
Bool VDS_ringBufferPrintInfo(VDS_ringBufferHndl ringBufferHnl);
Int32 VDS_ringBufferUpdateRdOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length);
Int32 VDS_ringBufferUpdateWrOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length);
Int32 VDS_ringBufferUpdateEncodedStreamCount(VDS_ringBufferHndl ringBufferHnl, Bool increment);
Int32 VDS_ringBufferDeInit(VDS_ringBufferHndl ringBufferHnl);
VDS_ringBufferHndl VDS_ringBufferOpen(Int32 chId);
Int32 VDS_ringBufferGetBuf(VDS_ringBufferHndl rbHndl,Sizet* addr,Uint32 size);
Int32 VDS_ringBufferRls(Handle Hndl,Sizet addr,Uint32 size);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
///////////////////////////////// .c
#include <vds_ringBuffer.h>
#include "mpi_sys.h"
VDS_ringBuffer gringBuffer[MAXRINGCHN];
VDS_ringBufferHndl VDS_ringBufferOpen(Int32 chId)
{
if((chId < 0)||(chId > MAXRINGCHN))
{
OSAL_ERROR("chId[%d] is not right\n",chId);
return NULL;
}
return &gringBuffer[chId];
}
Int32 VDS_ringBufferInit(VDS_ringBufferHndl ringBufferHnl, VDS_ringBufSets *pSets)
{
Int32 status = 0;
Sizet pBasePhyAddr=0;
Ptr pBaseVirtAddr = 0;
if (OSAL_isNull(pSets) || OSAL_isNull(ringBufferHnl))
{
OSAL_ERROR("VDS_ringBufferInit param err\n");
return OSAL_FAIL;
}
memset(ringBufferHnl, 0, sizeof(*ringBufferHnl));
status = HI_MPI_SYS_MmzAlloc((HI_U32*)&pBasePhyAddr,&pBaseVirtAddr,
"SYSMEM", OSAL_NULL, pSets->size);
if(status < 0)
{
OSAL_ERROR("malloc failed size=%u\n", pSets->size);
return -1;
}
OSAL_assert(pBaseVirtAddr != NULL);
ringBufferHnl->baseVirtAddr = pBaseVirtAddr;
ringBufferHnl->basePhyAddr= (Ptr)pBasePhyAddr;
ringBufferHnl->encodedStreamCount = 0;
ringBufferHnl->rdOfst = 0;
ringBufferHnl->wrOfst = 0;
ringBufferHnl->totalSize = pSets->size;
status = OSAL_mutexCreate(OSAL_MUTEX_NORMAL,&ringBufferHnl->bufferLock);
if(status < 0)
{
OSAL_ERROR("create mutex error\n");
return -1;
}
OSAL_memCpySize(&ringBufferHnl->sets, pSets, sizeof(ringBufferHnl->sets));
return 0;
}
Bool VDS_ringBufferIsFull(VDS_ringBufferHndl ringBufferHnl)
{
if ((ringBufferHnl->wrOfst == ringBufferHnl->rdOfst) &&
(ringBufferHnl->encodedStreamCount !=0))
return OSAL_TRUE;
else
return OSAL_FALSE;
}
Bool VDS_ringBufferIsEmpty(VDS_ringBufferHndl ringBufferHnl)
{
if ((ringBufferHnl->wrOfst == ringBufferHnl->rdOfst)
&& (ringBufferHnl->encodedStreamCount ==0))
return OSAL_TRUE;
else
return OSAL_FALSE;
}
Bool VDS_ringBufferPrintInfo(VDS_ringBufferHndl ringBufferHnl)
{
OSAL_INFO("\n******************ring buffer info *********************\n");
OSAL_INFO ("ring buffer info ringBufferHnl->baseAddr:0x%x\n" ,ringBufferHnl->baseVirtAddr);
OSAL_INFO ("ring buffer info ringBufferHnl->totalSize:0x%x\n" ,ringBufferHnl->totalSize);
OSAL_INFO ("ring buffer info ringBufferHnl->wrOfst:0x%x\n" ,ringBufferHnl->wrOfst);
OSAL_INFO ("ring buffer info ringBufferHnl->rdOfst:0x%x\n" ,ringBufferHnl->rdOfst);
OSAL_INFO ("ring buffer info ringBufferHnl->encodedStreamCount:%d\n" ,ringBufferHnl->encodedStreamCount);
OSAL_INFO ("ring buffer info ringBufferHnl->ringBufferLock:0x%x\n" ,ringBufferHnl->bufferLock);
return OSAL_TRUE;
}
Int32 VDS_ringBufferUpdateRdOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length)
{
length = OSAL_align(length, ringBufferHnl->sets.alignValue);
OSAL_mutexLock(ringBufferHnl->bufferLock);
ringBufferHnl->rdOfst = length % ringBufferHnl->totalSize;
OSAL_mutexUnlock(ringBufferHnl->bufferLock);
return 0;
}
Int32 VDS_ringBufferUpdateWrOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length)
{
length = OSAL_align(length, ringBufferHnl->sets.alignValue);
OSAL_mutexLock(ringBufferHnl->bufferLock);
ringBufferHnl->wrOfst = (ringBufferHnl->wrOfst + length)%ringBufferHnl->totalSize;
OSAL_mutexUnlock(ringBufferHnl->bufferLock);
return 0;
}
Int32 VDS_ringBufferUpdateEncodedStreamCount(VDS_ringBufferHndl ringBufferHnl,
Bool increment)
{
OSAL_mutexLock(ringBufferHnl->bufferLock);
if(increment)
ringBufferHnl->encodedStreamCount++;
else
ringBufferHnl->encodedStreamCount--;
OSAL_mutexUnlock(ringBufferHnl->bufferLock);
return 0;
}
Int32 VDS_ringBufferGetBuf(VDS_ringBufferHndl rbHndl,Sizet* addr,Uint32 size)
{
Uint32 rbLength = 0;
Sizet rbAddr = 0;
size = OSAL_align(size, rbHndl->sets.alignValue);
if(rbHndl->wrOfst > rbHndl->rdOfst) // case1
{
rbAddr = ((Sizet)rbHndl->baseVirtAddr+ rbHndl->wrOfst);
rbLength = rbHndl->totalSize - rbHndl->wrOfst;
if(rbLength < size)
{
Uint32 tmpSize = rbHndl->rdOfst;
if(tmpSize > size)
{
VDS_ringBufferUpdateWrOfst(rbHndl,rbLength);
rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;
rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
}
else
{
OSAL_ERROR("buffer is not enough,rbLength is %d,"\
"size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
}
}
}
else if(rbHndl->wrOfst == rbHndl->rdOfst)
{
if(rbHndl->rlsCnt == rbHndl->getCnt)
{
rbAddr = ((Sizet)rbHndl->baseVirtAddr+ rbHndl->wrOfst);
rbLength = rbHndl->totalSize - rbHndl->wrOfst;
if(rbLength < size)
{
Uint32 tmpSize = rbHndl->rdOfst;
if(tmpSize > size)
{
VDS_ringBufferUpdateWrOfst(rbHndl,rbLength);
rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;
rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
}
else
{
OSAL_ERROR("buffer is not enough,rbLength is %d,"\
"size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
}
}
}
else
{
OSAL_ERROR("rb buff is full\n");
}
}
else
{
rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;
rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
}
if(rbLength < size)
{
OSAL_ERROR("buffer is not enough,rbLength is %d,"\
"size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
*addr = 0;
return -1;
}
else
{
*addr = rbAddr;
rbHndl->getCnt++;
return 0;
}
}
Int32 VDS_ringBufferRls(Handle Hndl,Sizet addr,Uint32 size)
{
VDS_ringBufferHndl pHndl = (VDS_ringBufferHndl)Hndl;
OSAL_assert(pHndl != NULL);
size = OSAL_align(size, pHndl->sets.alignValue);
pHndl->rlsCnt++;
VDS_ringBufferUpdateRdOfst(pHndl,
(addr - (Sizet)pHndl->baseVirtAddr) + size);
VDS_ringBufferUpdateEncodedStreamCount(pHndl, OSAL_FALSE);
return 0;
}
Int32 VDS_ringBufferDeInit(VDS_ringBufferHndl ringBufferHnl)
{
HI_MPI_SYS_MmzFree((Sizet)ringBufferHnl->basePhyAddr, ringBufferHnl->baseVirtAddr);
ringBufferHnl->baseVirtAddr = NULL;
ringBufferHnl->basePhyAddr = NULL;
ringBufferHnl->totalSize = 0;
ringBufferHnl->wrOfst = 0;
ringBufferHnl->rdOfst = 0;
ringBufferHnl->encodedStreamCount = 0;
ringBufferHnl->rlsCnt = 0;
ringBufferHnl->getCnt = 0;
OSAL_mutexDelete(&ringBufferHnl->bufferLock);
return 0;
}
我来回答
回答0个
时间排序
认可量排序
暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
02019-09-28 17:06:35
-
02019-10-29 10:50:36
-
2012-12-05 14:28:56
-
2018-12-18 10:10:14
-
2012-12-05 13:32:58
-
2016-04-17 15:10:54
-
2019-07-22 10:45:02
-
2008-08-25 18:16:26
-
2015-10-10 14:40:45
-
2018-12-17 14:35:34
-
2020-11-28 13:36:36
-
2018-12-19 11:05:53
-
2015-07-08 21:40:32
-
2012-12-24 14:10:01
-
2008-07-18 20:46:59
-
2012-12-05 14:23:43
-
2012-12-24 14:11:21
-
2020-06-29 17:36:54
-
2008-08-07 18:54:01
-
2016-03-21 15:55:28
更多相似问答
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
20帮忙交叉编译个源码
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认