--- a/liveMedia/RTPSource.cpp 2008-06-23 13:55:51.000000000 -0400 +++ b/liveMedia/RTPSource.cpp 2008-06-24 07:43:45.000000000 -0400 @@ -363,12 +363,54 @@ gettimeofday(&fLastReceivedSR_time, NULL); - // Use this SR to update time synchronization information: - fSyncTimestamp = rtpTimestamp; - fSyncTime.tv_sec = ntpTimestampMSW - 0x83AA7E80; // 1/1/1900 -> 1/1/1970 - double microseconds = (ntpTimestampLSW*15625.0)/0x04000000; // 10^6/2^32 - fSyncTime.tv_usec = (unsigned)(microseconds+0.5); - fHasBeenSynchronized = True; + struct timeval delta, newSyncTime, normalized; + + + int timestampDiff = rtpTimestamp - fSyncTimestamp; + if (rtpTimestamp >= 0 && (ntpTimestampMSW || ntpTimestampLSW)) { + // Normalize the last Sync time since there has been a delay since it was + // last recorded + double timeDiff + = timestampDiff/(double)(fOurRTPSource.timestampFrequency()); + + normalized.tv_sec = fSyncTime.tv_sec + (unsigned)timeDiff; + normalized.tv_usec = fSyncTime.tv_usec + + (unsigned)((timeDiff - (unsigned)timeDiff)*MILLION); + if (normalized.tv_usec >= MILLION) { + normalized.tv_usec -= MILLION; + ++normalized.tv_sec; + } + + // Convert the NTP Timestamp into a UNIX epoch timeval + newSyncTime.tv_sec = ntpTimestampMSW - 0x83AA7E80; // 1/1/1900 -> 1/1/1970 + double microseconds = (ntpTimestampLSW*15625.0)/0x04000000; // 10^6/2^32 + newSyncTime.tv_usec = (unsigned)(microseconds+0.5); + + // Compare the last synchronized time to the new NTP time + delta.tv_sec = newSyncTime.tv_sec - normalized.tv_sec; + delta.tv_usec = newSyncTime.tv_usec - normalized.tv_usec; + if (delta.tv_usec < 0) { + delta.tv_sec--; + delta.tv_usec += MILLION; + } + + // We need to limit how far we're willing to adjust an already established + // clock in the name of synchronization. Decreasing the time may cause the + // receiver to reject new "old" packets. Increasing the time may result in + // an equivalent delay in playback. + // + // The sender is not even required to send a NTP timestamp derived from NTP + // or any other accurate clock. Some cameras will derive their timestamp as + // time since boot up which works out to some time in the early 1970s. +#define MAX_SR_TIME_SKEW 5 // Clocks must be within 5s to sync + if ((fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) || + abs(delta.tv_sec) < MAX_SR_TIME_SKEW) { + // Use this SR to update time synchronization information: + fSyncTimestamp = rtpTimestamp; + fSyncTime = newSyncTime; + fHasBeenSynchronized = True; + } + } } double RTPReceptionStats::totNumKBytesReceived() const {