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

Reply via email to