Boolean ReorderingPacketBuffer::storePacket(BufferedPacket* bPacket) { unsigned short rtpSeqNo = bPacket->rtpSeqNo(); if (!fHaveSeenFirstPacket) { fNextExpectedSeqNo = rtpSeqNo; // initialization bPacket->isFirstPacket() = True; fHaveSeenFirstPacket = True; } // Ignore this packet if its sequence number is less than the one // that we're looking for (in this case, it's been excessively delayed). if (seqNumLT(rtpSeqNo, fNextExpectedSeqNo)) return False; if (fTailPacket == NULL) { // Common case: There are no packets in the queue; this will be the first one: bPacket->nextPacket() = NULL; fHeadPacket = fTailPacket = bPacket; return True; } if (seqNumLT(fTailPacket->rtpSeqNo(), rtpSeqNo)) { // The next-most common case: There are packets already in the queue; this packet arrived in order => put it at the tail: bPacket->nextPacket() = NULL; fTailPacket->nextPacket() = bPacket; fTailPacket = bPacket; return True; } if (rtpSeqNo == fTailPacket->rtpSeqNo()) { // This is a duplicate packet - ignore it return False; } // Rare case: This packet is out-of-order. Run through the list (from the head), to figure out where it belongs: BufferedPacket* beforePtr = NULL; BufferedPacket* afterPtr = fHeadPacket; while (afterPtr != NULL) { if (seqNumLT(rtpSeqNo, afterPtr->rtpSeqNo())) break; // it comes here if (rtpSeqNo == afterPtr->rtpSeqNo()) { // This is a duplicate packet - ignore it return False; } beforePtr = afterPtr; afterPtr = afterPtr->nextPacket(); } // Link our new packet between "beforePtr" and "afterPtr": bPacket->nextPacket() = afterPtr; if (beforePtr == NULL) { fHeadPacket = bPacket; } else { beforePtr->nextPacket() = bPacket; } return True; }
double MediaSubsession::getNormalPlayTime(struct timeval const& presentationTime) { if (rtpSource() == NULL || rtpSource()->timestampFrequency() == 0) return 0.0; // no RTP source, or bad freq! // First, check whether our "RTPSource" object has already been synchronized using RTCP. // If it hasn't, then - as a special case - we need to use the RTP timestamp to compute the NPT. if (!rtpSource()->hasBeenSynchronizedUsingRTCP()) { if (!rtpInfo.infoIsNew) return 0.0; // the "rtpInfo" structure has not been filled in u_int32_t timestampOffset = rtpSource()->curPacketRTPTimestamp() - rtpInfo.timestamp; double nptOffset = (timestampOffset/(double)(rtpSource()->timestampFrequency()))*scale(); double npt = playStartTime() + nptOffset; return npt; } else { // Common case: We have been synchronized using RTCP. This means that the "presentationTime" parameter // will be accurate, and so we should use this to compute the NPT. double ptsDouble = (double)(presentationTime.tv_sec + presentationTime.tv_usec/1000000.0); if (rtpInfo.infoIsNew) { // This is the first time we've been called with a synchronized presentation time since the "rtpInfo" // structure was last filled in. Use this "presentationTime" to compute "fNPT_PTS_Offset": if (seqNumLT(rtpSource()->curPacketRTPSeqNum(), rtpInfo.seqNum)) return -0.1; // sanity check; ignore old packets u_int32_t timestampOffset = rtpSource()->curPacketRTPTimestamp() - rtpInfo.timestamp; double nptOffset = (timestampOffset/(double)(rtpSource()->timestampFrequency()))*scale(); double npt = playStartTime() + nptOffset; fNPT_PTS_Offset = npt - ptsDouble*scale(); rtpInfo.infoIsNew = False; // for next time return npt; } else { // Use the precomputed "fNPT_PTS_Offset" to compute the NPT from the PTS: if (fNPT_PTS_Offset == 0.0) return 0.0; // error: The "rtpInfo" structure was apparently never filled in return (double)(ptsDouble*scale() + fNPT_PTS_Offset); } } }
void QCELPDeinterleavingBuffer ::deliverIncomingFrame(unsigned frameSize, unsigned char interleaveL, unsigned char interleaveN, unsigned char frameIndex, unsigned short packetSeqNum, struct timeval presentationTime) { // First perform a sanity check on the parameters: // (This is overkill, as the source should have already done this.) if (frameSize > QCELP_MAX_FRAME_SIZE || interleaveL > QCELP_MAX_INTERLEAVE_L || interleaveN > interleaveL || frameIndex == 0 || frameIndex > QCELP_MAX_FRAMES_PER_PACKET) { #ifdef DEBUG fprintf(stderr, "QCELPDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, interleaveL, interleaveN, frameIndex); #endif abort(); } // The input "presentationTime" was that of the first frame in this // packet. Update it for the current frame: unsigned uSecIncrement = (frameIndex-1)*(interleaveL+1)*uSecsPerFrame; presentationTime.tv_usec += uSecIncrement; presentationTime.tv_sec += presentationTime.tv_usec/1000000; presentationTime.tv_usec = presentationTime.tv_usec%1000000; // Next, check whether this packet is part of a new interleave group if (!fHaveSeenPackets || seqNumLT(fLastPacketSeqNumForGroup, packetSeqNum)) { // We've moved to a new interleave group fHaveSeenPackets = True; fLastPacketSeqNumForGroup = packetSeqNum + interleaveL - interleaveN; // Switch the incoming and outgoing banks: fIncomingBankId ^= 1; unsigned char tmp = fIncomingBinMax; fIncomingBinMax = fOutgoingBinMax; fOutgoingBinMax = tmp; fNextOutgoingBin = 0; } // Now move the incoming frame into the appropriate bin: unsigned const binNumber = interleaveN + (frameIndex-1)*(interleaveL+1); FrameDescriptor& inBin = fFrames[binNumber][fIncomingBankId]; unsigned char* curBuffer = inBin.frameData; inBin.frameData = fInputBuffer; inBin.frameSize = frameSize; inBin.presentationTime = presentationTime; if (curBuffer == NULL) curBuffer = new unsigned char[QCELP_MAX_FRAME_SIZE]; fInputBuffer = curBuffer; if (binNumber >= fIncomingBinMax) { fIncomingBinMax = binNumber + 1; } }
void AMRDeinterleavingBuffer ::deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source, struct timeval presentationTime) { fILL = source->ILL(); unsigned char const ILP = source->ILP(); unsigned frameIndex = source->frameIndex(); unsigned short packetSeqNum = source->curPacketRTPSeqNum(); // First perform a sanity check on the parameters: // (This is overkill, as the source should have already done this.) if (ILP > fILL || frameIndex == 0) { #ifdef DEBUG fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, fILL, ILP, frameIndex); #endif source->envir().internalError(); } --frameIndex; // because it was incremented by the source when this frame was read u_int8_t frameHeader; if (frameIndex >= source->TOCSize()) { // sanity check frameHeader = FT_NO_DATA<<3; } else { frameHeader = source->TOC()[frameIndex]; } unsigned frameBlockIndex = frameIndex/fNumChannels; unsigned frameWithinFrameBlock = frameIndex%fNumChannels; // The input "presentationTime" was that of the first frame-block in this // packet. Update it for the current frame: unsigned uSecIncrement = frameBlockIndex*(fILL+1)*uSecsPerFrame; presentationTime.tv_usec += uSecIncrement; presentationTime.tv_sec += presentationTime.tv_usec/1000000; presentationTime.tv_usec = presentationTime.tv_usec%1000000; // Next, check whether this packet is part of a new interleave group if (!fHaveSeenPackets || seqNumLT(fLastPacketSeqNumForGroup, packetSeqNum + frameBlockIndex)) { // We've moved to a new interleave group #ifdef DEBUG fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): new interleave group\n"); #endif fHaveSeenPackets = True; fLastPacketSeqNumForGroup = packetSeqNum + fILL - ILP; // Switch the incoming and outgoing banks: fIncomingBankId ^= 1; unsigned char tmp = fIncomingBinMax; fIncomingBinMax = fOutgoingBinMax; fOutgoingBinMax = tmp; fNextOutgoingBin = 0; } // Now move the incoming frame into the appropriate bin: unsigned const binNumber = ((ILP + frameBlockIndex*(fILL+1))*fNumChannels + frameWithinFrameBlock) % fMaxInterleaveGroupSize; // the % is for sanity #ifdef DEBUG fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): frameIndex %d (%d,%d) put in bank %d, bin %d (%d): size %d, header 0x%02x, presentationTime %lu.%06ld\n", frameIndex, frameBlockIndex, frameWithinFrameBlock, fIncomingBankId, binNumber, fMaxInterleaveGroupSize, frameSize, frameHeader, presentationTime.tv_sec, presentationTime.tv_usec); #endif FrameDescriptor& inBin = fFrames[fIncomingBankId][binNumber]; unsigned char* curBuffer = inBin.frameData; inBin.frameData = fInputBuffer; inBin.frameSize = frameSize; inBin.frameHeader = frameHeader; inBin.presentationTime = presentationTime; inBin.fIsSynchronized = ((RTPSource*)source)->RTPSource::hasBeenSynchronizedUsingRTCP(); if (curBuffer == NULL) curBuffer = createNewBuffer(); fInputBuffer = curBuffer; if (binNumber >= fIncomingBinMax) { fIncomingBinMax = binNumber + 1; } }
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; }
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; }