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_linux\links\system的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 !!!\n", 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 !!!\n", 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 !!!\n",
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 !!!\n",
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 !!!\n",
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("\n IPCBITSOUTLINK: WARNING: User is asking for %d buffers per CH. But max allowed is %d. \n"
" Over riding user requested with max allowed \n\n",
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 !!!\n",
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\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;
//获取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\n");
#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 !!!\n",
Utils_getCurTimeInMsec());
#endif #ifdef SYSTEM_DEBUG
Vps_printf(" %d: SYSTEM : System Video Init Done !!!\n", 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 !!!\n", 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 !!!\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;
} 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 !!!\n",
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 !!!\n", 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 !!!\n",
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\n");
#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 !!!\n", 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 !!!\n",
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;
}
dm8148 videoM3 link源代码解析的更多相关文章
- Android源代码解析之(六)-->Log日志
转载请标明出处:一片枫叶的专栏 首先说点题外话,对于想学android framework源代码的同学,事实上能够在github中fork一份,详细地址:platform_frameworks_bas ...
- struts2 文件上传和下载,以及部分源代码解析
struts2 文件上传 和部分源代码解析,以及一般上传原理 (1) 单文件上传 一.简单介绍 Struts2并未提供自己的请求解析器,也就是就Struts2不会自己去处理multipart/form ...
- Android源代码解析之(七)-->LruCache缓存类
转载请标明出处:一片枫叶的专栏 android开发过程中常常会用到缓存.如今主流的app中图片等资源的缓存策略通常是分两级.一个是内存级别的缓存,一个是磁盘级别的缓存. 作为android系统的维护者 ...
- Tomcat请求处理过程(Tomcat源代码解析五)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- Spring源代码解析
Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...
- Arrays.sort源代码解析
Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...
- Spring源代码解析(收藏)
Spring源代码解析(收藏) Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的 ...
- volley源代码解析(七)--终于目的之Response<T>
在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...
- Cocos2d-x源代码解析(1)——地图模块(3)
接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...
随机推荐
- 洛谷P2056 采花
P2056 采花 52通过 99提交 题目提供者shengmingkexue 标签云端↑ 难度省选/NOI- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 求助莫队为什么被卡 ...
- 【06】react 之 PropsType
React组件创建的时候,需要传入属性,我们可以使用使用PropTypes进行类型检查,您可以使用React.PropTypes在组件的道具上运行. React.PropTypes.array Rea ...
- Reactor模式总结
Reactor是基于NIO中实现多路复用的一种模式. 什么是Reactor模式 同步的等待多个事件源到达(采用select()实现) 将事件多路分解以及分配相应的事件服务进行处理,这个分派采用serv ...
- 【转】利用ScriptManager实现Javascript调用WebService中的方法
原文发布时间为:2009-07-01 -- 来源于本人的百度文章 [由搬家工具导入] 前台调用后台方法,或者后台调用前台方法。ScriptManager实现 开发过程中,总想在前台直接调用后台的met ...
- 【Visual Studio】以管理员的身份运行软件
- [SaltStack] salt-master启动流程
SaltStack源码阅读 做salt有一段时间了, 一直没从源码层面去理解, 好吧, 开始读读源码 -_- 那就从salt-master的启动开始吧. 启动salt-master方法: /etc/i ...
- css 之 position定位
position属性一共有4个值,分别是static.absolute.relative.fixed. static为默认值,指块保持在原本应该在的位置上,即该值没有任何移动的效果. absolute ...
- LeetCode OJ-- Distinct Subsequences ** 递推
https://oj.leetcode.com/problems/distinct-subsequences/ 对于string S 和 T求,T 是 S的几种子串. 首先想到了递归方法,列出递归公式 ...
- AC日记——石子归并 51nod 1021
石子归并 思路: 经典动态规划——归并类问题: 我们把状态划为n个,即1-n的n个长度为n个状态: 那么,每个长度为i的状态都可以由i-1个长度为i-1的状态推出: 所以,dp转移方程: dp[i][ ...
- Codeforces 754A Lesha and array splitting (搜索)
题目链接 Lesha and array splitting 设s[i][j]为序列i到j的和,当s[i][j]≠0时,即可从i跳到j+1.目标为从1跳到n+1,所以按照题意暴力即可. #includ ...