I had a problem when using VLC to transcode from an AXIS camera into an RTP stream. In the RTCP Sender Report the AXIS camera is deriving its NTP time from the monotonic uptime instead of the wall clock. Then it converts it from unix epoch time into NTP time.
The real issue is that VLC/live555 start issuing timestamps based on the local wall clock. Then several seconds later the RTCP SR includes a timestamp which significantly alters the timestamps in the name of synchronization. Then VLC starts rejecting the new timestamps since they appear to be in the past. The attached diff will only synchronize the timestamp if: the timestamp has never been set; or the sender's and receiver's clocks appear to be on the same time reference. It determines the latter if they are less than five seconds apart. .mike
--- 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 {
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel