1 // Copyright (c) 2012 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.
5 #include "media/base/clock.h"
9 #include "base/logging.h"
10 #include "base/time/tick_clock.h"
11 #include "media/base/buffers.h"
15 Clock::Clock(base::TickClock* clock)
20 max_time_(kNoTimestamp()),
21 duration_(kNoTimestamp()) {
27 bool Clock::IsPlaying() const {
31 base::TimeDelta Clock::Play() {
33 UpdateReferencePoints();
38 base::TimeDelta Clock::Pause() {
40 UpdateReferencePoints();
45 void Clock::SetPlaybackRate(float playback_rate) {
46 UpdateReferencePoints();
47 playback_rate_ = playback_rate;
50 void Clock::SetTime(base::TimeDelta current_time, base::TimeDelta max_time) {
51 DCHECK(current_time <= max_time);
52 DCHECK(current_time != kNoTimestamp());
54 UpdateReferencePoints(current_time);
55 max_time_ = ClampToValidTimeRange(max_time);
59 base::TimeDelta Clock::Elapsed() {
60 if (duration_ == kNoTimestamp())
61 return base::TimeDelta();
63 // The clock is not advancing, so return the last recorded time.
64 if (!playing_ || underflow_)
67 base::TimeDelta elapsed = EstimatedElapsedTime();
68 if (max_time_ != kNoTimestamp() && elapsed > max_time_) {
69 UpdateReferencePoints(max_time_);
77 void Clock::SetMaxTime(base::TimeDelta max_time) {
78 DCHECK(max_time != kNoTimestamp());
80 UpdateReferencePoints();
81 max_time_ = ClampToValidTimeRange(max_time);
83 underflow_ = media_time_ > max_time_;
85 media_time_ = max_time_;
88 void Clock::SetDuration(base::TimeDelta duration) {
89 DCHECK(duration > base::TimeDelta());
92 media_time_ = ClampToValidTimeRange(media_time_);
93 if (max_time_ != kNoTimestamp())
94 max_time_ = ClampToValidTimeRange(max_time_);
97 base::TimeDelta Clock::ElapsedViaProvidedTime(
98 const base::TimeTicks& time) const {
99 // TODO(scherkus): floating point badness scaling time by playback rate.
100 int64 now_us = (time - reference_).InMicroseconds();
101 now_us = static_cast<int64>(now_us * playback_rate_);
102 return media_time_ + base::TimeDelta::FromMicroseconds(now_us);
105 base::TimeDelta Clock::ClampToValidTimeRange(base::TimeDelta time) const {
106 if (duration_ == kNoTimestamp())
107 return base::TimeDelta();
108 return std::max(std::min(time, duration_), base::TimeDelta());
111 base::TimeDelta Clock::Duration() const {
112 if (duration_ == kNoTimestamp())
113 return base::TimeDelta();
117 void Clock::UpdateReferencePoints() {
118 UpdateReferencePoints(Elapsed());
121 void Clock::UpdateReferencePoints(base::TimeDelta current_time) {
122 media_time_ = ClampToValidTimeRange(current_time);
123 reference_ = clock_->NowTicks();
126 base::TimeDelta Clock::EstimatedElapsedTime() {
127 return ClampToValidTimeRange(ElapsedViaProvidedTime(clock_->NowTicks()));