zoukankan      html  css  js  c++  java
  • dm8148 videoM3 link源代码解析

    样例:从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_linuxlinkssystem的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 !!!
    ", 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 !!!
    ", 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 !!!
    ",
                               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 !!!
    ",
                   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 !!!
    ",
                   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("
     IPCBITSOUTLINK: WARNING: User is asking for %d buffers per CH. But max allowed is %d. 
    "
                    " Over riding user requested with max allowed 
    
    ",
                    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 !!!
    ",
                   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
    ", 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传递到下一个link
        status = 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_RT
                    OSA_printf(" IPC_OUT: Dropping bitbuf
    ");
    #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 函数
    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) 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 函数;
    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.c
    
    Int32 System_init()
    {
        Int32 status = FVID2_SOK;
    
    #ifdef SYSTEM_DEBUG
        Vps_printf(" %d: SYSTEM  : System Video Init in progress !!!
    ",
                   Utils_getCurTimeInMsec());
    #endif
    
    #ifdef SYSTEM_DEBUG
        Vps_printf(" %d: SYSTEM  : System Video Init Done !!!
    ", 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 !!!
    ", 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 !!!
    ",
                   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 declink
    
    4.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 处理解码后的数据,发给下一个link
    
    
    static 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_RT
                    Vps_printf(" %d: IPC_FRAMES_OUT   : Received Notify !!!
    ",
                               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 !!!
    ", 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 !!!
    ",
                       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
    ");
    #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 函数
    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_IN
        OSA_printf(" %d: IPC_FRAMES_IN   : Delete Done !!!
    ", 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,然后
    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_RT
        OSA_printf(" %d: IPC_FRAMES_IN   : Recevived %d framebufs !!!
    ",
                   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函数)
    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;
    }
    
    
    
  • 相关阅读:
    工作中遇到的java 内存溢出,问题排查
    java线上内存溢出问题排查步骤
    性能测试-java内存溢出问题排查
    164 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 04 终止finally执行的方法
    163 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 03 使用多重catch结构处理异常
    162 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 02 使用try-catch结构处理异常
    161 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 01 try-catch-finally简介
    160 01 Android 零基础入门 03 Java常用工具类01 Java异常 03 异常处理简介 01 异常处理分类
    159 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 02 异常分类
    158 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 01 什么是异常?
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6782661.html
Copyright © 2011-2022 走看看