dm8148 videoM3 link源码解析

来源:互联网 发布:mac g5游戏免费完整版 编辑:程序博客网 时间:2024/06/05 20:24

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

dm8148 link之间数据传递1)在A8上调用IpcBitsOutLink_getEmptyVideoBitStreamBufs从IpcBitsOutLink获取buff;然后调用IpcBitsOutLink_putFullVideoBitStreamBufs将数据送入到IpcBitsOutLink;1.1)IpcBitsOutLinkA8调用IpcBitsOutLink将压缩数据(jpeg,mpeg4,h264)送入到videoM3;首先在/src_linux\links\system的system_common.c中调用IpcBitsOutLink_init函数;//system_init函数在app初始化时调用;Int32 System_init(){    Int32         status;    #ifdef SYSTEM_DEBUG    OSA_printf ( " %u: SYSTEM: System Common Init in progress !!!\n", OSA_getCurTimeInMsec());    #endif    memset(&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_DEBUG    OSA_printf ( " %u: SYSTEM: System Common Init Done !!!\n", OSA_getCurTimeInMsec());    #endif    return 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);//初始化ListMP        IpcBitsOutLink_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_RT                OSA_printf(" %d: IPC_BITS_OUT   : Received Notify !!!\n",                           OSA_getCurTimeInMsec());#endif                IpcBitsOutLink_releaseBitBufs(pObj);                break;            case SYSTEM_CMD_START://link start                IpcBitsOutLink_start(pObj);                OSA_tskAckOrFreeMsg(pMsg, status);                break;            case SYSTEM_CMD_STOP://link stop                IpcBitsOutLink_stop(pObj);                OSA_tskAckOrFreeMsg(pMsg, status);                break;            default:                OSA_tskAckOrFreeMsg(pMsg, status);                break;        }    }    IpcBitsOutLink_delete(pObj);#ifdef SYSTEM_DEBUG_IPC_BITS_OUT    OSA_printf(" %d: IPC_BITS_OUT   : Delete Done !!!\n",               OSA_getCurTimeInMsec());#endif    if (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_IPC    OSA_printf(" %d: IPC_BITS_OUT   : Create in progress !!!\n",               OSA_getCurTimeInMsec());#endif    memcpy(&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_IPC    OSA_printf(" %d: IPC_BITS_OUT   : Create Done !!!\n",               OSA_getCurTimeInMsec());#endif    return 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传递IpcBitsOutLinkInt32 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传递到下一个link    status = IpcBitsOutLink_putFullBufs(pObj,bufList);    return status;}1.7)IpcBitsOutLink_putFullBufs 将buff传递到下一个link,注意IpcBitsOutLink_listMPPut,将buff压入到输出队列,然后发送System_ipcSendNotify 发送通知,通知下一个link来取数据;staticInt32 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_RT                OSA_printf(" IPC_OUT: Dropping bitbuf\n");#endif            OSA_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_BITS            OSA_printf("IPCBITSOUT:!!!WARNING.!!! NO FULL BUF AVAILABLE. OCCURENCE COUNT:[%d]",                       pObj->stats.numNoFullBufCount);            #endif        }    }    return IPC_BITSOUT_LINK_S_SUCCESS;}1.8)IpcBitsOutLink_listMPPut 函数staticInt32 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) link    IpcBitsOutLink_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 函数;staticInt32 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_DEBUG    Vps_printf(" %d: SYSTEM  : System Video Init in progress !!!\n",               Utils_getCurTimeInMsec());#endif#ifdef SYSTEM_DEBUG    Vps_printf(" %d: SYSTEM  : System Video Init Done !!!\n", Utils_getCurTimeInMsec());#endif    IpcOutM3Link_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_IN    Vps_printf(" %d: IPC_BITS_IN   : Delete Done !!!\n", Utils_getCurTimeInMsec());#endif    if (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;//转化为bitbuff        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++;//压入到输出队列;        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;}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_RESET        DECLINK_INTERNAL_ERROR_LOG(DEC_LINK_E_INVALIDCMD,                                   "Link create should be first cmd."                                   "Received Cmd:%d", cmd);        #endif        Utils_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 frame                bufList.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 same            codec. 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_RESET                   UTILS_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)IpcFrameOutM35.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_RT                Vps_printf(" %d: IPC_FRAMES_OUT   : Received Notify !!!\n",                           Utils_getCurTimeInMsec());#endif                IpcFramesOutLink_releaseFrameBufs(pObj);                break;            default:                Utils_tskAckOrFreeMsg(pMsg, status);                break;        }    }    IpcFramesOutLink_delete(pObj);#ifdef SYSTEM_DEBUG_IPC_FRAMES_OUT    Vps_printf(" %d: IPC_FRAMES_OUT   : Delete Done !!!\n", Utils_getCurTimeInMsec());#endif    if (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_RT        Vps_printf(" %d: IPC_FRAMES_OUT   : Received %d framebufs !!!\n",                   Utils_getCurTimeInMsec(), bufList.numFrames);#endif        UTILS_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_PROFILE        Utils_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,赋值给pListElem            status =                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 0                Vps_printf(" IPC_OUT: Dropping framebuf\n");#endif                UTILS_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_PROFILE        Utils_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 函数staticInt 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_IN    OSA_printf(" %d: IPC_FRAMES_IN   : Delete Done !!!\n", OSA_getCurTimeInMsec());#endif    if (ackMsg && pMsg != NULL)        OSA_tskAckOrFreeMsg(pMsg, status);    return IPC_FRAMES_IN_LINK_S_SUCCESS;}7.2)IpcFramesInLink_processFrameBufs 调用ListMP_getHead获取listElem,然后staticInt32 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_RT    OSA_printf(" %d: IPC_FRAMES_IN   : Recevived %d framebufs !!!\n",               OSA_getCurTimeInMsec(), numFrameBufs);#endif    if (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函数)staticInt32 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;}
0 0
原创粉丝点击