summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-18 16:36:30 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-18 16:36:30 +0000
commit7ac4e53266b36040045733a5fde684837b7a4f5a (patch)
tree12316f55ef4b9dc2cb3bbda49e1e99ec35276a06 /media/base
parentccf6a5b847c59446baf30c1e57fa993d2f059c96 (diff)
downloadchromium_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.h42
-rw-r--r--media/base/wall_clock_time_source.cc65
-rw-r--r--media/base/wall_clock_time_source.h49
-rw-r--r--media/base/wall_clock_time_source_unittest.cc90
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