RTPReceptionStats::RTPReceptionStats(unsigned int SSRC,unsigned short initialSeq):m_SSRC(0),m_numPacketsReceivedSinceLastReset(0), m_totalNumPacketsReceived(0),m_totalBytesReceived_hi(0),m_totalBytesReceived_lo(0), m_haveSeenInitialSequenceNumber(0),m_baseExtSeqNumReceived(0),m_lastResetExtSeqNumReceived(0), m_highestExtSeqNumReceived(0),m_lastTransit(0),m_previousPacketRTPTimestamp(0), m_jitter(0),m_lastReceivedSR_NTPmsw(0),m_lastReceivedSR_NTPlsw(0), m_minInterPacketGapUS(0),m_maxInterPacketGapUS(0),m_hasBeenSynchronized(0) { gethostname(m_CNAME,100); m_CNAME_length=strlen(m_CNAME); initSeqNum(initialSeq); initStats(SSRC); }
void RTPReceptionStats ::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp, unsigned timestampFrequency, Boolean useForJitterCalculation, struct timeval& resultPresentationTime, Boolean& resultHasBeenSyncedUsingRTCP, unsigned packetSize) { if (!fHaveSeenInitialSequenceNumber) initSeqNum(seqNum); ++fNumPacketsReceivedSinceLastReset; ++fTotNumPacketsReceived; u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo; fTotBytesReceived_lo += packetSize; if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around ++fTotBytesReceived_hi; } // Check whether the new sequence number is the highest yet seen: unsigned oldSeqNum = (fHighestExtSeqNumReceived&0xFFFF); unsigned seqNumCycle = (fHighestExtSeqNumReceived&0xFFFF0000); unsigned seqNumDifference = (unsigned)((int)seqNum-(int)oldSeqNum); unsigned newSeqNum = 0; if (seqNumLT((u_int16_t)oldSeqNum, seqNum)) { // This packet was not an old packet received out of order, so check it: if (seqNumDifference >= 0x8000) { // The sequence number wrapped around, so start a new cycle: seqNumCycle += 0x10000; } newSeqNum = seqNumCycle|seqNum; if (newSeqNum > fHighestExtSeqNumReceived) { fHighestExtSeqNumReceived = newSeqNum; } } else if (fTotNumPacketsReceived > 1) { // This packet was an old packet received out of order if ((int)seqNumDifference >= 0x8000) { // The sequence number wrapped around, so switch to an old cycle: seqNumCycle -= 0x10000; } newSeqNum = seqNumCycle|seqNum; if (newSeqNum < fBaseExtSeqNumReceived) { fBaseExtSeqNumReceived = newSeqNum; } } // Record the inter-packet delay struct timeval timeNow; gettimeofday(&timeNow, NULL); if (fLastPacketReceptionTime.tv_sec != 0 || fLastPacketReceptionTime.tv_usec != 0) { unsigned gap = (timeNow.tv_sec - fLastPacketReceptionTime.tv_sec)*MILLION + timeNow.tv_usec - fLastPacketReceptionTime.tv_usec; if (gap > fMaxInterPacketGapUS) { fMaxInterPacketGapUS = gap; } if (gap < fMinInterPacketGapUS) { fMinInterPacketGapUS = gap; } fTotalInterPacketGaps.tv_usec += gap; if (fTotalInterPacketGaps.tv_usec >= MILLION) { ++fTotalInterPacketGaps.tv_sec; fTotalInterPacketGaps.tv_usec -= MILLION; } } fLastPacketReceptionTime = timeNow; // Compute the current 'jitter' using the received packet's RTP timestamp, // and the RTP timestamp that would correspond to the current time. // (Use the code from appendix A.8 in the RTP spec.) // Note, however, that we don't use this packet if its timestamp is // the same as that of the previous packet (this indicates a multi-packet // fragment), or if we've been explicitly told not to use this packet. if (useForJitterCalculation && rtpTimestamp != fPreviousPacketRTPTimestamp) { unsigned arrival = (timestampFrequency*timeNow.tv_sec); arrival += (unsigned) ((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000); // note: rounding int transit = arrival - rtpTimestamp; if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time int d = transit - fLastTransit; fLastTransit = transit; if (d < 0) d = -d; fJitter += (1.0/16.0) * ((double)d - fJitter); } // Return the 'presentation time' that corresponds to "rtpTimestamp": if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) { // This is the first timestamp that we've seen, so use the current // 'wall clock' time as the synchronization time. (This will be // corrected later when we receive RTCP SRs.) fSyncTimestamp = rtpTimestamp; fSyncTime = timeNow; } int timestampDiff = rtpTimestamp - fSyncTimestamp; // Note: This works even if the timestamp wraps around // (as long as "int" is 32 bits) // Divide this by the timestamp frequency to get real time: double timeDiff = timestampDiff/(double)timestampFrequency; // Add this to the 'sync time' to get our result: unsigned const million = 1000000; unsigned seconds, uSeconds; if (timeDiff >= 0.0) { seconds = fSyncTime.tv_sec + (unsigned)(timeDiff); uSeconds = fSyncTime.tv_usec + (unsigned)((timeDiff - (unsigned)timeDiff)*million); if (uSeconds >= million) { uSeconds -= million; ++seconds; } } else { timeDiff = -timeDiff; seconds = fSyncTime.tv_sec - (unsigned)(timeDiff); uSeconds = fSyncTime.tv_usec - (unsigned)((timeDiff - (unsigned)timeDiff)*million); if ((int)uSeconds < 0) { uSeconds += million; --seconds; } } resultPresentationTime.tv_sec = seconds; resultPresentationTime.tv_usec = uSeconds; resultHasBeenSyncedUsingRTCP = fHasBeenSynchronized; // Save these as the new synchronization timestamp & time: fSyncTimestamp = rtpTimestamp; fSyncTime = resultPresentationTime; fPreviousPacketRTPTimestamp = rtpTimestamp; }
RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, u_int16_t initialSeqNum) { initSeqNum(initialSeqNum); init(SSRC); }
void RTPReceptionStats::noteIncomingPacket( unsigned short seqNum, unsigned int rtpTimestamp,unsigned int timestampFrequency, bool useForJitterCalculation, timeval& resultPresentationTime, bool& resultHasBeenSyncedUsingRTCP, unsigned int packetSize) { if (!m_haveSeenInitialSequenceNumber) { initSeqNum(seqNum); } m_numPacketsReceivedSinceLastReset++; m_totalNumPacketsReceived++; unsigned int lastTotalBytesReceived_Io=m_totalBytesReceived_lo; m_totalBytesReceived_lo+=packetSize; if (m_totalBytesReceived_lo<lastTotalBytesReceived_Io) { m_totalBytesReceived_hi++; } unsigned int oldSeqNum=(m_highestExtSeqNumReceived&0xffff); unsigned int seqNumCycle=(m_highestExtSeqNumReceived&0xffff0000); unsigned int seqNumDifference=(unsigned int)((int)seqNum-(int)oldSeqNum); //32bit contains cycle seqNum; unsigned int newSeqNum=0; if (seqNumLT((unsigned short)oldSeqNum,seqNum)) { //newSeq<oldSeq,uint<0,seqNumDifference>>0,进入新的循环; if (seqNumDifference>0x8000) { seqNumCycle+=0x10000; } newSeqNum=seqNumCycle|seqNum; if (newSeqNum>m_highestExtSeqNumReceived) { m_highestExtSeqNumReceived=newSeqNum; } }else if(m_totalNumPacketsReceived>1) { //newSeq>>oldSeq回到上一个循环; if ((int)seqNumDifference>0x8000) { seqNumCycle-=0x10000; } newSeqNum=seqNumCycle|seqNum; if (m_baseExtSeqNumReceived>newSeqNum) { m_baseExtSeqNumReceived=newSeqNum; } } //记录包延时; timeval timeNow; gettimeofday(&timeNow,0); if (m_lastPacketReceptionTime.tv_sec!=0&& m_lastPacketReceptionTime.tv_usec!=0) { unsigned int gapUsec=(timeNow.tv_sec-m_lastPacketReceptionTime.tv_sec)*1000000+ (timeNow.tv_usec-m_lastPacketReceptionTime.tv_usec); if (gapUsec>m_maxInterPacketGapUS) { m_maxInterPacketGapUS=gapUsec; } if (gapUsec<m_minInterPacketGapUS) { m_minInterPacketGapUS=gapUsec; } m_totalInterPacketGaps.tv_usec+=gapUsec; while (m_totalInterPacketGaps.tv_usec>1000000) { m_totalInterPacketGaps.tv_sec++; m_totalInterPacketGaps.tv_usec-=1000000; } } m_lastPacketReceptionTime=timeNow; //rtp jitter:时间抖动; //Si:RTP 时间戳; //Ri:RTP 接收到时的时间戳; //D(i,j)=(Rj-Ri)-(Sj-Si)=(Rj-Sj)-(Ri-Si); //J=J+(|D(i-1,i)|-J)/16; //RFC 1889 A.8 if (useForJitterCalculation&& rtpTimestamp!=m_previousPacketRTPTimestamp) { unsigned int arrival=(timestampFrequency*timeNow.tv_sec); arrival+=(unsigned int)((2.0*timestampFrequency*timeNow.tv_usec+1000000.0)/2000000.0); int transit=arrival-rtpTimestamp; if (m_lastTransit==~0) { m_lastTransit=transit; } int d=transit-m_lastTransit; m_lastTransit=transit; if (d<0) { d=-d; } m_jitter+=(1.0/16.0)*((double)d-m_jitter); } if (m_syncTime.tv_usec==0&&m_syncTime.tv_sec==0) { m_syncTime=timeNow; m_syncTimestamp=rtpTimestamp; } //时间戳间距; int timestampDiff=rtpTimestamp-m_syncTimestamp; //乘以采样率,获得真实时间差; double timeDiff=timestampDiff/(double)timestampFrequency; unsigned int seconds=0,useconds=0; if (timeDiff>=0.0) { seconds=m_syncTime.tv_sec+(unsigned int)timeDiff; useconds=m_syncTime.tv_usec+ (unsigned int)((timeDiff-(unsigned int)timeDiff)*UMILLION); if (useconds>=UMILLION) { seconds++; useconds-=UMILLION; } }else { timeDiff=-timeDiff; seconds=m_syncTime.tv_sec-(unsigned int)timeDiff; useconds=m_syncTime.tv_usec- (unsigned int)((timeDiff-(unsigned int)timeDiff)*UMILLION); if ((int)useconds<0) { useconds+=UMILLION; --seconds; } } resultPresentationTime.tv_sec=seconds; resultPresentationTime.tv_usec=useconds; resultHasBeenSyncedUsingRTCP=m_hasBeenSynchronized; //保存这一包的信息; m_syncTimestamp=rtpTimestamp; m_syncTime=resultPresentationTime; m_previousPacketRTPTimestamp=rtpTimestamp; }