• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
12 
13 #include <cstdint>
14 
15 #include "modules/rtp_rtcp/source/time_util.h"
16 #include "rtc_base/logging.h"
17 #include "system_wrappers/include/clock.h"
18 #include "system_wrappers/include/ntp_time.h"
19 
20 namespace webrtc {
21 
22 namespace {
23 
24 constexpr int kMinimumNumberOfSamples = 2;
25 constexpr TimeDelta kTimingLogInterval = TimeDelta::Seconds(10);
26 constexpr int kClocksOffsetSmoothingWindow = 100;
27 
28 // Subtracts two NtpTime values keeping maximum precision.
Subtract(NtpTime minuend,NtpTime subtrahend)29 int64_t Subtract(NtpTime minuend, NtpTime subtrahend) {
30   uint64_t a = static_cast<uint64_t>(minuend);
31   uint64_t b = static_cast<uint64_t>(subtrahend);
32   return a >= b ? static_cast<int64_t>(a - b) : -static_cast<int64_t>(b - a);
33 }
34 
Add(NtpTime lhs,int64_t rhs)35 NtpTime Add(NtpTime lhs, int64_t rhs) {
36   uint64_t result = static_cast<uint64_t>(lhs);
37   if (rhs >= 0) {
38     result += static_cast<uint64_t>(rhs);
39   } else {
40     result -= static_cast<uint64_t>(-rhs);
41   }
42   return NtpTime(result);
43 }
44 
45 }  // namespace
46 
47 // TODO(wu): Refactor this class so that it can be shared with
48 // vie_sync_module.cc.
RemoteNtpTimeEstimator(Clock * clock)49 RemoteNtpTimeEstimator::RemoteNtpTimeEstimator(Clock* clock)
50     : clock_(clock),
51       ntp_clocks_offset_estimator_(kClocksOffsetSmoothingWindow) {}
52 
UpdateRtcpTimestamp(TimeDelta rtt,NtpTime sender_send_time,uint32_t rtp_timestamp)53 bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(TimeDelta rtt,
54                                                  NtpTime sender_send_time,
55                                                  uint32_t rtp_timestamp) {
56   switch (rtp_to_ntp_.UpdateMeasurements(sender_send_time, rtp_timestamp)) {
57     case RtpToNtpEstimator::kInvalidMeasurement:
58       return false;
59     case RtpToNtpEstimator::kSameMeasurement:
60       // No new RTCP SR since last time this function was called.
61       return true;
62     case RtpToNtpEstimator::kNewMeasurement:
63       break;
64   }
65 
66   // Assume connection is symmetric and thus time to deliver the packet is half
67   // the round trip time.
68   int64_t deliver_time_ntp = ToNtpUnits(rtt) / 2;
69 
70   // Update extrapolator with the new arrival time.
71   NtpTime receiver_arrival_time = clock_->CurrentNtpTime();
72   int64_t remote_to_local_clocks_offset =
73       Subtract(receiver_arrival_time, sender_send_time) - deliver_time_ntp;
74   ntp_clocks_offset_estimator_.Insert(remote_to_local_clocks_offset);
75   return true;
76 }
77 
EstimateNtp(uint32_t rtp_timestamp)78 NtpTime RemoteNtpTimeEstimator::EstimateNtp(uint32_t rtp_timestamp) {
79   NtpTime sender_capture = rtp_to_ntp_.Estimate(rtp_timestamp);
80   if (!sender_capture.Valid()) {
81     return sender_capture;
82   }
83 
84   int64_t remote_to_local_clocks_offset =
85       ntp_clocks_offset_estimator_.GetFilteredValue();
86   NtpTime receiver_capture = Add(sender_capture, remote_to_local_clocks_offset);
87 
88   Timestamp now = clock_->CurrentTime();
89   if (now - last_timing_log_ > kTimingLogInterval) {
90     RTC_LOG(LS_INFO) << "RTP timestamp: " << rtp_timestamp
91                      << " in NTP clock: " << sender_capture.ToMs()
92                      << " estimated time in receiver NTP clock: "
93                      << receiver_capture.ToMs();
94     last_timing_log_ = now;
95   }
96 
97   return receiver_capture;
98 }
99 
100 absl::optional<int64_t>
EstimateRemoteToLocalClockOffset()101 RemoteNtpTimeEstimator::EstimateRemoteToLocalClockOffset() {
102   if (ntp_clocks_offset_estimator_.GetNumberOfSamplesStored() <
103       kMinimumNumberOfSamples) {
104     return absl::nullopt;
105   }
106   return ntp_clocks_offset_estimator_.GetFilteredValue();
107 }
108 
109 }  // namespace webrtc
110