00001 /*************************************************************************** 00002 RTPReceiverInfo.cc - description 00003 ------------------- 00004 (C) 2007 Ahmed Ayadi <ahmed.ayadi@sophia.inria.fr> 00005 (C) 2001 Matthias Oppitz <Matthias.Oppitz@gmx.de> 00006 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 00023 #include "RTPReceiverInfo.h" 00024 00025 00026 Register_Class(RTPReceiverInfo); 00027 00028 RTPReceiverInfo::RTPReceiverInfo(uint32 ssrc) : RTPParticipantInfo(ssrc) 00029 { 00030 _sequenceNumberBase = 0; 00031 _highestSequenceNumber = 0; 00032 _highestSequenceNumberPrior = 0; 00033 _sequenceNumberCycles = 0; 00034 00035 _packetsReceived = 0; 00036 _packetsReceivedPrior = 0; 00037 00038 _jitter = 0.0; 00039 _clockRate = 0; 00040 _lastSenderReportRTPTimeStamp = 0; 00041 _lastSenderReportNTPTimeStamp = 0; 00042 _lastPacketRTPTimeStamp = 0; 00043 00044 _lastPacketArrivalTime = 0.0; 00045 _lastSenderReportArrivalTime = 0.0; 00046 00047 _inactiveIntervals = 0; 00048 _startOfInactivity = 0.0; 00049 _itemsReceived = 0; 00050 //_jitterOutVector.setName("Jitter"); 00051 //_packetLostOutVector.setName("Packet Lost"); 00052 00053 //packetSequenceLostLogFile = NULL; 00054 } 00055 00056 RTPReceiverInfo::RTPReceiverInfo(const RTPReceiverInfo& receiverInfo) : RTPParticipantInfo() 00057 { 00058 operator=(receiverInfo); 00059 } 00060 00061 RTPReceiverInfo::~RTPReceiverInfo() 00062 { 00063 } 00064 00065 RTPReceiverInfo& RTPReceiverInfo::operator=(const RTPReceiverInfo& receiverInfo) 00066 { 00067 RTPParticipantInfo::operator=(receiverInfo); 00068 00069 _sequenceNumberBase = receiverInfo._sequenceNumberBase; 00070 _highestSequenceNumber = receiverInfo._highestSequenceNumber; 00071 _highestSequenceNumberPrior = receiverInfo._highestSequenceNumberPrior; 00072 _sequenceNumberCycles = receiverInfo._sequenceNumberCycles; 00073 00074 _packetsReceived = receiverInfo._packetsReceived; 00075 _packetsReceivedPrior = receiverInfo._packetsReceivedPrior; 00076 00077 _jitter = receiverInfo._jitter; 00078 _clockRate = receiverInfo._clockRate; 00079 _lastSenderReportRTPTimeStamp = receiverInfo._lastSenderReportRTPTimeStamp; 00080 _lastSenderReportNTPTimeStamp = receiverInfo._lastSenderReportNTPTimeStamp; 00081 _lastPacketRTPTimeStamp = receiverInfo._lastPacketRTPTimeStamp; 00082 00083 _lastPacketArrivalTime = receiverInfo._lastPacketArrivalTime; 00084 _lastSenderReportArrivalTime = receiverInfo._lastSenderReportArrivalTime; 00085 00086 _inactiveIntervals = receiverInfo._inactiveIntervals; 00087 _startOfInactivity = receiverInfo._startOfInactivity; 00088 _itemsReceived = receiverInfo._itemsReceived; 00089 00090 return *this; 00091 } 00092 00093 RTPReceiverInfo *RTPReceiverInfo::dup() const 00094 { 00095 return new RTPReceiverInfo(*this); 00096 } 00097 00098 void RTPReceiverInfo::processRTPPacket(RTPPacket *packet,int id, simtime_t arrivalTime) 00099 { 00100 // this endsystem sends, it isn't inactive 00101 _inactiveIntervals = 0; 00102 00103 _packetsReceived++; 00104 _itemsReceived++; 00105 00106 if (_packetsReceived == 1) { 00107 _sequenceNumberBase = packet->getSequenceNumber(); 00108 } 00109 else { 00110 00111 /*if (packet->getSequenceNumber() > _highestSequenceNumber+1) 00112 { 00113 _packetLostOutVector.record(packet->getSequenceNumber() - _highestSequenceNumber -1); 00114 for (int i = _highestSequenceNumber+1; i< packet->getSequenceNumber(); i++ ) 00115 { 00116 //std::cout << "id = "<< id <<" SequeceNumber loss = "<<i<<endl; 00117 packetSequenceLostLogFile = fopen ("PacketLossLog.log","+w"); 00118 if (packetSequenceLostLogFile != NULL) 00119 { 00120 //sprintf (line, "id = %d SequeceNumber loss = %f ", id,i); 00121 fputs (i, packetSequenceLostLogFile); 00122 fclose (packetSequenceLostLogFile); 00123 } 00124 } 00125 }*/ 00126 00127 if (packet->getSequenceNumber() > _highestSequenceNumber) { 00128 // it is possible that this is a late packet from the 00129 // previous sequence wrap 00130 if (!(packet->getSequenceNumber() > 0xFFEF && _highestSequenceNumber < 0x10)) 00131 _highestSequenceNumber = packet->getSequenceNumber(); 00132 } 00133 else { 00134 // is it a sequence number wrap around 0xFFFF to 0x0000 ? 00135 if (packet->getSequenceNumber() < 0x10 && _highestSequenceNumber > 0xFFEF) { 00136 _sequenceNumberCycles += 0x00010000; 00137 _highestSequenceNumber = packet->getSequenceNumber(); 00138 } 00139 } 00140 // calculate interarrival jitter 00141 if (_clockRate != 0) { 00142 simtime_t d = packet->getTimeStamp() - _lastPacketRTPTimeStamp - (arrivalTime - _lastPacketArrivalTime) * (double)_clockRate; 00143 if (d < 0) 00144 d = -d; 00145 _jitter = _jitter + (d - _jitter) / 16; 00146 } 00147 00148 _lastPacketRTPTimeStamp = packet->getTimeStamp(); 00149 _lastPacketArrivalTime = arrivalTime; 00150 } 00151 00152 //_jitterOutVector.record((uint32)_jitter); 00153 00154 RTPParticipantInfo::processRTPPacket(packet, id, arrivalTime); 00155 } 00156 00157 void RTPReceiverInfo::processSenderReport(SenderReport *report, simtime_t arrivalTime) 00158 { 00159 _lastSenderReportArrivalTime = arrivalTime; 00160 if (_lastSenderReportRTPTimeStamp == 0) { 00161 _lastSenderReportRTPTimeStamp = report->getRTPTimeStamp(); 00162 _lastSenderReportNTPTimeStamp = report->getNTPTimeStamp(); 00163 } 00164 else if (_clockRate == 0) { 00165 uint32 rtpTicks = report->getRTPTimeStamp() - _lastSenderReportRTPTimeStamp; 00166 uint64 ntpDifference = report->getNTPTimeStamp() - _lastSenderReportNTPTimeStamp; 00167 long double ntpSeconds = (long double)ntpDifference / (long double)(0xFFFFFFFF); 00168 _clockRate = (int)((long double)rtpTicks / ntpSeconds); 00169 } 00170 00171 _inactiveIntervals = 0; 00172 _itemsReceived++; 00173 00174 delete report; 00175 } 00176 00177 void RTPReceiverInfo::processSDESChunk(SDESChunk *sdesChunk, simtime_t arrivalTime) 00178 { 00179 RTPParticipantInfo::processSDESChunk(sdesChunk, arrivalTime); 00180 _itemsReceived++; 00181 _inactiveIntervals = 0; 00182 } 00183 00184 ReceptionReport *RTPReceiverInfo::receptionReport(simtime_t now) 00185 { 00186 if (isSender()) { 00187 ReceptionReport *receptionReport = new ReceptionReport(); 00188 receptionReport->setSSRC(getSSRC()); 00189 00190 uint64 packetsExpected = _sequenceNumberCycles + (uint64)_highestSequenceNumber - (uint64)_sequenceNumberBase + (uint64)1; 00191 uint64 packetsLost = packetsExpected - _packetsReceived; 00192 00193 int32 packetsExpectedInInterval = _sequenceNumberCycles + _highestSequenceNumber - _highestSequenceNumberPrior; 00194 int32 packetsReceivedInInterval = _packetsReceived - _packetsReceivedPrior; 00195 int32 packetsLostInInterval = packetsExpectedInInterval - packetsReceivedInInterval; 00196 uint8 fractionLost = 0; 00197 if (packetsLostInInterval > 0) { 00198 fractionLost = (packetsLostInInterval << 8) / packetsExpectedInInterval; 00199 } 00200 00201 receptionReport->setFractionLost(fractionLost); 00202 receptionReport->setPacketsLostCumulative(packetsLost); 00203 receptionReport->setSequenceNumber(_sequenceNumberCycles + _highestSequenceNumber); 00204 00205 receptionReport->setJitter((uint32)SIMTIME_DBL(_jitter)); //XXX ??? store it in secs? --Andras 00206 00207 // the middle 32 bit of the ntp time stamp of the last sender report 00208 receptionReport->setLastSR((_lastSenderReportNTPTimeStamp >> 16) & 0xFFFFFFFF); 00209 00210 // the delay since the arrival of the last sender report in units 00211 // of 1 / 65536 seconds 00212 // 0 if no sender report has ben received 00213 00214 receptionReport->setDelaySinceLastSR(_lastSenderReportArrivalTime == 0.0 ? 0 : (uint32)(SIMTIME_DBL(now - _lastSenderReportArrivalTime) * 65536.0)); 00215 00216 return receptionReport; 00217 } 00218 else 00219 return NULL; 00220 } 00221 00222 void RTPReceiverInfo::nextInterval(simtime_t now) 00223 { 00224 _inactiveIntervals++; 00225 if (_inactiveIntervals == 5) { 00226 _startOfInactivity = now; 00227 } 00228 _highestSequenceNumberPrior = _highestSequenceNumber + _sequenceNumberCycles; 00229 _packetsReceivedPrior = _packetsReceived; 00230 RTPParticipantInfo::nextInterval(now); 00231 } 00232 00233 bool RTPReceiverInfo::isActive() 00234 { 00235 return (_inactiveIntervals < 5); 00236 } 00237 00238 bool RTPReceiverInfo::isValid() 00239 { 00240 return (_itemsReceived >= 5); 00241 } 00242 00243 bool RTPReceiverInfo::toBeDeleted(simtime_t now) 00244 { 00245 // an rtp system should be removed from the list of known systems 00246 // when it hasn't been validated and hasn't been active for 00247 // 5 rtcp intervals or if it has been validated and has been 00248 // inactive for 30 minutes 00249 return (!isValid() && !isActive()) || (isValid() && !isActive() && (now - _startOfInactivity > 60.0 * 30.0)); 00250 }