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 const uint32_t kOneMsInNtpFrac = 4294967;
21 const uint32_t kOneHourInNtpSec = 60 * 60;
22 const uint32_t kTimestampTicksPerMs = 90;
23 }  // namespace
24 
TEST(WrapAroundTests,OldRtcpWrapped_OldRtpTimestamp)25 TEST(WrapAroundTests, OldRtcpWrapped_OldRtpTimestamp) {
26   RtpToNtpEstimator estimator;
27   bool new_sr;
28   uint32_t ntp_sec = 0;
29   uint32_t ntp_frac = 1;
30   uint32_t timestamp = 0;
31   EXPECT_TRUE(
32       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
33   ntp_frac += kOneMsInNtpFrac;
34   timestamp -= kTimestampTicksPerMs;
35   // No wraparound will be detected, since we are not allowed to wrap below 0,
36   // but there will be huge rtp timestamp jump, e.g. old_timestamp = 0,
37   // new_timestamp = 4294967295, which should be detected.
38   EXPECT_FALSE(
39       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
40 }
41 
TEST(WrapAroundTests,OldRtcpWrapped_OldRtpTimestamp_Wraparound_Detected)42 TEST(WrapAroundTests, OldRtcpWrapped_OldRtpTimestamp_Wraparound_Detected) {
43   RtpToNtpEstimator estimator;
44   bool new_sr;
45   uint32_t ntp_sec = 0;
46   uint32_t ntp_frac = 1;
47   uint32_t timestamp = 0xFFFFFFFE;
48   EXPECT_TRUE(
49       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
50   ntp_frac += 2 * kOneMsInNtpFrac;
51   timestamp += 2 * kTimestampTicksPerMs;
52   EXPECT_TRUE(
53       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
54   ntp_frac += kOneMsInNtpFrac;
55   timestamp -= kTimestampTicksPerMs;
56   // Expected to fail since the older RTCP has a smaller RTP timestamp than the
57   // newer (old:10, new:4294967206).
58   EXPECT_FALSE(
59       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
60 }
61 
TEST(WrapAroundTests,NewRtcpWrapped)62 TEST(WrapAroundTests, NewRtcpWrapped) {
63   RtpToNtpEstimator estimator;
64   bool new_sr;
65   uint32_t ntp_sec = 0;
66   uint32_t ntp_frac = 1;
67   uint32_t timestamp = 0xFFFFFFFF;
68   EXPECT_TRUE(
69       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
70   ntp_frac += kOneMsInNtpFrac;
71   timestamp += kTimestampTicksPerMs;
72   EXPECT_TRUE(
73       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
74   int64_t timestamp_ms = -1;
75   EXPECT_TRUE(estimator.Estimate(0xFFFFFFFF, &timestamp_ms));
76   // Since this RTP packet has the same timestamp as the RTCP packet constructed
77   // at time 0 it should be mapped to 0 as well.
78   EXPECT_EQ(0, timestamp_ms);
79 }
80 
TEST(WrapAroundTests,RtpWrapped)81 TEST(WrapAroundTests, RtpWrapped) {
82   RtpToNtpEstimator estimator;
83   bool new_sr;
84   uint32_t ntp_sec = 0;
85   uint32_t ntp_frac = 1;
86   uint32_t timestamp = 0xFFFFFFFF - 2 * kTimestampTicksPerMs;
87   EXPECT_TRUE(
88       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
89   ntp_frac += kOneMsInNtpFrac;
90   timestamp += kTimestampTicksPerMs;
91   EXPECT_TRUE(
92       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
93 
94   int64_t timestamp_ms = -1;
95   EXPECT_TRUE(
96       estimator.Estimate(0xFFFFFFFF - 2 * kTimestampTicksPerMs, &timestamp_ms));
97   // Since this RTP packet has the same timestamp as the RTCP packet constructed
98   // at time 0 it should be mapped to 0 as well.
99   EXPECT_EQ(0, timestamp_ms);
100   // Two kTimestampTicksPerMs advanced.
101   timestamp += kTimestampTicksPerMs;
102   EXPECT_TRUE(estimator.Estimate(timestamp, &timestamp_ms));
103   EXPECT_EQ(2, timestamp_ms);
104   // Wrapped rtp.
105   timestamp += kTimestampTicksPerMs;
106   EXPECT_TRUE(estimator.Estimate(timestamp, &timestamp_ms));
107   EXPECT_EQ(3, timestamp_ms);
108 }
109 
TEST(WrapAroundTests,OldRtp_RtcpsWrapped)110 TEST(WrapAroundTests, OldRtp_RtcpsWrapped) {
111   RtpToNtpEstimator estimator;
112   bool new_sr;
113   uint32_t ntp_sec = 0;
114   uint32_t ntp_frac = 1;
115   uint32_t timestamp = 0xFFFFFFFF;
116   EXPECT_TRUE(
117       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
118   ntp_frac += kOneMsInNtpFrac;
119   timestamp += kTimestampTicksPerMs;
120   EXPECT_TRUE(
121       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
122   timestamp -= 2 * kTimestampTicksPerMs;
123   int64_t timestamp_ms = 0xFFFFFFFF;
124   EXPECT_FALSE(estimator.Estimate(timestamp, &timestamp_ms));
125 }
126 
TEST(WrapAroundTests,OldRtp_NewRtcpWrapped)127 TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) {
128   RtpToNtpEstimator estimator;
129   bool new_sr;
130   uint32_t ntp_sec = 0;
131   uint32_t ntp_frac = 1;
132   uint32_t timestamp = 0xFFFFFFFF;
133   EXPECT_TRUE(
134       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
135   ntp_frac += kOneMsInNtpFrac;
136   timestamp += kTimestampTicksPerMs;
137   EXPECT_TRUE(
138       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
139   timestamp -= kTimestampTicksPerMs;
140   int64_t timestamp_ms = -1;
141   EXPECT_TRUE(estimator.Estimate(timestamp, &timestamp_ms));
142   // Constructed at the same time as the first RTCP and should therefore be
143   // mapped to zero.
144   EXPECT_EQ(0, timestamp_ms);
145 }
146 
TEST(WrapAroundTests,GracefullyHandleRtpJump)147 TEST(WrapAroundTests, GracefullyHandleRtpJump) {
148   RtpToNtpEstimator estimator;
149   bool new_sr;
150   uint32_t ntp_sec = 0;
151   uint32_t ntp_frac = 1;
152   uint32_t timestamp = 0;
153   EXPECT_TRUE(
154       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
155   ntp_frac += kOneMsInNtpFrac;
156   timestamp += kTimestampTicksPerMs;
157   EXPECT_TRUE(
158       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
159   ntp_frac += kOneMsInNtpFrac;
160   timestamp -= kTimestampTicksPerMs;
161   int64_t timestamp_ms = -1;
162   EXPECT_TRUE(estimator.Estimate(timestamp, &timestamp_ms));
163   // Constructed at the same time as the first RTCP and should therefore be
164   // mapped to zero.
165   EXPECT_EQ(0, timestamp_ms);
166 
167   timestamp -= 0xFFFFF;
168   for (int i = 0; i < RtpToNtpEstimator::kMaxInvalidSamples - 1; ++i) {
169     EXPECT_FALSE(
170         estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
171     ntp_frac += kOneMsInNtpFrac;
172     timestamp += kTimestampTicksPerMs;
173   }
174   EXPECT_TRUE(
175       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
176   ntp_frac += kOneMsInNtpFrac;
177   timestamp += kTimestampTicksPerMs;
178   EXPECT_TRUE(
179       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
180   ntp_frac += kOneMsInNtpFrac;
181   timestamp += kTimestampTicksPerMs;
182 
183   timestamp_ms = -1;
184   EXPECT_TRUE(estimator.Estimate(timestamp, &timestamp_ms));
185   // 6 milliseconds has passed since the start of the test.
186   EXPECT_EQ(6, timestamp_ms);
187 }
188 
TEST(UpdateRtcpMeasurementTests,FailsForZeroNtp)189 TEST(UpdateRtcpMeasurementTests, FailsForZeroNtp) {
190   RtpToNtpEstimator estimator;
191   uint32_t ntp_sec = 0;
192   uint32_t ntp_frac = 0;
193   uint32_t timestamp = 0x12345678;
194   bool new_sr;
195   EXPECT_FALSE(
196       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
197   EXPECT_FALSE(new_sr);
198 }
199 
TEST(UpdateRtcpMeasurementTests,FailsForEqualNtp)200 TEST(UpdateRtcpMeasurementTests, FailsForEqualNtp) {
201   RtpToNtpEstimator estimator;
202   uint32_t ntp_sec = 0;
203   uint32_t ntp_frac = 699925050;
204   uint32_t timestamp = 0x12345678;
205   bool new_sr;
206   EXPECT_TRUE(
207       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
208   EXPECT_TRUE(new_sr);
209   // Ntp time already added, list not updated.
210   ++timestamp;
211   EXPECT_TRUE(
212       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
213   EXPECT_FALSE(new_sr);
214 }
215 
TEST(UpdateRtcpMeasurementTests,FailsForOldNtp)216 TEST(UpdateRtcpMeasurementTests, FailsForOldNtp) {
217   RtpToNtpEstimator estimator;
218   uint32_t ntp_sec = 1;
219   uint32_t ntp_frac = 699925050;
220   uint32_t timestamp = 0x12345678;
221   bool new_sr;
222   EXPECT_TRUE(
223       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
224   EXPECT_TRUE(new_sr);
225   // Old ntp time, list not updated.
226   ntp_frac -= kOneMsInNtpFrac;
227   timestamp += kTimestampTicksPerMs;
228   EXPECT_FALSE(
229       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
230 }
231 
TEST(UpdateRtcpMeasurementTests,FailsForTooNewNtp)232 TEST(UpdateRtcpMeasurementTests, FailsForTooNewNtp) {
233   RtpToNtpEstimator estimator;
234   uint32_t ntp_sec = 1;
235   uint32_t ntp_frac = 699925050;
236   uint32_t timestamp = 0x12345678;
237   bool new_sr;
238   EXPECT_TRUE(
239       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
240   EXPECT_TRUE(new_sr);
241   // Ntp time from far future, list not updated.
242   ntp_sec += kOneHourInNtpSec * 2;
243   timestamp += kTimestampTicksPerMs * 10;
244   EXPECT_FALSE(
245       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
246 }
247 
TEST(UpdateRtcpMeasurementTests,FailsForEqualTimestamp)248 TEST(UpdateRtcpMeasurementTests, FailsForEqualTimestamp) {
249   RtpToNtpEstimator estimator;
250   uint32_t ntp_sec = 0;
251   uint32_t ntp_frac = 2;
252   uint32_t timestamp = 0x12345678;
253   bool new_sr;
254   EXPECT_TRUE(
255       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
256   EXPECT_TRUE(new_sr);
257   // Timestamp already added, list not updated.
258   ++ntp_frac;
259   EXPECT_TRUE(
260       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
261   EXPECT_FALSE(new_sr);
262 }
263 
TEST(UpdateRtcpMeasurementTests,FailsForOldRtpTimestamp)264 TEST(UpdateRtcpMeasurementTests, FailsForOldRtpTimestamp) {
265   RtpToNtpEstimator estimator;
266   uint32_t ntp_sec = 0;
267   uint32_t ntp_frac = 2;
268   uint32_t timestamp = 0x12345678;
269   bool new_sr;
270   EXPECT_TRUE(
271       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
272   EXPECT_TRUE(new_sr);
273   // Old timestamp, list not updated.
274   ntp_frac += kOneMsInNtpFrac;
275   timestamp -= kTimestampTicksPerMs;
276   EXPECT_FALSE(
277       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
278   EXPECT_FALSE(new_sr);
279 }
280 
TEST(UpdateRtcpMeasurementTests,VerifyParameters)281 TEST(UpdateRtcpMeasurementTests, VerifyParameters) {
282   RtpToNtpEstimator estimator;
283   uint32_t ntp_sec = 1;
284   uint32_t ntp_frac = 2;
285   uint32_t timestamp = 0x12345678;
286   bool new_sr;
287   EXPECT_TRUE(
288       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
289   EXPECT_TRUE(new_sr);
290   EXPECT_FALSE(estimator.params());
291   // Add second report, parameters should be calculated.
292   ntp_frac += kOneMsInNtpFrac;
293   timestamp += kTimestampTicksPerMs;
294   EXPECT_TRUE(
295       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
296   EXPECT_TRUE(estimator.params());
297   EXPECT_DOUBLE_EQ(90.0, estimator.params()->frequency_khz);
298   EXPECT_NE(0.0, estimator.params()->offset_ms);
299 }
300 
TEST(RtpToNtpTests,FailsForNoParameters)301 TEST(RtpToNtpTests, FailsForNoParameters) {
302   RtpToNtpEstimator estimator;
303   uint32_t ntp_sec = 1;
304   uint32_t ntp_frac = 2;
305   uint32_t timestamp = 0x12345678;
306   bool new_sr;
307   EXPECT_TRUE(
308       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
309   EXPECT_TRUE(new_sr);
310   // Parameters are not calculated, conversion of RTP to NTP time should fail.
311   EXPECT_FALSE(estimator.params());
312   int64_t timestamp_ms = -1;
313   EXPECT_FALSE(estimator.Estimate(timestamp, &timestamp_ms));
314 }
315 
TEST(RtpToNtpTests,AveragesErrorOut)316 TEST(RtpToNtpTests, AveragesErrorOut) {
317   RtpToNtpEstimator estimator;
318   uint32_t ntp_sec = 1;
319   uint32_t ntp_frac = 90000000;  // More than 1 ms.
320   uint32_t timestamp = 0x12345678;
321   const int kNtpSecStep = 1;  // 1 second.
322   const int kRtpTicksPerMs = 90;
323   const int kRtpStep = kRtpTicksPerMs * 1000;
324   bool new_sr;
325   EXPECT_TRUE(
326       estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr));
327   EXPECT_TRUE(new_sr);
328 
329   Random rand(1123536L);
330   for (size_t i = 0; i < 1000; i++) {
331     // Advance both timestamps by exactly 1 second.
332     ntp_sec += kNtpSecStep;
333     timestamp += kRtpStep;
334     // Add upto 1ms of errors to NTP and RTP timestamps passed to estimator.
335     EXPECT_TRUE(estimator.UpdateMeasurements(
336         ntp_sec,
337         ntp_frac + rand.Rand(-static_cast<int>(kOneMsInNtpFrac),
338                              static_cast<int>(kOneMsInNtpFrac)),
339         timestamp + rand.Rand(-kRtpTicksPerMs, kRtpTicksPerMs), &new_sr));
340     EXPECT_TRUE(new_sr);
341 
342     int64_t estimated_ntp_ms;
343     EXPECT_TRUE(estimator.Estimate(timestamp, &estimated_ntp_ms));
344     // Allow upto 2 ms of error.
345     EXPECT_NEAR(NtpTime(ntp_sec, ntp_frac).ToMs(), estimated_ntp_ms, 2);
346   }
347 }
348 
349 }  // namespace webrtc
350