RTPReceiverInfo.cc

Go to the documentation of this file.
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 }