数据流量监测工具源玛共享3[带录制功能]

    技术2022-05-11  60

    在前一篇文章 《数据流量监测工具源玛共享2[嵌入式流媒体测试工具] 》提 到在shell 上输入rate_stat命令就可以全部显示数据在某模块中的所有走向;输入rate_show命令就可以知道某数据在某个检测点的数据包头信息,比如数 据包长度、序列号、尾包标志等参数。这篇文章对前面的工具作进一步的改进,将原来的rate_stat、rate_show、rate_probe分别改为pkt_prof、pkt_show、pkt_probe并添加定点和多点录象播发的功能pkt_rec(/sync). 1.如何使用录制功能及demo程序 a.启动MCU设备和终端设备,开视频会议

    b.telnet到ip为172.16.66.29的MCU设备,然后使用pkt_prof 命令罗列所有监测点

    c.录制指定点的数据流

    d.使用自己编写的播放工具播放录制下来的视频图象(感兴趣的网友可以留下email,可以发给你们)

    e.几个监测点的代码 这些demo来自于视频会议的。 demo1:将数据包发送到网络  NW_BOOL rtpDataSendFromCodec2Net(IN NW_VOID             * pData,                          IN NW_INT32        nLen,                          IN TRtpParam         * pRtpParam,                          IN NW_INT32        nDestNum,                          IN TForwardUnit     * pDests) {    static    NW_UINT8     tempBuf[1600= {0};    NW_INT32             nMaxCallID         = 0;    NW_INT32            nIndex;    NW_UINT8            nStackCallId;    NW_UINT8             *ptr;    NW_UINT8             *tempBuf1         = NULL;    NW_INT32             operationCode     = OP_STREAM;    EStRtpMediaType        eRtpMediaType     = pDests[0].oUnit.tRtpUnit.eRtpMediaType;        tempBuf1 = tempBuf;    ((TIPBoardPacketHdr*)tempBuf1)->sIdentifier        = PKT_ID;    ((TIPBoardPacketHdr*)tempBuf1)->byVersion        = PKT_VER;    ((TIPBoardPacketHdr*)tempBuf1)->byDirection        = PKT_DIR_MAIN_2_IP;    ((TIPBoardPacketHdr*)tempBuf1)->byDataType        = PKT_DATATYPE_STREAM;    ((TIPBoardPacketHdr*)tempBuf1)->byOperation        = operationCode;    ((TIPBoardPacketHdr*)tempBuf1)->byOperationType    = eRtpMediaType;    ((TIPBoardPacketHdr*)tempBuf1)->sPayloadLen        = /*36*/24 + nLen + nDestNum;        memcpy(tempBuf1+16,&nLen,4);    memcpy(tempBuf1+20,&nDestNum,4);        for (nIndex = 0; nIndex < nDestNum; nIndex++)    {        /* 进行判断防止因定义时是Union而导致了nDevID和nCallID的复用。[zhengxb, 2006-04-30] */        if(FU_NET != pDests[nIndex].eUnitType)        {            continue;        }                nStackCallId    = pDests[nIndex].oUnit.tRtpUnit.nCallId;        memcpy(tempBuf1+24+nIndex,&nStackCallId, 1);        if ( nStackCallId < MIN_GW_VCALLID && nMaxCallID < nStackCallId)        {            nMaxCallID = nStackCallId;        }            #ifdef _PACKET_PROFILER_            {            if (AUDIO_FIRST == eRtpMediaType)            {                static NW_INT32            nCallerID         = INVALID_VALUE;                static const EStreamType     eStreamType    = STREAM_AUDIO;                static EStreamIdType         eStreamIdType     = STREAM_ID_CALL;                    NW_INT32                 nStreamID         = nStackCallId;                TStream                    tStream;                                    tStream.nSequence        = pRtpParam->sequenceNumber;                        tStream.nMarker            = pRtpParam->marker;                tStream.nLen                = nLen - RTP_HEADER_LEN;                    tStream.pData            = pData + RTP_HEADER_LEN;                tStream.bKeyframe        = FALSE;                pkt_probe(ADD_PREFIX("DP"),__LINE__,&nCallerID,eStreamIdType,nStreamID,eStreamType,&tStream);            }            else            {                static NW_INT32            nCallerID         = INVALID_VALUE;                static const EStreamType     eStreamType    = STREAM_VIDEO;                static EStreamIdType         eStreamIdType     = STREAM_ID_CALL;                    NW_INT32                 nStreamID         = nStackCallId;                TStream                    tStream;                                    tStream.nSequence        = pRtpParam->sequenceNumber;                        tStream.nMarker            = pRtpParam->marker;                tStream.nLen                = nLen - RESERVE_HEADER_LEN;                    tStream.pData            = pData + RESERVE_HEADER_LEN;                tStream.bKeyframe        = mdfIsKeyFrame(pRtpParam->payload, pData + RESERVE_HEADER_LEN);                pkt_probe(ADD_PREFIX("DP"),__LINE__,&nCallerID,eStreamIdType,nStreamID,eStreamType,&tStream);            }            }#endif        }        stRtpPack(nMaxCallID, eRtpMediaType, pData, nLen, pRtpParam);    memcpy(tempBuf1+24+nDestNum,pData, nLen);    if (NULL != ibCallBackSendData)    {            ibCallBackSendData(0, tempBuf,24+nLen+nDestNum,eRtpMediaType,nMaxCallID,TRUE);    }    return TRUE;} 在1.c中录制的监测点位于 sfDataWrite中 demo2:将数据从编码缓冲写到平滑缓冲,平滑处理后调用 rtpDataSendFromCodec2Net发送到网络    NW_BOOL sfDataWrite(IN NW_INT32 nRingId, IN NW_VOID *  pContext) {    PTSfEntryInfo            pEntry        = NULL;    PTSfRingInfo            pRing        = NULL;    NW_INT32                nCodecId;        NW_INT32                nSfPacketNum;    NW_INT32                nIndex;    NW_UINT8                *pData        = NULL;    NW_INT32                nLen        = 0;    NW_INT32                nPacketNum    = 0;    NW_UINT16                nSequenceNum;    NW_UINT32                nTimestamp;    TRtpParam                *pRtpParam    = NULL;    EPayload                ePayload;    TFrameBufferInfo        *pFrame        = (TFrameBufferInfo*)pContext;    TVBufferInfoFromCodec    *pBuffer    = NULL;        if(nRingId<0 || nRingId>=DP_SF_MAX_RING_NUM)        return FALSE;    pRing            = &(g_pStRingInfo[nRingId]);    nSfPacketNum    = pRing->nRxPacketNum;    pBuffer            = &(pFrame->buffer_info.bufferInfoFromVCoder);    pData            = pBuffer->buffer;    nLen                = pBuffer->dataLen;    。。。    if (nSfPacketNum < DP_SF_MAX_RX_PACKET_NUM)    {        for (nIndex = 0; nIndex < nPacketNum; nIndex++)        {                        pEntry    = &(pRing->pEntry[pRing->nWrite]);                        nSequenceNum                = rtpVideoSequenceNumGet(MIXER_INDEX(nCodecId));            pRtpParam                    = &(pEntry->tRtpParam);            pEntry->nLen                    = mdfLenGet(pData);            pEntry->bKeyframe            = pBuffer->bKeyFrame;            pRtpParam->payload            = ePayload;                        pRtpParam->sequenceNumber    = nSequenceNum;            pRtpParam->timestamp            = nTimestamp;            pRtpParam->sByte                = RTP_HEADER_LEN;            pRtpParam->len                = pEntry->nLen;            if (nIndex == nPacketNum - 1)            {                pRtpParam->marker        = TRUE;            }            else            {                pRtpParam->marker        = FALSE;            }            #ifdef _PACKET_PROFILER_                {                static NW_INT32            nCallerID         = INVALID_VALUE;                static const EStreamType     eStreamType    = STREAM_VIDEO;                static const EStreamIdType     eStreamIdType     = STREAM_ID_CHAN;                    static TStream                tStream;                                    NW_INT32                 nStreamID         = nRingId;                tStream.nSequence        = pRtpParam->sequenceNumber;                        tStream.nMarker            = pRtpParam->marker;                tStream.nLen                = pRtpParam->len - RESERVE_HEADER_LEN;                    tStream.pData            = pData  + BUFFER_NODE_HEADER_SIZE + RESERVE_HEADER_LEN;                tStream.bKeyframe        = pBuffer->bKeyFrame;                pkt_probe(ADD_PREFIX("DP"),__LINE__,&nCallerID,eStreamIdType,nStreamID,eStreamType,&tStream);            }#endif                memcpy(pEntry->pData, pData + BUFFER_NODE_HEADER_SIZE, pEntry->nLen);            pEntry->bState    = TRUE;            ++(pRing->nRxPacketNum);            pRing->nWrite    = (pRing->nWrite + 1 + DP_SF_MAX_ENTRY_NUM)%DP_SF_MAX_ENTRY_NUM;            pData    += NET_BUFFER_VIDEO_NODE_SIZE;            pEntry->bState    = TRUE;                }        return TRUE;    }    else    {        sfRingReset(nRingId, TRUE);        return FALSE;    }} 2.pkt_profiler.h ...    #define  _PACKET_PROFILER_ #ifdef _PACKET_PROFILER_ #define  ADD_PREFIX(x) (x##"@"##__FUNCTION__)    /*添加模块名前缀,可用于模块检索*/ typedef  struct  _tagStream {        NW_BYTE        nMarker;                        /*一帧数据的尾包吗*/        NW_UINT16    nSequence;                        /*数据包序列号*/        NW_BOOL    bKeyframe;                        /*I 帧标识*/    NW_UINT8*    pData;                            /*裸数据包地址*/    NW_INT32    nLen;                            /*裸数据包长度*/}  TStream;typedef  enum  _tagStreamType {    STREAM_NONE            = 0,    STREAM_AUDIO        = 1 << 0,    STREAM_VIDEO        = 1 << 1}  EStreamType;typedef  enum  _tagStreamIdType {    STREAM_ID_INVALID        = 0,     STREAM_ID_DSP            = 1,                 /*数据包发给DSP 或从DSP 接收*/    STREAM_ID_CHAN        = 2,                    /*数据包写入缓冲 或从 缓冲读取*/        STREAM_ID_CALL        = 3                    /*数据包发给协议栈 或从 协议栈读取*/}  EStreamIdType;NW_VOID pkt_probe(     const  NW_CHAR *      pchFuncName,                 /*监测点所在函数的函数名信息*/      const  NW_INT32     nLine,                         /*监测点所在位置*/     NW_INT32 *          pCallerID,                     /*监测点所在函数的调用ID ,唯一*/     EStreamIdType     eStreamIdType,                 /*监测点数据来源类型*/     NW_INT32         nStreamId,                     /*监测点数据通道ID,唯一*/     EStreamType         eStreamType,                 /*监测点数据类型,音频或视频*/     TStream *          pStream    );                     /*监测点数据流详细信息*/ #endif /*_PACKET_PROFILER_*/ 3.pkt_profiler.c ...#ifdef _PACKET_PROFILER_ /**  * 1.工具介绍:   *  a.<功能>:数据诊断工具packet profiler 主要用于查看全部或某  *  具体监测点(每个监测点使用pkt_probe 探测数据)  *  的数据流状况并在出现异常情况时可以使用  *  pkt_prof、pkt_show、pkt_rec、pkt_check 等命令诊断数据流。   *  这些命令的具体功能和用法可以使用pkt_help 查看。  *  b.<用法>:这些命令的提供提高了数据流bug 的诊断能力,  *  也提高了对数据流bug 定位的正确性、便利性、  *  快捷性。如果你想查看某个检测点的状况,可以  *  先使用pkt_prof 显示音频或视频类型某模块下的所有  *  检测点的Caller ID ,接着使用pkt_show、pkt_rec、pkt_check   *  查看具体检测点下的异常情况。我们可以使用  *  pkt_probe 添加检测点。  *  c.<建议>:该工具支持多任务支持跨模块调用,建议以后  *  单独拿出来作为一个公共工具模块放在common目录下  *  让更多的模块享受这种调式的乐趣。    * 2.工具命令:  *  a.<pkt_prof>:可以在异常情况下打印所有或某模块中的  *  数据流的流向。 虽然有fdtShow 提供流向表查询功能  *  但它无法知晓某数据通道是否确实有数据流经已经  *  以及以多少码流流过。  *  b.<pkt_show>:可以在异常情况下打印某具体监测点数据  *  详细信息包括数据长度、数据地址、序列号等信息。  *  这个命令用于代码开发阶段很使用。  *  c.<pkt_rec/sync>:可以在异常情况下录制声音或图象。  *  比如发现某路数据声音出现断断续续或重音现象  *  就可以使用该功能去检查有嫌疑的检测点并最终  *  定位异常源自模块中的哪个位置。*/ static  NW_UINT32 dword_swap(NW_UINT32 x) {    return ( ((x & 0x000000FF<< 24| ((x & 0xFF000000>> 24|            (((x) & 0xFF00<< 8| (((x) & 0xFF0000>> 8));} #define  CALLER_ID0                (1) #define  MAX_CALLERS             (50)                         /*流量统计监测点的最大数目*/ #define  MAX_CHANNELS             (200)                        /*每个监测点支持通道的最大数目*/ #define  MAX_FUNC_NAME_LEN     (50)                            /*监测点调用函数的函数名最大长度*/ #define  MAX_HINT_INFO_LEN         (80)                            /*监测点调用函数的函数名最大长度*/ #define  TICKS_PER_SECOND        (60) /*  NOTE:  * 1.为了不干扰正在运行的其它程序,profiler  的录制功能  * (record) 块使用静态内存。虽然可以在初始化阶段为其分  * 配动态内存,但为了坚守profiler 模块的独立性,还是不建议。  * 2.如果考虑内存消耗,可以关闭_PACKET_WRITE_FILE_ 来关闭录制  * (record) 功能。目前不支持多路数据同时保存。  */ #define  _PACKET_WRITE_FILE_                                 /*如果要考虑到内存分配,那么可以关闭此功能*/ typedef  struct  _TagPacketInfo {        NW_INT32         nPackets;                                /*监测点流经总包数*/        NW_INT32         nPacketRate;                            /*监测点流量*/        NW_INT32        nPrevPackets;                            /*该点上一次监测的累计包数*/            NW_INT32        nPrevTicks;                                /*该点上一次监测的累计时间*/    NW_INT32        nPacketShown;                            /*显示数据包头的数目*/    NW_INT32         nInterval;                                /*前后两次监测的时间跨度*/    NW_BOOL         bFrame;                                    /*如果统计单位为帧*/    #ifdef _PACKET_WRITE_FILE_    NW_BOOL         bSaved;                                    /*录制该通道*/        NW_INT32         nOffsetPrev;                                /*录制开始标志*/        NW_INT32         nOffsetCurr;                                /*录制起始偏移量*/        NW_INT32         nFrameLen;        NW_BOOL         bFisrtPacket;                        NW_BOOL         bStart;    NW_BOOL         bReady;            #endif    EStreamIdType     eStreamIdType;                            /*数据流来源ID 类型,可以是DSP ID,可以是CHANNEL ID*/} TPacketInfo;typedef  struct  _TagCallerInfo {        NW_CHAR        pchFuncName[MAX_FUNC_NAME_LEN];        /*调用函数的函数名,caller名称*/    NW_CHAR         nFuncLen;                                /*调用函数的函数名实际长度*/            NW_SHORT        nLine;                                    /*调用函数的调用点位置*/            TPacketInfo        tPacket[MAX_CHANNELS];                    /*调用函数的调用的统计信息*/} TCallerInfo; static  TCallerInfo     g_tCaller[MAX_CALLERS]; static  NW_INT32    g_nCallers                  =  CALLER_ID0;                     /*不从0 开始,可以提供更多灵活性,见pkt_rec*/ static  NW_BOOL    g_bActivated              =  FALSE; static  NW_BOOL     g_bInitialized              =  FALSE; static  NW_INT32    g_eStreamType              =   0 ;     static  NW_CHAR     g_strModulePrefix[MAX_FUNC_NAME_LEN]; static  NW_BOOL    g_bModulePrefixFiltered      =  FALSE;NW_VOID         pkt_start( void );NW_VOID         pkt_stop( void );NW_BOOL         pkt_started( void );NW_VOID         pkt_stat( void );NW_VOID          pkt_help(NW_INT32 nSelection); NW_VOID         pkt_check(NW_INT32 nCallerID,NW_INT32 nStreamId);#ifdef _PACKET_WRITE_FILE_NW_VOID         pkt_rec(NW_INT32 nCallerID,NW_INT32 nStreamId,NW_INT32 nRecoredLen); #endif #ifdef _PACKET_WRITE_FILE_  #define              MAX_MULTI_RECORD_POINTS        16 #define              MAX_BUF_SIZE                     200*1024 /*录制缓冲区大小*/ typedef  struct  _TagRec {        NW_INT32  nCallerID;                                NW_INT32  nChannelID;    } TRec;     static  NW_UINT8    s_pFileBuf[MAX_BUF_SIZE]; static  NW_UINT32    s_nFileBufLen     = 0 ;NW_VOID pkt_dump( const  NW_CHAR *  pchFuncName,NW_INT32 nStreamId,EStreamType eStreamType,TPacketInfo *  ptPacket);NW_VOID pkt_dump( const  NW_CHAR *  pchFuncName,NW_INT32 nStreamId,EStreamType eStreamType,TPacketInfo *  ptPacket) {    FILE    *            fptr                 = NULL;    static NW_BYTE     nFilename[100]    = {0};    EStreamIdType     eStreamIdType    = 0;    NW_INT32         nOffset            = 0;        if (NULL == pchFuncName)    {        printf("Invalid function name! ");        return;    }    if (NULL == ptPacket)    {        printf("%s:Invalid packet info! ",pchFuncName);        return;    }    eStreamIdType     = ptPacket->eStreamIdType;    nOffset            = ptPacket->nOffsetCurr - ptPacket->nOffsetPrev;        if (STREAM_ID_DSP != eStreamIdType     && STREAM_ID_CHAN != eStreamIdType     && STREAM_ID_CALL != eStreamIdType)    {            printf("%s:Invalid stream id type %d! ",pchFuncName,eStreamIdType);            return;    }            if (nStreamId>=0 && nStreamId<MAX_CHANNELS)    {        sprintf(nFilename,"%s.%s_%s_%d.%s",            pchFuncName,STREAM_AUDIO==eStreamType?"audio":"video",                STREAM_ID_DSP == eStreamIdType?"dsp":(STREAM_ID_CHAN == eStreamIdType? "chan":"call"),                    nStreamId,STREAM_AUDIO==eStreamType?"dat":"mpeg4");        fptr = fopen(nFilename,"wb");                if (NULL == fptr)        {            printf("%s:Failed to open %s! ",pchFuncName,nFilename);                return;        }        else        {            if (nOffset > 0)            {                if (nOffset > s_nFileBufLen)                 {                    nOffset = s_nFileBufLen;                }                                    fwrite(s_pFileBuf+ptPacket->nOffsetPrev,1,nOffset, fptr);            }        }                fclose(fptr);    }    else    {        printf("%s:Invalid stream id %d! ",pchFuncName,nStreamId);    }} #endif  /*_PACKET_WRITE_FILE_*/ NW_VOID pkt_probe( const  NW_CHAR *  pchFuncName, const  NW_INT32 nLine,NW_INT32 *  pCallerID,EStreamIdType eStreamIdType,NW_INT32 nStreamId,EStreamType eStreamType,TStream *  pStream) {    NW_INT32         nCaller                 = 0;    NW_INT32         nChannel            = 0;    NW_INT32        nCurrTicks             = 0;        NW_INT32        nModulePrefixLen    = 0;    NW_INT32        nPrefix                = 0;    TCallerInfo*         ptCaller                = NULL;    TPacketInfo*        ptPacket            = NULL;    if (!pkt_started())    {        return;    }    if (!g_bInitialized)    {        return;    }        if (NULL == pchFuncName || NULL == pCallerID)    {        printf("Invalid function name or caller ID pointer!");        return;    }    if (nStreamId < 0 || nStreamId >= MAX_CHANNELS)    {        printf("%s:Invalid stream id %d!",pchFuncName,nStreamId);        return;    }        if (STREAM_ID_DSP != eStreamIdType     && STREAM_ID_CHAN != eStreamIdType     && STREAM_ID_CALL != eStreamIdType)    {            printf("%s:Invalid stream id type %d!",pchFuncName,eStreamIdType);        return;    }        if (!(eStreamType & g_eStreamType))    {/*过滤不想统计的通道*/            return;                }        if (INVALID_VALUE == *pCallerID)    {    /*分配CALLER ID , 支持多任务!*/        if ((nCaller = g_nCallers++>= MAX_CALLERS)        {            printf("%s:Falied to allocate caller ID %d!",pchFuncName,nCaller);            return;            }                ptCaller                 = &g_tCaller[nCaller];        ptCaller->nFuncLen    = strlen(pchFuncName);        if (ptCaller->nFuncLen >= MAX_FUNC_NAME_LEN)        {            printf("%s:Too long function name! ",pchFuncName);                    return;        }                ptCaller->nFuncLen     = sprintf(ptCaller->pchFuncName,"%s",pchFuncName);        ptCaller->nLine        = nLine;        *pCallerID             = nCaller;/*返回当前监测点的ID,以备后用*/    }    else    {        nCaller = *pCallerID;    }    ptCaller     = &g_tCaller[nCaller];    ptPacket     = &g_tCaller[nCaller].tPacket[nStreamId];    if (nCaller >= CALLER_ID0 && nCaller < MAX_CALLERS)    {        if (STREAM_ID_DSP != ptPacket->eStreamIdType         && STREAM_ID_CHAN != ptPacket->eStreamIdType        && STREAM_ID_CALL != ptPacket->eStreamIdType)            {            ptPacket->eStreamIdType = eStreamIdType;        }            if (NULL != pStream && ptPacket->nPacketShown>0 && ptPacket->nPacketShown-->0)        {            printf("%s(M):len M,seqence %d,marker %d,keyframe %d ",                    ptCaller->pchFuncName,ptCaller->nLine,pStream->nLen,pStream->nSequence,pStream->nMarker,pStream->bKeyframe);                        return;        }            if (g_bModulePrefixFiltered)        {            nModulePrefixLen = strlen(g_strModulePrefix);            if (nModulePrefixLen> 0 && nModulePrefixLen< MAX_FUNC_NAME_LEN)            {                while (nModulePrefixLen>0)                 {                    if (ptCaller->pchFuncName[nModulePrefixLen-1!= g_strModulePrefix[nModulePrefixLen-1])                    {                        return;                            }                    nModulePrefixLen--;                }            }        }    #ifdef _PACKET_WRITE_FILE_        /*录制声音或图象*/        if (ptPacket->bSaved        && NULL != pStream && NULL != pStream->pData         && pStream->nLen >0 && pStream->nLen < 1600)        {            NW_BYTE*        pData            = NULL;            NW_INT32         nDataLen        = 0;                NW_INT32         nMarker            = FALSE;                pData             = pStream->pData;            nDataLen            = pStream->nLen;            nMarker            = pStream->nMarker;                    if(!ptPacket->bReady && ptPacket->nOffsetPrev == ptPacket->nOffsetCurr)            {                        ptPacket->bStart = TRUE;                if (STREAM_VIDEO == eStreamType)                {                    if (pStream->bKeyframe)                    {                        ptPacket->bReady         = TRUE;                        ptPacket->bFisrtPacket    = FALSE;                        ptPacket->nFrameLen    = 0;                        if (0 == ptPacket->nOffsetPrev)                        {                                                printf("0%s ","%");                        }                    }                }                else                 {                    ptPacket->bReady             = TRUE;                    if (0 == ptPacket->nOffsetPrev)                    {                                            printf("0%s ","%");                    }                }                            }                        /*            *audio:|pkt 1||pkt 2|...|pkt n|...            *video:|frame len|pkt 1||pkt 2|...|pkt n|...                            */            if(ptPacket->bReady)            {                        if (!ptPacket->bFisrtPacket && STREAM_VIDEO == eStreamType) /*first packet of a frame*/                {                    ptPacket->bFisrtPacket     =     TRUE;                                                    ptPacket->nFrameLen    =     0;                    ptPacket->nOffsetCurr    +=     sizeof(ptPacket->nFrameLen);                                    }                                            if (ptPacket->nOffsetCurr - ptPacket->nOffsetPrev + nDataLen < s_nFileBufLen)                {                    memcpy(s_pFileBuf + ptPacket->nOffsetCurr,pData,nDataLen);                    if (0 == ptPacket->nOffsetPrev && ((10*(ptPacket->nOffsetCurr - ptPacket->nOffsetPrev))/s_nFileBufLen) !=                     ((10*(ptPacket->nOffsetCurr - ptPacket->nOffsetPrev + nDataLen))/s_nFileBufLen))                    {                        printf("█ ");                    }                                ptPacket->nOffsetCurr += (nDataLen+0x3)&~0x3;                    if (STREAM_VIDEO == eStreamType)                    {                        ptPacket->nFrameLen += (nDataLen+0x3)&~0x3;                        if (nMarker) /*last packet of a frame*/                                            {                            *(NW_INT32*)(s_pFileBuf+ptPacket->nOffsetCurr - ptPacket->nFrameLen - sizeof(ptPacket->nFrameLen)) = dword_swap(ptPacket->nFrameLen);                                ptPacket->nFrameLen     = 0;                            ptPacket->bFisrtPacket     = FALSE;                        }                        }                }                else                {                    ptPacket->bSaved    = FALSE;                    ptPacket->bReady    = FALSE;                                        pkt_dump(ptCaller->pchFuncName,nStreamId,eStreamType,ptPacket);                                        for (nCaller = CALLER_ID0; nCaller < g_nCallers; nCaller++)                    {                            for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)                        {                             if (g_tCaller[nCaller].tPacket[nChannel].bStart                             && g_tCaller[nCaller].tPacket[nChannel].bSaved)                            {                                break;                            }                        }                        if (MAX_CHANNELS != nChannel)                        {                            break;                        }                    }                    if (nCaller == g_nCallers)                    {                        printf("█ 100%s","%");                        pkt_stop();                        }                }                }        }        #endif        /*等待用户设置检测时间*/        if (1 > ptPacket->nInterval)         {                return;        }        /*如果统计单位是帧*/        if (STREAM_VIDEO == eStreamType)         {            if (NULL != pStream && pStream->nMarker && !ptPacket->bFrame)            {                ptPacket->bFrame = TRUE;            }                        if (NULL != pStream && ptPacket->bFrame && !pStream->nMarker)            {                return;            }        }        ptPacket->nPackets++;        nCurrTicks = tickGet();        if (0 == ptPacket->nPrevTicks)        {            ptPacket->nPrevPackets     = ptPacket->nPackets;            ptPacket->nPrevTicks        = nCurrTicks;        }        else        {            if (nCurrTicks != ptPacket->nPrevTicks            && nCurrTicks-ptPacket->nPrevTicks >= ptPacket->nInterval)            {                ptPacket->nPacketRate    = TICKS_PER_SECOND*(ptPacket->nPackets - ptPacket->nPrevPackets)                     /(nCurrTicks - ptPacket->nPrevTicks);                ptPacket->nPrevTicks         = 0;                ptPacket->nInterval         = 0;            }        }    }} NW_VOID     pkt_prof(NW_CHAR *  pchMediaType,NW_CHAR *  pchModulePrefix) {    TCallerInfo*             ptCaller                = NULL;    TPacketInfo*            ptPacket            = NULL;    NW_INT32             nCaller                = 0;    NW_INT32             nChannel            = 0;    NW_INT32            nModulePrefixLen    = 0;    static const NW_INT32     nInterval            = 4*TICKS_PER_SECOND;/*second*/    static const NW_INT32     nErrorPercentage        = 5;/*误差占整个计时的百分比*/    if (NULL == pchMediaType && NULL == pchModulePrefix)    {        if (g_eStreamType > 0)        {            pkt_stat();            return;        }        pkt_help(1);        return;    }    if (1 > nInterval || 1 > nErrorPercentage)    {        printf("%s:Invalid param,interval %d,error %d! ",pchMediaType,nInterval,nErrorPercentage);        return;    }        pkt_stop();    if (NULL != pchModulePrefix)    {        nModulePrefixLen = strlen(pchModulePrefix);        if (nModulePrefixLen> MAX_FUNC_NAME_LEN)        {            printf("%s:Too long module prefix! ",pchModulePrefix);            return;        }                g_bModulePrefixFiltered = FALSE;        taskDelay(3);/*等待pkt_prof  g_bModulePrefixFiltered 相关代码执行完毕*/        memset(&g_strModulePrefix[0],0,sizeof(NW_CHAR)*MAX_FUNC_NAME_LEN);        sprintf(g_strModulePrefix,"%s",pchModulePrefix);        g_bModulePrefixFiltered = TRUE;    }    else    {        g_bModulePrefixFiltered = FALSE;        taskDelay(3);        memset(&g_strModulePrefix[0],0,sizeof(NW_CHAR)*MAX_FUNC_NAME_LEN);    }    g_eStreamType = 0;            if (0 == strcmp(pchMediaType,"audio"))    {        g_eStreamType |= STREAM_AUDIO;    }    else if (0 == strcmp(pchMediaType,"video"))    {        g_eStreamType |= STREAM_VIDEO;            }    else    {        pkt_help(1);        return;    }            /*如果有数据流,设置统计时间*/    if (!g_bInitialized)    {    /*第一次要初始化*/        memset(&g_tCaller[0],0,sizeof(TCallerInfo)*MAX_CALLERS);        for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)        {                for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)            {                g_tCaller[nCaller].tPacket[nChannel].bFrame             = FALSE; #ifdef _PACKET_WRITE_FILE_                g_tCaller[nCaller].tPacket[nChannel].bSaved            = FALSE; #endif                g_tCaller[nCaller].tPacket[nChannel].eStreamIdType     = STREAM_ID_INVALID;             }        }        g_bInitialized = TRUE;    }    for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)    {            for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)        {            g_tCaller[nCaller].tPacket[nChannel].nInterval         = nInterval;            g_tCaller[nCaller].tPacket[nChannel].nPackets         = 0;            g_tCaller[nCaller].tPacket[nChannel].nPacketRate     = 0;        }    }    pkt_start();            printf("wait %d seconds for profiling %s rates%s%s... ",((TICKS_PER_SECOND/10)+nInterval+nInterval/(100/nErrorPercentage))/TICKS_PER_SECOND,        pchMediaType,NULL == pchModulePrefix? "":" from the module with prefix ",NULL == pchModulePrefix? "":pchModulePrefix);    taskDelay(nInterval);/*统计时间*/        taskDelay(nInterval/(100/nErrorPercentage));/*考虑大概  的偏差*/            pkt_stat();        pkt_stop();} /*显示数据包RTP 头信息*/ NW_VOID pkt_show(NW_INT32 nCallerID,NW_INT32 nStreamId,NW_INT32 nPacketNum) {    static NW_INT32     nCallerID2        = 0;     static NW_INT32     nStreamId2        = 0;    static NW_INT32     nPacketNum2    = 0;        NW_INT32         nCaller            = 0;    NW_INT32         nChannel        = 0;    if (!g_bInitialized)    {        printf("You gotta use pkt_prof to do initialization first!");        return;    }        pkt_stop();        if (0 != nCallerID)    {        nCallerID2     = nCallerID;        nStreamId2     = nStreamId;        nPacketNum2     = nPacketNum;        }    if (nCallerID2 <CALLER_ID0 || nCallerID2 >= MAX_CALLERS)    {        printf("Invalid caller ID %d ",nCallerID2);            pkt_help(2);        return;    }        if (nStreamId2 < 0 || nStreamId2 >= MAX_CHANNELS)    {        printf("Invalid stream ID %d ",nStreamId2);                pkt_help(2);        return;    }            if (1 > nPacketNum2)    {        printf("Invalid packet num %d ",nPacketNum2);                    pkt_help(2);        return;        }                    if (1 > g_tCaller[nCallerID2].nFuncLen)     {        printf("Invalid func len %d ",g_tCaller[nCallerID2].nFuncLen);                return;    }    for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)    {            for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)        {            g_tCaller[nCaller].tPacket[nChannel].nPacketShown = 0;        }    }        g_tCaller[nCallerID2].tPacket[nStreamId2].nPacketShown = nPacketNum2;    pkt_start();        taskDelay(300*nPacketNum2/TICKS_PER_SECOND);/*300 为一秒中可能接收到的最大包数目*/            pkt_stop();            } #ifdef _PACKET_WRITE_FILE_  /*record*/     NW_BOOL pkt_confirmed( void ) {    static NW_BOOL     bFtpOpened         = FALSE;            NW_BYTE         szLocalIP[16]    = {0};    NW_CHAR        ch            = '0';        if (!bFtpOpened)    {        printf("NOTE:Be 100%s sure whether host wftp server has been opened or not. ","%",szLocalIP);                    printf("Opened yet? Go,check and enter 'Y' or 'N' to make sure:");        ch = getchar();        while ('Y' != ch && 'N' != ch)        {                                ch = getchar();        }                if('N' == ch)        {            printf("Open WFTP server and enter 'Y' to continue or 'A'  to exit:");            ch = getchar();            while ('Y' != ch && 'A' != ch )            {                ch = getchar();            }                if('Y' != ch)            {                return FALSE;            }            else            {                printf("Warning:it'll cause a long delay in multi-pictures if WFTP server wasn't opened practically!");            }        }        bFtpOpened = TRUE;    }    return TRUE;} /*单点录制*/ NW_VOID pkt_rec(NW_INT32 nCallerID,NW_INT32 nStreamId,NW_INT32 nRecoredLen) {    static NW_INT32     nCallerID2        = 0;     static NW_INT32     nStreamId2        = 0;    static NW_INT32     nRecoredLen2    = 0;    NW_INT32         nCaller            = 0;    NW_INT32         nChannel        = 0;        NW_CHAR        ch                = '0';    if (!g_bInitialized)    {        printf("You gotta use pkt_prof to do initialization first!");        return;    }        pkt_stop();                    if (0 != nCallerID)    {        nCallerID2     = nCallerID;        nStreamId2     = nStreamId;        nRecoredLen2    = nRecoredLen;        }    if (nCallerID2 < CALLER_ID0 || nCallerID2 >= MAX_CALLERS)    {        printf("Invalid caller ID %d ",nCallerID2);                pkt_help(5);        return;    }        if (nStreamId2 < 0 || nStreamId2 >= MAX_CHANNELS)    {        printf("Invalid stream ID %d ",nStreamId2);                pkt_help(5);        return;    }        if (1 > g_tCaller[nCallerID2].nFuncLen)     {        printf("Invalid func len %d ",g_tCaller[nCallerID2].nFuncLen);                    return;    }        /*如果nRecoredLen 没有输入或0 则采取默认值*/    if (0 == nRecoredLen2)    {        nRecoredLen2 = MAX_BUF_SIZE;    }    if (nRecoredLen2 > MAX_BUF_SIZE)    {        pkt_help(4);        return;    }    else    {        s_nFileBufLen = nRecoredLen2;    }    if (!pkt_confirmed())    {    /*确认不成功*/        printf("Failed to confirm! ");                return;    }        for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)    {            for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)        {            g_tCaller[nCaller].tPacket[nChannel].bSaved         = FALSE;            g_tCaller[nCaller].tPacket[nChannel].bStart        = FALSE;            g_tCaller[nCaller].tPacket[nChannel].bReady        = FALSE;                        g_tCaller[nCaller].tPacket[nChannel].nOffsetPrev    = 0;            g_tCaller[nCaller].tPacket[nChannel].nOffsetCurr    = 0;        }    }    memset(s_pFileBuf+g_tCaller[nCallerID2].tPacket[nStreamId2].nOffsetCurr,0,s_nFileBufLen*sizeof(NW_UINT8));    g_tCaller[nCallerID2].tPacket[nStreamId2].nFrameLen     = 0;        g_tCaller[nCallerID2].tPacket[nStreamId2].bFisrtPacket     = FALSE;        g_tCaller[nCallerID2].tPacket[nStreamId2].bSaved         = TRUE;    pkt_start();} /*多点录制: 为了同步多点的数据流, 所有  *同步录制的点共享MAX_BUF_SIZE 长度的内存  *空间。一次设定多点录制列表,之后可  *以使用pkt_rec2() 反复利用。该功能对调试  *音频重音很有用。*/ NW_VOID pkt_rec_sync(NW_INT32 nRecordedPoints) {    TPacketInfo*        ptPacket                    = NULL;    static TRec          tRecList[MAX_MULTI_RECORD_POINTS];    static NW_BOOL     bInitialized                    = FALSE;    static NW_INT32    nPoints                        = 0;    NW_INT32        nPoint,nRecPoints            = nRecordedPoints;    NW_INT32         nRecoredLen                    = 0;    NW_INT32        nCaller,nCallerID                = 0;    NW_INT32        nChannel,nChannelID            = 0;    NW_INT32        nChannelPrev,nChannelIDPrev    = 0;        if (!bInitialized)    {        if (nRecPoints < 1 || nRecPoints > MAX_MULTI_RECORD_POINTS)        {            printf("Invalid caller num %d! ",nRecPoints);            pkt_help(6);            return;        }        if (!pkt_confirmed())        {    /*确认不成功*/            printf("Failed to confirm! ");                    return;        }        memset(&tRecList[0],0,sizeof(TRec)*MAX_MULTI_RECORD_POINTS);        bInitialized    = TRUE;        nPoints        = 0;            }    if (bInitialized)    {                if (nRecPoints < 0 || nRecPoints > MAX_MULTI_RECORD_POINTS)        {            printf("Invalid caller num %d! ",nRecPoints);            pkt_help(6);            return;        }                pkt_stop();            if (nRecPoints > 0)        {            nPoints = nRecPoints;        }                if (0 == nPoints)        {            printf("recorded points overriden %d! ",nPoints);                            return;        }        for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)        {                for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)            {                g_tCaller[nCaller].tPacket[nChannel].bSaved         = FALSE;                g_tCaller[nCaller].tPacket[nChannel].bStart        = FALSE;                g_tCaller[nCaller].tPacket[nChannel].bReady        = FALSE;                g_tCaller[nCaller].tPacket[nChannel].nOffsetPrev    = 0;                g_tCaller[nCaller].tPacket[nChannel].nOffsetCurr    = 0;            }        }                nRecoredLen = (MAX_BUF_SIZE/nPoints - 0x1& ~0x3;        s_nFileBufLen = nRecoredLen;                for (nPoint =0; nPoint < nPoints; nPoint++)        {            nCallerID     = INVALID_VALUE;            nChannelID    = INVALID_VALUE;                        if (0 == nRecPoints)            {                nCallerID        = tRecList[nPoint].nCallerID;                nChannelID    = tRecList[nPoint].nChannelID;                        }            else            {                printf("Recorded point ID %d:Enter caller ID and channel ID:",nPoint);                            while (nCallerID <CALLER_ID0 || nCallerID >= MAX_CALLERS                 || nChannelID < CALLER_ID0 || nChannelID >= MAX_CHANNELS                 || (nPoint > 0 && nCallerID == tRecList[nPoint-1].nCallerID && nChannelID == tRecList[nPoint-1].nChannelID))                {                    if ((nPoint > 0 && nCallerID == tRecList[nPoint-1].nCallerID && nChannelID == tRecList[nPoint-1].nChannelID))                     {                        printf("No repeat points allowed! Enter again:");                                }                                         scanf("%d,%d",&nCallerID,&nChannelID);                }                            tRecList[nPoint].nCallerID     = nCallerID;                tRecList[nPoint].nChannelID     = nChannelID;            }                        ptPacket                     = &g_tCaller[nCallerID].tPacket[nChannelID];            ptPacket->nOffsetPrev        = nPoint*nRecoredLen;            ptPacket->nOffsetCurr        = nPoint*nRecoredLen;            ptPacket->bFisrtPacket         = FALSE;                                    ptPacket->nFrameLen         = 0;                ptPacket->bSaved             = TRUE;            memset(s_pFileBuf + ptPacket->nOffsetPrev,0,nRecoredLen*sizeof(NW_UINT8));        }        pkt_start();    }} #endif NW_VOID     pkt_stat( void ) {    TCallerInfo*             ptCaller        = NULL;    TPacketInfo*            ptPacket    = NULL;    NW_INT32             nCaller        = 0;    NW_INT32             nChannel    = 0;    NW_BOOL            bFound        = 0;    if (!g_bInitialized)    {        printf("You gotta use pkt_prof to do initialization first!");        return;    }        if (1 > g_nCallers)    {        printf("No stream coming! ");        return;    }    printf("------------------------------------------------------------------------------- ");            for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)    {            ptCaller     = &g_tCaller[nCaller];        if (1 > ptCaller->nFuncLen)         {            continue;        }                bFound = FALSE;                    for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)        {            ptPacket     = &g_tCaller[nCaller].tPacket[nChannel];            if (ptPacket->nInterval > 0)            {                ptPacket->nInterval = 0;            }            if (ptPacket->nPacketRate > 0)            {                printf("%-28s(%-4d) caller %-2d,%-4s id %-3d: %-3d %-s/s,%-3d %-7s ",                    ptCaller->pchFuncName,ptCaller->nLine,nCaller,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":                        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,                            ptPacket->nPacketRate,ptPacket->bFrame? "f":"p",                                ptPacket->nPackets,ptPacket->bFrame? "frames":"packets");                            bFound = TRUE;            }        }                if (bFound)        {            printf(" ");                }    }    printf("------------------------------------------------------------------------------- ");        } NW_VOID     pkt_check(NW_INT32 nCallerID,NW_INT32 nStreamId) {    TPacketInfo*        ptPacket        = NULL;    static NW_INT32     nCallerID2        = 0;     static NW_INT32     nStreamId2        = 0;    NW_INT32         nCaller            = 0;    NW_INT32         nChannel        = 0;    if (!g_bInitialized)    {        printf("You gotta use pkt_prof to do initialization first!");        return;    }        if (0 != nCallerID)    {        nCallerID2     = nCallerID;        nStreamId2     = nStreamId;    }    if (nCallerID2 <CALLER_ID0 || nCallerID2 >= MAX_CALLERS)    {        printf("Invalid caller ID %d ",nCallerID2);            pkt_help(2);        return;    }        if (nStreamId2 < 0 || nStreamId2 >= MAX_CHANNELS)    {        printf("Invalid stream ID %d ",nStreamId2);                pkt_help(2);        return;    }                    if (1 > g_tCaller[nCallerID2].nFuncLen)     {        printf("Invalid func len %d ",g_tCaller[nCallerID2].nFuncLen);                return;    }    ptPacket     = &g_tCaller[nCallerID2].tPacket[nStreamId2];    printf("caller %-2d,%-4s id %-2d:nPackets     %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nPackets);    printf("caller %-2d,%-4s id %-2d:nPacketRate  %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nPacketRate);    printf("caller %-2d,%-4s id %-2d:nPrevPackets %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nPrevPackets);    printf("caller %-2d,%-4s id %-2d:nPrevTicks   %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nPrevTicks);    printf("caller %-2d,%-4s id %-2d:nPacketShown %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nPacketShown);    printf("caller %-2d,%-4s id %-2d:nInterval    %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->nInterval);    printf("caller %-2d,%-4s id %-2d:bFrame       %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->bFrame);    printf("caller %-2d,%-4s id %-2d:bSaved       %-d ",nCallerID2,STREAM_ID_DSP == ptPacket->eStreamIdType?"dsp":        (STREAM_ID_CHAN == ptPacket->eStreamIdType? "chan":"call"),nChannel,ptPacket->bSaved);    } NW_VOID     pkt_start( void ) {    g_bActivated = TRUE;} NW_VOID     pkt_stop( void ) {    g_bActivated = FALSE;} NW_BOOL     pkt_started( void ) {    return g_bActivated;} NW_VOID     pkt_reset( void ) {    NW_INT32         nCaller                 = 0;    NW_INT32         nChannel            = 0;    for (nCaller = CALLER_ID0; nCaller < MAX_CALLERS; nCaller++)    {            for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)        {            g_tCaller[nCaller].tPacket[nChannel].bFrame             = FALSE; #ifdef _PACKET_WRITE_FILE_            g_tCaller[nCaller].tPacket[nChannel].bSaved            = FALSE; #endif            g_tCaller[nCaller].tPacket[nChannel].eStreamIdType     = STREAM_ID_INVALID;         }    }    g_eStreamType             = 0;        g_bModulePrefixFiltered     = FALSE;    g_bActivated             = FALSE;    memset(&g_strModulePrefix[0],0,sizeof(NW_CHAR)*MAX_FUNC_NAME_LEN);} /*当出现异常时, 本模块可以诊断的手段*/ NW_VOID      pkt_help(NW_INT32 nSelection)  {    /*NOTE : 打印是否对齐在UltraEdit 下看*/    switch (nSelection)    {        case 0:        {                printf("------------------------------------------------------------------------------ ");                    printf("pkt_help(0)        详细介绍pkt_help ");            printf("pkt_help(1)        详细介绍pkt_prof ");            printf("pkt_help(2)        详细介绍pkt_show ");            printf("pkt_help(3)        详细介绍pkt_check ");            printf("pkt_help(4)        详细介绍pkt_reset ");#ifdef _PACKET_WRITE_FILE_            printf("pkt_help(5)        详细介绍pkt_rec ");            printf("pkt_help(6)        详细介绍pkt_rec_sync ");#endif            printf("------------------------------------------------------------------------------ ");                }break;                    case 1:        {                        printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_prof(NW_CHAR* pchMediaType,NW_CHAR* pchModulePrefix) ");            printf("1. 功能介绍:       打印所有或某监测点数据流通路径及速率 ");                        printf("2. 范例展示:       pkt_prof 'video','DP'  ");                            printf("3. 参数输入: ");            printf("   pchMediaType:   媒体流类型, 如输入字符串audio  / video 显示音视频 ");                            printf("   pchModulePrefix:模块的前缀, 如输入字符串COMM / DP表示通信层或DP ");                            printf("------------------------------------------------------------------------------ ");                  }break;                case 2:        {            printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_show(NW_INT32 nCallerID,NW_INT32 nStreamId,NW_INT32 nPacketNum) ");            printf("1. 功能介绍:       打印某监测点的一系列序列号 ");            printf("2. 范例展示:       pkt_show 2,1,10 ");                                printf("3. 参数输入: ");            printf("   nCallerID:      监测点的函数调用ID, 调用pkt_prof 可以查看 ");                            printf("   nStreamId:      监测点的通道ID, 调用pkt_prof 可以查看 ");                            printf("   nPacketNum:     要求打印的数据包数目 ");                                    printf("------------------------------------------------------------------------------ ");                }break;            case 3:        {            printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_check(NW_INT32 nCallerID,NW_INT32 nStreamId) ");            printf("1. 功能介绍:       打印某监测点的详细统计信息 ");            printf("2. 范例展示:       pkt_check 2,1 ");                                printf("3. 参数输入: ");            printf("   nCallerID:      监测点的函数调用ID, 调用pkt_prof 可以查看 ");                            printf("   nStreamId:      监测点的通道ID, 调用pkt_prof 可以查看 ");                            printf("------------------------------------------------------------------------------ ");                }break;                    case 4:        {            printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_reset(void) ");            printf("1. 功能介绍:       复位所有监测点状态 ");            printf("2. 范例展示:       pkt_reset ");                            printf("3. 参数输入:       NONE ");            printf("------------------------------------------------------------------------------ ");                }break;            #ifdef _PACKET_WRITE_FILE_        case 5:        {            printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_rec(NW_INT32 nCallerID,NW_INT32 nStreamId,NW_INT32 nRecoredLen)) ");            printf("1. 功能介绍:       录制某监测点的数据流并传送到WFTP 用户目录 ");            printf("2. 范例展示:       pkt_rec 2,1 ");                            printf("3. 参数输入: ");            printf("   nCallerID:      监测点的函数调用ID, 调用pkt_prof 可以查看 ");                            printf("   nStreamId:      监测点的通道ID, 调用pkt_prof 可以查看 ");                            printf("   nRecoredLen:    准备录制多少长度,不超过%d K ",MAX_BUF_SIZE/1024);                                        printf("------------------------------------------------------------------------------ ");                }break;            case 6:        {            printf("------------------------------------------------------------------------------ ");                    printf("NW_VOID pkt_rec_sync(NW_INT32 nRecordedPoints) ");            printf("1. 功能介绍:       同时录制多个监测点的数据流 ");            printf("2. 范例展示:       pkt_rec_sync 2 ");                            printf("3. 参数输入: ");            printf("   nRecordedPoints:同时录制多少个检测点, 最多支持%d 点 ",MAX_MULTI_RECORD_POINTS);                            printf("4. 注意事项:       该功能只对具备录制能力的监测点(rate:f/s) ");            printf("------------------------------------------------------------------------------ ");                }break;            #endif        default:        {    /*递归显示*/            pkt_help(0);        }break;                        }}

    最新回复(0)