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