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 #include "absl/types/optional.h"
13 #include "modules/rtp_rtcp/source/time_util.h"
14 #include "system_wrappers/include/clock.h"
15 #include "system_wrappers/include/ntp_time.h"
16 #include "test/gmock.h"
17 #include "test/gtest.h"
18
19 namespace webrtc {
20
21 constexpr int64_t kTestRtt = 10;
22 constexpr int64_t kLocalClockInitialTimeMs = 123;
23 constexpr int64_t kRemoteClockInitialTimeMs = 345;
24 constexpr uint32_t kTimestampOffset = 567;
25 constexpr int64_t kRemoteToLocalClockOffsetMs =
26 kLocalClockInitialTimeMs - kRemoteClockInitialTimeMs;
27
28 class RemoteNtpTimeEstimatorTest : public ::testing::Test {
29 protected:
RemoteNtpTimeEstimatorTest()30 RemoteNtpTimeEstimatorTest()
31 : local_clock_(kLocalClockInitialTimeMs * 1000),
32 remote_clock_(kRemoteClockInitialTimeMs * 1000),
33 estimator_(new RemoteNtpTimeEstimator(&local_clock_)) {}
34 ~RemoteNtpTimeEstimatorTest() override = default;
35
AdvanceTimeMilliseconds(int64_t ms)36 void AdvanceTimeMilliseconds(int64_t ms) {
37 local_clock_.AdvanceTimeMilliseconds(ms);
38 remote_clock_.AdvanceTimeMilliseconds(ms);
39 }
40
GetRemoteTimestamp()41 uint32_t GetRemoteTimestamp() {
42 return static_cast<uint32_t>(remote_clock_.TimeInMilliseconds()) * 90 +
43 kTimestampOffset;
44 }
45
GetRemoteNtpTime()46 NtpTime GetRemoteNtpTime() {
47 return TimeMicrosToNtp(remote_clock_.TimeInMicroseconds());
48 }
49
SendRtcpSr()50 void SendRtcpSr() {
51 uint32_t rtcp_timestamp = GetRemoteTimestamp();
52 NtpTime ntp = GetRemoteNtpTime();
53
54 AdvanceTimeMilliseconds(kTestRtt / 2);
55 ReceiveRtcpSr(kTestRtt, rtcp_timestamp, ntp.seconds(), ntp.fractions());
56 }
57
SendRtcpSrInaccurately(int64_t ntp_error_ms,int64_t networking_delay_ms)58 void SendRtcpSrInaccurately(int64_t ntp_error_ms,
59 int64_t networking_delay_ms) {
60 uint32_t rtcp_timestamp = GetRemoteTimestamp();
61 int64_t ntp_error_fractions =
62 ntp_error_ms * static_cast<int64_t>(NtpTime::kFractionsPerSecond) /
63 1000;
64 NtpTime ntp(static_cast<uint64_t>(GetRemoteNtpTime()) +
65 ntp_error_fractions);
66 AdvanceTimeMilliseconds(kTestRtt / 2 + networking_delay_ms);
67 ReceiveRtcpSr(kTestRtt, rtcp_timestamp, ntp.seconds(), ntp.fractions());
68 }
69
UpdateRtcpTimestamp(int64_t rtt,uint32_t ntp_secs,uint32_t ntp_frac,uint32_t rtp_timestamp,bool expected_result)70 void UpdateRtcpTimestamp(int64_t rtt,
71 uint32_t ntp_secs,
72 uint32_t ntp_frac,
73 uint32_t rtp_timestamp,
74 bool expected_result) {
75 EXPECT_EQ(expected_result, estimator_->UpdateRtcpTimestamp(
76 rtt, ntp_secs, ntp_frac, rtp_timestamp));
77 }
78
ReceiveRtcpSr(int64_t rtt,uint32_t rtcp_timestamp,uint32_t ntp_seconds,uint32_t ntp_fractions)79 void ReceiveRtcpSr(int64_t rtt,
80 uint32_t rtcp_timestamp,
81 uint32_t ntp_seconds,
82 uint32_t ntp_fractions) {
83 UpdateRtcpTimestamp(rtt, ntp_seconds, ntp_fractions, rtcp_timestamp, true);
84 }
85
86 SimulatedClock local_clock_;
87 SimulatedClock remote_clock_;
88 std::unique_ptr<RemoteNtpTimeEstimator> estimator_;
89 };
90
TEST_F(RemoteNtpTimeEstimatorTest,Estimate)91 TEST_F(RemoteNtpTimeEstimatorTest, Estimate) {
92 // Failed without valid NTP.
93 UpdateRtcpTimestamp(kTestRtt, 0, 0, 0, false);
94
95 AdvanceTimeMilliseconds(1000);
96 // Remote peer sends first RTCP SR.
97 SendRtcpSr();
98
99 // Remote sends a RTP packet.
100 AdvanceTimeMilliseconds(15);
101 uint32_t rtp_timestamp = GetRemoteTimestamp();
102 int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
103
104 // Local peer needs at least 2 RTCP SR to calculate the capture time.
105 const int64_t kNotEnoughRtcpSr = -1;
106 EXPECT_EQ(kNotEnoughRtcpSr, estimator_->Estimate(rtp_timestamp));
107 EXPECT_EQ(absl::nullopt, estimator_->EstimateRemoteToLocalClockOffsetMs());
108
109 AdvanceTimeMilliseconds(800);
110 // Remote sends second RTCP SR.
111 SendRtcpSr();
112
113 // Local peer gets enough RTCP SR to calculate the capture time.
114 EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
115 EXPECT_EQ(kRemoteToLocalClockOffsetMs,
116 estimator_->EstimateRemoteToLocalClockOffsetMs());
117 }
118
TEST_F(RemoteNtpTimeEstimatorTest,AveragesErrorsOut)119 TEST_F(RemoteNtpTimeEstimatorTest, AveragesErrorsOut) {
120 // Remote peer sends first 10 RTCP SR without errors.
121 for (int i = 0; i < 10; ++i) {
122 AdvanceTimeMilliseconds(1000);
123 SendRtcpSr();
124 }
125
126 AdvanceTimeMilliseconds(150);
127 uint32_t rtp_timestamp = GetRemoteTimestamp();
128 int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
129 // Local peer gets enough RTCP SR to calculate the capture time.
130 EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
131 EXPECT_EQ(kRemoteToLocalClockOffsetMs,
132 estimator_->EstimateRemoteToLocalClockOffsetMs());
133
134 // Remote sends corrupted RTCP SRs
135 AdvanceTimeMilliseconds(1000);
136 SendRtcpSrInaccurately(/*ntp_error_ms=*/2, /*networking_delay_ms=*/-1);
137 AdvanceTimeMilliseconds(1000);
138 SendRtcpSrInaccurately(/*ntp_error_ms=*/-2, /*networking_delay_ms=*/1);
139
140 // New RTP packet to estimate timestamp.
141 AdvanceTimeMilliseconds(150);
142 rtp_timestamp = GetRemoteTimestamp();
143 capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
144
145 // Errors should be averaged out.
146 EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
147 EXPECT_EQ(kRemoteToLocalClockOffsetMs,
148 estimator_->EstimateRemoteToLocalClockOffsetMs());
149 }
150
151 } // namespace webrtc
152