1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CAST_STREAMING_CLOCK_DRIFT_SMOOTHER_H_ 6 #define CAST_STREAMING_CLOCK_DRIFT_SMOOTHER_H_ 7 8 #include <chrono> 9 10 #include "platform/api/time.h" 11 12 namespace openscreen { 13 namespace cast { 14 15 // Tracks the jitter and drift between clocks, providing a smoothed offset. 16 // Internally, a Simple IIR filter is used to maintain a running average that 17 // moves at a rate based on the passage of time. 18 class ClockDriftSmoother { 19 public: 20 // |time_constant| is the amount of time an impulse signal takes to decay by 21 // ~62.6%. Interpretation: If the value passed to several Update() calls is 22 // held constant for T seconds, then the running average will have moved 23 // towards the value by ~62.6% from where it started. 24 explicit ClockDriftSmoother(Clock::duration time_constant); 25 ~ClockDriftSmoother(); 26 27 // Returns the current offset. 28 Clock::duration Current() const; 29 30 // Discard all history and reset to exactly |offset|, measured |now|. 31 void Reset(Clock::time_point now, Clock::duration offset); 32 33 // Update the current offset, which was measured |now|. The weighting that 34 // |measured_offset| will have on the running average is influenced by how 35 // much time has passed since the last call to this method (or Reset()). 36 // |now| should be monotonically non-decreasing over successive calls of this 37 // method. 38 void Update(Clock::time_point now, Clock::duration measured_offset); 39 40 // A time constant suitable for most use cases, where the clocks are expected 41 // to drift very little with respect to each other, and the jitter caused by 42 // clock imprecision is effectively canceled out. 43 static constexpr std::chrono::seconds kDefaultTimeConstant{30}; 44 45 private: 46 const std::chrono::duration<double, Clock::duration::period> time_constant_; 47 48 // The time at which |estimated_tick_offset_| was last updated. 49 Clock::time_point last_update_time_; 50 51 // The current estimated offset, as number of Clock::duration ticks. 52 double estimated_tick_offset_; 53 }; 54 55 } // namespace cast 56 } // namespace openscreen 57 58 #endif // CAST_STREAMING_CLOCK_DRIFT_SMOOTHER_H_ 59