| // Copyright 2014 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. |
| |
| #include "media/cast/common/clock_drift_smoother.h" |
| |
| #include "base/logging.h" |
| #include "starboard/types.h" |
| |
| namespace cobalt { |
| namespace media { |
| namespace cast { |
| |
| ClockDriftSmoother::ClockDriftSmoother(base::TimeDelta time_constant) |
| : time_constant_(time_constant), estimate_us_(0.0) { |
| DCHECK(time_constant_ > base::TimeDelta()); |
| } |
| |
| ClockDriftSmoother::~ClockDriftSmoother() {} |
| |
| base::TimeDelta ClockDriftSmoother::Current() const { |
| DCHECK(!last_update_time_.is_null()); |
| return base::TimeDelta::FromMicroseconds(static_cast<int64_t>( |
| estimate_us_ + 0.5)); // Round to nearest microsecond. |
| } |
| |
| void ClockDriftSmoother::Reset(base::TimeTicks now, |
| base::TimeDelta measured_offset) { |
| DCHECK(!now.is_null()); |
| last_update_time_ = now; |
| estimate_us_ = static_cast<double>(measured_offset.InMicroseconds()); |
| } |
| |
| void ClockDriftSmoother::Update(base::TimeTicks now, |
| base::TimeDelta measured_offset) { |
| DCHECK(!now.is_null()); |
| if (last_update_time_.is_null()) { |
| Reset(now, measured_offset); |
| } else if (now < last_update_time_) { |
| // |now| is not monotonically non-decreasing. |
| NOTREACHED(); |
| } else { |
| const double elapsed_us = |
| static_cast<double>((now - last_update_time_).InMicroseconds()); |
| last_update_time_ = now; |
| const double weight = |
| elapsed_us / (elapsed_us + time_constant_.InMicroseconds()); |
| estimate_us_ = weight * measured_offset.InMicroseconds() + |
| (1.0 - weight) * estimate_us_; |
| } |
| } |
| |
| // static |
| base::TimeDelta ClockDriftSmoother::GetDefaultTimeConstant() { |
| static const int kDefaultTimeConstantInSeconds = 30; |
| return base::TimeDelta::FromSeconds(kDefaultTimeConstantInSeconds); |
| } |
| |
| } // namespace cast |
| } // namespace media |
| } // namespace cobalt |