样例:从A8送一帧jpeg图片到videoM3解码,然后在将解码的数据传递到A8, 这个流程涉及的link源代码例如以下:

dm8148 link之间数据传递1)在A8上调用IpcBitsOutLink_getEmptyVideoBitStreamBufs从IpcBitsOutLink获取buff;然后调用IpcBitsOutLink_putFullVideoBitStreamBufs将数据送入到IpcBitsOutLink。1.1)IpcBitsOutLink
A8调用IpcBitsOutLink将压缩数据(jpeg,mpeg4,h264)送入到videoM3;首先在/src_linux\links\system的system_common.c中调用IpcBitsOutLink_init函数;
//system_init函数在app初始化时调用;
Int32 System_init()
{Int32         status;#ifdef SYSTEM_DEBUGOSA_printf ( " %u: SYSTEM: System Common Init in progress !!!\n", OSA_getCurTimeInMsec());#endifmemset(&gSystem_objCommon, 0, sizeof(gSystem_objCommon));System_ipcInit();IpcBitsInLink_init();IpcBitsOutLink_init();IpcFramesInLink_init();IpcFramesOutLink_init();...........status = OSA_mbxCreate(&gSystem_objCommon.mbx);UTILS_assert(  status==OSA_SOK);SystemLink_init();#ifdef SYSTEM_DEBUGOSA_printf ( " %u: SYSTEM: System Common Init Done !!!\n", OSA_getCurTimeInMsec());#endifreturn status;
}1.2)IpcBitsOutLink_init函数
Int32 IpcBitsOutLink_init()
{Int32 status;System_LinkObj linkObj;UInt32 ipcBitsOutId;IpcBitsOutLink_Obj *pObj;char tskName[32];UInt32 procId = System_getSelfProcId();OSA_COMPILETIME_ASSERT(offsetof(SystemIpcBits_ListElem, bitBuf) == 0);OSA_COMPILETIME_ASSERT(offsetof(Bitstream_Buf, reserved) == 0);OSA_COMPILETIME_ASSERT(sizeof(((Bitstream_Buf *) 0)->reserved) ==sizeof(ListMP_Elem));for (ipcBitsOutId = 0; ipcBitsOutId < IPC_BITS_OUT_LINK_OBJ_MAX;ipcBitsOutId++){pObj = &gIpcBitsOutLink_obj[ipcBitsOutId];memset(pObj, 0, sizeof(*pObj));pObj->tskId =SYSTEM_MAKE_LINK_ID(procId,SYSTEM_LINK_ID_IPC_BITS_OUT_0) + ipcBitsOutId;linkObj.pTsk = &pObj->tsk;linkObj.getLinkInfo = IpcBitsOutLink_getLinkInfo;System_registerLink(pObj->tskId, &linkObj);OSA_SNPRINTF(tskName, "IPC_BITS_OUT%d", ipcBitsOutId);//注冊通知System_ipcRegisterNotifyCb(pObj->tskId, IpcBitsOutLink_notifyCb);//初始化ListMPIpcBitsOutLink_initListMP(pObj);status = OSA_tskCreate(&pObj->tsk,IpcBitsOutLink_tskMain,IPC_LINK_TSK_PRI,IPC_LINK_TSK_STACK_SIZE, 0, pObj);OSA_assert(status == OSA_SOK);}return status;
}1.3)IpcBitsOutLink_tskMain函数
Int IpcBitsOutLink_tskMain(struct OSA_TskHndl * pTsk, OSA_MsgHndl * pMsg,Uint32 curState)
{UInt32 cmd = OSA_msgGetCmd(pMsg);Bool ackMsg, done;Int32 status = IPC_BITSOUT_LINK_S_SUCCESS;//appData中保存的是和link相关的參数IpcBitsOutLink_Obj *pObj = (IpcBitsOutLink_Obj *) pTsk->appData;//SYSTEM_CMD_CREATE为System_linkCreate函数的命令号。假设cmd!=SYSTEM_CMD_CREATE,主函数退出???if (cmd != SYSTEM_CMD_CREATE){OSA_tskAckOrFreeMsg(pMsg, OSA_EFAIL);return status;}status = IpcBitsOutLink_create(pObj, OSA_msgGetPrm(pMsg));OSA_tskAckOrFreeMsg(pMsg, status);if (status != OSA_SOK)return status;done = FALSE;ackMsg = FALSE;while (!done){status = OSA_tskWaitMsg(pTsk, &pMsg);if (status != OSA_SOK)break;cmd = OSA_msgGetCmd(pMsg);switch (cmd){case SYSTEM_CMD_DELETE:done = TRUE;ackMsg = TRUE;break;case SYSTEM_IPC_CMD_RELEASE_FRAMES:OSA_tskAckOrFreeMsg(pMsg, status);#ifdef SYSTEM_DEBUG_IPC_RTOSA_printf(" %d: IPC_BITS_OUT   : Received Notify !!!\n",OSA_getCurTimeInMsec());
#endifIpcBitsOutLink_releaseBitBufs(pObj);break;case SYSTEM_CMD_START://link startIpcBitsOutLink_start(pObj);OSA_tskAckOrFreeMsg(pMsg, status);break;case SYSTEM_CMD_STOP://link stopIpcBitsOutLink_stop(pObj);OSA_tskAckOrFreeMsg(pMsg, status);break;default:OSA_tskAckOrFreeMsg(pMsg, status);break;}}IpcBitsOutLink_delete(pObj);#ifdef SYSTEM_DEBUG_IPC_BITS_OUTOSA_printf(" %d: IPC_BITS_OUT   : Delete Done !!!\n",OSA_getCurTimeInMsec());
#endifif (ackMsg && pMsg != NULL)OSA_tskAckOrFreeMsg(pMsg, status);return IPC_BITSOUT_LINK_S_SUCCESS;
}1.4)IpcBitsOutLink_create函数
Int32 IpcBitsOutLink_create(IpcBitsOutLink_Obj * pObj,IpcBitsOutLinkHLOS_CreateParams * pPrm)
{Int32 status;UInt32 i;#ifdef SYSTEM_DEBUG_IPCOSA_printf(" %d: IPC_BITS_OUT   : Create in progress !!!\n",OSA_getCurTimeInMsec());
#endifmemcpy(&pObj->createArgs, pPrm, sizeof(pObj->createArgs));for (i=0; i<IPC_LINK_BITS_OUT_MAX_NUM_ALLOC_POOLS; i++){OSA_assert(i < IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS);if(pObj->createArgs.numBufPerCh[i] == 0)pObj->createArgs.numBufPerCh[i] =IPC_BITS_OUT_LINK_MAX_OUT_FRAMES_PER_CH;if(pObj->createArgs.numBufPerCh[i] >IPC_BITS_OUT_LINK_MAX_OUT_FRAMES_PER_CH){OSA_printf("\n IPCBITSOUTLINK: WARNING: User is asking for %d buffers per CH. But max allowed is %d. \n"" Over riding user requested with max allowed \n\n",pObj->createArgs.numBufPerCh[i],IPC_BITS_OUT_LINK_MAX_OUT_FRAMES_PER_CH);pObj->createArgs.numBufPerCh[i] =IPC_BITS_OUT_LINK_MAX_OUT_FRAMES_PER_CH;}}//listMP 队列清空status = System_ipcListMPReset(pObj->listMPOutHndl, pObj->listMPInHndl);OSA_assert(status == OSA_SOK);//分配link的内存IpcBitsOutLink_createOutObj(pObj);IpcBitsOutLink_initStats(pObj);pObj->startProcessing = FALSE;#ifdef SYSTEM_DEBUG_IPCOSA_printf(" %d: IPC_BITS_OUT   : Create Done !!!\n",OSA_getCurTimeInMsec());
#endifreturn IPC_BITSOUT_LINK_S_SUCCESS;
}1.5)IpcBitsOutLink_createOutObj函数分配该link须要多少内存,link的内存由link自己管理,在建立link时,告诉该link 内存池的个数。每一个池中的buff的个数。link自己决定分配多少内存;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;srBitBufHeapHandle = SharedRegion_getHeap(srIndex);OSA_assert(srBitBufHeapHandle != NULL);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;//获取Buf的指针listElem->srBufPtr = SharedRegion_getSRPtr(listElem->bitBuf.addr,srIndex);OSA_assert(listElem->srBufPtr != IPC_LINK_INVALID_SRPTR);//将分配的buff挂在插入list队列,使用时,从队列中取empty buff。比方在A8须要将bit数据拷贝传递到IpcBitsOutLink。调用IpcBitsOutLink_getEmptyVideoBitStreamBufs(IpcBitsOutLink_getEmptyBufs)从队列中取buff;status =OSA_quePut(&pObj->listElemQue[poolId], (Int32) listElem,OSA_TIMEOUT_NONE);OSA_assert(status == OSA_SOK);}}return status;
}1.6)A8中调用该函数将buff传递IpcBitsOutLink
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;}pTsk = System_getLinkTskHndl(linkId);pObj = pTsk->appData;//将buff传递到下一个linkstatus = IpcBitsOutLink_putFullBufs(pObj,bufList);return status;
}1.7)IpcBitsOutLink_putFullBufs 将buff传递到下一个link,注意IpcBitsOutLink_listMPPut。将buff压入到输出队列。然后发送System_ipcSendNotify 发送通知,通知下一个link来取数据。
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); 
      pListElem = (SystemIpcBits_ListElem *)pBitBuf;OSA_assert(SharedRegion_getPtr(pListElem->srBufPtr) ==pBitBuf->addr);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_RTOSA_printf(" IPC_OUT: Dropping bitbuf\n");
#endifOSA_assert(freeBitBufList.numBufs <VIDBITSTREAM_MAX_BITSTREAM_BUFS);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);//压入到输出队列IpcBitsOutLink_listMPPut(pObj, pListElem);putDone = TRUE;}}if (freeBitBufList.numBufs){IpcBitsOutLink_putEmptyBufs(pObj, &freeBitBufList);}if (putDone && (pObj->createArgs.baseCreateParams.notifyNextLink)){//通知下一个link。调用Notify_sendEvent函数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_BITSOSA_printf("IPCBITSOUT:!!!WARNING.!!! NO FULL BUF AVAILABLE. OCCURENCE COUNT:[%d]",pObj->stats.numNoFullBufCount);#endif}}return IPC_BITSOUT_LINK_S_SUCCESS;
}1.8)IpcBitsOutLink_listMPPut 函数
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);//cache 多核之间数据拷贝,传递到ipcbitsIn(videoM3) linkIpcBitsOutLink_doPrePutCacheOp(pObj, pListElem);status = ListMP_putTail(pObj->listMPOutHndl, (ListMP_Elem *) pListElem);OSA_assert(status == ListMP_S_SUCCESS);return IPC_BITSOUT_LINK_S_SUCCESS;
}1.9)IpcBitsOutLink_doPrePutCacheOp 函数;
static
Int32 IpcBitsOutLink_doPrePutCacheOp(IpcBitsOutLink_Obj * pObj,SystemIpcBits_ListElem * pListElem)
{if (pListElem->bitBuf.fillLength){Cache_wbInv(pListElem->bitBuf.addr,pListElem->bitBuf.fillLength, Cache_Type_ALL, TRUE);}/* No cache ops done since pListElem is allocated from non-cached memory */UTILS_assert(SharedRegion_isCacheEnabled(SharedRegion_getId(pListElem)) ==FALSE);return IPC_BITSOUT_LINK_S_SUCCESS;
}ListMP_putTail 和ListMP_getHead 作用。多核之间用吗?相邻2个核之间的link公用一个ListMp队列吗?ipcBitsOutLink(A8)发送通知Notify_sendEvent告诉ipcBitsInLink(videoM3),在ListMP队列已经存在数据。ListMP实现了多宿主双向循环链表。即该双向循环链表为多个处理器共有,能够由多个处理器共同维护,共同使用。
ListMP的实现差别于一般的双向循环链表,因此它不仅具有双向循环链表的特性外,还增添了其它的特性,比方下面几点:
1.实现了简单的多宿主协议,支持多个读写者(multi-reader、multi-writee);
2.使用Gate作为内部保护机制,防止多个宿主处理器同一时候訪问该链表;
ListMP的实现并未增加通知机制。假设须要的话,能够在外部封装是引入Notify机制来实现;使用ListMP机制来管理的buffers都须要从共享内存区分配。包含从堆内存分配的buffers以及动态分配的内存。2)videoM3 systemLink 多核之间数据传递要用到systemlink,下面是videoM3中systemLink的初始化函数;主要有IpcOutM3Link_init()函数和IpcInM3Link_init()函数。
mcfw/src_bios6/links_m3video/system ;system_m3video.cInt32 System_init()
{Int32 status = FVID2_SOK;#ifdef SYSTEM_DEBUGVps_printf(" %d: SYSTEM  : System Video Init in progress !!!\n",Utils_getCurTimeInMsec());
#endif#ifdef SYSTEM_DEBUGVps_printf(" %d: SYSTEM  : System Video Init Done !!!\n", Utils_getCurTimeInMsec());
#endifIpcOutM3Link_init();IpcInM3Link_init();IpcBitsInLink_init();IpcBitsOutLink_init();IpcFramesInLink_init();IpcFramesOutLink_init();Utils_encdecInit();//编解码link初始化System_initLinks();return status;
}3)IpcBitsInLink(mcfw_bios6)3.1)初始化函数
Int32 IpcBitsInLink_init()
{Int32 status;System_LinkObj linkObj;UInt32 ipcBitsInId;IpcBitsInLink_Obj *pObj;char tskName[32];UInt32 procId = System_getSelfProcId();UTILS_COMPILETIME_ASSERT(offsetof(SystemIpcBits_ListElem, bitBuf) == 0);UTILS_COMPILETIME_ASSERT(offsetof(Bitstream_Buf, reserved) == 0);UTILS_COMPILETIME_ASSERT(sizeof(((Bitstream_Buf *) 0)->reserved) ==sizeof(ListMP_Elem));for (ipcBitsInId = 0; ipcBitsInId < IPC_BITS_IN_LINK_OBJ_MAX; ipcBitsInId++){pObj = &gIpcBitsInLink_obj[ipcBitsInId];memset(pObj, 0, sizeof(*pObj));pObj->tskId =SYSTEM_MAKE_LINK_ID(procId,SYSTEM_LINK_ID_IPC_BITS_IN_0) + ipcBitsInId;pObj->state = IPC_BITS_IN_LINK_STATE_INACTIVE;linkObj.pTsk = &pObj->tsk;linkObj.linkGetFullFrames = NULL;linkObj.linkPutEmptyFrames = NULL;linkObj.linkGetFullBitBufs = IpcBitsInLink_getFullBitBufs;linkObj.linkPutEmptyBitBufs = IpcBitsInLink_putEmptyBitBufs;linkObj.getLinkInfo = IpcBitsInLink_getLinkInfo;System_registerLink(pObj->tskId, &linkObj);UTILS_SNPRINTF(tskName, "IPC_BITS_IN%d", ipcBitsInId);System_ipcRegisterNotifyCb(pObj->tskId, IpcBitsInLink_notifyCb);status = Utils_tskCreate(&pObj->tsk,IpcBitsInLink_tskMain,IPC_LINK_TSK_PRI,gIpcBitsInLink_tskStack[ipcBitsInId],IPC_LINK_TSK_STACK_SIZE, pObj, tskName);UTILS_assert(status == FVID2_SOK);}return status;
}3.2)IpcBitsInLink_tskMain 主函数
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;}//ListMP 和队列资源初始化status = IpcBitsInLink_create(pObj, Utils_msgGetPrm(pMsg));Utils_tskAckOrFreeMsg(pMsg, status);if (status != FVID2_SOK)return;done = FALSE;ackMsg = FALSE;while (!done){//接收消息,是接收从ipcbitsOutlink(A8)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;case SYSTEM_CMD_NEW_DATA://从IpcInM3 Link获取消息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_INVps_printf(" %d: IPC_BITS_IN   : Delete Done !!!\n", Utils_getCurTimeInMsec());
#endifif (ackMsg && pMsg != NULL)Utils_tskAckOrFreeMsg(pMsg, status);return;
}3.3)IpcBitsInLink_processBitBufs函数
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){//获取listElem。多核之间获取数据;pListElem = ListMP_getHead(pObj->listMPOutHndl);if (pListElem == NULL)break;//转化为bitbuffIpcBitsInLink_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++;//压入到输出队列;status = Utils_quePut(&pObj->outBitBufQue, pBitBuf, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);numBitBufs++;}#ifdef SYSTEM_DEBUG_IPC_RTVps_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;
}4)VideoM3 declink4.1)解码link初始化函数
Int32 DecLink_init()
{Int32 status;System_LinkObj linkObj;DecLink_Obj *pObj;char name[32];UInt32 objId;for (objId = 0; objId < DEC_LINK_OBJ_MAX; objId++){pObj = &gDecLink_obj[objId];memset(pObj, 0, sizeof(*pObj));pObj->linkId = SYSTEM_LINK_ID_VDEC_0 + objId;linkObj.pTsk = &pObj->tsk;linkObj.linkGetFullFrames = DecLink_getFullFrames;linkObj.linkPutEmptyFrames = DecLink_putEmptyFrames;linkObj.linkGetFullBitBufs = NULL;linkObj.linkPutEmptyBitBufs = NULL;linkObj.getLinkInfo = DecLink_getInfo;UTILS_SNPRINTF(name, "DEC%d   ", objId);System_registerLink(pObj->linkId, &linkObj);status = Utils_tskCreate(&pObj->tsk,DecLink_tskMain,DEC_LINK_TSK_PRI,gDecLink_tskStack[objId],DEC_LINK_TSK_STACK_SIZE, pObj, name);UTILS_assert(status == FVID2_SOK);}return status;
}4.2)DecLink_tskMain 主函数
Void DecLink_tskMain(struct Utils_TskHndl *pTsk, Utils_MsgHndl * pMsg)
{UInt32 cmd = Utils_msgGetCmd(pMsg);Bool ackMsg, done;Int32 status;DecLink_Obj *pObj;UInt32 flushCmds[2];pObj = (DecLink_Obj *) pTsk->appData;if (cmd != SYSTEM_CMD_CREATE){#ifndef DEC_LINK_SUPRESS_ERROR_AND_RESETDECLINK_INTERNAL_ERROR_LOG(DEC_LINK_E_INVALIDCMD,"Link create should be first cmd.""Received Cmd:%d", cmd);#endifUtils_tskAckOrFreeMsg(pMsg, FVID2_EFAIL);return;}//分配link的内存等资源,创建解码线程(调用该函数DecLink_codecCreateProcessTsk(pObj, tskId);)status = DecLink_codecCreate(pObj, Utils_msgGetPrm(pMsg));Utils_tskAckOrFreeMsg(pMsg, status);if (status != FVID2_SOK)return;Utils_encdecHdvicpPrfInit();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_NEW_DATA:Utils_tskAckOrFreeMsg(pMsg, status);flushCmds[0] = SYSTEM_CMD_NEW_DATA;Utils_tskFlushMsg(pTsk, flushCmds, 1);//link收到数据。调用该函数进行解码DecLink_codecProcessData(pObj);break;case DEC_LINK_CMD_GET_PROCESSED_DATA:Utils_tskAckOrFreeMsg(pMsg, status);flushCmds[0] = DEC_LINK_CMD_GET_PROCESSED_DATA;Utils_tskFlushMsg(pTsk, flushCmds, 1);DecLink_codecGetProcessedDataMsgHandler(pObj);break;case DEC_LINK_CMD_PRINT_IVAHD_STATISTICS:Utils_tskAckOrFreeMsg(pMsg, status);Utils_encdecHdvicpPrfPrint();break;case DEC_LINK_CMD_PRINT_STATISTICS:DecLink_printStatistics(pObj, TRUE);Utils_tskAckOrFreeMsg(pMsg, status);break;case DEC_LINK_CMD_PRINT_BUFFER_STATISTICS:Utils_tskAckOrFreeMsg(pMsg, status);DecLink_printBufferStatus(pObj);break;case DEC_LINK_CMD_DISABLE_CHANNEL:{DecLink_ChannelInfo *params;params = (DecLink_ChannelInfo *) Utils_msgGetPrm(pMsg);DecLink_codecDisableChannel(pObj, params);Utils_tskAckOrFreeMsg(pMsg, status);}break;case DEC_LINK_CMD_ENABLE_CHANNEL:{DecLink_ChannelInfo *params;params = (DecLink_ChannelInfo *) Utils_msgGetPrm(pMsg);DecLink_codecEnableChannel(pObj, params);Utils_tskAckOrFreeMsg(pMsg, status);}break;case DEC_LINK_CMD_SET_TRICKPLAYCONFIG:{DecLink_TPlayConfig * params;params = (DecLink_TPlayConfig *) Utils_msgGetPrm(pMsg);DecLink_setTPlayConfig(pObj, params);Utils_tskAckOrFreeMsg(pMsg, status);}break;case SYSTEM_CMD_STOP:DecLink_codecStop(pObj);Utils_tskAckOrFreeMsg(pMsg, status);break;case SYSTEM_CMD_DELETE:DecLink_codecStop(pObj);done = TRUE;ackMsg = TRUE;break;default:Utils_tskAckOrFreeMsg(pMsg, status);break;}}DecLink_codecDelete(pObj);if (ackMsg && pMsg != NULL)Utils_tskAckOrFreeMsg(pMsg, status);return;
}4.3)DecLink_codecProcessData函数从上一个link中获取bit数据,调用videoM3的解码器进行解码;
Int32 DecLink_codecProcessData(DecLink_Obj * pObj)
{Int32 status;pObj->newDataProcessOnFrameFree = FALSE;DecLink_codecQueueBufsToChQue(pObj);do{status = DecLink_codecSubmitData(pObj);} while (status == FVID2_SOK);return FVID2_SOK;
}4.4)DecLink_codecQueueBufsToChQue调用System_getLinksFullBufs从prelink中获取bit数据,保存在BitStream_Buf结构中。
static Int32 DecLink_codecQueueBufsToChQue(DecLink_Obj * pObj)
{UInt32 bufId, freeBufNum;Bitstream_Buf *pBuf;System_LinkInQueParams *pInQueParams;Bitstream_BufList bufList;DecLink_ChObj *pChObj;Int32 status;UInt32 curTime;pInQueParams = &pObj->createArgs.inQueParams;System_getLinksFullBufs(pInQueParams->prevLinkId,pInQueParams->prevLinkQueId, &bufList);if (bufList.numBufs){pObj->inBufGetCount += bufList.numBufs;freeBufNum = 0;curTime = Utils_getCurTimeInMsec();for (bufId = 0; bufId < bufList.numBufs; bufId++){pBuf = bufList.bufs[bufId];pChObj = &pObj->chObj[pBuf->channelNum];pChObj->inFrameRecvCount++;// pBuf->fid = pChObj->nextFid;if(pChObj->disableChn && pChObj->skipFrame == FALSE){pChObj->skipFrame = TRUE;}else if((pChObj->disableChn == FALSE) && pChObj->skipFrame){if(pBuf->isKeyFrame == TRUE){pChObj->skipFrame = FALSE;}}if (((pChObj->IFrameOnlyDecode) &&(!pBuf->isKeyFrame)) || pChObj->skipFrame){pChObj->inBufSkipCount++;pChObj->inFrameUserSkipCount++;// Drop if not a I framebufList.bufs[freeBufNum] = pBuf;freeBufNum++;}else{pChObj->totalInFrameCnt++;if (pChObj->totalInFrameCnt > DEC_LINK_STATS_START_THRESHOLD){pChObj->totalFrameIntervalTime +=(curTime - pChObj->prevFrmRecvTime);}else{pChObj->totalFrameIntervalTime = 0;pChObj->totalProcessTime = 0;DecLink_resetStatistics(pObj);}pChObj->prevFrmRecvTime = curTime;//将buff压入队列提供解码器status = Utils_quePut(&pChObj->inQue, pBuf, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);pChObj->inBufQueCount++;}}if (freeBufNum){bufList.numBufs = freeBufNum;System_putLinksEmptyBufs(pInQueParams->prevLinkId,pInQueParams->prevLinkQueId, &bufList);pObj->inBufPutCount += freeBufNum;}}return FVID2_SOK;
}4.5)System_getLinksFullBufs函数调用systemLink api(pTsk->linkGetFullBitBufs函数)从上一个link获取bit码流数据
Int32 System_getLinksFullBufs(UInt32 linkId, UInt16 queId,Bitstream_BufList * pBufList)
{System_LinkObj *pTsk;linkId = SYSTEM_GET_LINK_ID(linkId);UTILS_assert(linkId < SYSTEM_LINK_ID_MAX);pTsk = &gSystem_objCommon.linkObj[linkId];if (pTsk->linkGetFullBitBufs != NULL)return pTsk->linkGetFullBitBufs(pTsk->pTsk, queId, pBufList);return FVID2_EFAIL;
}4.6)DecLink_codecSubmitData对bit数据进行解码
static Int32 DecLink_codecSubmitData(DecLink_Obj * pObj)
{DecLink_ReqObj *pReqObj;DecLink_ChObj *pChObj;UInt32 chCount,chIdIndex, numProcessCh;Bitstream_Buf *pInBuf;FVID2_Frame *pOutFrame;Int32 status = FVID2_EFAIL, numReqObjPerProcess;UInt32 tskId, i;static UInt32 startChID = 0;System_FrameInfo *pOutFrameInfo;UInt32 curTime = Utils_getCurTimeInMsec();numProcessCh = 0;chIdIndex    = startChID;for (chCount = 0; chCount < pObj->inQueInfo.numCh; chCount++,chIdIndex++){numReqObjPerProcess = 0;if (chIdIndex >= pObj->inQueInfo.numCh)chIdIndex = 0;pChObj = &pObj->chObj[chIdIndex];if (Utils_queIsEmpty(&pObj->outObj.bufOutQue.emptyQue[pChObj->allocPoolID])){pObj->newDataProcessOnFrameFree = TRUE;}while(numReqObjPerProcess < pChObj->numReqObjPerProcess) {numReqObjPerProcess++;status =Utils_queGet(&pObj->reqQue, (Ptr *) & pReqObj, 1,BIOS_NO_WAIT);if (UTILS_ISERROR(status)) {break;}pObj->reqQueCount++;UTILS_assert(DEC_LINK_MAX_REQ >= pObj->reqQueCount);tskId = pObj->ch2ProcessTskId[chIdIndex];if (pChObj->algObj.algCreateParams.fieldMergeDecodeEnable){/* pReqObj->OutFrameList.numFrames should be set to 2 once         *//*  codec has support to consume 2 output pointers rather than     *//*  just one pointer with 2 contigous fields in field merged       *//*  interlaced decode use case.                                    */pReqObj->OutFrameList.numFrames = 1;}else{pReqObj->OutFrameList.numFrames = 1;}if ((status == FVID2_SOK) &&(pChObj->inBufQueCount) &&(Utils_queGetQueuedCount(&pObj->outObj.bufOutQue.emptyQue[pChObj->allocPoolID]) >= pReqObj->OutFrameList.numFrames) &&!(Utils_queIsFull(&pObj->decProcessTsk[tskId].processQue))){for (i=0; i<pReqObj->OutFrameList.numFrames; i++){pOutFrame = NULL;status =Utils_bufGetEmptyFrameExt(&pObj->outObj.bufOutQue,&pOutFrame,pObj->outObj.ch2poolMap[chIdIndex],BIOS_NO_WAIT);if (pOutFrame){declink_codec_init_outframe(pObj, chIdIndex, pOutFrame);pReqObj->OutFrameList.frames[i] = pOutFrame;}else{break;}}if ((status == FVID2_SOK) && (pOutFrame)){//获取待解码的数据Utils_queGet(&pChObj->inQue, (Ptr *) & pInBuf, 1, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);pReqObj->InBuf = pInBuf;pChObj->inBufQueCount--;for (i=0; i<pReqObj->OutFrameList.numFrames; i++){pReqObj->OutFrameList.frames[i]->channelNum =pInBuf->channelNum;//pInBuf->timeStamp  = curTime;pReqObj->OutFrameList.frames[i]->timeStamp=pInBuf->timeStamp;pOutFrameInfo = (System_FrameInfo *) pReqObj->OutFrameList.frames[i]->appData;pOutFrameInfo->ts64  = (UInt32)pInBuf->upperTimeStamp;pOutFrameInfo->ts64 <<= 32;pOutFrameInfo->ts64  = pOutFrameInfo->ts64 | ((UInt32)pInBuf->lowerTimeStamp);}numProcessCh++;//插入到解码处理队列status =Utils_quePut(&pObj->decProcessTsk[tskId].processQue,pReqObj, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);pChObj->processReqestCount++;}else{status = Utils_quePut(&pObj->reqQue, pReqObj, BIOS_NO_WAIT);startChID = chIdIndex;UTILS_assert(status == FVID2_SOK);pObj->reqQueCount--;status = FVID2_EFAIL;continue;}}else{status = Utils_quePut(&pObj->reqQue, pReqObj, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);pObj->reqQueCount--;startChID = chIdIndex;status = FVID2_EFAIL;if (Utils_queIsEmpty(&pObj->outObj.bufOutQue.emptyQue[pChObj->allocPoolID])){pObj->newDataProcessOnFrameFree = TRUE;}}}}return status;
}4.7)DecLink_codecCreateProcessTsk函数
该函数为解码任务函数;从pObj->decProcessTsk[tskId].processQue队列中获取数据。然后进行解码;
static Void DecLink_codecProcessTskFxn(UArg arg1, UArg arg2)
{Int32 status, chId, i, j;DecLink_Obj *pObj;DecLink_ChObj *pChObj;DecLink_ReqObj *pReqObj;FVID2_FrameList freeFrameList;UInt32 tskId;pObj = (DecLink_Obj *) arg1;tskId = (UInt32) arg2;while (pObj->state != SYSTEM_LINK_STATE_STOP){pObj->reqObjBatch[tskId].numReqObjsInBatch = 0;status = DEC_LINK_S_SUCCESS;//从队列中获取待解码的数据status = Utils_queGet(&pObj->decProcessTsk[tskId].processQue,(Ptr *) & pReqObj, 1, BIOS_WAIT_FOREVER);if (!UTILS_ISERROR(status)){status = DecLink_PrepareBatch (pObj, tskId, pReqObj, &pObj->reqObjBatch[tskId]);if (UTILS_ISERROR(status)){UTILS_warn("DEC : IVAHDID : %d ENCLINK:ERROR in ""DecLink_SubmitBatch.Status[%d]", tskId, status);}else {/*Log Batch size statistics*/pObj->batchStatistics[tskId].numBatchesSubmitted++;pObj->batchStatistics[tskId].currentBatchSize = pObj->reqObjBatch[tskId].numReqObjsInBatch;if (pObj->batchStatistics[tskId].maxAchievedBatchSize <pObj->batchStatistics[tskId].currentBatchSize){pObj->batchStatistics[tskId].maxAchievedBatchSize =pObj->batchStatistics[tskId].currentBatchSize;}pObj->batchStatistics[tskId].aggregateBatchSize = pObj->batchStatistics[tskId].aggregateBatchSize + pObj->batchStatistics[tskId].currentBatchSize;pObj->batchStatistics[tskId].averageBatchSize = pObj->batchStatistics[tskId].aggregateBatchSize /pObj->batchStatistics[tskId].numBatchesSubmitted;}            }freeFrameList.numFrames = 0;if (pObj->reqObjBatch[tskId].numReqObjsInBatch){/*Its made sure that for every batch created all ReqObj have the samecodec. And every Request Batch has atleast one ReqObj */chId = pObj->reqObjBatch[tskId].pReqObj[0]->InBuf->channelNum;pChObj = &pObj->chObj[chId];switch (pChObj->algObj.algCreateParams.format){case IVIDEO_H264BP:case IVIDEO_H264MP:case IVIDEO_H264HP:status = Declink_h264DecodeFrameBatch(pObj, &pObj->reqObjBatch[tskId],&freeFrameList, tskId);if (UTILS_ISERROR(status)){#ifndef DEC_LINK_SUPRESS_ERROR_AND_RESET/*UTILS_warn("DECLINK:ERROR in ""Declink_h264DecodeFrameBatch.Status[%d]", status); */#endif   }break;case IVIDEO_MPEG4SP:case IVIDEO_MPEG4ASP:status = Declink_mpeg4DecodeFrameBatch(pObj, &pObj->reqObjBatch[tskId],&freeFrameList);if (UTILS_ISERROR(status)){#ifndef DEC_LINK_SUPRESS_ERROR_AND_RESETUTILS_warn("DECLINK:ERROR in ""Declink_mpeg4DecodeFrameBatch.Status[%d]", status);#endif}break;case IVIDEO_MJPEG://调用该函数进行解码status = Declink_jpegDecodeFrameBatch(pObj, &pObj->reqObjBatch[tskId],&freeFrameList);if (UTILS_ISERROR(status)){UTILS_warn("DECLINK:ERROR in ""Declink_jpegDecodeFrameBatch.Status[%d]", status);}break;default:UTILS_assert(FALSE);}}for (i = 0; i < pObj->reqObjBatch[tskId].numReqObjsInBatch; i++){pReqObj = pObj->reqObjBatch[tskId].pReqObj[i];for (j = 0; j < pReqObj->OutFrameList.numFrames; j++){FVID2_Frame *displayFrame;DecLink_codecGetDisplayFrame(pObj,pReqObj->OutFrameList.frames[j],&freeFrameList, &displayFrame);pReqObj->OutFrameList.frames[j] = displayFrame;}//将解码后的数据插入到队列。主函数会调用DecLink_codecGetProcessedDataMsgHandler函数对数据进行处理。发给下一个link;status = Utils_quePut(&pObj->processDoneQue, pReqObj,BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);}DecLink_codecFreeProcessedFrames(pObj, &freeFrameList);}return;
}4.8)jpeg解码函数(Declink_jpegDecodeFrameBatch)例如以下:
Int32 Declink_jpegDecodeFrameBatch(DecLink_Obj * pObj,DecLink_ReqBatch * pReqObjBatch,FVID2_FrameList * freeFrameList)
{int error = XDM_EFAIL, reqObjIdx, chId;Int32 i, freeBufIdx, prosIdx;IJPEGVDEC_InArgs *inArgs;IJPEGVDEC_OutArgs *outArgs;XDM2_BufDesc *inputBufDesc;XDM2_BufDesc *outputBufDesc;IJPEGVDEC_Handle handle;IALG_Fxns *fxns = NULL;FVID2_Frame *outFrame = NULL;IVIDEO2_BufDesc *displayBufs = NULL;UInt32 bytesConsumed;DecLink_ReqObj *pReqObj;DecLink_ChObj *pChObj;System_FrameInfo *pFrameInfo;/*Make sure that the Req Object is not empty*/UTILS_assert (pReqObjBatch->numReqObjsInBatch > 0);for (reqObjIdx = 0; reqObjIdx < pReqObjBatch->numReqObjsInBatch; reqObjIdx++){pReqObj = pReqObjBatch->pReqObj[reqObjIdx];chId = pReqObj->InBuf->channelNum;pChObj = &pObj->chObj[chId];inArgs = &pChObj->algObj.u.jpegAlgIfObj.inArgs;outArgs = &pChObj->algObj.u.jpegAlgIfObj.outArgs;inputBufDesc = &pChObj->algObj.u.jpegAlgIfObj.inBufs;outputBufDesc = &pChObj->algObj.u.jpegAlgIfObj.outBufs;handle = pChObj->algObj.u.jpegAlgIfObj.algHandle;UTILS_assert(handle != NULL);fxns = (IALG_Fxns *) handle->fxns;//IRESMAN_HDVICP2_EarlyAcquire((IALG_Handle) handle,//                             pChObj->algObj.u.jpegAlgIfObj.ivaChID);bytesConsumed = 0;for (prosIdx=0; prosIdx< pReqObj->OutFrameList.numFrames; prosIdx++){/*----------------------------------------------------------------*//* Initialize the input ID in input arguments to the bufferid of  *//* buffer element returned from getfreebuffer() function.         *//*----------------------------------------------------------------*//* inputID & numBytes need to update before every decode call */if (FALSE == outArgs->viddecOutArgs.outBufsInUseFlag){outFrame = pReqObj->OutFrameList.frames[prosIdx];}else{UTILS_assert(NULL != pChObj->algObj.prevOutFrame);/* Previous buffer was in use. Free the current outBuf */outFrame = pChObj->algObj.prevOutFrame;freeFrameList->frames[freeFrameList->numFrames] = pReqObj->OutFrameList.frames[prosIdx];pChObj->numBufsInCodec--;freeFrameList->numFrames++;}inArgs->viddecInArgs.inputID = (UInt32) outFrame;inArgs->viddecInArgs.numBytes = pReqObj->InBuf->fillLength - bytesConsumed;for (i = 0; i < inputBufDesc->numBufs; i++){/* Set proper buffer addresses for bitstreamn data *//*---------------------------------------------------------------*/inputBufDesc->descs[i].buf = (XDAS_Int8 *) pReqObj->InBuf->addr +  bytesConsumed;inputBufDesc->descs[i].bufSize.bytes = pReqObj->InBuf->bufSize;}for (i = 0; i < outputBufDesc->numBufs; i++){/* Set proper buffer addresses for Frame data *//*------------------------------------------------------------*/if (pChObj->algObj.algCreateParams.tilerEnable){outputBufDesc->descs[i].buf =(Ptr)Utils_tilerAddr2CpuAddr((UInt32) (outFrame->addr[0][i]));}else{outputBufDesc->descs[i].buf = outFrame->addr[0][i];}}fxns->algActivate((IALG_Handle) handle);//调用visa api进行jpeg解码error = handle->fxns->ividdec.process((IVIDDEC3_Handle) handle,inputBufDesc,outputBufDesc,(IVIDDEC3_InArgs *) inArgs,(IVIDDEC3_OutArgs *) outArgs);fxns->algDeactivate((IALG_Handle) handle);bytesConsumed = outArgs->viddecOutArgs.bytesConsumed;if (error != XDM_EOK){DECLINK_INTERNAL_ERROR_LOG(error, "ALGPROCESS FAILED:STATUS");}pChObj->algObj.prevOutFrame = outFrame;pReqObj->status = error;pReqObj->OutFrameList.frames[prosIdx] = NULL;UTILS_assert(outArgs->viddecOutArgs.displayBufsMode ==IVIDDEC3_DISPLAYBUFS_EMBEDDED);displayBufs = &(outArgs->viddecOutArgs.displayBufs.bufDesc[0]);if ((outArgs->viddecOutArgs.outputID[0] != 0)&& (displayBufs->numPlanes)){XDAS_Int8 *pExpectedBuf;pReqObj->OutFrameList.frames[prosIdx] =(FVID2_Frame *) outArgs->viddecOutArgs.outputID[0];if (pChObj->algObj.algCreateParams.tilerEnable){pExpectedBuf = (Ptr) Utils_tilerAddr2CpuAddr((UInt32) pReqObj->OutFrameList.frames[prosIdx]->addr[0][0]);}else{pExpectedBuf = pReqObj->OutFrameList.frames[prosIdx]->addr[0][0];}UTILS_assert(displayBufs->planeDesc[0].buf == pExpectedBuf);/* Enable this code once SysTemFrameInfo is updated with support* for storing frame resolution info */pFrameInfo = (System_FrameInfo *) pReqObj->OutFrameList.frames[prosIdx]->appData;{UTILS_assert(pFrameInfo != NULL);pFrameInfo->rtChInfo.width =displayBufs->activeFrameRegion.bottomRight.x -displayBufs->activeFrameRegion.topLeft.x;pFrameInfo->rtChInfo.height =displayBufs->activeFrameRegion.bottomRight.y -displayBufs->activeFrameRegion.topLeft.y;pFrameInfo->rtChInfo.pitch[0] = displayBufs->imagePitch[0];pFrameInfo->rtChInfo.pitch[1] = displayBufs->imagePitch[1];pFrameInfo->rtChInfoUpdate = TRUE;}pReqObj->OutFrameList.frames[prosIdx]->fid =Utils_encdecMapXDMContentType2FVID2FID(displayBufs->contentType);}freeBufIdx = 0;while (outArgs->viddecOutArgs.freeBufID[freeBufIdx] != 0){freeFrameList->frames[freeFrameList->numFrames] =(FVID2_Frame *) outArgs->viddecOutArgs.freeBufID[freeBufIdx];freeFrameList->numFrames++;pChObj->numBufsInCodec--;freeBufIdx++;}}}return (error);
}4.9)DecLink_codecGetProcessedDataMsgHandler函数功能获取解码后的数据,该函数在DecLink_tskMain中调用;
Int32 DecLink_codecGetProcessedDataMsgHandler(DecLink_Obj * pObj)
{Int32 status;status = DecLink_codecGetProcessedData(pObj);UTILS_assert(status == FVID2_SOK);return DEC_LINK_S_SUCCESS;}4.10)DecLink_codecGetProcessedData 处理解码后的数据,发给下一个linkstatic Int32 DecLink_codecGetProcessedData(DecLink_Obj * pObj)
{Bitstream_BufList inBufList;FVID2_FrameList outFrameList;FVID2_FrameList outFrameSkipList;UInt32 chId, sendCmd;System_LinkInQueParams *pInQueParams;DecLink_ChObj *pChObj;DecLink_ReqObj *pReqObj;Int32 status, j;UInt32 curTime;sendCmd = FALSE;inBufList.numBufs = 0;inBufList.appData = NULL;outFrameList.numFrames = 0;outFrameSkipList.numFrames = 0;curTime = Utils_getCurTimeInMsec();while(!Utils_queIsEmpty(&pObj->processDoneQue)&&(inBufList.numBufs < (VIDBITSTREAM_MAX_BITSTREAM_BUFS - 1))&&(outFrameList.numFrames < (FVID2_MAX_FVID_FRAME_PTR - 1))){//获取解码后的数据status = Utils_queGet(&pObj->processDoneQue, (Ptr *) & pReqObj, 1,BIOS_NO_WAIT);if (status != FVID2_SOK){break;}UTILS_assert(pReqObj->InBuf != NULL);chId = pReqObj->InBuf->channelNum;pChObj = &pObj->chObj[chId];//if (pChObj->totalInFrameCnt > DEC_LINK_STATS_START_THRESHOLD){if (curTime > pReqObj->InBuf->timeStamp){pChObj->totalProcessTime +=(curTime - pReqObj->InBuf->timeStamp);}}pChObj->getProcessedBufCount++;pChObj->outFrameCount++;inBufList.bufs[inBufList.numBufs] = pReqObj->InBuf;inBufList.numBufs++;for (j = 0; j < pReqObj->OutFrameList.numFrames; j++){if (pReqObj->OutFrameList.frames[j]){UTILS_assert(pReqObj->InBuf->channelNum ==pReqObj->OutFrameList.frames[j]->channelNum);UTILS_assert(pChObj->allocPoolID < UTILS_BUF_MAX_ALLOC_POOLS);pChObj->trickPlayObj.skipFrame = Utils_doSkipFrame(&(pChObj->trickPlayObj.frameSkipCtx));if (pChObj->trickPlayObj.skipFrame == TRUE){/* Skip the output frame */outFrameSkipList.frames[outFrameSkipList.numFrames] =pReqObj->OutFrameList.frames[j];outFrameSkipList.numFrames++;}else{outFrameList.frames[outFrameList.numFrames] =pReqObj->OutFrameList.frames[j];outFrameList.numFrames++;}}}//归还队列;status = Utils_quePut(&pObj->reqQue, pReqObj, BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);pObj->reqQueCount--;}if (outFrameList.numFrames){//解码后的数据,压入到队列,供下一个link使用status = Utils_bufPutFullExt(&pObj->outObj.bufOutQue,&outFrameList);UTILS_assert(status == FVID2_SOK);sendCmd = TRUE;}if (outFrameSkipList.numFrames){status = DecLink_codecFreeProcessedFrames(pObj, &outFrameSkipList);UTILS_assert(status == DEC_LINK_S_SUCCESS);}if (inBufList.numBufs){/* Free input frames */pInQueParams = &pObj->createArgs.inQueParams;System_putLinksEmptyBufs(pInQueParams->prevLinkId,pInQueParams->prevLinkQueId, &inBufList);pObj->inBufPutCount += inBufList.numBufs;}/* Send-out the output bitbuffer */if (sendCmd == TRUE){//往下一个link发送消息,告诉下一个link数据已经准备好了System_sendLinkCmd(pObj->createArgs.outQueParams.nextLink,SYSTEM_CMD_NEW_DATA);}return FVID2_SOK;
}4.11)Utils_bufPutFullExt 就是将buff压入到输出full队列。然后提供api供外部的其它link使用;
Int32 Utils_bufPutFullExt(Utils_BufHndlExt * pHndl, FVID2_FrameList * pFrameList)
{UInt32 idx;Int32 status;UTILS_assert(pHndl != NULL);UTILS_assert(pFrameList != NULL);UTILS_assert(pFrameList->numFrames <= FVID2_MAX_FVID_FRAME_PTR);for (idx = 0; idx < pFrameList->numFrames; idx++){status =Utils_quePut(&pHndl->fullQue, pFrameList->frames[idx],BIOS_NO_WAIT);UTILS_assert(status == FVID2_SOK);}return FVID2_SOK;
}4.12)DecLink_getFullFrames 函数提供外部调用,获取解码后的帧数据。Int32 DecLink_getFullFrames(Utils_TskHndl * pTsk, UInt16 queId,FVID2_FrameList * pFrameList)
{DecLink_Obj *pObj = (DecLink_Obj *) pTsk->appData;UTILS_assert(queId < DEC_LINK_MAX_OUT_QUE);return Utils_bufGetFullExt(&pObj->outObj.bufOutQue, pFrameList,BIOS_NO_WAIT);
}在解码器初始化函数已经注冊了该回调函数linkObj.linkGetFullFrames = DecLink_getFullFrames;在下一个link调用preLink的该函数获取解码后的数据。5)IpcFrameOutM3
5.1)IpcFramesOutLink_tskMain函数中调用 IpcFramesOutLink_processFrameBufs获取解码后的数据;
Void IpcFramesOutLink_tskMain(struct Utils_TskHndl * pTsk, Utils_MsgHndl * pMsg)
{UInt32 cmd = Utils_msgGetCmd(pMsg);Bool ackMsg, done;Int32 status;IpcFramesOutLink_Obj *pObj = (IpcFramesOutLink_Obj *) pTsk->appData;if (cmd != SYSTEM_CMD_CREATE){Utils_tskAckOrFreeMsg(pMsg, FVID2_EFAIL);return;}status = IpcFramesOutLink_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;case SYSTEM_CMD_NEW_DATA:Utils_tskAckOrFreeMsg(pMsg, status);IpcFramesOutLink_processFrameBufs(pObj);IpcFramesOutLink_releaseFrameBufs(pObj);break;case IPCFRAMESOUTRTOS_LINK_CMD_SET_FRAME_RATE:{IpcOutM3Link_ChFpsParams *params;params = (IpcOutM3Link_ChFpsParams *) Utils_msgGetPrm(pMsg);IpcFramesOutLink_SetFrameRate(pObj, params);Utils_tskAckOrFreeMsg(pMsg, status);}break;case IPCFRAMESOUTRTOS_LINK_CMD_PRINT_STATISTICS:IpcFramesOutLink_printStatistics(pObj, TRUE);Utils_tskAckOrFreeMsg(pMsg, status);break;case SYSTEM_IPC_CMD_RELEASE_FRAMES:Utils_tskAckOrFreeMsg(pMsg, status);#ifdef SYSTEM_DEBUG_IPC_RTVps_printf(" %d: IPC_FRAMES_OUT   : Received Notify !!!\n",Utils_getCurTimeInMsec());
#endifIpcFramesOutLink_releaseFrameBufs(pObj);break;default:Utils_tskAckOrFreeMsg(pMsg, status);break;}}IpcFramesOutLink_delete(pObj);#ifdef SYSTEM_DEBUG_IPC_FRAMES_OUTVps_printf(" %d: IPC_FRAMES_OUT   : Delete Done !!!\n", Utils_getCurTimeInMsec());
#endifif (ackMsg && pMsg != NULL)Utils_tskAckOrFreeMsg(pMsg, status);return;
}5.2)IpcFramesOutLink_processFrameBufs获取数据;Int32 IpcFramesOutLink_processFrameBufs(IpcFramesOutLink_Obj * pObj)
{System_LinkInQueParams *pInQueParams;FVID2_FrameList bufList;FVID2_Frame *pFrameBuf = NULL;SystemIpcFrames_ListElem *pListElem;Int32 status;Int32 bufId;UInt32 curTime;FVID2_FrameList freeFrameBufList;UInt8 queId;UInt32 sendMsgToTsk = 0;UInt32 chPerQueue;IpcFramesOutLink_ChObj *pChObj;pInQueParams = &pObj->createArgs.baseCreateParams.inQueParams;bufList.numFrames = 0;//以下函数是从解码link获取数据,数据保存在bufList中;System_getLinksFullFrames(pInQueParams->prevLinkId,pInQueParams->prevLinkQueId, &bufList);freeFrameBufList.numFrames = 0;curTime = Utils_getCurTimeInMsec();if (bufList.numFrames){
#ifdef SYSTEM_DEBUG_IPC_RTVps_printf(" %d: IPC_FRAMES_OUT   : Received %d framebufs !!!\n",Utils_getCurTimeInMsec(), bufList.numFrames);
#endifUTILS_assert(bufList.numFrames <= FVID2_MAX_FVID_FRAME_PTR);pObj->stats.recvCount += bufList.numFrames;sendMsgToTsk = 0;chPerQueue =(pObj->numCh / pObj->createArgs.baseCreateParams.numOutQue);#ifdef IPC_FRAMES_IN_ENABLE_PROFILEUtils_prfTsBegin(pObj->stats.tsHandle);
#endif                                                     /* IPC_FRAMES_IN_ENABLE_PROFILE*/pObj->totalFrameCount += bufList.numFrames;for (bufId = 0; bufId < bufList.numFrames; bufId++){Bool          doFrameDrop;pFrameBuf = bufList.frames[bufId];UTILS_assert(pFrameBuf != NULL);pChObj = &pObj->chObj[pFrameBuf->channelNum];pChObj->inFrameRecvCount++;doFrameDrop = Utils_doSkipFrame(&(pChObj->frameSkipCtx));/* frame skipped due to user setting */if(doFrameDrop){pChObj->inFrameUserSkipCount++;UTILS_assert(freeFrameBufList.numFrames <FVID2_MAX_FVID_FRAME_PTR);freeFrameBufList.frames[freeFrameBufList.numFrames] =pFrameBuf;freeFrameBufList.numFrames++;pObj->stats.droppedCount++;continue;}queId = (pFrameBuf->channelNum / chPerQueue);//从队列中取一个buff,赋值给pListElemstatus =Utils_queGet(&pObj->listElemQue, (Ptr *) & pListElem, 1,BIOS_NO_WAIT);UTILS_assert(!UTILS_ISERROR(status));if (status != FVID2_SOK){/* normally this condition should not happen, if it happens* return the framebuf back to its generator */
#if 0Vps_printf(" IPC_OUT: Dropping framebuf\n");
#endifUTILS_assert(freeFrameBufList.numFrames <FVID2_MAX_FVID_FRAME_PTR);freeFrameBufList.frames[freeFrameBufList.numFrames] =pFrameBuf;freeFrameBufList.numFrames++;pObj->stats.droppedCount++;pChObj->inFrameUserSkipCount++;continue;}UTILS_assert(SYSTEM_IPC_FRAMES_GET_BUFSTATE(pListElem->bufState)== IPC_FRAMEBUF_STATE_FREE);UTILS_assert(SYSTEM_IPC_FRAMES_GET_BUFOWNERPROCID(pListElem->bufState)== System_getSelfProcId());SYSTEM_IPC_FRAMES_SET_BUFSTATE(pListElem->bufState,IPC_FRAMEBUF_STATE_ALLOCED);IpcFramesOutLink_copyFrameBufInfo2ListElem(pObj, pListElem, pFrameBuf);pFrameBuf->timeStamp = curTime;SYSTEM_IPC_FRAMES_SET_BUFSTATE(pListElem->bufState,IPC_FRAMEBUF_STATE_OUTQUE);sendMsgToTsk |= (1 << queId);//压入到ListMP,提供给IpcFrameInLink(A8)调用;status =ListMP_putTail(pObj->listMPOutHndl, (ListMP_Elem *) pListElem);UTILS_assert(status == ListMP_S_SUCCESS);pChObj->inFrameProcessCount++;}#ifdef IPC_FRAMES_IN_ENABLE_PROFILEUtils_prfTsEnd(pObj->stats.tsHandle, bufList.numFrames);
#endif                                                     /* IPC_FRAMES_IN_ENABLE_PROFILE*/if (freeFrameBufList.numFrames){System_putLinksEmptyFrames(pInQueParams->prevLinkId,pInQueParams->prevLinkQueId,&freeFrameBufList);}/* ProcessLink enable, send the notification to processLink else send to next Link *///发送通知;if (pObj->createArgs.baseCreateParams.processLink != SYSTEM_LINK_ID_INVALID){if (pObj->createArgs.baseCreateParams.notifyProcessLink){System_ipcSendNotify(pObj->createArgs.baseCreateParams.processLink);}}else{for (queId = 0; queId < pObj->createArgs.baseCreateParams.numOutQue; queId++){if ((pObj->createArgs.baseCreateParams.notifyNextLink) && (sendMsgToTsk & 0x1)){System_ipcSendNotify(pObj->createArgs.baseCreateParams.outQueParams[queId].nextLink);}sendMsgToTsk >>= 1;if (sendMsgToTsk == 0)break;}}if (pObj->createArgs.baseCreateParams.noNotifyMode){if (FALSE == pObj->prd.clkStarted){IpcFramesOutLink_startPrdObj(pObj,IPC_FRAMESOUT_LINK_DONE_PERIOD_MS,FALSE);}}}return FVID2_SOK;
}7)IpcFrameInHost(A8)
A8怎样获取到数据;7.1)IpcFramesInLink_tskMain 函数
static
Int IpcFramesInLink_tskMain(struct OSA_TskHndl * pTsk, OSA_MsgHndl * pMsg,Uint32 curState)
{UInt32 cmd = OSA_msgGetCmd(pMsg);Bool ackMsg, done;Int status = IPC_FRAMES_IN_LINK_S_SUCCESS;IpcFramesInLink_Obj *pObj = (IpcFramesInLink_Obj *) pTsk->appData;OSA_printf("%s:Entered", __func__);if (cmd != SYSTEM_CMD_CREATE){OSA_tskAckOrFreeMsg(pMsg, OSA_EFAIL);return status;}status = IpcFramesInLink_create(pObj, OSA_msgGetPrm(pMsg));OSA_tskAckOrFreeMsg(pMsg, status);if (status != OSA_SOK)return status;done = FALSE;ackMsg = FALSE;while (!done){status = OSA_tskWaitMsg(pTsk, &pMsg);if (status != OSA_SOK)break;cmd = OSA_msgGetCmd(pMsg);switch (cmd){case SYSTEM_CMD_DELETE:done = TRUE;ackMsg = TRUE;break;case SYSTEM_CMD_NEW_DATA:OSA_tskAckOrFreeMsg(pMsg, status);//OSA_assert(pObj->prd.numPendingCmd > 0);OSA_mutexLock(&pObj->prd.mutexPendingCmd);pObj->prd.numPendingCmd--;OSA_mutexUnlock(&pObj->prd.mutexPendingCmd);//从ipcOutLink中获取数据IpcFramesInLink_processFrameBufs(pObj);break;case SYSTEM_CMD_STOP:IpcFramesInLink_stop(pObj);OSA_tskAckOrFreeMsg(pMsg, status);break;default:OSA_tskAckOrFreeMsg(pMsg, status);break;}}IpcFramesInLink_delete(pObj);#ifdef SYSTEM_DEBUG_IPC_FRAMES_INOSA_printf(" %d: IPC_FRAMES_IN   : Delete Done !!!\n", OSA_getCurTimeInMsec());
#endifif (ackMsg && pMsg != NULL)OSA_tskAckOrFreeMsg(pMsg, status);return IPC_FRAMES_IN_LINK_S_SUCCESS;
}7.2)IpcFramesInLink_processFrameBufs 调用ListMP_getHead获取listElem,然后
static
Int32 IpcFramesInLink_processFrameBufs(IpcFramesInLink_Obj * pObj)
{VIDFrame_Buf *pFrameBuf;SystemIpcFrames_ListElem *pListElem;UInt32 numFrameBufs;Int32 status;UInt32 curTime;numFrameBufs = 0;curTime = OSA_getCurTimeInMsec();while (1){pListElem = ListMP_getHead(pObj->listMPOutHndl);if (pListElem == NULL)break;IpcFramesInLink_getFrameBuf(pObj, pListElem, &pFrameBuf);OSA_assert(SYSTEM_IPC_FRAMES_GET_BUFSTATE(pListElem->bufState)== IPC_FRAMEBUF_STATE_OUTQUE);pListElem->timeStamp = curTime;pListElem->frameBuf.linkPrivate = (Ptr)pListElem;SYSTEM_IPC_FRAMES_SET_BUFOWNERPROCID(pListElem->bufState);SYSTEM_IPC_FRAMES_SET_BUFSTATE(pListElem->bufState,IPC_FRAMEBUF_STATE_DEQUEUED);pObj->stats.recvCount++;//压入队列status = OSA_quePut(&pObj->outFrameBufQue,(Int32)pFrameBuf, OSA_TIMEOUT_NONE);OSA_assert(status == OSA_SOK);numFrameBufs++;}#ifdef SYSTEM_DEBUG_IPC_RTOSA_printf(" %d: IPC_FRAMES_IN   : Recevived %d framebufs !!!\n",OSA_getCurTimeInMsec(), numFrameBufs);
#endifif (numFrameBufs){if (pObj->createArgs.cbFxn){pObj->createArgs.cbFxn(pObj->createArgs.cbCtx);}}return IPC_FRAMES_IN_LINK_S_SUCCESS;
}7.3)IpcFramesInLink_getFullFrames提供给外部api使用(IpcFramesInLink_getFullVideoFrames函数)
static
Int32 IpcFramesInLink_getFullFrames(IpcFramesInLink_Obj * pObj,VIDFrame_BufList * pFrameBufList)
{UInt32 idx;Int32 status;VIDFrame_Buf *pFrame;for (idx = 0; idx < VIDFRAME_MAX_FRAME_BUFS; idx++){status =OSA_queGet(&pObj->outFrameBufQue, (Int32 *) & pFrame,OSA_TIMEOUT_NONE);if (status != OSA_SOK)break;pFrameBufList->frames[idx] = *pFrame;}pFrameBufList->numFrames = idx;return IPC_FRAMES_IN_LINK_S_SUCCESS;
}

转载于:https://www.cnblogs.com/claireyuancy/p/6782661.html

dm8148 videoM3 link源代码解析相关推荐

  1. overlayfs源代码解析

    overlayfs源代码解析 mount挂载 注册文件系统 挂载文件系统 读写目录 openat系统调用打开目录 getdents系统调用,搜索目录 创建/删除文件 创建文件 删除文件 读写文件 读/ ...

  2. Tiktok抖音最新无人互动直播项目:猜成语V4版(带语音感谢用户送礼物功能)源代码解析

    之前写的文章是关于Tiktok抖音最新无人互动直播项目:猜成语V1版源代码解析,可以参考之前的文章https://blog.csdn.net/u010978757/article/details/12 ...

  3. Spring源代码解析(收藏)

    Spring源代码解析(收藏) Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339  Spring源代码解析(二):IoC容器在Web容器中的启 ...

  4. Android源代码解析之(四)--gt;HandlerThread

    转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了AsyncTast的基本使用以及实现原理,我们知道AsyncTask内部是通过线程池和Handler实现的.通过对线程池和handler的封装实现 ...

  5. AUTOSAR从入门到精通100讲(十五)-AURIX TC3xx MCAL中Link文件解析以及代码变量定位方法详解

    一 TC3xx系列MCAL中TASKING Link文件解析以及代码变量定位方法 1 TASKING Link文件解析 1.1 DSRAM中的数据存放: 在AURIX™ 2G中(以TC387为例),每 ...

  6. Tomcat源代码解析系列

    学web也有一段时间了.为了从底层了解web应用在Tomcat中的执行,决定看一下Tomcat的源代码參见<How Tomcat works>    和大牛博客.对大体架构有了一定的了解, ...

  7. 【backtrader源码解析52】indicators部分代码解读(枯燥,仅供参考,源代码解析结束,后面会增加一个backtrader框架分析)

    指标类里面有很多不同的指标,如果对如何使用指标做策略感兴趣的话,可以考虑阅读下相关的源码和指标的用法,就仅仅指标的源代码而言,似乎没有什么可讲的.另外,关于backtrader源代码的注释,放到网站上 ...

  8. keil rt-thread link.sct 解析

    link.sct 解析 #define m_flash_config_start 0x60000000 #define m_flash_config_size 0x00001000#define m_ ...

  9. 历经一个月,终于搞定了SVM(支持向量机)-附源代码解析

    历经一个月,终于搞定了SVM(支持向量机)-附源代码解析 前言 其实整体算下来,断断续续的也得有快两个月了(原谅博主比较笨).中间也有好几次放弃,不想写这篇总结了,但是之前立下的誓言,要将学习到的每一 ...

最新文章

  1. 说说标准服务器架构(WWW+Image/CSS/JS+File+DB)
  2. 仟叶学校:武汉老师最燃演讲“人生很贵,请别浪费”
  3. 第K极值(Tyvj)
  4. “羊贵妃”没走“牛魔王”又来?牛肉价格屡创新高
  5. Step by step to create time dependent view
  6. 以色辨位的Farmer(洛谷P5832题题解,Java语言描述)
  7. shell中可能经常能看到:/dev/null 21
  8. 怎么在cmd中安装python库_cmd中安装python库时出现的错误
  9. js系列教程9-表单元素全解
  10. Java 垃圾收集策略、垃圾分代回收算法、垃圾回收运作流程
  11. PAIP.在程序中设置壁纸墙纸
  12. js-纳税人识别码验证
  13. 重置计算机的网络配置是什么意思,电脑怎么重置网络设置 win10网络重置后连不上网怎么办...
  14. pmf源解析_科研进展 | 不同燃烧排放的一次有机物源谱特征及其在源解析中的应用...
  15. 乱记春秋-或跃在渊 (苏阳飘零记)
  16. 微信开发者工具button,input鼠标点击坐标偏移
  17. 实验二:交换机基本配置
  18. JVM 中一次完整的 GC 流程是什么样子的,对象如何晋升到老年代,
  19. 机器学习实战教程(八):支持向量机原理篇
  20. 微信公众号:关注取关事件

热门文章

  1. ibatis This SQL map does not contain a MappedStatement
  2. Oracle 收购Sun之后的演义:IBM 和SAP何去何从
  3. 飞船向上飞pygame用k_up_十分钟就能用Python教你开发出一个迷你打飞机的游戏
  4. pythondef元组参数传递_Python参数传递(传值传引用)
  5. 欧奈尔4个经典形态_股票K线图基础知识:图解4大经典K线组合形态
  6. ubuntu14.04安装arm-linux-gcc,Ubuntu14.04下arm-linux-gcc交叉编译环境搭建
  7. pip matplotlib 使用镜像源,pytorch 1.5 cpu
  8. 3-25Pytorch与张量填充3-26Pytorch与傅里叶变化
  9. java http请求 工具类_java模拟http请求调用远程接口工具类
  10. if判断用户名 linux,Shell脚本IF条件判断和判断条件总结