diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-18 16:36:30 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-18 16:36:30 +0000 |
commit | 7ac4e53266b36040045733a5fde684837b7a4f5a (patch) | |
tree | 12316f55ef4b9dc2cb3bbda49e1e99ec35276a06 /media/base | |
parent | ccf6a5b847c59446baf30c1e57fa993d2f059c96 (diff) | |
download | chromium_src-7ac4e53266b36040045733a5fde684837b7a4f5a.zip chromium_src-7ac4e53266b36040045733a5fde684837b7a4f5a.tar.gz chromium_src-7ac4e53266b36040045733a5fde684837b7a4f5a.tar.bz2 |
Introduce media::TimeSource.
TimeSource represents the canonical source of time and will eventually
replace the time-updating callback from AudioRenderer and VideoRenderer.
A wall-clock based implementation is also provided for media pipelines
that do not contain any audio.
BUG=370634
Review URL: https://codereview.chromium.org/379343005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284122 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/time_source.h | 42 | ||||
-rw-r--r-- | media/base/wall_clock_time_source.cc | 65 | ||||
-rw-r--r-- | media/base/wall_clock_time_source.h | 49 | ||||
-rw-r--r-- | media/base/wall_clock_time_source_unittest.cc | 90 |
4 files changed, 246 insertions, 0 deletions
diff --git a/media/base/time_source.h b/media/base/time_source.h new file mode 100644 index 0000000..2c5a720 --- /dev/null +++ b/media/base/time_source.h @@ -0,0 +1,42 @@ +// 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. + +#ifndef MEDIA_BASE_TIME_SOURCE_H_ +#define MEDIA_BASE_TIME_SOURCE_H_ + +#include "base/time/time.h" +#include "media/base/media_export.h" + +namespace media { + +// A TimeSource is capable of providing the current media time. +class MEDIA_EXPORT TimeSource { + public: + TimeSource() {} + virtual ~TimeSource() {} + + // Signal the time source to start ticking. It is expected that values from + // CurrentMediaTime() will start increasing. + virtual void StartTicking() = 0; + + // Signal the time source to stop ticking. It is expected that values from + // CurrentMediaTime() will remain constant. + virtual void StopTicking() = 0; + + // Updates the current playback rate. It is expected that values from + // CurrentMediaTime() will eventually reflect the new playback rate (e.g., the + // media time will advance at half speed if the rate was set to 0.5f). + virtual void SetPlaybackRate(float playback_rate) = 0; + + // Sets the media time to start ticking from. Only valid to call while the + // time source is not ticking. + virtual void SetMediaTime(base::TimeDelta time) = 0; + + // Returns the current media time. + virtual base::TimeDelta CurrentMediaTime() = 0; +}; + +} // namespace media + +#endif // MEDIA_BASE_TIME_SOURCE_H_ diff --git a/media/base/wall_clock_time_source.cc b/media/base/wall_clock_time_source.cc new file mode 100644 index 0000000..67b16f71 --- /dev/null +++ b/media/base/wall_clock_time_source.cc @@ -0,0 +1,65 @@ +// 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/base/wall_clock_time_source.h" + +#include "base/logging.h" +#include "base/time/default_tick_clock.h" + +namespace media { + +WallClockTimeSource::WallClockTimeSource() + : tick_clock_(new base::DefaultTickClock()), + ticking_(false), + playback_rate_(1.0f) { +} + +WallClockTimeSource::~WallClockTimeSource() { +} + +void WallClockTimeSource::StartTicking() { + DCHECK(!ticking_); + ticking_ = true; + reference_wall_ticks_ = tick_clock_->NowTicks(); +} + +void WallClockTimeSource::StopTicking() { + DCHECK(ticking_); + base_time_ = CurrentMediaTime(); + ticking_ = false; + reference_wall_ticks_ = tick_clock_->NowTicks(); +} + +void WallClockTimeSource::SetPlaybackRate(float playback_rate) { + // Estimate current media time using old rate to use as a new base time for + // the new rate. + if (ticking_) { + base_time_ = CurrentMediaTime(); + reference_wall_ticks_ = tick_clock_->NowTicks(); + } + + playback_rate_ = playback_rate; +} + +void WallClockTimeSource::SetMediaTime(base::TimeDelta time) { + CHECK(!ticking_); + base_time_ = time; +} + +base::TimeDelta WallClockTimeSource::CurrentMediaTime() { + if (!ticking_) + return base_time_; + + base::TimeTicks now = tick_clock_->NowTicks(); + return base_time_ + + base::TimeDelta::FromMicroseconds( + (now - reference_wall_ticks_).InMicroseconds() * playback_rate_); +} + +void WallClockTimeSource::SetTickClockForTesting( + scoped_ptr<base::TickClock> tick_clock) { + tick_clock_.swap(tick_clock); +} + +} // namespace media diff --git a/media/base/wall_clock_time_source.h b/media/base/wall_clock_time_source.h new file mode 100644 index 0000000..9f97a5c --- /dev/null +++ b/media/base/wall_clock_time_source.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef MEDIA_BASE_WALL_CLOCK_TIME_SOURCE_H_ +#define MEDIA_BASE_WALL_CLOCK_TIME_SOURCE_H_ + +#include "base/memory/scoped_ptr.h" +#include "media/base/media_export.h" +#include "media/base/time_source.h" + +namespace base { +class TickClock; +} + +namespace media { + +// A time source that uses interpolation based on the system clock. +class MEDIA_EXPORT WallClockTimeSource : public TimeSource { + public: + WallClockTimeSource(); + virtual ~WallClockTimeSource(); + + // TimeSource implementation. + virtual void StartTicking() OVERRIDE; + virtual void StopTicking() OVERRIDE; + virtual void SetPlaybackRate(float playback_rate) OVERRIDE; + virtual void SetMediaTime(base::TimeDelta time) OVERRIDE; + virtual base::TimeDelta CurrentMediaTime() OVERRIDE; + + void SetTickClockForTesting(scoped_ptr<base::TickClock> tick_clock); + + private: + scoped_ptr<base::TickClock> tick_clock_; + bool ticking_; + + // While ticking we can interpolate the current media time by measuring the + // delta between our reference ticks and the current system ticks and scaling + // that time by the playback rate. + float playback_rate_; + base::TimeDelta base_time_; + base::TimeTicks reference_wall_ticks_; + + DISALLOW_COPY_AND_ASSIGN(WallClockTimeSource); +}; + +} // namespace media + +#endif // MEDIA_BASE_WALL_CLOCK_TIME_SOURCE_H_ diff --git a/media/base/wall_clock_time_source_unittest.cc b/media/base/wall_clock_time_source_unittest.cc new file mode 100644 index 0000000..2b03151 --- /dev/null +++ b/media/base/wall_clock_time_source_unittest.cc @@ -0,0 +1,90 @@ +// 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 "base/test/simple_test_tick_clock.h" +#include "media/base/wall_clock_time_source.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class WallClockTimeSourceTest : public testing::Test { + public: + WallClockTimeSourceTest() : tick_clock_(new base::SimpleTestTickClock()) { + time_source_.SetTickClockForTesting( + scoped_ptr<base::TickClock>(tick_clock_)); + } + virtual ~WallClockTimeSourceTest() {} + + void AdvanceTimeInSeconds(int seconds) { + tick_clock_->Advance(base::TimeDelta::FromSeconds(seconds)); + } + + int CurrentMediaTimeInSeconds() { + return time_source_.CurrentMediaTime().InSeconds(); + } + + void SetMediaTimeInSeconds(int seconds) { + return time_source_.SetMediaTime(base::TimeDelta::FromSeconds(seconds)); + } + + WallClockTimeSource time_source_; + + private: + base::SimpleTestTickClock* tick_clock_; // Owned by |time_source_|. + + DISALLOW_COPY_AND_ASSIGN(WallClockTimeSourceTest); +}; + +TEST_F(WallClockTimeSourceTest, InitialTimeIsZero) { + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); +} + +TEST_F(WallClockTimeSourceTest, InitialTimeIsNotTicking) { + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); + AdvanceTimeInSeconds(100); + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); +} + +TEST_F(WallClockTimeSourceTest, InitialPlaybackRateIsOne) { + time_source_.StartTicking(); + + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); + AdvanceTimeInSeconds(100); + EXPECT_EQ(100, CurrentMediaTimeInSeconds()); +} + +TEST_F(WallClockTimeSourceTest, SetMediaTime) { + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); + SetMediaTimeInSeconds(10); + EXPECT_EQ(10, CurrentMediaTimeInSeconds()); +} + +TEST_F(WallClockTimeSourceTest, SetPlaybackRate) { + time_source_.StartTicking(); + + time_source_.SetPlaybackRate(0.5); + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); + AdvanceTimeInSeconds(10); + EXPECT_EQ(5, CurrentMediaTimeInSeconds()); + + time_source_.SetPlaybackRate(2); + EXPECT_EQ(5, CurrentMediaTimeInSeconds()); + AdvanceTimeInSeconds(10); + EXPECT_EQ(25, CurrentMediaTimeInSeconds()); +} + +TEST_F(WallClockTimeSourceTest, StopTicking) { + time_source_.StartTicking(); + + EXPECT_EQ(0, CurrentMediaTimeInSeconds()); + AdvanceTimeInSeconds(10); + EXPECT_EQ(10, CurrentMediaTimeInSeconds()); + + time_source_.StopTicking(); + + AdvanceTimeInSeconds(10); + EXPECT_EQ(10, CurrentMediaTimeInSeconds()); +} + +} // namespace media |