1 /*
2 * Copyright (c) 2012 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 "system_wrappers/include/rtp_to_ntp_estimator.h"
12
13 #include <stddef.h>
14
15 #include "rtc_base/random.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19 namespace {
20 constexpr uint64_t kOneMsInNtp = 4294967;
21 constexpr uint64_t kOneHourInNtp = uint64_t{60 * 60} << 32;
22 constexpr uint32_t kTimestampTicksPerMs = 90;
23 } // namespace
24
TEST(WrapAroundTests,OldRtcpWrapped_OldRtpTimestamp)25 TEST(WrapAroundTests, OldRtcpWrapped_OldRtpTimestamp) {
26 RtpToNtpEstimator estimator;
27 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(kOneMsInNtp), 0),
28 RtpToNtpEstimator::kNewMeasurement);
29 // No wraparound will be detected, since we are not allowed to wrap below 0,
30 // but there will be huge rtp timestamp jump, e.g. old_timestamp = 0,
31 // new_timestamp = 4294967295, which should be detected.
32 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(2 * kOneMsInNtp),
33 -kTimestampTicksPerMs),
34 RtpToNtpEstimator::kInvalidMeasurement);
35 }
36
TEST(WrapAroundTests,OldRtcpWrapped_OldRtpTimestamp_Wraparound_Detected)37 TEST(WrapAroundTests, OldRtcpWrapped_OldRtpTimestamp_Wraparound_Detected) {
38 RtpToNtpEstimator estimator;
39 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), 0xFFFFFFFE),
40 RtpToNtpEstimator::kNewMeasurement);
41 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + 2 * kOneMsInNtp),
42 0xFFFFFFFE + 2 * kTimestampTicksPerMs),
43 RtpToNtpEstimator::kNewMeasurement);
44 // Expected to fail since the older RTCP has a smaller RTP timestamp than the
45 // newer (old:10, new:4294967206).
46 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + 3 * kOneMsInNtp),
47 0xFFFFFFFE + kTimestampTicksPerMs),
48 RtpToNtpEstimator::kInvalidMeasurement);
49 }
50
TEST(WrapAroundTests,NewRtcpWrapped)51 TEST(WrapAroundTests, NewRtcpWrapped) {
52 RtpToNtpEstimator estimator;
53 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), 0xFFFFFFFF),
54 RtpToNtpEstimator::kNewMeasurement);
55 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + kOneMsInNtp),
56 0xFFFFFFFF + kTimestampTicksPerMs),
57 RtpToNtpEstimator::kNewMeasurement);
58 // Since this RTP packet has the same timestamp as the RTCP packet constructed
59 // at time 0 it should be mapped to 0 as well.
60 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF), NtpTime(1));
61 }
62
TEST(WrapAroundTests,RtpWrapped)63 TEST(WrapAroundTests, RtpWrapped) {
64 RtpToNtpEstimator estimator;
65 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1),
66 0xFFFFFFFF - 2 * kTimestampTicksPerMs),
67 RtpToNtpEstimator::kNewMeasurement);
68 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + kOneMsInNtp),
69 0xFFFFFFFF - kTimestampTicksPerMs),
70 RtpToNtpEstimator::kNewMeasurement);
71
72 // Since this RTP packet has the same timestamp as the RTCP packet constructed
73 // at time 0 it should be mapped to 0 as well.
74 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF - 2 * kTimestampTicksPerMs),
75 NtpTime(1));
76 // Two kTimestampTicksPerMs advanced.
77 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF), NtpTime(1 + 2 * kOneMsInNtp));
78 // Wrapped rtp.
79 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF + kTimestampTicksPerMs),
80 NtpTime(1 + 3 * kOneMsInNtp));
81 }
82
TEST(WrapAroundTests,OldRtp_RtcpsWrapped)83 TEST(WrapAroundTests, OldRtp_RtcpsWrapped) {
84 RtpToNtpEstimator estimator;
85 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), 0xFFFFFFFF),
86 RtpToNtpEstimator::kNewMeasurement);
87 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + kOneMsInNtp),
88 0xFFFFFFFF + kTimestampTicksPerMs),
89 RtpToNtpEstimator::kNewMeasurement);
90
91 EXPECT_FALSE(estimator.Estimate(0xFFFFFFFF - kTimestampTicksPerMs).Valid());
92 }
93
TEST(WrapAroundTests,OldRtp_NewRtcpWrapped)94 TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) {
95 RtpToNtpEstimator estimator;
96 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), 0xFFFFFFFF),
97 RtpToNtpEstimator::kNewMeasurement);
98 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + kOneMsInNtp),
99 0xFFFFFFFF + kTimestampTicksPerMs),
100 RtpToNtpEstimator::kNewMeasurement);
101
102 // Constructed at the same time as the first RTCP and should therefore be
103 // mapped to zero.
104 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF), NtpTime(1));
105 }
106
TEST(WrapAroundTests,GracefullyHandleRtpJump)107 TEST(WrapAroundTests, GracefullyHandleRtpJump) {
108 RtpToNtpEstimator estimator;
109 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), 0xFFFFFFFF),
110 RtpToNtpEstimator::kNewMeasurement);
111 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1 + kOneMsInNtp),
112 0xFFFFFFFF + kTimestampTicksPerMs),
113 RtpToNtpEstimator::kNewMeasurement);
114
115 // Constructed at the same time as the first RTCP and should therefore be
116 // mapped to zero.
117 EXPECT_EQ(estimator.Estimate(0xFFFFFFFF), NtpTime(1));
118
119 uint32_t timestamp = 0xFFFFFFFF - 0xFFFFF;
120 uint64_t ntp_raw = 1 + 2 * kOneMsInNtp;
121 for (int i = 0; i < RtpToNtpEstimator::kMaxInvalidSamples - 1; ++i) {
122 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw), timestamp),
123 RtpToNtpEstimator::kInvalidMeasurement);
124 ntp_raw += kOneMsInNtp;
125 timestamp += kTimestampTicksPerMs;
126 }
127 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw), timestamp),
128 RtpToNtpEstimator::kNewMeasurement);
129 ntp_raw += kOneMsInNtp;
130 timestamp += kTimestampTicksPerMs;
131 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw), timestamp),
132 RtpToNtpEstimator::kNewMeasurement);
133
134 EXPECT_EQ(estimator.Estimate(timestamp), NtpTime(ntp_raw));
135 }
136
TEST(UpdateRtcpMeasurementTests,FailsForZeroNtp)137 TEST(UpdateRtcpMeasurementTests, FailsForZeroNtp) {
138 RtpToNtpEstimator estimator;
139
140 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(0), 0x12345678),
141 RtpToNtpEstimator::kInvalidMeasurement);
142 }
143
TEST(UpdateRtcpMeasurementTests,FailsForEqualNtp)144 TEST(UpdateRtcpMeasurementTests, FailsForEqualNtp) {
145 RtpToNtpEstimator estimator;
146 NtpTime ntp(0, 699925050);
147 uint32_t timestamp = 0x12345678;
148
149 EXPECT_EQ(estimator.UpdateMeasurements(ntp, timestamp),
150 RtpToNtpEstimator::kNewMeasurement);
151 // Ntp time already added, list not updated.
152 EXPECT_EQ(estimator.UpdateMeasurements(ntp, timestamp + 1),
153 RtpToNtpEstimator::kSameMeasurement);
154 }
155
TEST(UpdateRtcpMeasurementTests,FailsForOldNtp)156 TEST(UpdateRtcpMeasurementTests, FailsForOldNtp) {
157 RtpToNtpEstimator estimator;
158 uint64_t ntp_raw = 699925050;
159 NtpTime ntp(ntp_raw);
160 uint32_t timestamp = 0x12345678;
161 EXPECT_EQ(estimator.UpdateMeasurements(ntp, timestamp),
162 RtpToNtpEstimator::kNewMeasurement);
163
164 // Old ntp time, list not updated.
165 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw - kOneMsInNtp),
166 timestamp + kTimestampTicksPerMs),
167 RtpToNtpEstimator::kInvalidMeasurement);
168 }
169
TEST(UpdateRtcpMeasurementTests,FailsForTooNewNtp)170 TEST(UpdateRtcpMeasurementTests, FailsForTooNewNtp) {
171 RtpToNtpEstimator estimator;
172
173 uint64_t ntp_raw = 699925050;
174 uint32_t timestamp = 0x12345678;
175 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw), timestamp),
176 RtpToNtpEstimator::kNewMeasurement);
177
178 // Ntp time from far future, list not updated.
179 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw + 2 * kOneHourInNtp),
180 timestamp + 10 * kTimestampTicksPerMs),
181 RtpToNtpEstimator::kInvalidMeasurement);
182 }
183
TEST(UpdateRtcpMeasurementTests,FailsForEqualTimestamp)184 TEST(UpdateRtcpMeasurementTests, FailsForEqualTimestamp) {
185 RtpToNtpEstimator estimator;
186
187 uint32_t timestamp = 0x12345678;
188 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(2), timestamp),
189 RtpToNtpEstimator::kNewMeasurement);
190 // Timestamp already added, list not updated.
191 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(3), timestamp),
192 RtpToNtpEstimator::kSameMeasurement);
193 }
194
TEST(UpdateRtcpMeasurementTests,FailsForOldRtpTimestamp)195 TEST(UpdateRtcpMeasurementTests, FailsForOldRtpTimestamp) {
196 RtpToNtpEstimator estimator;
197 uint32_t timestamp = 0x12345678;
198
199 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(2), timestamp),
200 RtpToNtpEstimator::kNewMeasurement);
201 // Old timestamp, list not updated.
202 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(2 + kOneMsInNtp),
203 timestamp - kTimestampTicksPerMs),
204 RtpToNtpEstimator::kInvalidMeasurement);
205 }
206
TEST(UpdateRtcpMeasurementTests,VerifyParameters)207 TEST(UpdateRtcpMeasurementTests, VerifyParameters) {
208 RtpToNtpEstimator estimator;
209 uint32_t timestamp = 0x12345678;
210
211 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(kOneMsInNtp), timestamp),
212 RtpToNtpEstimator::kNewMeasurement);
213
214 EXPECT_DOUBLE_EQ(estimator.EstimatedFrequencyKhz(), 0.0);
215
216 // Add second report, parameters should be calculated.
217 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(2 * kOneMsInNtp),
218 timestamp + kTimestampTicksPerMs),
219 RtpToNtpEstimator::kNewMeasurement);
220
221 EXPECT_NEAR(estimator.EstimatedFrequencyKhz(), kTimestampTicksPerMs, 0.01);
222 }
223
TEST(RtpToNtpTests,FailsForNoParameters)224 TEST(RtpToNtpTests, FailsForNoParameters) {
225 RtpToNtpEstimator estimator;
226 uint32_t timestamp = 0x12345678;
227
228 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(1), timestamp),
229 RtpToNtpEstimator::kNewMeasurement);
230 // Parameters are not calculated, conversion of RTP to NTP time should fail.
231 EXPECT_DOUBLE_EQ(estimator.EstimatedFrequencyKhz(), 0.0);
232 EXPECT_FALSE(estimator.Estimate(timestamp).Valid());
233 }
234
TEST(RtpToNtpTests,AveragesErrorOut)235 TEST(RtpToNtpTests, AveragesErrorOut) {
236 RtpToNtpEstimator estimator;
237 uint64_t ntp_raw = 90000000; // More than 1 ms.
238 ASSERT_GT(ntp_raw, kOneMsInNtp);
239 uint32_t timestamp = 0x12345678;
240 constexpr uint64_t kNtpSecStep = uint64_t{1} << 32; // 1 second.
241 constexpr int kRtpTicksPerMs = 90;
242 constexpr int kRtpStep = kRtpTicksPerMs * 1000;
243
244 EXPECT_EQ(estimator.UpdateMeasurements(NtpTime(ntp_raw), timestamp),
245 RtpToNtpEstimator::kNewMeasurement);
246
247 Random rand(1123536L);
248 for (size_t i = 0; i < 1000; i++) {
249 // Advance both timestamps by exactly 1 second.
250 ntp_raw += kNtpSecStep;
251 timestamp += kRtpStep;
252 // Add upto 1ms of errors to NTP and RTP timestamps passed to estimator.
253 EXPECT_EQ(
254 estimator.UpdateMeasurements(
255 NtpTime(ntp_raw + rand.Rand(-int{kOneMsInNtp}, int{kOneMsInNtp})),
256 timestamp + rand.Rand(-kRtpTicksPerMs, kRtpTicksPerMs)),
257 RtpToNtpEstimator::kNewMeasurement);
258
259 NtpTime estimated_ntp = estimator.Estimate(timestamp);
260 EXPECT_TRUE(estimated_ntp.Valid());
261 // Allow upto 2 ms of error.
262 EXPECT_NEAR(ntp_raw, static_cast<uint64_t>(estimated_ntp), 2 * kOneMsInNtp);
263 }
264 }
265
266 } // namespace webrtc
267