• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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