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
19 namespace webrtc {
20
21 namespace {
22
23 constexpr int kMinimumNumberOfSamples = 2;
24 constexpr int kTimingLogIntervalMs = 10000;
25 constexpr int kClocksOffsetSmoothingWindow = 100;
26
27 } // namespace
28
29 // TODO(wu): Refactor this class so that it can be shared with
30 // vie_sync_module.cc.
RemoteNtpTimeEstimator(Clock * clock)31 RemoteNtpTimeEstimator::RemoteNtpTimeEstimator(Clock* clock)
32 : clock_(clock),
33 ntp_clocks_offset_estimator_(kClocksOffsetSmoothingWindow),
34 last_timing_log_ms_(-1) {}
35
~RemoteNtpTimeEstimator()36 RemoteNtpTimeEstimator::~RemoteNtpTimeEstimator() {}
37
UpdateRtcpTimestamp(int64_t rtt,uint32_t ntp_secs,uint32_t ntp_frac,uint32_t rtp_timestamp)38 bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(int64_t rtt,
39 uint32_t ntp_secs,
40 uint32_t ntp_frac,
41 uint32_t rtp_timestamp) {
42 bool new_rtcp_sr = false;
43 if (!rtp_to_ntp_.UpdateMeasurements(ntp_secs, ntp_frac, rtp_timestamp,
44 &new_rtcp_sr)) {
45 return false;
46 }
47 if (!new_rtcp_sr) {
48 // No new RTCP SR since last time this function was called.
49 return true;
50 }
51
52 // Update extrapolator with the new arrival time.
53 // The extrapolator assumes the ntp time.
54 int64_t receiver_arrival_time_ms =
55 clock_->TimeInMilliseconds() + NtpOffsetMs();
56 int64_t sender_send_time_ms = Clock::NtpToMs(ntp_secs, ntp_frac);
57 int64_t sender_arrival_time_ms = sender_send_time_ms + rtt / 2;
58 int64_t remote_to_local_clocks_offset =
59 receiver_arrival_time_ms - sender_arrival_time_ms;
60 ntp_clocks_offset_estimator_.Insert(remote_to_local_clocks_offset);
61 return true;
62 }
63
Estimate(uint32_t rtp_timestamp)64 int64_t RemoteNtpTimeEstimator::Estimate(uint32_t rtp_timestamp) {
65 int64_t sender_capture_ntp_ms = 0;
66 if (!rtp_to_ntp_.Estimate(rtp_timestamp, &sender_capture_ntp_ms)) {
67 return -1;
68 }
69
70 int64_t remote_to_local_clocks_offset =
71 ntp_clocks_offset_estimator_.GetFilteredValue();
72 int64_t receiver_capture_ntp_ms =
73 sender_capture_ntp_ms + remote_to_local_clocks_offset;
74
75 // TODO(bugs.webrtc.org/11327): Clock::CurrentNtpInMilliseconds() was
76 // previously used to calculate the offset between the local and the remote
77 // clock. However, rtc::TimeMillis() + NtpOffsetMs() is now used as the local
78 // ntp clock value. To preserve the old behavior of this method, the return
79 // value is adjusted with the difference between the two local ntp clocks.
80 int64_t now_ms = clock_->TimeInMilliseconds();
81 int64_t offset_between_local_ntp_clocks =
82 clock_->CurrentNtpInMilliseconds() - now_ms - NtpOffsetMs();
83 receiver_capture_ntp_ms += offset_between_local_ntp_clocks;
84
85 if (now_ms - last_timing_log_ms_ > kTimingLogIntervalMs) {
86 RTC_LOG(LS_INFO) << "RTP timestamp: " << rtp_timestamp
87 << " in NTP clock: " << sender_capture_ntp_ms
88 << " estimated time in receiver NTP clock: "
89 << receiver_capture_ntp_ms;
90 last_timing_log_ms_ = now_ms;
91 }
92 return receiver_capture_ntp_ms;
93 }
94
95 absl::optional<int64_t>
EstimateRemoteToLocalClockOffsetMs()96 RemoteNtpTimeEstimator::EstimateRemoteToLocalClockOffsetMs() {
97 if (ntp_clocks_offset_estimator_.GetNumberOfSamplesStored() <
98 kMinimumNumberOfSamples) {
99 return absl::nullopt;
100 }
101 return ntp_clocks_offset_estimator_.GetFilteredValue();
102 }
103
104 } // namespace webrtc
105