// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CAST_STREAMING_NTP_TIME_H_ #define CAST_STREAMING_NTP_TIME_H_ #include #include "platform/api/time.h" namespace cast { namespace streaming { // NTP timestamps are 64-bit timestamps that consist of two 32-bit parts: 1) The // number of seconds since 1 January 1900; and 2) The fraction of the second, // where 0 maps to 0x00000000 and each unit increment represents another 2^-32 // seconds. // // Note that it is part of the design of NTP for the seconds part to roll around // on 7 February 2036. using NtpTimestamp = uint64_t; // NTP fixed-point time math: Declare two std::chrono::duration types with the // bit-width necessary to reliably perform all conversions to/from NTP format. using NtpSeconds = std::chrono::duration; using NtpFraction = std::chrono::duration>; constexpr NtpSeconds NtpSecondsPart(NtpTimestamp timestamp) { return NtpSeconds(timestamp >> 32); } constexpr NtpFraction NtpFractionPart(NtpTimestamp timestamp) { return NtpFraction(timestamp & 0xffffffff); } constexpr NtpTimestamp AssembleNtpTimestamp(NtpSeconds seconds, NtpFraction fraction) { return (static_cast(seconds.count()) << 32) | static_cast(fraction.count()); } // Converts between openscreen::platform::Clock::time_points and NtpTimestamps. // The class is instantiated with the current openscreen::platform::Clock time // and the current wall clock time, and these are used to determine a fixed // origin reference point for all conversions. Thus, to avoid introducing // unintended timing-related behaviors, only one NtpTimeConverter instance // should be used for converting all the NTP timestamps in the same streaming // session. class NtpTimeConverter { public: NtpTimeConverter(openscreen::platform::Clock::time_point now, std::chrono::seconds since_unix_epoch = openscreen::platform::GetWallTimeSinceUnixEpoch()); ~NtpTimeConverter(); NtpTimestamp ToNtpTimestamp( openscreen::platform::Clock::time_point time_point) const; openscreen::platform::Clock::time_point ToLocalTime( NtpTimestamp timestamp) const; private: // The time point on the platform clock's timeline that corresponds to // approximately the same time point on the NTP timeline. Note that it is // acceptable for the granularity of the NTP seconds value to be whole seconds // here: Both a Cast Streaming Sender and Receiver will assume their clocks // can be off (with respect to each other) by even a large amount; and all // that matters is that time ticks forward at a reasonable pace from some // initial point. const openscreen::platform::Clock::time_point start_time_; const NtpSeconds since_ntp_epoch_; }; } // namespace streaming } // namespace cast #endif // CAST_STREAMING_NTP_TIME_H_