MythTV  0.26-pre
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 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2005 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),
00057     fRTPPayloadFormat(rtpPayloadFormat),
00058     fTimestampFrequency(rtpTimestampFrequency),
00059     fSSRC(our_random32()) {
00060   fReceptionStatsDB = new RTPReceptionStatsDB(*this);
00061 }
00062 
00063 RTPSource::~RTPSource() {
00064   delete fReceptionStatsDB;
00065 }
00066 
00067 void RTPSource::getAttributes() const {
00068   envir().setResultMsg(""); // Fix later to get attributes from  header #####
00069 }
00070 
00071 
00073 
00074 RTPReceptionStatsDB::RTPReceptionStatsDB(RTPSource& rtpSource)
00075   : fOurRTPSource(rtpSource),
00076     fTable(HashTable::create(ONE_WORD_HASH_KEYS)), fTotNumPacketsReceived(0) {
00077   reset();
00078 }
00079 
00080 void RTPReceptionStatsDB::reset() {
00081   fNumActiveSourcesSinceLastReset = 0;
00082 
00083   Iterator iter(*this);
00084   RTPReceptionStats* stats;
00085   while ((stats = iter.next()) != NULL) {
00086     stats->reset();
00087   }
00088 }
00089 
00090 RTPReceptionStatsDB::~RTPReceptionStatsDB() {
00091   // First, remove and delete all stats records from the table:
00092   RTPReceptionStats* stats;
00093   while ((stats = (RTPReceptionStats*)fTable->RemoveNext()) != NULL) {
00094     delete stats;
00095   }
00096 
00097   // Then, delete the table itself:
00098   delete fTable;
00099 }
00100 
00101 void RTPReceptionStatsDB
00102 ::noteIncomingPacket(u_int32_t SSRC, u_int16_t seqNum,
00103                      u_int32_t rtpTimestamp, unsigned timestampFrequency,
00104                      Boolean useForJitterCalculation,
00105                      struct timeval& resultPresentationTime,
00106                      Boolean& resultHasBeenSyncedUsingRTCP,
00107                      unsigned packetSize) {
00108   ++fTotNumPacketsReceived;
00109   RTPReceptionStats* stats = lookup(SSRC);
00110   if (stats == NULL) {
00111     // This is the first time we've heard from this SSRC.
00112     // Create a new record for it:
00113     stats = new RTPReceptionStats(fOurRTPSource, SSRC, seqNum);
00114     if (stats == NULL) return;
00115     add(SSRC, stats);
00116   }
00117 
00118   if (stats->numPacketsReceivedSinceLastReset() == 0) {
00119     ++fNumActiveSourcesSinceLastReset;
00120   }
00121 
00122   stats->noteIncomingPacket(seqNum, rtpTimestamp, timestampFrequency,
00123                             useForJitterCalculation,
00124                             resultPresentationTime,
00125                             resultHasBeenSyncedUsingRTCP, packetSize);
00126 }
00127 
00128 void RTPReceptionStatsDB
00129 ::noteIncomingSR(u_int32_t SSRC,
00130                  u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
00131                  u_int32_t rtpTimestamp) {
00132   RTPReceptionStats* stats = lookup(SSRC);
00133   if (stats == NULL) {
00134     // This is the first time we've heard of this SSRC.
00135     // Create a new record for it:
00136     stats = new RTPReceptionStats(fOurRTPSource, SSRC);
00137     if (stats == NULL) return;
00138     add(SSRC, stats);
00139   }
00140 
00141   stats->noteIncomingSR(ntpTimestampMSW, ntpTimestampLSW, rtpTimestamp);
00142 }
00143 
00144 void RTPReceptionStatsDB::removeRecord(u_int32_t SSRC) {
00145   RTPReceptionStats* stats = lookup(SSRC);
00146   if (stats != NULL) {
00147     long SSRC_long = (long)SSRC;
00148     fTable->Remove((char const*)SSRC_long);
00149     delete stats;
00150   }
00151 }
00152 
00153 RTPReceptionStatsDB::Iterator
00154 ::Iterator(RTPReceptionStatsDB& receptionStatsDB)
00155   : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
00156 }
00157 
00158 RTPReceptionStatsDB::Iterator::~Iterator() {
00159   delete fIter;
00160 }
00161 
00162 RTPReceptionStats*
00163 RTPReceptionStatsDB::Iterator::next(Boolean includeInactiveSources) {
00164   char const* key; // dummy
00165 
00166   // If asked, skip over any sources that haven't been active
00167   // since the last reset:
00168   RTPReceptionStats* stats;
00169   do {
00170     stats = (RTPReceptionStats*)(fIter->next(key));
00171   } while (stats != NULL && !includeInactiveSources
00172            && stats->numPacketsReceivedSinceLastReset() == 0);
00173 
00174   return stats;
00175 }
00176 
00177 RTPReceptionStats* RTPReceptionStatsDB::lookup(u_int32_t SSRC) const {
00178   long SSRC_long = (long)SSRC;
00179   return (RTPReceptionStats*)(fTable->Lookup((char const*)SSRC_long));
00180 }
00181 
00182 void RTPReceptionStatsDB::add(u_int32_t SSRC, RTPReceptionStats* stats) {
00183   long SSRC_long = (long)SSRC;
00184   fTable->Add((char const*)SSRC_long, stats);
00185 }
00186 
00188 
00189 RTPReceptionStats::RTPReceptionStats(RTPSource& rtpSource, u_int32_t SSRC,
00190                                      u_int16_t initialSeqNum)
00191   : fOurRTPSource(rtpSource) {
00192   initSeqNum(initialSeqNum);
00193   init(SSRC);
00194 }
00195 
00196 RTPReceptionStats::RTPReceptionStats(RTPSource& rtpSource, u_int32_t SSRC)
00197   : fOurRTPSource(rtpSource) {
00198   init(SSRC);
00199 }
00200 
00201 RTPReceptionStats::~RTPReceptionStats() {
00202 }
00203 
00204 void RTPReceptionStats::init(u_int32_t SSRC) {
00205   fSSRC = SSRC;
00206   fTotNumPacketsReceived = 0;
00207   fTotBytesReceived_hi = fTotBytesReceived_lo = 0;
00208   fHaveSeenInitialSequenceNumber = False;
00209   fLastTransit = ~0;
00210   fPreviousPacketRTPTimestamp = 0;
00211   fJitter = 0.0;
00212   fLastReceivedSR_NTPmsw = fLastReceivedSR_NTPlsw = 0;
00213   fLastReceivedSR_time.tv_sec = fLastReceivedSR_time.tv_usec = 0;
00214   fLastPacketReceptionTime.tv_sec = fLastPacketReceptionTime.tv_usec = 0;
00215   fMinInterPacketGapUS = 0x7FFFFFFF;
00216   fMaxInterPacketGapUS = 0;
00217   fTotalInterPacketGaps.tv_sec = fTotalInterPacketGaps.tv_usec = 0;
00218   fHasBeenSynchronized = False;
00219   fSyncTime.tv_sec = fSyncTime.tv_usec = 0;
00220   reset();
00221 }
00222 
00223 void RTPReceptionStats::initSeqNum(u_int16_t initialSeqNum) {
00224     fBaseExtSeqNumReceived = initialSeqNum-1;
00225     fHighestExtSeqNumReceived = initialSeqNum;
00226     fHaveSeenInitialSequenceNumber = True;
00227 }
00228 
00229 #ifndef MILLION
00230 #define MILLION 1000000
00231 #endif
00232 
00233 void RTPReceptionStats
00234 ::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
00235                      unsigned timestampFrequency,
00236                      Boolean useForJitterCalculation,
00237                      struct timeval& resultPresentationTime,
00238                      Boolean& resultHasBeenSyncedUsingRTCP,
00239                      unsigned packetSize) {
00240   if (!fHaveSeenInitialSequenceNumber) initSeqNum(seqNum);
00241 
00242   ++fNumPacketsReceivedSinceLastReset;
00243   ++fTotNumPacketsReceived;
00244   u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo;
00245   fTotBytesReceived_lo += packetSize;
00246   if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around
00247     ++fTotBytesReceived_hi;
00248   }
00249 
00250   // Check whether the sequence number has wrapped around:
00251   unsigned seqNumCycle = (fHighestExtSeqNumReceived&0xFFFF0000);
00252   unsigned oldSeqNum = (fHighestExtSeqNumReceived&0xFFFF);
00253   unsigned seqNumDifference = (unsigned)((int)seqNum-(int)oldSeqNum);
00254   if (seqNumDifference >= 0x8000
00255       && seqNumLT((u_int16_t)oldSeqNum, seqNum)) {
00256     // sequence number wrapped around => start a new cycle:
00257     seqNumCycle += 0x10000;
00258   }
00259 
00260   unsigned newSeqNum = seqNumCycle|seqNum;
00261   if (newSeqNum > fHighestExtSeqNumReceived) {
00262     fHighestExtSeqNumReceived = newSeqNum;
00263   }
00264 
00265   // Record the inter-packet delay
00266   struct timeval timeNow;
00267   gettimeofday(&timeNow, NULL);
00268   if (fLastPacketReceptionTime.tv_sec != 0
00269       || fLastPacketReceptionTime.tv_usec != 0) {
00270     unsigned gap
00271       = (timeNow.tv_sec - fLastPacketReceptionTime.tv_sec)*MILLION
00272       + timeNow.tv_usec - fLastPacketReceptionTime.tv_usec; 
00273     if (gap > fMaxInterPacketGapUS) {
00274       fMaxInterPacketGapUS = gap;
00275     }
00276     if (gap < fMinInterPacketGapUS) {
00277       fMinInterPacketGapUS = gap;
00278     }
00279     fTotalInterPacketGaps.tv_usec += gap;
00280     if (fTotalInterPacketGaps.tv_usec >= MILLION) {
00281       ++fTotalInterPacketGaps.tv_sec;
00282       fTotalInterPacketGaps.tv_usec -= MILLION;
00283     }
00284   }
00285   fLastPacketReceptionTime = timeNow;
00286 
00287   // Compute the current 'jitter' using the received packet's RTP timestamp,
00288   // and the RTP timestamp that would correspond to the current time.
00289   // (Use the code from appendix A.8 in the RTP spec.)
00290   // Note, however, that we don't use this packet if its timestamp is
00291   // the same as that of the previous packet (this indicates a multi-packet
00292   // fragment), or if we've been explicitly told not to use this packet.
00293   if (useForJitterCalculation
00294       && rtpTimestamp != fPreviousPacketRTPTimestamp) {
00295     unsigned arrival = (timestampFrequency*timeNow.tv_sec);
00296     arrival += (unsigned)
00297       ((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000);
00298             // note: rounding
00299     int transit = arrival - rtpTimestamp;
00300     if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time
00301     int d = transit - fLastTransit;
00302     fLastTransit = transit;
00303     if (d < 0) d = -d;
00304     fJitter += (1.0/16.0) * ((double)d - fJitter);
00305   }
00306 
00307   // Return the 'presentation time' that corresponds to "rtpTimestamp":
00308   if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) {
00309     // This is the first timestamp that we've seen, so use the current
00310     // 'wall clock' time as the synchronization time.  (This will be
00311     // corrected later when we receive RTCP SRs.)
00312     fSyncTimestamp = rtpTimestamp;
00313     fSyncTime = timeNow;
00314   }
00315 
00316   int timestampDiff = rtpTimestamp - fSyncTimestamp;
00317       // Note: This works even if the timestamp wraps around
00318       // (as long as "int" is 32 bits)
00319 
00320   // Divide this by the timestamp frequency to get real time:
00321   double timeDiff
00322     = timestampDiff/(double)(fOurRTPSource.timestampFrequency());
00323 
00324   // Add this to the 'sync time' to get our result:
00325   unsigned const million = 1000000;
00326   unsigned seconds, uSeconds;
00327   if (timeDiff >= 0.0) {
00328     seconds = fSyncTime.tv_sec + (unsigned)(timeDiff);
00329     uSeconds = fSyncTime.tv_usec
00330       + (unsigned)((timeDiff - (unsigned)timeDiff)*million);
00331     if (uSeconds >= million) {
00332       uSeconds -= million;
00333       ++seconds;
00334     }
00335   } else {
00336     timeDiff = -timeDiff;
00337     seconds = fSyncTime.tv_sec - (unsigned)(timeDiff);
00338     uSeconds = fSyncTime.tv_usec
00339       - (unsigned)((timeDiff - (unsigned)timeDiff)*million);
00340     if ((int)uSeconds < 0) {
00341       uSeconds += million;
00342       --seconds;
00343     }
00344   }
00345   resultPresentationTime.tv_sec = seconds;
00346   resultPresentationTime.tv_usec = uSeconds;
00347   resultHasBeenSyncedUsingRTCP = fHasBeenSynchronized;
00348 
00349   // Save these as the new synchronization timestamp & time:
00350   fSyncTimestamp = rtpTimestamp;
00351   fSyncTime = resultPresentationTime;
00352 
00353   fPreviousPacketRTPTimestamp = rtpTimestamp;
00354 }
00355 
00356 void RTPReceptionStats::noteIncomingSR(u_int32_t ntpTimestampMSW,
00357                                        u_int32_t ntpTimestampLSW,
00358                                        u_int32_t rtpTimestamp) {
00359   fLastReceivedSR_NTPmsw = ntpTimestampMSW;
00360   fLastReceivedSR_NTPlsw = ntpTimestampLSW;
00361 
00362   gettimeofday(&fLastReceivedSR_time, NULL);
00363 
00364   // Use this SR to update time synchronization information:
00365   fSyncTimestamp = rtpTimestamp;
00366   fSyncTime.tv_sec = ntpTimestampMSW - 0x83AA7E80; // 1/1/1900 -> 1/1/1970
00367   double microseconds = (ntpTimestampLSW*15625.0)/0x04000000; // 10^6/2^32
00368   fSyncTime.tv_usec = (unsigned)(microseconds+0.5);
00369   fHasBeenSynchronized = True;
00370 }
00371 
00372 double RTPReceptionStats::totNumKBytesReceived() const {
00373   double const hiMultiplier = 0x20000000/125.0; // == (2^32)/(10^3)
00374   return fTotBytesReceived_hi*hiMultiplier + fTotBytesReceived_lo/1000.0;
00375 }
00376 
00377 unsigned RTPReceptionStats::jitter() const {
00378   return (unsigned)fJitter;
00379 }
00380 
00381 void RTPReceptionStats::reset() {
00382   fNumPacketsReceivedSinceLastReset = 0;
00383   fLastResetExtSeqNumReceived = fHighestExtSeqNumReceived;
00384 }
00385 
00386 Boolean seqNumLT(u_int16_t s1, u_int16_t s2) {
00387   // a 'less-than' on 16-bit sequence numbers
00388   int diff = s2-s1;
00389   if (diff > 0) {
00390     return (diff < 0x8000);
00391   } else if (diff < 0) {
00392     return (diff < -0x8000);
00393   } else { // diff == 0
00394     return False;
00395   }
00396 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends