dm81xx link内存分配及link之间数据传递

每个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;

}

 

你可能感兴趣的:(TI,8148,dm8148,平台软件开发)