是周期性调用吗?
具体代码在哪?
谢谢!
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.
这个问题还不知原因.
TI中文支持网
