liveMedia/RTPSource.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 Live Networks, Inc.  All rights reserved.
00018 // RTP Sources
00019 // Implementation
00020 
00021 #include "RTPSource.hh"
00022 #include "GroupsockHelper.hh"
00023 
00025 
00026 Boolean RTPSource::lookupByName(UsageEnvironment& env,
00027                                 char const* sourceName,
00028                                 RTPSource*& resultSource) {
00029   resultSource = NULL; // unless we succeed
00030 
00031   MediaSource* source;
00032   if (!MediaSource::lookupByName(env, sourceName, source)) return False;
00033 
00034   if (!source->isRTPSource()) {
00035     env.setResultMsg(sourceName, " is not a RTP source");
00036     return False;
00037   }
00038 
00039   resultSource = (RTPSource*)source;
00040   return True;
00041 }
00042 
00043 Boolean RTPSource::hasBeenSynchronizedUsingRTCP() {
00044   return fCurPacketHasBeenSynchronizedUsingRTCP;
00045 }
00046 
00047 Boolean RTPSource::isRTPSource() const {
00048   return True;
00049 }
00050 
00051 RTPSource::RTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00052                      unsigned char rtpPayloadFormat,
00053                      u_int32_t rtpTimestampFrequency)
00054   : FramedSource(env),
00055     fRTPInterface(this, RTPgs),
00056     fCurPacketHasBeenSynchronizedUsingRTCP(False), fLastReceivedSSRC(0),
00057     fRTPPayloadFormat(rtpPayloadFormat), fTimestampFrequency(rtpTimestampFrequency),
00058     fSSRC(our_random32()), fEnableRTCPReports(True) {
00059   fReceptionStatsDB = new RTPReceptionStatsDB();
00060 }
00061 
00062 RTPSource::~RTPSource() {
00063   delete fReceptionStatsDB;
00064 }
00065 
00066 void RTPSource::getAttributes() const {
00067   envir().setResultMsg(""); // Fix later to get attributes from  header #####
00068 }
00069 
00070 
00072 
00073 RTPReceptionStatsDB::RTPReceptionStatsDB()
00074   : fTable(HashTable::create(ONE_WORD_HASH_KEYS)), fTotNumPacketsReceived(0) {
00075   reset();
00076 }
00077 
00078 void RTPReceptionStatsDB::reset() {
00079   fNumActiveSourcesSinceLastReset = 0;
00080 
00081   Iterator iter(*this);
00082   RTPReceptionStats* stats;
00083   while ((stats = iter.next()) != NULL) {
00084     stats->reset();
00085   }
00086 }
00087 
00088 RTPReceptionStatsDB::~RTPReceptionStatsDB() {
00089   // First, remove and delete all stats records from the table:
00090   RTPReceptionStats* stats;
00091   while ((stats = (RTPReceptionStats*)fTable->RemoveNext()) != NULL) {
00092     delete stats;
00093   }
00094 
00095   // Then, delete the table itself:
00096   delete fTable;
00097 }
00098 
00099 void RTPReceptionStatsDB
00100 ::noteIncomingPacket(u_int32_t SSRC, u_int16_t seqNum,
00101                      u_int32_t rtpTimestamp, unsigned timestampFrequency,
00102                      Boolean useForJitterCalculation,
00103                      struct timeval& resultPresentationTime,
00104                      Boolean& resultHasBeenSyncedUsingRTCP,
00105                      unsigned packetSize) {
00106   ++fTotNumPacketsReceived;
00107   RTPReceptionStats* stats = lookup(SSRC);
00108   if (stats == NULL) {
00109     // This is the first time we've heard from this SSRC.
00110     // Create a new record for it:
00111     stats = new RTPReceptionStats(SSRC, seqNum);
00112     if (stats == NULL) return;
00113     add(SSRC, stats);
00114   }
00115 
00116   if (stats->numPacketsReceivedSinceLastReset() == 0) {
00117     ++fNumActiveSourcesSinceLastReset;
00118   }
00119 
00120   stats->noteIncomingPacket(seqNum, rtpTimestamp, timestampFrequency,
00121                             useForJitterCalculation,
00122                             resultPresentationTime,
00123                             resultHasBeenSyncedUsingRTCP, packetSize);
00124 }
00125 
00126 void RTPReceptionStatsDB
00127 ::noteIncomingSR(u_int32_t SSRC,
00128                  u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
00129                  u_int32_t rtpTimestamp) {
00130   RTPReceptionStats* stats = lookup(SSRC);
00131   if (stats == NULL) {
00132     // This is the first time we've heard of this SSRC.
00133     // Create a new record for it:
00134     stats = new RTPReceptionStats(SSRC);
00135     if (stats == NULL) return;
00136     add(SSRC, stats);
00137   }
00138 
00139   stats->noteIncomingSR(ntpTimestampMSW, ntpTimestampLSW, rtpTimestamp);
00140 }
00141 
00142 void RTPReceptionStatsDB::removeRecord(u_int32_t SSRC) {
00143   RTPReceptionStats* stats = lookup(SSRC);
00144   if (stats != NULL) {
00145     long SSRC_long = (long)SSRC;
00146     fTable->Remove((char const*)SSRC_long);
00147     delete stats;
00148   }
00149 }
00150 
00151 RTPReceptionStatsDB::Iterator
00152 ::Iterator(RTPReceptionStatsDB& receptionStatsDB)
00153   : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
00154 }
00155 
00156 RTPReceptionStatsDB::Iterator::~Iterator() {
00157   delete fIter;
00158 }
00159 
00160 RTPReceptionStats*
00161 RTPReceptionStatsDB::Iterator::next(Boolean includeInactiveSources) {
00162   char const* key; // dummy
00163 
00164   // If asked, skip over any sources that haven't been active
00165   // since the last reset:
00166   RTPReceptionStats* stats;
00167   do {
00168     stats = (RTPReceptionStats*)(fIter->next(key));
00169   } while (stats != NULL && !includeInactiveSources
00170            && stats->numPacketsReceivedSinceLastReset() == 0);
00171 
00172   return stats;
00173 }
00174 
00175 RTPReceptionStats* RTPReceptionStatsDB::lookup(u_int32_t SSRC) const {
00176   long SSRC_long = (long)SSRC;
00177   return (RTPReceptionStats*)(fTable->Lookup((char const*)SSRC_long));
00178 }
00179 
00180 void RTPReceptionStatsDB::add(u_int32_t SSRC, RTPReceptionStats* stats) {
00181   long SSRC_long = (long)SSRC;
00182   fTable->Add((char const*)SSRC_long, stats);
00183 }
00184 
00186 
00187 RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, u_int16_t initialSeqNum) {
00188   initSeqNum(initialSeqNum);
00189   init(SSRC);
00190 }
00191 
00192 RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC) {
00193   init(SSRC);
00194 }
00195 
00196 RTPReceptionStats::~RTPReceptionStats() {
00197 }
00198 
00199 void RTPReceptionStats::init(u_int32_t SSRC) {
00200   fSSRC = SSRC;
00201   fTotNumPacketsReceived = 0;
00202   fTotBytesReceived_hi = fTotBytesReceived_lo = 0;
00203   fBaseExtSeqNumReceived = 0;
00204   fHighestExtSeqNumReceived = 0;
00205   fHaveSeenInitialSequenceNumber = False;
00206   fLastTransit = ~0;
00207   fPreviousPacketRTPTimestamp = 0;
00208   fJitter = 0.0;
00209   fLastReceivedSR_NTPmsw = fLastReceivedSR_NTPlsw = 0;
00210   fLastReceivedSR_time.tv_sec = fLastReceivedSR_time.tv_usec = 0;
00211   fLastPacketReceptionTime.tv_sec = fLastPacketReceptionTime.tv_usec = 0;
00212   fMinInterPacketGapUS = 0x7FFFFFFF;
00213   fMaxInterPacketGapUS = 0;
00214   fTotalInterPacketGaps.tv_sec = fTotalInterPacketGaps.tv_usec = 0;
00215   fHasBeenSynchronized = False;
00216   fSyncTime.tv_sec = fSyncTime.tv_usec = 0;
00217   reset();
00218 }
00219 
00220 void RTPReceptionStats::initSeqNum(u_int16_t initialSeqNum) {
00221     fBaseExtSeqNumReceived = 0x10000 | initialSeqNum;
00222     fHighestExtSeqNumReceived = 0x10000 | initialSeqNum;
00223     fHaveSeenInitialSequenceNumber = True;
00224 }
00225 
00226 #ifndef MILLION
00227 #define MILLION 1000000
00228 #endif
00229 
00230 void RTPReceptionStats
00231 ::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
00232                      unsigned timestampFrequency,
00233                      Boolean useForJitterCalculation,
00234                      struct timeval& resultPresentationTime,
00235                      Boolean& resultHasBeenSyncedUsingRTCP,
00236                      unsigned packetSize) {
00237   if (!fHaveSeenInitialSequenceNumber) initSeqNum(seqNum);
00238 
00239   ++fNumPacketsReceivedSinceLastReset;
00240   ++fTotNumPacketsReceived;
00241   u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo;
00242   fTotBytesReceived_lo += packetSize;
00243   if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around
00244     ++fTotBytesReceived_hi;
00245   }
00246 
00247   // Check whether the new sequence number is the highest yet seen:
00248   unsigned oldSeqNum = (fHighestExtSeqNumReceived&0xFFFF);
00249   unsigned seqNumCycle = (fHighestExtSeqNumReceived&0xFFFF0000);
00250   unsigned seqNumDifference = (unsigned)((int)seqNum-(int)oldSeqNum);
00251   unsigned newSeqNum = 0;
00252   if (seqNumLT((u_int16_t)oldSeqNum, seqNum)) {
00253     // This packet was not an old packet received out of order, so check it:
00254     
00255     if (seqNumDifference >= 0x8000) {
00256       // The sequence number wrapped around, so start a new cycle:
00257       seqNumCycle += 0x10000;
00258     }
00259     
00260     newSeqNum = seqNumCycle|seqNum;
00261     if (newSeqNum > fHighestExtSeqNumReceived) {
00262       fHighestExtSeqNumReceived = newSeqNum;
00263     }
00264   } else if (fTotNumPacketsReceived > 1) {
00265     // This packet was an old packet received out of order
00266     
00267     if ((int)seqNumDifference >= 0x8000) {
00268       // The sequence number wrapped around, so switch to an old cycle:
00269       seqNumCycle -= 0x10000;
00270     }
00271     
00272     newSeqNum = seqNumCycle|seqNum;
00273     if (newSeqNum < fBaseExtSeqNumReceived) {
00274       fBaseExtSeqNumReceived = newSeqNum;
00275     }
00276   }
00277 
00278   // Record the inter-packet delay
00279   struct timeval timeNow;
00280   gettimeofday(&timeNow, NULL);
00281   if (fLastPacketReceptionTime.tv_sec != 0
00282       || fLastPacketReceptionTime.tv_usec != 0) {
00283     unsigned gap
00284       = (timeNow.tv_sec - fLastPacketReceptionTime.tv_sec)*MILLION
00285       + timeNow.tv_usec - fLastPacketReceptionTime.tv_usec; 
00286     if (gap > fMaxInterPacketGapUS) {
00287       fMaxInterPacketGapUS = gap;
00288     }
00289     if (gap < fMinInterPacketGapUS) {
00290       fMinInterPacketGapUS = gap;
00291     }
00292     fTotalInterPacketGaps.tv_usec += gap;
00293     if (fTotalInterPacketGaps.tv_usec >= MILLION) {
00294       ++fTotalInterPacketGaps.tv_sec;
00295       fTotalInterPacketGaps.tv_usec -= MILLION;
00296     }
00297   }
00298   fLastPacketReceptionTime = timeNow;
00299 
00300   // Compute the current 'jitter' using the received packet's RTP timestamp,
00301   // and the RTP timestamp that would correspond to the current time.
00302   // (Use the code from appendix A.8 in the RTP spec.)
00303   // Note, however, that we don't use this packet if its timestamp is
00304   // the same as that of the previous packet (this indicates a multi-packet
00305   // fragment), or if we've been explicitly told not to use this packet.
00306   if (useForJitterCalculation
00307       && rtpTimestamp != fPreviousPacketRTPTimestamp) {
00308     unsigned arrival = (timestampFrequency*timeNow.tv_sec);
00309     arrival += (unsigned)
00310       ((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000);
00311             // note: rounding
00312     int transit = arrival - rtpTimestamp;
00313     if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time
00314     int d = transit - fLastTransit;
00315     fLastTransit = transit;
00316     if (d < 0) d = -d;
00317     fJitter += (1.0/16.0) * ((double)d - fJitter);
00318   }
00319 
00320   // Return the 'presentation time' that corresponds to "rtpTimestamp":
00321   if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) {
00322     // This is the first timestamp that we've seen, so use the current
00323     // 'wall clock' time as the synchronization time.  (This will be
00324     // corrected later when we receive RTCP SRs.)
00325     fSyncTimestamp = rtpTimestamp;
00326     fSyncTime = timeNow;
00327   }
00328 
00329   int timestampDiff = rtpTimestamp - fSyncTimestamp;
00330       // Note: This works even if the timestamp wraps around
00331       // (as long as "int" is 32 bits)
00332 
00333   // Divide this by the timestamp frequency to get real time:
00334   double timeDiff = timestampDiff/(double)timestampFrequency;
00335 
00336   // Add this to the 'sync time' to get our result:
00337   unsigned const million = 1000000;
00338   unsigned seconds, uSeconds;
00339   if (timeDiff >= 0.0) {
00340     seconds = fSyncTime.tv_sec + (unsigned)(timeDiff);
00341     uSeconds = fSyncTime.tv_usec
00342       + (unsigned)((timeDiff - (unsigned)timeDiff)*million);
00343     if (uSeconds >= million) {
00344       uSeconds -= million;
00345       ++seconds;
00346     }
00347   } else {
00348     timeDiff = -timeDiff;
00349     seconds = fSyncTime.tv_sec - (unsigned)(timeDiff);
00350     uSeconds = fSyncTime.tv_usec
00351       - (unsigned)((timeDiff - (unsigned)timeDiff)*million);
00352     if ((int)uSeconds < 0) {
00353       uSeconds += million;
00354       --seconds;
00355     }
00356   }
00357   resultPresentationTime.tv_sec = seconds;
00358   resultPresentationTime.tv_usec = uSeconds;
00359   resultHasBeenSyncedUsingRTCP = fHasBeenSynchronized;
00360 
00361   // Save these as the new synchronization timestamp & time:
00362   fSyncTimestamp = rtpTimestamp;
00363   fSyncTime = resultPresentationTime;
00364 
00365   fPreviousPacketRTPTimestamp = rtpTimestamp;
00366 }
00367 
00368 void RTPReceptionStats::noteIncomingSR(u_int32_t ntpTimestampMSW,
00369                                        u_int32_t ntpTimestampLSW,
00370                                        u_int32_t rtpTimestamp) {
00371   fLastReceivedSR_NTPmsw = ntpTimestampMSW;
00372   fLastReceivedSR_NTPlsw = ntpTimestampLSW;
00373 
00374   gettimeofday(&fLastReceivedSR_time, NULL);
00375 
00376   // Use this SR to update time synchronization information:
00377   fSyncTimestamp = rtpTimestamp;
00378   fSyncTime.tv_sec = ntpTimestampMSW - 0x83AA7E80; // 1/1/1900 -> 1/1/1970
00379   double microseconds = (ntpTimestampLSW*15625.0)/0x04000000; // 10^6/2^32
00380   fSyncTime.tv_usec = (unsigned)(microseconds+0.5);
00381   fHasBeenSynchronized = True;
00382 }
00383 
00384 double RTPReceptionStats::totNumKBytesReceived() const {
00385   double const hiMultiplier = 0x20000000/125.0; // == (2^32)/(10^3)
00386   return fTotBytesReceived_hi*hiMultiplier + fTotBytesReceived_lo/1000.0;
00387 }
00388 
00389 unsigned RTPReceptionStats::jitter() const {
00390   return (unsigned)fJitter;
00391 }
00392 
00393 void RTPReceptionStats::reset() {
00394   fNumPacketsReceivedSinceLastReset = 0;
00395   fLastResetExtSeqNumReceived = fHighestExtSeqNumReceived;
00396 }
00397 
00398 Boolean seqNumLT(u_int16_t s1, u_int16_t s2) {
00399   // a 'less-than' on 16-bit sequence numbers
00400   int diff = s2-s1;
00401   if (diff > 0) {
00402     return (diff < 0x8000);
00403   } else if (diff < 0) {
00404     return (diff < -0x8000);
00405   } else { // diff == 0
00406     return False;
00407   }
00408 }

Generated on Mon Apr 29 13:28:03 2013 for live by  doxygen 1.5.2