dm81xx link記憶體分配及link之間資料傳遞
每個link都有管理著自己的佇列,相當於一個記憶體池,一個輸入佇列,一個輸出佇列,當一個link處理完後,將資料放在自己的輸出佇列後,通過傳送通知的方式告訴下一個link取資料,這個地方涉及到多核通訊;
Link Output Queue – is the queue which is used by another link (via the inter link API) to exchange frames with that link
下面是IPCBitsOutLink:
Link資料結構:
typedef struct IpcBitsOutLink_Obj {
UInt32 tskId; /**< IpcBitsOutLink instance linkID */
OSA_TskHndl tsk; /**< IpcBitsInLink task handle */
IpcBitsOutLinkHLOS_CreateParams createArgs;
/**< Application passed create Args */
ListMP_Handle listMPOutHndl; /**< IPC SystemIpcBits_ListElem full queue */
ListMP_Handle listMPInHndl; /**< IPC SystemIpcBits_ListElem empty queue */
GateMP_Handle gateMPInHndl; /**< IPC Gate for listMPOutHndl */
GateMP_Handle gateMPOutHndl; /**< IPC Gate for listMPInHndl */
SystemIpcBits_ListElem *listElem[SYSTEM_IPC_BITS_MAX_LIST_ELEM];
/**< Array of listElems populated at creat time */
OSA_QueHndl listElemQue[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];
/**< Queue holding free listElems */
Ptr bitBufPoolPtr[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];
/**< Pool bit buffer pointer . */
UInt32 bitBufPoolSize[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];
/**< Size of Pools bitstream buffer. */
Bitstream_BufList freeBitBufList; /**< BitStream buffers to be freed */
IpcBitsOutStats stats; /**< Statistics accumulation member */
IpcBitsOutLink_OutQueueInfo outQueInfo; /**< Output BitStream queue info */
volatile Bool startProcessing; /**< Flag to control start of processing */
} IpcBitsOutLink_Obj;
typedef struct
{
OSA_TskHndl *pTsk;
System_GetLinkInfoCb getLinkInfo;
/**< Function that returns the LINKs output channel configurations */
} System_LinkObj;
//初始化IpcBitsOutLink的資料結構
static Int IpcBitsOutLink_createOutObj(IpcBitsOutLink_Obj * pObj)
{
Int status = OSA_SOK;
Int32 poolId, elemId, bufId;
IHeap_Handle srBitBufHeapHandle;
UInt32 bufSize, numBufs, totBufSize, cacheLineSize;
const UInt32 srIndex = SYSTEM_IPC_SR_CACHED;
Ptr phyAddr;
ipcbitsoutlink_populate_outbuf_pool_size_info(&pObj->createArgs,
&pObj->createArgs.inQueInfo,
&pObj->outQueInfo);
elemId = 0;
//共享區域獲取heap的控制程式碼,從堆上分配記憶體;
srBitBufHeapHandle =SharedRegion_getHeap(srIndex);
OSA_assert(srBitBufHeapHandle != NULL);
//獲取cache的一行的size
cacheLineSize = SharedRegion_getCacheLineSize(srIndex);
for (poolId = 0; poolId < pObj->outQueInfo.allocPoolInfo.numPools; poolId++)
{
//建立一個佇列
status = OSA_queCreate(&pObj->listElemQue[poolId],
SYSTEM_IPC_BITS_MAX_LIST_ELEM);
OSA_assert(status == OSA_SOK);
bufSize =
OSA_align(pObj->outQueInfo.allocPoolInfo.bufPoolInfo[poolId].
bufSize, cacheLineSize);
numBufs = pObj->outQueInfo.allocPoolInfo.bufPoolInfo[poolId].numBufs;
totBufSize = bufSize * numBufs;
OSA_printf ("###Bit buff of size from the SR # %d : %d\n", srIndex, totBufSize);
//分配佇列的記憶體,
pObj->bitBufPoolPtr[poolId] =
Memory_alloc(srBitBufHeapHandle, totBufSize, cacheLineSize, NULL);
OSA_assert(pObj->bitBufPoolPtr[poolId] != NULL);
OSA_printf("IPC_BITSOUT:BitBuffer Alloc.PoolID:%d,Size:0x%X",
poolId,totBufSize);
//虛擬記憶體到實體記憶體對映
phyAddr = IpcBitsOutLink_MapUsrVirt2Phy(pObj->bitBufPoolPtr[poolId]);
pObj->bitBufPoolSize[poolId] = totBufSize;
//給佇列中的每個元素分配記憶體
for (bufId = 0; bufId < numBufs; bufId++)
{
SystemIpcBits_ListElem *listElem;
OSA_assert(elemId < SYSTEM_IPC_BITS_MAX_LIST_ELEM);
listElem = pObj->listElem[elemId];
elemId++;
SYSTEM_IPC_BITS_SET_BUFOWNERPROCID(listElem->bufState);
SYSTEM_IPC_BITS_SET_BUFSTATE(listElem->bufState,
IPC_BITBUF_STATE_FREE);
listElem->bitBuf.addr =
(Ptr) (((UInt32) (pObj->bitBufPoolPtr[poolId])) +
(bufSize * bufId));
if (phyAddr)
{
listElem->bitBuf.phyAddr =
(UInt32) ((UInt32) (phyAddr) + (bufSize * bufId));
}
listElem->bitBuf.allocPoolID = poolId;
listElem->bitBuf.bufSize = bufSize;
listElem->bitBuf.fillLength = 0;
listElem->bitBuf.mvDataFilledSize = 0;
listElem->bitBuf.startOffset = 0;
listElem->bitBuf.bottomFieldBitBufSize = 0;
listElem->bitBuf.doNotDisplay = FALSE;
listElem->srBufPtr = SharedRegion_getSRPtr(listElem->bitBuf.addr,
srIndex);
OSA_assert(listElem->srBufPtr != IPC_LINK_INVALID_SRPTR);
//將元素壓入到佇列
status =
OSA_quePut(&pObj->listElemQue[poolId], (Int32) listElem,
OSA_TIMEOUT_NONE);
OSA_assert(status == OSA_SOK);
}
}
return status;
}
// IpcBitsOutLink_getEmptyVideoBitStreamBufs函式的作用是從IpcBitsOutLink的佇列中獲取一個空的buff
Int32 IpcBitsOutLink_getEmptyVideoBitStreamBufs(UInt32 linkId,
Bitstream_BufList *bufList,
IpcBitsOutLinkHLOS_BitstreamBufReqInfo *reqInfo)
{
OSA_TskHndl * pTsk;
IpcBitsOutLink_Obj * pObj;
Int status;
OSA_assert(bufList != NULL);
if (!((linkId >= SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0)
&&
(linkId < (SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0 + IPC_BITS_OUT_LINK_OBJ_MAX))))
{
return IPC_BITSOUT_LINK_E_INVALIDLINKID;
}
pTsk = System_getLinkTskHndl(linkId);
pObj = pTsk->appData;
bufList->numBufs = 0;
if (pObj->startProcessing)
{
IpcBitsOutLink_releaseBitBufs(pObj);
status = IpcBitsOutLink_getEmptyBufs(pObj,bufList,reqInfo);
}
else
{
status = IPC_BITSOUT_LINK_S_SUCCESS;
}
return status;
}
// IpcBitsOutLink_putFullVideoBitStreamBufs函式的作用是將Bitstream_BufList資料傳遞到下一個link;
Int32 IpcBitsOutLink_putFullVideoBitStreamBufs(UInt32 linkId,
Bitstream_BufList *bufList)
{
OSA_TskHndl * pTsk;
IpcBitsOutLink_Obj * pObj;
Int status;
OSA_assert(bufList != NULL);
if (!((linkId >= SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0)
&&
(linkId < (SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0 + IPC_BITS_OUT_LINK_OBJ_MAX))))
{
return IPC_BITSOUT_LINK_E_INVALIDLINKID;
}
//通過linkId獲取link任務的資料
pTsk = System_getLinkTskHndl(linkId);
//獲取link的appData,將pObj指向該link的appData記憶體地址;
pObj = pTsk->appData;
status = IpcBitsOutLink_putFullBufs(pObj,bufList);
return status;
}
//資料如何從IpcBitsOutLink傳遞到VideoM3
static
Int32 IpcBitsOutLink_putFullBufs(IpcBitsOutLink_Obj *pObj,
Bitstream_BufList *pBufList)
{
SystemIpcBits_ListElem *pListElem;
Bitstream_Buf *pBitBuf;
Bitstream_BufList freeBitBufList;
Bool putDone = FALSE;
Int32 bufId;
UInt32 curTime;
freeBitBufList.numBufs = 0;
curTime = OSA_getCurTimeInMsec();
for (bufId = 0; bufId < pBufList->numBufs; bufId++)
{
pBitBuf = pBufList->bufs[bufId];
curTime = pBitBuf->timeStamp = Get_timeStamp(pBitBuf->channelNum); // for playback side avsync support
// OSA_printf(" A8 IPC_BITS_OUT : TS = %d !!!\n", pBitBuf->timeStamp); //test1
//獲取pBufList的每一個元素
pListElem = (SystemIpcBits_ListElem *)pBitBuf;
//判斷指標是否一致
OSA_assert(SharedRegion_getPtr(pListElem->srBufPtr) ==
pBitBuf->addr);
//如果資料長度為0,直接將資料歸還到佇列
if (0 == pBitBuf->fillLength)
{
/* filled length of 0 indicates application
* did not fill any data in this buffer.
* Free it immediately */
#ifdef SYSTEM_DEBUG_IPC_RT
OSA_printf(" IPC_OUT: Dropping bitbuf\n");
#endif
OSA_assert(freeBitBufList.numBufs <
VIDBITSTREAM_MAX_BITSTREAM_BUFS);
//歸還buff
freeBitBufList.bufs[freeBitBufList.numBufs] = pBitBuf;
freeBitBufList.numBufs++;
pObj->stats.droppedCount++;
continue;
}
else
{
pObj->stats.recvCount++;
OSA_assert(SYSTEM_IPC_BITS_GET_BUFSTATE(pListElem->bufState)
== IPC_BITBUF_STATE_FREE);
OSA_assert(SYSTEM_IPC_BITS_GET_BUFOWNERPROCID(pListElem->bufState)
== System_getSelfProcId());
pListElem->ipcPrivData = (Ptr) curTime;
SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState,
IPC_BITBUF_STATE_ALLOCED);
//將資料傳遞給下一個link,ListMP :在多個核之間共享一個List指標佇列;
IpcBitsOutLink_listMPPut(pObj, pListElem);
putDone = TRUE;
}
}
if (freeBitBufList.numBufs)
{
IpcBitsOutLink_putEmptyBufs(pObj, &freeBitBufList);
}
if (putDone && (pObj->createArgs.baseCreateParams.notifyNextLink))
{
//給下一個link傳送通知,
這裡是給videoM3的ipcBitsInLink傳送訊息
System_ipcSendNotify(pObj->createArgs.baseCreateParams.outQueParams[0].
nextLink);
}
if (!putDone)
{
pObj->stats.numNoFullBufCount++;
if ((pObj->stats.numNoFullBufCount % IPC_BITSOUT_STATS_WARN_INTERVAL) == 0)
{
#ifdef DEBUG_IPC_BITS
OSA_printf("IPCBITSOUT:!!!WARNING.!!! NO FULL BUF AVAILABLE. OCCURENCE COUNT:[%d]",
pObj->stats.numNoFullBufCount);
#endif
}
}
return IPC_BITSOUT_LINK_S_SUCCESS;
}
//
static
Int32 IpcBitsOutLink_listMPPut(IpcBitsOutLink_Obj * pObj,
SystemIpcBits_ListElem * pListElem)
{
Int32 status = IPC_BITSOUT_LINK_S_SUCCESS;
SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState, IPC_BITBUF_STATE_OUTQUE);
IpcBitsOutLink_doPrePutCacheOp(pObj, pListElem);
//掛在link的佇列末尾
status = ListMP_putTail(pObj->listMPOutHndl, (ListMP_Elem *) pListElem);
OSA_assert(status == ListMP_S_SUCCESS);
return IPC_BITSOUT_LINK_S_SUCCESS;
}
pcBitsInVideoM3Id
Main函式:link起來後等待訊息,
Void IpcBitsInLink_tskMain(struct Utils_TskHndl * pTsk, Utils_MsgHndl * pMsg)
{
UInt32 cmd = Utils_msgGetCmd(pMsg);
Bool ackMsg, done;
Int32 status;
IpcBitsInLink_Obj *pObj = (IpcBitsInLink_Obj *) pTsk->appData;
if (cmd != SYSTEM_CMD_CREATE)
{
Utils_tskAckOrFreeMsg(pMsg, FVID2_EFAIL);
return;
}
status = IpcBitsInLink_create(pObj, Utils_msgGetPrm(pMsg));
Utils_tskAckOrFreeMsg(pMsg, status);
if (status != FVID2_SOK)
return;
done = FALSE;
ackMsg = FALSE;
while (!done)
{
status = Utils_tskRecvMsg(pTsk, &pMsg, BIOS_WAIT_FOREVER);
if (status != FVID2_SOK)
break;
cmd = Utils_msgGetCmd(pMsg);
switch (cmd)
{
case SYSTEM_CMD_DELETE:
done = TRUE;
ackMsg = TRUE;
break;
//等待A8 IpcBitsOutLink,傳送訊號,
case SYSTEM_CMD_NEW_DATA:
Utils_tskAckOrFreeMsg(pMsg, status);
IpcBitsInLink_processBitBufs(pObj);
break;
case SYSTEM_CMD_STOP:
IpcBitsInLink_stop(pObj);
Utils_tskAckOrFreeMsg(pMsg, status);
break;
default:
Utils_tskAckOrFreeMsg(pMsg, status);
break;
}
}
IpcBitsInLink_delete(pObj);
#ifdef SYSTEM_DEBUG_IPC_BITS_IN
Vps_printf(" %d: IPC_BITS_IN : Delete Done !!!\n", Utils_getCurTimeInMsec());
#endif
if (ackMsg && pMsg != NULL)
Utils_tskAckOrFreeMsg(pMsg, status);
return;
}
訊號的傳送,A8的IpcBitsOutLink中呼叫它傳送訊號;
Void IpcBitsInLink_notifyCb(Utils_TskHndl * pTsk)
{
IpcBitsInLink_Obj *pObj = (IpcBitsInLink_Obj *) pTsk->appData;
IpcBitsInLink_reconfigPrdObj(pObj, IPC_BITS_IN_LINK_DONE_PERIOD_MS);
Utils_tskSendCmd(pTsk, SYSTEM_CMD_NEW_DATA);
}
//
Int32 IpcBitsInLink_processBitBufs(IpcBitsInLink_Obj * pObj)
{
Bitstream_Buf *pBitBuf;
SystemIpcBits_ListElem *pListElem;
UInt32 numBitBufs;
Int32 status;
UInt32 curTime;
numBitBufs = 0;
curTime = Utils_getCurTimeInMsec();
while (1)
{
//獲取Buff
pListElem = ListMP_getHead(pObj->listMPOutHndl);
if (pListElem == NULL)
break;
//轉化到Bitbuf
IpcBitsInLink_getBitBuf(pObj, pListElem, &pBitBuf);
UTILS_assert(SYSTEM_IPC_BITS_GET_BUFSTATE(pListElem->bufState)
== IPC_BITBUF_STATE_OUTQUE);
pBitBuf->reserved[0] = curTime;
SYSTEM_IPC_BITS_SET_BUFOWNERPROCID(pListElem->bufState);
SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState,
IPC_BITBUF_STATE_DEQUEUED);
pObj->stats.recvCount++;
//壓入到佇列,同一個核使用Utils_quePut函式
status = Utils_quePut(&pObj->outBitBufQue, pBitBuf, BIOS_NO_WAIT);
UTILS_assert(status == FVID2_SOK);
numBitBufs++;
}
#ifdef SYSTEM_DEBUG_IPC_RT
Vps_printf(" %d: IPC_BITS_IN : Recevived %d bitbufs !!!\n",
Utils_getCurTimeInMsec(), numBitBufs);
#endif
//往下一個link傳送資料
if (numBitBufs && pObj->createArgs.baseCreateParams.notifyNextLink)
{
UTILS_assert(pObj->createArgs.baseCreateParams.numOutQue == 1);
System_sendLinkCmd(pObj->createArgs.baseCreateParams.outQueParams[0].
nextLink, SYSTEM_CMD_NEW_DATA);
}
return IPC_BITS_IN_LINK_S_SUCCESS;
}
相關文章
- 頁面之間傳遞資料
- 基本資料型別與引用資料型別,及記憶體分配資料型別記憶體
- ORACLE 資料泵之NETWORK_LINKOracle
- vue元件之間的資料傳遞Vue元件
- jvm:記憶體模型、記憶體分配及GC垃圾回收機制JVM記憶體模型GC
- Vue.js 元件之間傳遞資料Vue.js元件
- oracle資料庫記憶體分配(sga和pga)Oracle資料庫記憶體
- JVM 之 記憶體分配與回收策略JVM記憶體
- 利用DB Link實現資料庫間的表同步資料庫
- JavaScript記憶體分配JavaScript記憶體
- JVM記憶體分配JVM記憶體
- java記憶體分配Java記憶體
- postman(五):在不同介面之間傳遞資料Postman
- react元件與元件之間的資料傳遞React元件
- bundle實現Activity之間的資料傳遞
- 不同順序InBoundHandler之間的資料傳遞
- 垃圾收集器與記憶體分配策略_記憶體分配策略記憶體
- WinForm登陸:窗體間的資料傳遞ORM
- Vue元件間傳遞資料Vue元件
- JVM 記憶體模型 記憶體分配,JVM鎖JVM記憶體模型
- JVM基礎:JVM記憶體組成及分配JVM記憶體
- Java物件記憶體分配原理及原始碼分析Java物件記憶體原始碼
- Ability之間或者程式間資料傳遞之物件(Sequenceable序列化)物件
- Android視窗管理分析(4):Android View繪製記憶體的分配、傳遞、使用AndroidView記憶體
- 探索iOS記憶體分配iOS記憶體
- Java 記憶體分配策略Java記憶體
- java jvm 記憶體分配JavaJVM記憶體
- [C++]記憶體分配C++記憶體
- 動態記憶體分配記憶體
- 微信小程式父子元件之間的資料傳遞微信小程式元件
- Netty 中的記憶體分配淺析-資料容器Netty記憶體
- 分散式資料庫元件——Database Link分散式資料庫元件Database
- Flutter學習之Route跳轉及資料傳遞Flutter
- IOS開發筆記之應用間的跳轉和資料傳遞iOS筆記
- 027 Rust死靈書之Vec記憶體分配Rust記憶體
- JavaScript之記憶體空間JavaScript記憶體
- JVM記憶體分配策略,及垃圾回收演算法JVM記憶體演算法
- node link 踩坑記錄