|
MythTV
0.26-pre
|
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 }
1.7.6.1