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