1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/common/clock_drift_smoother.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace media {
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace cast {
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ClockDriftSmoother::ClockDriftSmoother(base::TimeDelta time_constant)
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : time_constant_(time_constant),
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      estimate_us_(0.0) {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(time_constant_ > base::TimeDelta());
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ClockDriftSmoother::~ClockDriftSmoother() {}
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::TimeDelta ClockDriftSmoother::Current() const {
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!last_update_time_.is_null());
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return base::TimeDelta::FromMicroseconds(
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<int64>(estimate_us_ + 0.5));  // Round to nearest microsecond.
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ClockDriftSmoother::Reset(base::TimeTicks now,
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               base::TimeDelta measured_offset) {
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!now.is_null());
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  last_update_time_ = now;
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  estimate_us_ = measured_offset.InMicroseconds();
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ClockDriftSmoother::Update(base::TimeTicks now,
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                base::TimeDelta measured_offset) {
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!now.is_null());
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (last_update_time_.is_null()) {
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Reset(now, measured_offset);
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (now < last_update_time_) {
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // |now| is not monotonically non-decreasing.
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NOTREACHED();
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const double elapsed_us = (now - last_update_time_).InMicroseconds();
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    last_update_time_ = now;
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const double weight =
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        elapsed_us / (elapsed_us + time_constant_.InMicroseconds());
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    estimate_us_ = weight * measured_offset.InMicroseconds() +
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (1.0 - weight) * estimate_us_;
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::TimeDelta ClockDriftSmoother::GetDefaultTimeConstant() {
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const int kDefaultTimeConstantInSeconds = 30;
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return base::TimeDelta::FromSeconds(kDefaultTimeConstantInSeconds);
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace cast
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace media
59