tsbpd_time.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * SRT - Secure, Reliable, Transport
  3. * Copyright (c) 2021 Haivision Systems Inc.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. */
  10. #ifndef INC_SRT_TSBPD_TIME_H
  11. #define INC_SRT_TSBPD_TIME_H
  12. #include "platform_sys.h"
  13. #include "sync.h"
  14. #include "utilities.h"
  15. namespace srt
  16. {
  17. /// @brief TimeStamp-Based Packet Delivery Mode (TSBPD) time conversion logic.
  18. /// Used by the receiver to calculate delivery time of data packets.
  19. /// See SRT Internet Draft Section "Timestamp-Based Packet Delivery".
  20. class CTsbpdTime
  21. {
  22. typedef srt::sync::steady_clock steady_clock;
  23. typedef steady_clock::time_point time_point;
  24. typedef steady_clock::duration duration;
  25. typedef srt::sync::Mutex Mutex;
  26. public:
  27. CTsbpdTime()
  28. : m_iFirstRTT(-1)
  29. , m_bTsbPdMode(false)
  30. , m_tdTsbPdDelay(0)
  31. , m_bTsbPdWrapCheck(false)
  32. {
  33. }
  34. /// Set TimeStamp-Based Packet Delivery Mode (receiver).
  35. /// @param [in] timebase local time base (uSec) of packet time stamps including buffering delay.
  36. /// @param [in] wrap wrapping period.
  37. /// @param [in] delay negotiated TsbPD delay (buffering latency).
  38. void setTsbPdMode(const time_point& timebase, bool wrap, duration delay);
  39. /// @brief Check if TSBPD logic is enabled.
  40. /// @return true if TSBPD is enabled.
  41. bool isEnabled() const { return m_bTsbPdMode; }
  42. /// @brief Apply new state derived from other members of a socket group.
  43. /// @param timebase TSBPD base time.
  44. /// @param wrp wrap period (enabled or not).
  45. /// @param delay TSBPD delay.
  46. /// @param udrift clock drift.
  47. void applyGroupTime(const time_point& timebase, bool wrp, uint32_t delay, const duration& udrift);
  48. /// @brief Apply new clock state (TSBPD base and drift) derived from other members of a socket group.
  49. /// @param timebase TSBPD base time.
  50. /// @param wrp state of the wrapping period (enabled or disabled).
  51. /// @param udrift clock drift.
  52. void applyGroupDrift(const time_point& timebase, bool wrp, const duration& udrift);
  53. /// @brief Add new drift sample from an ACK-ACKACK pair.
  54. /// ACKACK packets are sent immediately (except for UDP buffering).
  55. /// Therefore their timestamp roughly corresponds to the time of sending
  56. /// and can be used to estimate clock drift.
  57. ///
  58. /// @param [in] pktTimestamp Timestamp of the arrived ACKACK packet.
  59. /// @param [in] tsPktArrival packet arrival time.
  60. /// @param [in] usRTTSample RTT sample from an ACK-ACKACK pair. If no sample, pass '-1'.
  61. ///
  62. /// @return true if TSBPD base time has changed, false otherwise.
  63. bool addDriftSample(uint32_t pktTimestamp, const time_point& tsPktArrival, int usRTTSample);
  64. /// @brief Handle timestamp of data packet when 32-bit integer carryover is about to happen.
  65. /// When packet timestamp approaches CPacket::MAX_TIMESTAMP, the TSBPD base time should be
  66. /// shifted accordingly to correctly handle new packets with timestamps starting from zero.
  67. /// @param usPktTimestamp timestamp field value of a data packet.
  68. void updateTsbPdTimeBase(uint32_t usPktTimestamp);
  69. /// @brief Get TSBPD base time adjusted for carryover, which occurs when
  70. /// a packet's timestamp exceeds the UINT32_MAX and continues from zero.
  71. /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds).
  72. ///
  73. /// @return TSBPD base time for a provided packet timestamp.
  74. time_point getTsbPdTimeBase(uint32_t usPktTimestamp) const;
  75. /// @brief Get packet TSBPD time without buffering delay and clock drift, which is
  76. /// the target time for delivering the packet to an upstream application.
  77. /// Essentially: getTsbPdTimeBase(usPktTimestamp) + usPktTimestamp
  78. /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds).
  79. ///
  80. /// @return Packet TSBPD base time without buffering delay.
  81. time_point getPktTsbPdBaseTime(uint32_t usPktTimestamp) const;
  82. /// @brief Get packet TSBPD time with buffering delay and clock drift, which is
  83. /// the target time for delivering the packet to an upstream application
  84. /// (including drift and carryover effects, if any).
  85. /// Essentially: getPktTsbPdBaseTime(usPktTimestamp) + m_tdTsbPdDelay + drift()
  86. /// @param [in] usPktTimestamp 32-bit value of packet timestamp field (microseconds).
  87. ///
  88. /// @return Packet TSBPD time with buffering delay.
  89. time_point getPktTsbPdTime(uint32_t usPktTimestamp) const;
  90. /// @brief Get current drift value.
  91. /// @return current drift value.
  92. int64_t drift() const { return m_DriftTracer.drift(); }
  93. /// @brief Get current overdrift value.
  94. /// @return current overdrift value.
  95. int64_t overdrift() const { return m_DriftTracer.overdrift(); }
  96. /// @brief Get internal state to apply to another member of a socket group.
  97. /// @param w_tb TsbPd base time.
  98. /// @param w_udrift drift value.
  99. /// @param w_wrp wrap check.
  100. void getInternalTimeBase(time_point& w_tb, bool& w_wrp, duration& w_udrift) const;
  101. private:
  102. int m_iFirstRTT; // First measured RTT sample.
  103. bool m_bTsbPdMode; // Receiver buffering and TSBPD is active when true.
  104. duration m_tdTsbPdDelay; // Negotiated buffering delay.
  105. /// @brief Local time base for TsbPd.
  106. /// @note m_tsTsbPdTimeBase is changed in the following cases:
  107. /// 1. Initialized upon SRT_CMD_HSREQ packet as the difference with the current time:
  108. /// = (NOW - PACKET_TIMESTAMP), at the time of HSREQ reception.
  109. /// 2. Shifted forward on timestamp overflow (@see CTsbpdTime::updateTsbPdTimeBase), when overflow
  110. /// of the timestamp field value of a data packet is detected.
  111. /// += CPacket::MAX_TIMESTAMP + 1
  112. /// 3. Clock drift (@see CTsbpdTime::addDriftSample, executed exclusively
  113. /// from ACKACK handler). This is updated with (positive or negative) TSBPD_DRIFT_MAX_VALUE
  114. /// once the value of average drift exceeds this value in either direction.
  115. /// += (+/-)TSBPD_DRIFT_MAX_VALUE
  116. ///
  117. /// @note The TSBPD base time is expected to hold the following condition:
  118. /// (PACKET_TIMESTAMP + m_tsTsbPdTimeBase + drift) == NOW.
  119. /// Then it can be used to estimate the origin time of a data packet, and calculate its delivery time
  120. /// with buffering delay applied.
  121. time_point m_tsTsbPdTimeBase;
  122. /// @note Packet timestamps wrap around every 01h11m35s (32-bit in usec).
  123. /// A wrap check period starts 30 seconds (TSBPD_WRAP_PERIOD) before the wrap point.
  124. /// During the wrap check period, packet timestamps smaller than 30 seconds
  125. /// are considered to have been wrapped around.
  126. /// The wrap check period ends 30 seconds after the wrap point,
  127. /// after which the TSBPD base time is adjusted.
  128. bool m_bTsbPdWrapCheck; // true: check packet time stamp wraparound (overflow).
  129. static const uint32_t TSBPD_WRAP_PERIOD = (30 * 1000000); // 30 seconds (in usec) for timestamp wrapping period.
  130. /// Maximum clock drift (microseconds) above which TsbPD base time is already adjusted.
  131. static const int TSBPD_DRIFT_MAX_VALUE = 5000;
  132. /// Number of samples (ACKACK packets) on which to perform drift calculation and compensation.
  133. static const int TSBPD_DRIFT_MAX_SAMPLES = 1000;
  134. DriftTracer<TSBPD_DRIFT_MAX_SAMPLES, TSBPD_DRIFT_MAX_VALUE> m_DriftTracer;
  135. /// Protect simultaneous change of state (read/write).
  136. mutable Mutex m_mtxRW;
  137. };
  138. } // namespace srt
  139. #endif // INC_SRT_TSBPD_TIME_H