Commit 76f62954 authored by scherkus@chromium.org's avatar scherkus@chromium.org

Remove duration from media::Clock.

It has no business being in there. Instead let Pipeline track duration
and cap interpolated time values as needed.

BUG=370634

Review URL: https://codereview.chromium.org/375003002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@281935 0039d316-1c4b-4281-b951-d872f2087c98
parent 21ef2114
...@@ -173,7 +173,7 @@ void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { ...@@ -173,7 +173,7 @@ void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
} }
base::TimeDelta MediaSourcePlayer::GetCurrentTime() { base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
return clock_.Elapsed(); return std::min(clock_.Elapsed(), duration_);
} }
base::TimeDelta MediaSourcePlayer::GetDuration() { base::TimeDelta MediaSourcePlayer::GetDuration() {
...@@ -237,7 +237,6 @@ void MediaSourcePlayer::OnDemuxerConfigsAvailable( ...@@ -237,7 +237,6 @@ void MediaSourcePlayer::OnDemuxerConfigsAvailable(
DVLOG(1) << __FUNCTION__; DVLOG(1) << __FUNCTION__;
DCHECK(!HasAudio() && !HasVideo()); DCHECK(!HasAudio() && !HasVideo());
duration_ = configs.duration; duration_ = configs.duration;
clock_.SetDuration(duration_);
audio_decoder_job_->SetDemuxerConfigs(configs); audio_decoder_job_->SetDemuxerConfigs(configs);
video_decoder_job_->SetDemuxerConfigs(configs); video_decoder_job_->SetDemuxerConfigs(configs);
...@@ -257,7 +256,6 @@ void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { ...@@ -257,7 +256,6 @@ void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) {
void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) {
duration_ = duration; duration_ = duration;
clock_.SetDuration(duration_);
} }
void MediaSourcePlayer::OnMediaCryptoReady() { void MediaSourcePlayer::OnMediaCryptoReady() {
......
...@@ -17,8 +17,7 @@ Clock::Clock(base::TickClock* clock) ...@@ -17,8 +17,7 @@ Clock::Clock(base::TickClock* clock)
playing_(false), playing_(false),
underflow_(false), underflow_(false),
playback_rate_(1.0f), playback_rate_(1.0f),
max_time_(kNoTimestamp()), max_time_(kNoTimestamp()) {
duration_(kNoTimestamp()) {
DCHECK(clock_); DCHECK(clock_);
} }
...@@ -57,9 +56,6 @@ void Clock::SetTime(base::TimeDelta current_time, base::TimeDelta max_time) { ...@@ -57,9 +56,6 @@ void Clock::SetTime(base::TimeDelta current_time, base::TimeDelta max_time) {
} }
base::TimeDelta Clock::Elapsed() { base::TimeDelta Clock::Elapsed() {
if (duration_ == kNoTimestamp())
return base::TimeDelta();
// The clock is not advancing, so return the last recorded time. // The clock is not advancing, so return the last recorded time.
if (!playing_ || underflow_) if (!playing_ || underflow_)
return media_time_; return media_time_;
...@@ -85,15 +81,6 @@ void Clock::SetMaxTime(base::TimeDelta max_time) { ...@@ -85,15 +81,6 @@ void Clock::SetMaxTime(base::TimeDelta max_time) {
media_time_ = max_time_; media_time_ = max_time_;
} }
void Clock::SetDuration(base::TimeDelta duration) {
DCHECK(duration > base::TimeDelta());
duration_ = duration;
media_time_ = ClampToValidTimeRange(media_time_);
if (max_time_ != kNoTimestamp())
max_time_ = ClampToValidTimeRange(max_time_);
}
base::TimeDelta Clock::ElapsedViaProvidedTime( base::TimeDelta Clock::ElapsedViaProvidedTime(
const base::TimeTicks& time) const { const base::TimeTicks& time) const {
// TODO(scherkus): floating point badness scaling time by playback rate. // TODO(scherkus): floating point badness scaling time by playback rate.
...@@ -103,15 +90,7 @@ base::TimeDelta Clock::ElapsedViaProvidedTime( ...@@ -103,15 +90,7 @@ base::TimeDelta Clock::ElapsedViaProvidedTime(
} }
base::TimeDelta Clock::ClampToValidTimeRange(base::TimeDelta time) const { base::TimeDelta Clock::ClampToValidTimeRange(base::TimeDelta time) const {
if (duration_ == kNoTimestamp()) return std::max(base::TimeDelta(), time);
return base::TimeDelta();
return std::max(std::min(time, duration_), base::TimeDelta());
}
base::TimeDelta Clock::Duration() const {
if (duration_ == kNoTimestamp())
return base::TimeDelta();
return duration_;
} }
void Clock::UpdateReferencePoints() { void Clock::UpdateReferencePoints() {
......
...@@ -54,25 +54,14 @@ class MEDIA_EXPORT Clock { ...@@ -54,25 +54,14 @@ class MEDIA_EXPORT Clock {
// Forcefully sets the media time to |current_time|. The second parameter is // Forcefully sets the media time to |current_time|. The second parameter is
// the |max_time| that the clock should progress after a call to Play(). This // the |max_time| that the clock should progress after a call to Play(). This
// value is often the time of the end of the last frame buffered and decoded. // value is often the time of the end of the last frame buffered and decoded.
//
// These values are clamped to the duration of the video, which is initially
// set to 0 (before SetDuration() is called).
void SetTime(base::TimeDelta current_time, base::TimeDelta max_time); void SetTime(base::TimeDelta current_time, base::TimeDelta max_time);
// Sets the |max_time| to be returned by a call to Elapsed(). // Sets the |max_time| to be returned by a call to Elapsed().
void SetMaxTime(base::TimeDelta max_time); void SetMaxTime(base::TimeDelta max_time);
// Returns the current elapsed media time. Returns 0 if SetDuration() has // Returns the current elapsed media time.
// never been called.
base::TimeDelta Elapsed(); base::TimeDelta Elapsed();
// Sets the duration of the video. Clock expects the duration will be set
// exactly once.
void SetDuration(base::TimeDelta duration);
// Returns the duration of the clock, or 0 if not set.
base::TimeDelta Duration() const;
private: private:
// Updates the reference points based on the current calculated time. // Updates the reference points based on the current calculated time.
void UpdateReferencePoints(); void UpdateReferencePoints();
...@@ -113,9 +102,6 @@ class MEDIA_EXPORT Clock { ...@@ -113,9 +102,6 @@ class MEDIA_EXPORT Clock {
// The maximum time that can be returned by calls to Elapsed(). // The maximum time that can be returned by calls to Elapsed().
base::TimeDelta max_time_; base::TimeDelta max_time_;
// Duration of the media.
base::TimeDelta duration_;
DISALLOW_COPY_AND_ASSIGN(Clock); DISALLOW_COPY_AND_ASSIGN(Clock);
}; };
......
...@@ -2,46 +2,18 @@ ...@@ -2,46 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/compiler_specific.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "base/time/clock.h"
#include "media/base/clock.h" #include "media/base/clock.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
using ::testing::InSequence;
using ::testing::Return;
using ::testing::StrictMock;
namespace base {
// Provide a stream output operator so we can use EXPECT_EQ(...) with TimeDelta.
//
// TODO(scherkus): move this into the testing package.
static std::ostream& operator<<(std::ostream& stream, const TimeDelta& time) {
return (stream << time.ToInternalValue());
}
} // namespace
namespace media { namespace media {
static const int kDurationInSeconds = 120;
class ClockTest : public ::testing::Test { class ClockTest : public ::testing::Test {
public: public:
ClockTest() : clock_(&test_tick_clock_) { ClockTest() : clock_(&test_tick_clock_) {}
SetDuration();
}
protected: protected:
void SetDuration() {
const base::TimeDelta kDuration =
base::TimeDelta::FromSeconds(kDurationInSeconds);
clock_.SetDuration(kDuration);
EXPECT_EQ(kDuration, clock_.Duration());
}
void AdvanceSystemTime(base::TimeDelta delta) { void AdvanceSystemTime(base::TimeDelta delta) {
test_tick_clock_.Advance(delta); test_tick_clock_.Advance(delta);
} }
...@@ -154,10 +126,11 @@ TEST_F(ClockTest, Pause) { ...@@ -154,10 +126,11 @@ TEST_F(ClockTest, Pause) {
TEST_F(ClockTest, SetTime_Paused) { TEST_F(ClockTest, SetTime_Paused) {
const base::TimeDelta kFirstTime = base::TimeDelta::FromSeconds(4); const base::TimeDelta kFirstTime = base::TimeDelta::FromSeconds(4);
const base::TimeDelta kSecondTime = base::TimeDelta::FromSeconds(16); const base::TimeDelta kSecondTime = base::TimeDelta::FromSeconds(16);
const base::TimeDelta kArbitraryMaxTime = base::TimeDelta::FromSeconds(100);
clock_.SetTime(kFirstTime, clock_.Duration()); clock_.SetTime(kFirstTime, kArbitraryMaxTime);
EXPECT_EQ(kFirstTime, clock_.Elapsed()); EXPECT_EQ(kFirstTime, clock_.Elapsed());
clock_.SetTime(kSecondTime, clock_.Duration()); clock_.SetTime(kSecondTime, kArbitraryMaxTime);
EXPECT_EQ(kSecondTime, clock_.Elapsed()); EXPECT_EQ(kSecondTime, clock_.Elapsed());
} }
...@@ -167,44 +140,17 @@ TEST_F(ClockTest, SetTime_Playing) { ...@@ -167,44 +140,17 @@ TEST_F(ClockTest, SetTime_Playing) {
const base::TimeDelta kZero; const base::TimeDelta kZero;
const base::TimeDelta kPlayDuration = base::TimeDelta::FromSeconds(4); const base::TimeDelta kPlayDuration = base::TimeDelta::FromSeconds(4);
const base::TimeDelta kUpdatedTime = base::TimeDelta::FromSeconds(12); const base::TimeDelta kUpdatedTime = base::TimeDelta::FromSeconds(12);
const base::TimeDelta kArbitraryMaxTime = base::TimeDelta::FromSeconds(100);
const base::TimeDelta kExpected = kUpdatedTime + kPlayDuration; const base::TimeDelta kExpected = kUpdatedTime + kPlayDuration;
EXPECT_EQ(kZero, clock_.Play()); EXPECT_EQ(kZero, clock_.Play());
AdvanceSystemTime(kPlayDuration); AdvanceSystemTime(kPlayDuration);
clock_.SetTime(kUpdatedTime, clock_.Duration()); clock_.SetTime(kUpdatedTime, kArbitraryMaxTime);
AdvanceSystemTime(kPlayDuration); AdvanceSystemTime(kPlayDuration);
EXPECT_EQ(kExpected, clock_.Elapsed()); EXPECT_EQ(kExpected, clock_.Elapsed());
} }
TEST_F(ClockTest, CapAtMediaDuration_Paused) {
const base::TimeDelta kDuration =
base::TimeDelta::FromSeconds(kDurationInSeconds);
const base::TimeDelta kTimeOverDuration =
base::TimeDelta::FromSeconds(kDurationInSeconds + 4);
// Elapsed time should always be capped at the duration of the media.
clock_.SetTime(kTimeOverDuration, kTimeOverDuration);
EXPECT_EQ(kDuration, clock_.Elapsed());
}
TEST_F(ClockTest, CapAtMediaDuration_Playing) {
const base::TimeDelta kZero;
const base::TimeDelta kDuration =
base::TimeDelta::FromSeconds(kDurationInSeconds);
const base::TimeDelta kTimeOverDuration =
base::TimeDelta::FromSeconds(kDurationInSeconds + 4);
// Play for twice as long as the duration of the media.
EXPECT_EQ(kZero, clock_.Play());
AdvanceSystemTime(2 * kDuration);
EXPECT_EQ(kDuration, clock_.Elapsed());
// Manually set the time past the duration.
clock_.SetTime(kTimeOverDuration, kTimeOverDuration);
EXPECT_EQ(kDuration, clock_.Elapsed());
}
TEST_F(ClockTest, SetMaxTime) { TEST_F(ClockTest, SetMaxTime) {
const base::TimeDelta kZero; const base::TimeDelta kZero;
const base::TimeDelta kTimeInterval = base::TimeDelta::FromSeconds(4); const base::TimeDelta kTimeInterval = base::TimeDelta::FromSeconds(4);
...@@ -225,11 +171,12 @@ TEST_F(ClockTest, SetMaxTime) { ...@@ -225,11 +171,12 @@ TEST_F(ClockTest, SetMaxTime) {
TEST_F(ClockTest, SetMaxTime_MultipleTimes) { TEST_F(ClockTest, SetMaxTime_MultipleTimes) {
const base::TimeDelta kZero; const base::TimeDelta kZero;
const base::TimeDelta kTimeInterval = base::TimeDelta::FromSeconds(4); const base::TimeDelta kTimeInterval = base::TimeDelta::FromSeconds(4);
const base::TimeDelta kMaxTime0 = base::TimeDelta::FromSeconds(120);
const base::TimeDelta kMaxTime1 = base::TimeDelta::FromSeconds(6); const base::TimeDelta kMaxTime1 = base::TimeDelta::FromSeconds(6);
const base::TimeDelta kMaxTime2 = base::TimeDelta::FromSeconds(12); const base::TimeDelta kMaxTime2 = base::TimeDelta::FromSeconds(12);
EXPECT_EQ(kZero, clock_.Play()); EXPECT_EQ(kZero, clock_.Play());
clock_.SetMaxTime(clock_.Duration()); clock_.SetMaxTime(kMaxTime0);
AdvanceSystemTime(kTimeInterval); AdvanceSystemTime(kTimeInterval);
EXPECT_EQ(kTimeInterval, clock_.Elapsed()); EXPECT_EQ(kTimeInterval, clock_.Elapsed());
......
...@@ -156,7 +156,7 @@ void Pipeline::SetVolume(float volume) { ...@@ -156,7 +156,7 @@ void Pipeline::SetVolume(float volume) {
TimeDelta Pipeline::GetMediaTime() const { TimeDelta Pipeline::GetMediaTime() const {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
return clock_->Elapsed(); return std::min(clock_->Elapsed(), duration_);
} }
Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const {
...@@ -166,7 +166,7 @@ Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { ...@@ -166,7 +166,7 @@ Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const {
TimeDelta Pipeline::GetMediaDuration() const { TimeDelta Pipeline::GetMediaDuration() const {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
return clock_->Duration(); return duration_;
} }
bool Pipeline::DidLoadingProgress() { bool Pipeline::DidLoadingProgress() {
...@@ -320,7 +320,7 @@ void Pipeline::SetDuration(TimeDelta duration) { ...@@ -320,7 +320,7 @@ void Pipeline::SetDuration(TimeDelta duration) {
UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
clock_->SetDuration(duration); duration_ = duration;
if (!duration_change_cb_.is_null()) if (!duration_change_cb_.is_null())
duration_change_cb_.Run(); duration_change_cb_.Run();
} }
...@@ -705,7 +705,7 @@ void Pipeline::DoAudioRendererEnded() { ...@@ -705,7 +705,7 @@ void Pipeline::DoAudioRendererEnded() {
// Start clock since there is no more audio to trigger clock updates. // Start clock since there is no more audio to trigger clock updates.
{ {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
clock_->SetMaxTime(clock_->Duration()); clock_->SetMaxTime(duration_);
StartClockIfWaitingForTimeUpdate_Locked(); StartClockIfWaitingForTimeUpdate_Locked();
} }
...@@ -751,7 +751,7 @@ void Pipeline::RunEndedCallbackIfNeeded() { ...@@ -751,7 +751,7 @@ void Pipeline::RunEndedCallbackIfNeeded() {
{ {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
PauseClockAndStopRendering_Locked(); PauseClockAndStopRendering_Locked();
clock_->SetTime(clock_->Duration(), clock_->Duration()); clock_->SetTime(duration_, duration_);
} }
DCHECK_EQ(status_, PIPELINE_OK); DCHECK_EQ(status_, PIPELINE_OK);
...@@ -882,7 +882,7 @@ void Pipeline::StartPlayback() { ...@@ -882,7 +882,7 @@ void Pipeline::StartPlayback() {
} else { } else {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
clock_state_ = CLOCK_PLAYING; clock_state_ = CLOCK_PLAYING;
clock_->SetMaxTime(clock_->Duration()); clock_->SetMaxTime(duration_);
clock_->Play(); clock_->Play();
} }
} }
......
...@@ -346,6 +346,9 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost { ...@@ -346,6 +346,9 @@ class MEDIA_EXPORT Pipeline : public DemuxerHost {
// the filters. // the filters.
float playback_rate_; float playback_rate_;
// Current duration as reported by |demuxer_|.
base::TimeDelta duration_;
// base::TickClock used by |clock_|. // base::TickClock used by |clock_|.
base::DefaultTickClock default_tick_clock_; base::DefaultTickClock default_tick_clock_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment