xref: /aosp_15_r20/external/webrtc/system_wrappers/include/ntp_time.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #ifndef SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
11*d9f75844SAndroid Build Coastguard Worker #define SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <cmath>
14*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
15*d9f75844SAndroid Build Coastguard Worker #include <limits>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker class NtpTime {
22*d9f75844SAndroid Build Coastguard Worker  public:
23*d9f75844SAndroid Build Coastguard Worker   static constexpr uint64_t kFractionsPerSecond = 0x100000000;
NtpTime()24*d9f75844SAndroid Build Coastguard Worker   NtpTime() : value_(0) {}
NtpTime(uint64_t value)25*d9f75844SAndroid Build Coastguard Worker   explicit NtpTime(uint64_t value) : value_(value) {}
NtpTime(uint32_t seconds,uint32_t fractions)26*d9f75844SAndroid Build Coastguard Worker   NtpTime(uint32_t seconds, uint32_t fractions)
27*d9f75844SAndroid Build Coastguard Worker       : value_(seconds * kFractionsPerSecond + fractions) {}
28*d9f75844SAndroid Build Coastguard Worker 
29*d9f75844SAndroid Build Coastguard Worker   NtpTime(const NtpTime&) = default;
30*d9f75844SAndroid Build Coastguard Worker   NtpTime& operator=(const NtpTime&) = default;
uint64_t()31*d9f75844SAndroid Build Coastguard Worker   explicit operator uint64_t() const { return value_; }
32*d9f75844SAndroid Build Coastguard Worker 
Set(uint32_t seconds,uint32_t fractions)33*d9f75844SAndroid Build Coastguard Worker   void Set(uint32_t seconds, uint32_t fractions) {
34*d9f75844SAndroid Build Coastguard Worker     value_ = seconds * kFractionsPerSecond + fractions;
35*d9f75844SAndroid Build Coastguard Worker   }
Reset()36*d9f75844SAndroid Build Coastguard Worker   void Reset() { value_ = 0; }
37*d9f75844SAndroid Build Coastguard Worker 
ToMs()38*d9f75844SAndroid Build Coastguard Worker   int64_t ToMs() const {
39*d9f75844SAndroid Build Coastguard Worker     static constexpr double kNtpFracPerMs = 4.294967296E6;  // 2^32 / 1000.
40*d9f75844SAndroid Build Coastguard Worker     const double frac_ms = static_cast<double>(fractions()) / kNtpFracPerMs;
41*d9f75844SAndroid Build Coastguard Worker     return 1000 * static_cast<int64_t>(seconds()) +
42*d9f75844SAndroid Build Coastguard Worker            static_cast<int64_t>(frac_ms + 0.5);
43*d9f75844SAndroid Build Coastguard Worker   }
44*d9f75844SAndroid Build Coastguard Worker   // NTP standard (RFC1305, section 3.1) explicitly state value 0 is invalid.
Valid()45*d9f75844SAndroid Build Coastguard Worker   bool Valid() const { return value_ != 0; }
46*d9f75844SAndroid Build Coastguard Worker 
seconds()47*d9f75844SAndroid Build Coastguard Worker   uint32_t seconds() const {
48*d9f75844SAndroid Build Coastguard Worker     return rtc::dchecked_cast<uint32_t>(value_ / kFractionsPerSecond);
49*d9f75844SAndroid Build Coastguard Worker   }
fractions()50*d9f75844SAndroid Build Coastguard Worker   uint32_t fractions() const {
51*d9f75844SAndroid Build Coastguard Worker     return rtc::dchecked_cast<uint32_t>(value_ % kFractionsPerSecond);
52*d9f75844SAndroid Build Coastguard Worker   }
53*d9f75844SAndroid Build Coastguard Worker 
54*d9f75844SAndroid Build Coastguard Worker  private:
55*d9f75844SAndroid Build Coastguard Worker   uint64_t value_;
56*d9f75844SAndroid Build Coastguard Worker };
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker inline bool operator==(const NtpTime& n1, const NtpTime& n2) {
59*d9f75844SAndroid Build Coastguard Worker   return static_cast<uint64_t>(n1) == static_cast<uint64_t>(n2);
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker inline bool operator!=(const NtpTime& n1, const NtpTime& n2) {
62*d9f75844SAndroid Build Coastguard Worker   return !(n1 == n2);
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker // Converts `int64_t` milliseconds to Q32.32-formatted fixed-point seconds.
66*d9f75844SAndroid Build Coastguard Worker // Performs clamping if the result overflows or underflows.
Int64MsToQ32x32(int64_t milliseconds)67*d9f75844SAndroid Build Coastguard Worker inline int64_t Int64MsToQ32x32(int64_t milliseconds) {
68*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/10893): Change to use `rtc::saturated_cast` once the
69*d9f75844SAndroid Build Coastguard Worker   // bug has been fixed.
70*d9f75844SAndroid Build Coastguard Worker   double result =
71*d9f75844SAndroid Build Coastguard Worker       std::round(milliseconds * (NtpTime::kFractionsPerSecond / 1000.0));
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker   // Explicitly cast values to double to avoid implicit conversion warnings
74*d9f75844SAndroid Build Coastguard Worker   // The conversion of the std::numeric_limits<int64_t>::max() triggers
75*d9f75844SAndroid Build Coastguard Worker   // -Wimplicit-int-float-conversion warning in clang 10.0.0 without explicit
76*d9f75844SAndroid Build Coastguard Worker   // cast
77*d9f75844SAndroid Build Coastguard Worker   if (result <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
78*d9f75844SAndroid Build Coastguard Worker     return std::numeric_limits<int64_t>::min();
79*d9f75844SAndroid Build Coastguard Worker   }
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker   if (result >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
82*d9f75844SAndroid Build Coastguard Worker     return std::numeric_limits<int64_t>::max();
83*d9f75844SAndroid Build Coastguard Worker   }
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker   return rtc::dchecked_cast<int64_t>(result);
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker // Converts `int64_t` milliseconds to UQ32.32-formatted fixed-point seconds.
89*d9f75844SAndroid Build Coastguard Worker // Performs clamping if the result overflows or underflows.
Int64MsToUQ32x32(int64_t milliseconds)90*d9f75844SAndroid Build Coastguard Worker inline uint64_t Int64MsToUQ32x32(int64_t milliseconds) {
91*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/10893): Change to use `rtc::saturated_cast` once the
92*d9f75844SAndroid Build Coastguard Worker   // bug has been fixed.
93*d9f75844SAndroid Build Coastguard Worker   double result =
94*d9f75844SAndroid Build Coastguard Worker       std::round(milliseconds * (NtpTime::kFractionsPerSecond / 1000.0));
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   // Explicitly cast values to double to avoid implicit conversion warnings
97*d9f75844SAndroid Build Coastguard Worker   // The conversion of the std::numeric_limits<int64_t>::max() triggers
98*d9f75844SAndroid Build Coastguard Worker   // -Wimplicit-int-float-conversion warning in clang 10.0.0 without explicit
99*d9f75844SAndroid Build Coastguard Worker   // cast
100*d9f75844SAndroid Build Coastguard Worker   if (result <= static_cast<double>(std::numeric_limits<uint64_t>::min())) {
101*d9f75844SAndroid Build Coastguard Worker     return std::numeric_limits<uint64_t>::min();
102*d9f75844SAndroid Build Coastguard Worker   }
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker   if (result >= static_cast<double>(std::numeric_limits<uint64_t>::max())) {
105*d9f75844SAndroid Build Coastguard Worker     return std::numeric_limits<uint64_t>::max();
106*d9f75844SAndroid Build Coastguard Worker   }
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker   return rtc::dchecked_cast<uint64_t>(result);
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker 
111*d9f75844SAndroid Build Coastguard Worker // Converts Q32.32-formatted fixed-point seconds to `int64_t` milliseconds.
Q32x32ToInt64Ms(int64_t q32x32)112*d9f75844SAndroid Build Coastguard Worker inline int64_t Q32x32ToInt64Ms(int64_t q32x32) {
113*d9f75844SAndroid Build Coastguard Worker   return rtc::dchecked_cast<int64_t>(
114*d9f75844SAndroid Build Coastguard Worker       std::round(q32x32 * (1000.0 / NtpTime::kFractionsPerSecond)));
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker 
117*d9f75844SAndroid Build Coastguard Worker // Converts UQ32.32-formatted fixed-point seconds to `int64_t` milliseconds.
UQ32x32ToInt64Ms(uint64_t q32x32)118*d9f75844SAndroid Build Coastguard Worker inline int64_t UQ32x32ToInt64Ms(uint64_t q32x32) {
119*d9f75844SAndroid Build Coastguard Worker   return rtc::dchecked_cast<int64_t>(
120*d9f75844SAndroid Build Coastguard Worker       std::round(q32x32 * (1000.0 / NtpTime::kFractionsPerSecond)));
121*d9f75844SAndroid Build Coastguard Worker }
122*d9f75844SAndroid Build Coastguard Worker 
123*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
124*d9f75844SAndroid Build Coastguard Worker #endif  // SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
125