xref: /aosp_15_r20/external/openscreen/cast/streaming/ntp_time.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/ntp_time.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard namespace openscreen {
10*3f982cf4SFabien Sanglard namespace cast {
11*3f982cf4SFabien Sanglard 
12*3f982cf4SFabien Sanglard namespace {
13*3f982cf4SFabien Sanglard 
14*3f982cf4SFabien Sanglard // The number of seconds between 1 January 1900 and 1 January 1970.
15*3f982cf4SFabien Sanglard constexpr NtpSeconds kTimeBetweenNtpEpochAndUnixEpoch{INT64_C(2208988800)};
16*3f982cf4SFabien Sanglard 
17*3f982cf4SFabien Sanglard }  // namespace
18*3f982cf4SFabien Sanglard 
NtpTimeConverter(Clock::time_point now,std::chrono::seconds since_unix_epoch)19*3f982cf4SFabien Sanglard NtpTimeConverter::NtpTimeConverter(Clock::time_point now,
20*3f982cf4SFabien Sanglard                                    std::chrono::seconds since_unix_epoch)
21*3f982cf4SFabien Sanglard     : start_time_(now),
22*3f982cf4SFabien Sanglard       since_ntp_epoch_(
23*3f982cf4SFabien Sanglard           std::chrono::duration_cast<NtpSeconds>(since_unix_epoch) +
24*3f982cf4SFabien Sanglard           kTimeBetweenNtpEpochAndUnixEpoch) {}
25*3f982cf4SFabien Sanglard 
26*3f982cf4SFabien Sanglard NtpTimeConverter::~NtpTimeConverter() = default;
27*3f982cf4SFabien Sanglard 
ToNtpTimestamp(Clock::time_point time_point) const28*3f982cf4SFabien Sanglard NtpTimestamp NtpTimeConverter::ToNtpTimestamp(
29*3f982cf4SFabien Sanglard     Clock::time_point time_point) const {
30*3f982cf4SFabien Sanglard   const Clock::duration time_since_start = time_point - start_time_;
31*3f982cf4SFabien Sanglard   const auto whole_seconds =
32*3f982cf4SFabien Sanglard       std::chrono::duration_cast<NtpSeconds>(time_since_start);
33*3f982cf4SFabien Sanglard   const auto remainder =
34*3f982cf4SFabien Sanglard       std::chrono::duration_cast<NtpFraction>(time_since_start - whole_seconds);
35*3f982cf4SFabien Sanglard   return AssembleNtpTimestamp(since_ntp_epoch_ + whole_seconds, remainder);
36*3f982cf4SFabien Sanglard }
37*3f982cf4SFabien Sanglard 
ToLocalTime(NtpTimestamp timestamp) const38*3f982cf4SFabien Sanglard Clock::time_point NtpTimeConverter::ToLocalTime(NtpTimestamp timestamp) const {
39*3f982cf4SFabien Sanglard   auto ntp_seconds = NtpSecondsPart(timestamp);
40*3f982cf4SFabien Sanglard   // Year 2036 wrap-around check: If the NTP timestamp appears to be a
41*3f982cf4SFabien Sanglard   // point-in-time before 1970, assume the 2036 wrap-around has occurred, and
42*3f982cf4SFabien Sanglard   // adjust to compensate.
43*3f982cf4SFabien Sanglard   if (ntp_seconds <= kTimeBetweenNtpEpochAndUnixEpoch) {
44*3f982cf4SFabien Sanglard     constexpr NtpSeconds kNtpSecondsPerEra{INT64_C(1) << 32};
45*3f982cf4SFabien Sanglard     ntp_seconds += kNtpSecondsPerEra;
46*3f982cf4SFabien Sanglard   }
47*3f982cf4SFabien Sanglard 
48*3f982cf4SFabien Sanglard   const auto whole_seconds = ntp_seconds - since_ntp_epoch_;
49*3f982cf4SFabien Sanglard   const auto seconds_since_start =
50*3f982cf4SFabien Sanglard       Clock::to_duration(whole_seconds) + start_time_;
51*3f982cf4SFabien Sanglard   const auto remainder = Clock::to_duration(NtpFractionPart(timestamp));
52*3f982cf4SFabien Sanglard   return seconds_since_start + remainder;
53*3f982cf4SFabien Sanglard }
54*3f982cf4SFabien Sanglard 
55*3f982cf4SFabien Sanglard }  // namespace cast
56*3f982cf4SFabien Sanglard }  // namespace openscreen
57