TI中文支持网
TI专业的中文技术问题搜集分享网站

请问DVR RDK中displayLink的callback函数是怎么被调用起来的?

是周期性调用吗?
具体代码在哪?

谢谢!

Ternence_Hsu:

你好;

       你这里指的回调函数,具体是说的什么地方的程序?

       你是指dispaly link 的运行的源码吗?

       dvr_rdk/mcfw/src_bios6/links_m3vpss/display 

       是这样代码吗?

       

lu kingkuang:

回复 Chris Meng:

是的,谢谢!

如下代码说明:

/* Create capture driver */Int32 CaptureLink_drvCreateInst(CaptureLink_Obj * pObj, UInt16 instId){

    …

   pVipCreateArgs->periodicCallbackEnable = TRUE;

   …

}

但是我在《HDVPSS_UserGuide》手册中没有找到Vsync相关说明。

而且还是不能完全明白displayLink的数据接收处理机制,还请进一步指导:

(1) displayLink的前一个Link(m3vpssInLink)通过下面的代码给displayLink发送“SYSTEM_CMD_NEW_DATA”消息指示:

           System_sendLinkCmd(pObj->createArgs.baseCreateParams.outQueParams[i].nextLink, SYSTEM_CMD_NEW_DATA);

          但是为何displayLink内没有“SYSTEM_CMD_NEW_DATA”对应处理?

          而是对“ DISPLAY_LINK_CMD_DO_DEQUE”消息的处理:

          Int32 DisplayLink_tskRun(DisplayLink_Obj * pObj, Utils_TskHndl * pTsk,                         Utils_MsgHndl ** pMsg, Bool * done, Bool * ackMsg)         {

                   …

                    case DISPLAY_LINK_CMD_DO_DEQUE:                             status = DisplayLink_drvProcessData(pObj);

                    …

           }

          “ DISPLAY_LINK_CMD_DO_DEQUE”消息是由下面的回调函数发出的:

           Int32 DisplayLink_drvFvidCb(FVID2_Handle handle, Ptr appData, Ptr reserved)           {               …                Utils_tskSendCmd(&pObj->tsk, DISPLAY_LINK_CMD_DO_DEQUE);

               …

          }

(2) displayLink通过下面三种情况获取帧数据,不是很理解,请帮忙解释一下三种情况:         

Int32 DisplayLink_drvProcessData(DisplayLink_Obj * pObj){    FVID2_FrameList frameList;    FVID2_FrameList freeFrameList;    FVID2_FrameList displayFrameList;    UInt32 freeFrameNum, elaspedTime;    System_LinkInQueParams *pInQueParams;    FVID2_Frame *pFrame;    Int32 status;    UInt32 latency;    Int i;    UInt32 frameIdx;    elaspedTime = Utils_getCurTimeInMsec() – pObj->startTime;    if ((elaspedTime – pObj->prevTime) > 24 * 60 * 60 * 1000)    {        DisplayLink_drvPrintRtStatus(pObj, elaspedTime);        pObj->prevTime = elaspedTime;    }    if(pObj->displayInstId==0)    {        System_displayUnderflowCheck(FALSE);    }    do    {        UInt32 freeQueueId;       //*情况一:*/ /* dequeue all completed frames *        status = DisplayLink_drvDeQueue(pObj,&freeFrameList,                                        &freeQueueId);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : drvDeQueue Frames %d  !!!\n",    Utils_getCurTimeInMsec(), freeFrameList.numFrames);#endif        if (freeFrameList.numFrames)        {            pObj->inFramePutCount += freeFrameList.numFrames;            UTILS_assert(freeQueueId <                         pObj->createArgs.numInputQueues);            pInQueParams = &pObj->createArgs.inQueParams[freeQueueId];            System_putLinksEmptyFrames(pInQueParams->prevLinkId,                                       pInQueParams->prevLinkQueId, &freeFrameList);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : 1st putLinksEmptyFrames %d  !!!\n",    Utils_getCurTimeInMsec(), freeFrameList.numFrames);#endif        }    } while (status == FVID2_SOK);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : numInputQueues = %d , curActiveQueue =  %d !!!\n",    Utils_getCurTimeInMsec(), pObj->createArgs.numInputQueues,pObj->curActiveQueue);#endif    /*情况二:*//* Free frames queued in inactive queues immediately */    for (i = 0; i < pObj->createArgs.numInputQueues;i++)    {        if (i != pObj->curActiveQueue)        {            frameList.numFrames = 0;            pInQueParams =              &pObj->createArgs.inQueParams[i];                        System_getLinksFullFrames(pInQueParams->prevLinkId,                                      pInQueParams->prevLinkQueId,                                      &frameList);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : 1st getLinksFullFrames %d  !!!\n",    Utils_getCurTimeInMsec(), frameList.numFrames);#endif            if (frameList.numFrames)            {                pObj->inFrameGetCount += frameList.numFrames;                pObj->inFramePutCount += frameList.numFrames;                System_putLinksEmptyFrames(pInQueParams->prevLinkId,                                           pInQueParams->prevLinkQueId,                                           &frameList);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : 2nd putLinksEmptyFrames %d  !!!\n",    Utils_getCurTimeInMsec(), freeFrameList.numFrames);#endif            }        }    }    UTILS_assert(pObj->curActiveQueue < pObj->createArgs.numInputQueues);    pInQueParams = &pObj->createArgs.inQueParams[pObj->curActiveQueue];       /*情况三:*/ /* que frames if any */    System_getLinksFullFrames(pInQueParams->prevLinkId,                              pInQueParams->prevLinkQueId, &frameList);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : 2st getLinksFullFrames %d  !!!\n",    Utils_getCurTimeInMsec(), frameList.numFrames);#endif    pObj->inFrameGetCount += frameList.numFrames;    freeFrameNum = 0;    DisplayLink_drvLock(pObj);    frameIdx = 0;    while((pObj->maxQueueCount)          &&          (frameIdx < frameList.numFrames))    {        pFrame = frameList.frames[frameIdx];        frameIdx++;        UTILS_assert(pFrame != NULL);        if (pFrame->channelNum == pObj->curDisplayChannelNum)        {            Bool frameReject;            UInt32 pitch0,pitch1;            pitch0 = pObj->displayFormat.pitch[0];            pitch1 = pObj->displayFormat.pitch[1];            if (DisplayLink_drvDoInputPitchDoubling(pObj))            {                pitch0 /= 2;                pitch1 /= 2;            }            UTILS_assert(DISPLAY_LINK_BLANK_FRAME_CHANNEL_NUM !=                         pFrame->channelNum);            pFrame->addr[1][0] =                (UInt8 *) pFrame->addr[0][0] + pitch0;            pFrame->addr[1][1] =                (UInt8 *) pFrame->addr[0][1] + pitch1;#ifdef SYSTEM_DEBUG_DISPLAY_RT            Vps_printf(" %d: DISPLAY: Queue %d frames\n", Utils_getCurTimeInMsec(),                       displayFrameList.numFrames);#endif            latency = Utils_getCurTimeInMsec() – pFrame->timeStamp;            if(latency>pObj->maxLatency)                pObj->maxLatency = latency;            if(latency<pObj->minLatency)                pObj->minLatency = latency;            /* queue frame for display */            displayFrameList.numFrames = 0;            DisplayLink_drvSetFrameInfo(pObj,                                        &pFrame,                                        &frameReject);            if (pFrame)            {                if (frameReject)                {                    UTILS_assert(freeFrameNum <                                 UTILS_ARRAYSIZE(freeFrameList.frames));                    /* error in queing to display, instead of asserting                        release the frame and continue                    */                    freeFrameList.frames[freeFrameNum] = pFrame;                    freeFrameNum++;                }                else                {                    displayFrameList.frames[displayFrameList.numFrames] = pFrame;                    displayFrameList.numFrames++;                    displayFrameList.perListCfg = NULL;                    DisplayLink_drvHandleDynamicPitchChange(pObj,&displayFrameList);                    DisplayLink_validateFrameList(pObj,                                                  &displayFrameList);                    pObj->queueCount += displayFrameList.numFrames;                    pObj->numBufsInDriver++;                    status = FVID2_queue(pObj->displayHndl,                                         &displayFrameList,                                         0);                    pObj->maxQueueCount–;                    if(status!=FVID2_SOK)                    {                         Vps_rprintf(" %d: DISPLAY (%d): Queue to driver failed !!!\n", Utils_getCurTimeInMsec(),                               pObj->tskId);                        UTILS_assert(freeFrameNum <                                     UTILS_ARRAYSIZE(freeFrameList.frames));                        /* error in queing to display, instead of asserting                            release the frame and continue                        */                        freeFrameList.frames[freeFrameNum] = pFrame;                        freeFrameNum++;                        DisplayLink_drvFreeFrameInfo(pObj,                                                     &displayFrameList);                    }                }           }        }        else        {            UTILS_assert(freeFrameNum <                         UTILS_ARRAYSIZE(freeFrameList.frames));            freeFrameList.frames[freeFrameNum] = pFrame;            freeFrameNum++;        }    }    DisplayLink_drvUnlock(pObj);    for (i = frameIdx; i < frameList.numFrames;i++)    {        UTILS_assert(freeFrameNum < UTILS_ARRAYSIZE(freeFrameList.frames));        freeFrameList.frames[freeFrameNum] = frameList.frames[i];        freeFrameNum++;    }    if (freeFrameNum)    {        freeFrameList.numFrames = freeFrameNum;        pObj->inFramePutCount += freeFrameList.numFrames;        System_putLinksEmptyFrames(pInQueParams->prevLinkId,                                   pInQueParams->prevLinkQueId, &freeFrameList);#ifdef SYSTEM_DEBUG_FLOW         Vps_printf(" %d: DisplayLink_drvProcessData   : 3rd putLinksEmptyFrames %d  !!!\n",    Utils_getCurTimeInMsec(), freeFrameList.numFrames);#endif    }    return FVID2_SOK;}

(3)我们现在遇到的问题如下(经打印的Log分析显示),请帮忙分析原因:

(3.1) displayLink的前一个Link(m3vpssInLink)通过下面的代码给displayLink发送“SYSTEM_CMD_NEW_DATA”消息指示,发送了19个帧(19次,每次一个帧)数据;

(3.2) displayLink仅在上述:

                 /*情况一:*/    获取5帧数据,有release framebuffer操作;

                 /*情况三:*/    获取7帧数据,没有release framebuffer操作(要继续查原因);

(3.3) 后续m3vpssInLink不再接收到frame数据,c6xdsp在 ListMP_getHead(pObj->listMPInHndl)后来总是返回NULL后挂死:        

Int32 IpcFramesOutLink_releaseFrameBufs(IpcFramesOutLink_Obj * pObj){    System_LinkInQueParams *pInQueParams;    SystemIpcFrames_ListElem *pListElem = NULL;    Int32 status;    UInt32 curTime, roundTripTime;    FVID2_Frame *pFrameBuf = NULL;    FVID2_FrameList freeFrameBufList;    UInt8 queId;    UInt32 chPerQueue;    UInt32 times = 0;    pInQueParams = &pObj->createArgs.baseCreateParams.inQueParams;    do    {        freeFrameBufList.numFrames = 0;        curTime = Utils_getCurTimeInMsec();        while (freeFrameBufList.numFrames < FVID2_MAX_FVID_FRAME_PTR)        {            pListElem = ListMP_getHead(pObj->listMPInHndl);            if (pListElem == NULL)                break;            UTILS_assert(SYSTEM_IPC_FRAMES_GET_BUFSTATE(pListElem->bufState)                         == IPC_FRAMEBUF_STATE_INQUE);            IpcFramesOutLink_mapListElem2FrameBuf(pObj, pListElem, &pFrameBuf);            UTILS_assert(pFrameBuf != NULL);            if (curTime > pFrameBuf->timeStamp)            {                roundTripTime = curTime – pFrameBuf->timeStamp;                pObj->stats.totalRoundTrip += roundTripTime;            }            /* Restore the original timestamp as it may be used by next link */            pFrameBuf->timeStamp = pListElem->frameBuf.timeStamp;            freeFrameBufList.frames[freeFrameBufList.numFrames] = pFrameBuf;            freeFrameBufList.numFrames++;            UTILS_assert(freeFrameBufList.numFrames <=                         FVID2_MAX_FVID_FRAME_PTR);            /* release ListElem back to queue */            SYSTEM_IPC_FRAMES_SET_BUFOWNERPROCID(pListElem->bufState);            SYSTEM_IPC_FRAMES_SET_BUFSTATE(pListElem->bufState,                                         IPC_FRAMEBUF_STATE_FREE);            status = Utils_quePut(&pObj->listElemQue, pListElem, BIOS_NO_WAIT);            UTILS_assert(status == FVID2_SOK);        }#ifdef SYSTEM_DEBUG_IPC_RT        Vps_printf(" %d: IPC_FRAMES_OUT   : Releasing %d framebufs !!!\n",                   Utils_getCurTimeInMsec(), freeFrameBufList.numFrames);#endif        if (freeFrameBufList.numFrames)        {            /* If the buffer is released via processing link, pass it to next link */            /* NextLink will take care to release the buffer to privLink */            if(pObj->createArgs.baseCreateParams.processLink != SYSTEM_LINK_ID_INVALID)            {                Int i;                UInt32 sendMsgToTsk = 0;                for (i = 0; i < freeFrameBufList.numFrames;i++)                {                    pObj->stats.forwardCount++;                    /** Split the frames into both the output queues,                    * if they are enabled. Else use output queue 0 only.                    * Also, if output queue 1 is used, frames sent to this queue                    * should be modified before submitting so that the                    * pFrame->channelNum should start with 0 and not with                    * (pObj->nsfCreateParams.numCh / 2).                    */                    pFrameBuf = freeFrameBufList.frames[i];                    chPerQueue =                        (pObj->numCh / pObj->createArgs.baseCreateParams.numOutQue);                    queId = (pFrameBuf->channelNum / chPerQueue);                    pFrameBuf->channelNum = pFrameBuf->channelNum % chPerQueue;                    status =  Utils_quePut(&pObj->outFrameBufQue[queId],                                           freeFrameBufList.frames[i],                                           BIOS_NO_WAIT);                    UTILS_assert(!UTILS_ISERROR(status));                    sendMsgToTsk |= (1 << queId);                }                if (pObj->createArgs.baseCreateParams.notifyNextLink)                {                    for (i = 0; i < pObj->createArgs.baseCreateParams.numOutQue;i++)                    {                        if (sendMsgToTsk & 0x1)                        {                            System_sendLinkCmd(pObj->createArgs.baseCreateParams.outQueParams[i].                                nextLink, SYSTEM_CMD_NEW_DATA);                        }                        sendMsgToTsk >>= 1;                        if (sendMsgToTsk == 0)                            break;                    }                }            }            else            {                System_putLinksEmptyFrames(pInQueParams->prevLinkId,                                           pInQueParams->prevLinkQueId,                                           &freeFrameBufList);            }        }    } while (pListElem != NULL);    return FVID2_SOK;}

lu kingkuang:

回复 Chris Meng:

good idea!我把dspAlgLink “bypass”掉看看情况.

lu kingkuang:

回复 Chris Meng:

仔细对照Log分析了displayLink代码,认为displayLink处理数据流是这样的:
1. displayLink调用前一个link(m3vpssInLink)的GetFullFrameBufs()获取发送过来的帧数据buffer;
2. displayLink调用Frame_que()将获取的帧数据buffer再交给displayLink驱动;
3.displayLink调用Frame_deque() 获取 displayLink驱动返回的数据buffer,再将此buffer释放给前一个Link;我们的问题还是上面第1步获取的帧数据较前一个Link发送的少很多,导致前一个Link后来再也获取不到displayLink释放的buffer而挂死.
还请大家指导!

lu kingkuang:

回复 lu kingkuang:

我把dspAlgLink “bypass”掉,图像是正常、稳定显示的.
还是dspAlgLink代码有问题!

lu kingkuang:

回复 lu kingkuang:

hi,chris问题已定位.是由于displayLink内QUE和DEQUE次数不一致导致.
如果前一个Link QUE的是无效帧数据,displayLink不公正常Deque回来.
确保帧数据有效,问题解决.但即使QUE了无效数据,displayLink按理也该Deque回帧buffer.
这个问题还不知原因.

赞(0)
未经允许不得转载:TI中文支持网 » 请问DVR RDK中displayLink的callback函数是怎么被调用起来的?
分享到: 更多 (0)