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