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;
    }
    
    
    
  • 相关阅读:
    Python 3学习 ——目录 Json Pickle
    Python 3 学习——函数扩展and迭代器生成器装饰器
    Python 3 学习——深浅拷贝以及函数
    Python 3 学习的第七小节——Linux-Ubuntu
    Python 3 —— 文件操作
    Python 3 学习的第五小节——字符编码与三级菜单实践
    关于PHP代码复用‘traits’的一段代码
    一个将对象彻底冻结的函数
    详解vue-cli脚手架项目-package.json
    关于element-ui日期选择器disabledDate使用心得
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6782661.html
Copyright © 2011-2022 走看看