dm81xx link記憶體分配及link之間資料傳遞

smilestone322發表於2015-04-16

每個link都有管理著自己的佇列,相當於一個記憶體池,一個輸入佇列,一個輸出佇列,當一個link處理完後,將資料放在自己的輸出佇列後,通過傳送通知的方式告訴下一個link取資料,這個地方涉及到多核通訊;

Link Output Queue – is the queue which is used by another link (via the inter link API) to exchange frames with that link

 

下面是IPCBitsOutLink:

Link資料結構:

typedef struct IpcBitsOutLink_Obj {

   UInt32 tskId;              /**< IpcBitsOutLink instance linkID */

   OSA_TskHndl tsk;           /**< IpcBitsInLink task handle */

   IpcBitsOutLinkHLOS_CreateParams createArgs;

                              /**< Application passed create Args */

   ListMP_Handle listMPOutHndl; /**< IPC SystemIpcBits_ListElem full queue */

   ListMP_Handle listMPInHndl;  /**< IPC SystemIpcBits_ListElem empty queue */

   GateMP_Handle gateMPInHndl;  /**< IPC Gate for listMPOutHndl */

   GateMP_Handle gateMPOutHndl; /**< IPC Gate for listMPInHndl */

   SystemIpcBits_ListElem *listElem[SYSTEM_IPC_BITS_MAX_LIST_ELEM];

                                /**< Array of listElems populated at creat time */

   OSA_QueHndl listElemQue[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];

                                    /**< Queue holding free listElems */

   Ptr         bitBufPoolPtr[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];

                                /**< Pool bit buffer pointer . */

   UInt32 bitBufPoolSize[IPC_BITS_OUT_MAX_NUM_ALLOC_POOLS];

                                /**< Size of Pools bitstream buffer. */

   Bitstream_BufList freeBitBufList; /**< BitStream buffers to be freed  */

   IpcBitsOutStats stats;            /**< Statistics accumulation member */

   IpcBitsOutLink_OutQueueInfo outQueInfo; /**< Output BitStream queue info   */

   volatile Bool startProcessing;    /**< Flag to control start of processing */

 

} IpcBitsOutLink_Obj;

 

typedef struct

{

   OSA_TskHndl                *pTsk;

   System_GetLinkInfoCb            getLinkInfo;

   /**<  Function that returns the LINKs output channel configurations */

} System_LinkObj;

 

//初始化IpcBitsOutLink的資料結構

static Int IpcBitsOutLink_createOutObj(IpcBitsOutLink_Obj * pObj)

{

   Int status = OSA_SOK;

   Int32 poolId, elemId, bufId;

   IHeap_Handle srBitBufHeapHandle;

   UInt32 bufSize, numBufs, totBufSize, cacheLineSize;

   const UInt32 srIndex = SYSTEM_IPC_SR_CACHED;

   Ptr   phyAddr;

 

   ipcbitsoutlink_populate_outbuf_pool_size_info(&pObj->createArgs,

                                                 &pObj->createArgs.inQueInfo,

                                                 &pObj->outQueInfo);

elemId = 0;

//共享區域獲取heap的控制程式碼,從堆上分配記憶體;

   srBitBufHeapHandle =SharedRegion_getHeap(srIndex);

OSA_assert(srBitBufHeapHandle != NULL);

//獲取cache的一行的size

   cacheLineSize = SharedRegion_getCacheLineSize(srIndex);

   for (poolId = 0; poolId < pObj->outQueInfo.allocPoolInfo.numPools; poolId++)

{

    //建立一個佇列

       status = OSA_queCreate(&pObj->listElemQue[poolId],

                              SYSTEM_IPC_BITS_MAX_LIST_ELEM);

       OSA_assert(status == OSA_SOK);

       bufSize =

           OSA_align(pObj->outQueInfo.allocPoolInfo.bufPoolInfo[poolId].

                      bufSize, cacheLineSize);

       numBufs = pObj->outQueInfo.allocPoolInfo.bufPoolInfo[poolId].numBufs;

       totBufSize = bufSize * numBufs;

       OSA_printf ("###Bit buff of size from the SR # %d : %d\n", srIndex, totBufSize);

      //分配佇列的記憶體,

       pObj->bitBufPoolPtr[poolId] =

           Memory_alloc(srBitBufHeapHandle, totBufSize, cacheLineSize, NULL);

       OSA_assert(pObj->bitBufPoolPtr[poolId] != NULL);

       OSA_printf("IPC_BITSOUT:BitBuffer Alloc.PoolID:%d,Size:0x%X",

                   poolId,totBufSize);

      //虛擬記憶體到實體記憶體對映

       phyAddr = IpcBitsOutLink_MapUsrVirt2Phy(pObj->bitBufPoolPtr[poolId]);

       pObj->bitBufPoolSize[poolId] = totBufSize;

      //給佇列中的每個元素分配記憶體

       for (bufId = 0; bufId < numBufs; bufId++)

       {

           SystemIpcBits_ListElem *listElem;

           OSA_assert(elemId < SYSTEM_IPC_BITS_MAX_LIST_ELEM);

           listElem = pObj->listElem[elemId];

           elemId++;

           SYSTEM_IPC_BITS_SET_BUFOWNERPROCID(listElem->bufState);

           SYSTEM_IPC_BITS_SET_BUFSTATE(listElem->bufState,

                                        IPC_BITBUF_STATE_FREE);

           listElem->bitBuf.addr =

               (Ptr) (((UInt32) (pObj->bitBufPoolPtr[poolId])) +

                      (bufSize * bufId));

           if (phyAddr)

           {

               listElem->bitBuf.phyAddr =

                   (UInt32) ((UInt32) (phyAddr) +  (bufSize * bufId));

           }

           listElem->bitBuf.allocPoolID = poolId;

           listElem->bitBuf.bufSize = bufSize;

           listElem->bitBuf.fillLength = 0;

           listElem->bitBuf.mvDataFilledSize = 0;

           listElem->bitBuf.startOffset = 0;

           listElem->bitBuf.bottomFieldBitBufSize = 0;

           listElem->bitBuf.doNotDisplay = FALSE;

           listElem->srBufPtr = SharedRegion_getSRPtr(listElem->bitBuf.addr,

                                                      srIndex);

           OSA_assert(listElem->srBufPtr != IPC_LINK_INVALID_SRPTR);

     //將元素壓入到佇列

            status =

               OSA_quePut(&pObj->listElemQue[poolId], (Int32) listElem,

                          OSA_TIMEOUT_NONE);

           OSA_assert(status == OSA_SOK);

       }

   }

   return status;

}

// IpcBitsOutLink_getEmptyVideoBitStreamBufs函式的作用是從IpcBitsOutLink的佇列中獲取一個空的buff

Int32 IpcBitsOutLink_getEmptyVideoBitStreamBufs(UInt32 linkId,

                                               Bitstream_BufList *bufList,

                                               IpcBitsOutLinkHLOS_BitstreamBufReqInfo *reqInfo)

{

   OSA_TskHndl * pTsk;

   IpcBitsOutLink_Obj * pObj;

   Int status;

 

   OSA_assert(bufList != NULL);

   if (!((linkId  >= SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0)

         &&

         (linkId  < (SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0 + IPC_BITS_OUT_LINK_OBJ_MAX))))

   {

       return IPC_BITSOUT_LINK_E_INVALIDLINKID;

   }

   pTsk = System_getLinkTskHndl(linkId);

   pObj = pTsk->appData;

   bufList->numBufs = 0;

   if (pObj->startProcessing)

   {

       IpcBitsOutLink_releaseBitBufs(pObj);

       status = IpcBitsOutLink_getEmptyBufs(pObj,bufList,reqInfo);

   }

   else

   {

       status = IPC_BITSOUT_LINK_S_SUCCESS;

   }

   return status;

}

// IpcBitsOutLink_putFullVideoBitStreamBufs函式的作用是將Bitstream_BufList資料傳遞到下一個link

Int32 IpcBitsOutLink_putFullVideoBitStreamBufs(UInt32 linkId,

                                              Bitstream_BufList *bufList)

{

   OSA_TskHndl * pTsk;

   IpcBitsOutLink_Obj * pObj;

   Int status;

 

   OSA_assert(bufList != NULL);

   if (!((linkId  >= SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0)

         &&

         (linkId  < (SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0 + IPC_BITS_OUT_LINK_OBJ_MAX))))

   {

       return IPC_BITSOUT_LINK_E_INVALIDLINKID;

}

//通過linkId獲取link任務的資料

pTsk = System_getLinkTskHndl(linkId);

//獲取linkappData,將pObj指向該linkappData記憶體地址;

   pObj = pTsk->appData;

   status = IpcBitsOutLink_putFullBufs(pObj,bufList);

   return status;

}

 

//資料如何從IpcBitsOutLink傳遞到VideoM3

static

Int32 IpcBitsOutLink_putFullBufs(IpcBitsOutLink_Obj *pObj,

                                Bitstream_BufList *pBufList)

{

   SystemIpcBits_ListElem *pListElem;

   Bitstream_Buf *pBitBuf;

   Bitstream_BufList freeBitBufList;

   Bool putDone = FALSE;

   Int32 bufId;

   UInt32 curTime;

 

   freeBitBufList.numBufs = 0;

   curTime = OSA_getCurTimeInMsec();

   for (bufId = 0; bufId < pBufList->numBufs; bufId++)

   {

       pBitBuf = pBufList->bufs[bufId];

          curTime = pBitBuf->timeStamp = Get_timeStamp(pBitBuf->channelNum); // for playback side avsync support

                 // OSA_printf(" A8 IPC_BITS_OUT : TS = %d !!!\n", pBitBuf->timeStamp);  //test1

      //獲取pBufList的每一個元素

       pListElem = (SystemIpcBits_ListElem *)pBitBuf;

      //判斷指標是否一致

       OSA_assert(SharedRegion_getPtr(pListElem->srBufPtr) ==

                  pBitBuf->addr);

     //如果資料長度為0,直接將資料歸還到佇列

       if (0 == pBitBuf->fillLength)

       {

           /* filled length of 0 indicates application

            * did not fill any data in this buffer.

            * Free it immediately */

#ifdef SYSTEM_DEBUG_IPC_RT

               OSA_printf(" IPC_OUT: Dropping bitbuf\n");

#endif

 

           OSA_assert(freeBitBufList.numBufs <

                      VIDBITSTREAM_MAX_BITSTREAM_BUFS);

     //歸還buff

           freeBitBufList.bufs[freeBitBufList.numBufs] = pBitBuf;

           freeBitBufList.numBufs++;

           pObj->stats.droppedCount++;

           continue;

       }

       else

       {

           pObj->stats.recvCount++;

           OSA_assert(SYSTEM_IPC_BITS_GET_BUFSTATE(pListElem->bufState)

                      == IPC_BITBUF_STATE_FREE);

           OSA_assert(SYSTEM_IPC_BITS_GET_BUFOWNERPROCID(pListElem->bufState)

                      == System_getSelfProcId());

           pListElem->ipcPrivData = (Ptr) curTime;

           SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState,

                                        IPC_BITBUF_STATE_ALLOCED);

         //將資料傳遞給下一個link,ListMP :在多個核之間共享一個List指標佇列;

           IpcBitsOutLink_listMPPut(pObj, pListElem);

           putDone = TRUE;

       }

   }

   if (freeBitBufList.numBufs)

   {

       IpcBitsOutLink_putEmptyBufs(pObj, &freeBitBufList);

   }

 

   if (putDone && (pObj->createArgs.baseCreateParams.notifyNextLink))

{

//給下一個link傳送通知,

這裡是給videoM3ipcBitsInLink傳送訊息

       System_ipcSendNotify(pObj->createArgs.baseCreateParams.outQueParams[0].

                            nextLink);

   }

   if (!putDone)

   {

       pObj->stats.numNoFullBufCount++;

       if ((pObj->stats.numNoFullBufCount % IPC_BITSOUT_STATS_WARN_INTERVAL) == 0)

       {

           #ifdef DEBUG_IPC_BITS

           OSA_printf("IPCBITSOUT:!!!WARNING.!!! NO FULL BUF AVAILABLE. OCCURENCE COUNT:[%d]",

                      pObj->stats.numNoFullBufCount);

           #endif

       }

   }

   return IPC_BITSOUT_LINK_S_SUCCESS;

}

 

//

static

Int32 IpcBitsOutLink_listMPPut(IpcBitsOutLink_Obj * pObj,

                              SystemIpcBits_ListElem * pListElem)

{

   Int32 status = IPC_BITSOUT_LINK_S_SUCCESS;

 

   SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState, IPC_BITBUF_STATE_OUTQUE);

IpcBitsOutLink_doPrePutCacheOp(pObj, pListElem);

//掛在link的佇列末尾

   status = ListMP_putTail(pObj->listMPOutHndl, (ListMP_Elem *) pListElem);

   OSA_assert(status == ListMP_S_SUCCESS);

   return IPC_BITSOUT_LINK_S_SUCCESS;

}

 

pcBitsInVideoM3Id

 

Main函式:link起來後等待訊息,

Void IpcBitsInLink_tskMain(struct Utils_TskHndl * pTsk, Utils_MsgHndl * pMsg)

{

    UInt32 cmd = Utils_msgGetCmd(pMsg);

    Bool ackMsg, done;

    Int32 status;

    IpcBitsInLink_Obj *pObj = (IpcBitsInLink_Obj *) pTsk->appData;

 

    if (cmd != SYSTEM_CMD_CREATE)

    {

        Utils_tskAckOrFreeMsg(pMsg, FVID2_EFAIL);

        return;

    }

 

    status = IpcBitsInLink_create(pObj, Utils_msgGetPrm(pMsg));

 

    Utils_tskAckOrFreeMsg(pMsg, status);

 

    if (status != FVID2_SOK)

        return;

 

    done = FALSE;

    ackMsg = FALSE;

 

    while (!done)

    {

        status = Utils_tskRecvMsg(pTsk, &pMsg, BIOS_WAIT_FOREVER);

        if (status != FVID2_SOK)

            break;

 

        cmd = Utils_msgGetCmd(pMsg);

 

        switch (cmd)

        {

            case SYSTEM_CMD_DELETE:

                done = TRUE;

                ackMsg = TRUE;

                break;

      //等待A8 IpcBitsOutLink,傳送訊號,

            case SYSTEM_CMD_NEW_DATA:

                Utils_tskAckOrFreeMsg(pMsg, status);

                IpcBitsInLink_processBitBufs(pObj);

                break;

            case SYSTEM_CMD_STOP:

                IpcBitsInLink_stop(pObj);

                Utils_tskAckOrFreeMsg(pMsg, status);

                break;

            default:

                Utils_tskAckOrFreeMsg(pMsg, status);

                break;

        }

    }

 

    IpcBitsInLink_delete(pObj);

 

#ifdef SYSTEM_DEBUG_IPC_BITS_IN

    Vps_printf(" %d: IPC_BITS_IN   : Delete Done !!!\n", Utils_getCurTimeInMsec());

#endif

 

    if (ackMsg && pMsg != NULL)

        Utils_tskAckOrFreeMsg(pMsg, status);

 

    return;

}

 

訊號的傳送,A8IpcBitsOutLink中呼叫它傳送訊號;

Void IpcBitsInLink_notifyCb(Utils_TskHndl * pTsk)

{

    IpcBitsInLink_Obj *pObj = (IpcBitsInLink_Obj *) pTsk->appData;

    IpcBitsInLink_reconfigPrdObj(pObj, IPC_BITS_IN_LINK_DONE_PERIOD_MS);

    Utils_tskSendCmd(pTsk, SYSTEM_CMD_NEW_DATA);

}

 

//

Int32 IpcBitsInLink_processBitBufs(IpcBitsInLink_Obj * pObj)

{

    Bitstream_Buf *pBitBuf;

    SystemIpcBits_ListElem *pListElem;

    UInt32 numBitBufs;

    Int32 status;

    UInt32 curTime;

 

    numBitBufs = 0;

    curTime = Utils_getCurTimeInMsec();

    while (1)

{

  //獲取Buff

        pListElem = ListMP_getHead(pObj->listMPOutHndl);

        if (pListElem == NULL)

            break;

       //轉化到Bitbuf

        IpcBitsInLink_getBitBuf(pObj, pListElem, &pBitBuf);

        UTILS_assert(SYSTEM_IPC_BITS_GET_BUFSTATE(pListElem->bufState)

                     == IPC_BITBUF_STATE_OUTQUE);

        pBitBuf->reserved[0] = curTime;

        SYSTEM_IPC_BITS_SET_BUFOWNERPROCID(pListElem->bufState);

        SYSTEM_IPC_BITS_SET_BUFSTATE(pListElem->bufState,

                                     IPC_BITBUF_STATE_DEQUEUED);

        pObj->stats.recvCount++;

       //壓入到佇列,同一個核使用Utils_quePut函式

        status = Utils_quePut(&pObj->outBitBufQue, pBitBuf, BIOS_NO_WAIT);

        UTILS_assert(status == FVID2_SOK);

       

        numBitBufs++;

    }

 

#ifdef SYSTEM_DEBUG_IPC_RT

    Vps_printf(" %d: IPC_BITS_IN   : Recevived %d bitbufs !!!\n",

               Utils_getCurTimeInMsec(), numBitBufs);

#endif

//往下一個link傳送資料

    if (numBitBufs && pObj->createArgs.baseCreateParams.notifyNextLink)

    {

        UTILS_assert(pObj->createArgs.baseCreateParams.numOutQue == 1);

        System_sendLinkCmd(pObj->createArgs.baseCreateParams.outQueParams[0].

                           nextLink, SYSTEM_CMD_NEW_DATA);

    }

 

    return IPC_BITS_IN_LINK_S_SUCCESS;

}

 

相關文章