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#include "media/cast/common/clock_drift_smoother.h"
6
7#include "base/logging.h"
8
9namespace media {
10namespace cast {
11
12ClockDriftSmoother::ClockDriftSmoother(base::TimeDelta time_constant)
13    : time_constant_(time_constant),
14      estimate_us_(0.0) {
15  DCHECK(time_constant_ > base::TimeDelta());
16}
17
18ClockDriftSmoother::~ClockDriftSmoother() {}
19
20base::TimeDelta ClockDriftSmoother::Current() const {
21  DCHECK(!last_update_time_.is_null());
22  return base::TimeDelta::FromMicroseconds(
23      static_cast<int64>(estimate_us_ + 0.5));  // Round to nearest microsecond.
24}
25
26void ClockDriftSmoother::Reset(base::TimeTicks now,
27                               base::TimeDelta measured_offset) {
28  DCHECK(!now.is_null());
29  last_update_time_ = now;
30  estimate_us_ = measured_offset.InMicroseconds();
31}
32
33void ClockDriftSmoother::Update(base::TimeTicks now,
34                                base::TimeDelta measured_offset) {
35  DCHECK(!now.is_null());
36  if (last_update_time_.is_null()) {
37    Reset(now, measured_offset);
38  } else if (now < last_update_time_) {
39    // |now| is not monotonically non-decreasing.
40    NOTREACHED();
41  } else {
42    const double elapsed_us = (now - last_update_time_).InMicroseconds();
43    last_update_time_ = now;
44    const double weight =
45        elapsed_us / (elapsed_us + time_constant_.InMicroseconds());
46    estimate_us_ = weight * measured_offset.InMicroseconds() +
47        (1.0 - weight) * estimate_us_;
48  }
49}
50
51// static
52base::TimeDelta ClockDriftSmoother::GetDefaultTimeConstant() {
53  static const int kDefaultTimeConstantInSeconds = 30;
54  return base::TimeDelta::FromSeconds(kDefaultTimeConstantInSeconds);
55}
56
57}  // namespace cast
58}  // namespace media
59