summaryrefslogtreecommitdiffstats
path: root/media/base/synchronizer.cc
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-30 04:56:46 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-30 04:56:46 +0000
commit7663e411f3f65fb232093cb3b078a5ef733562e6 (patch)
treed66fd4f5601890e64f104eec26814fe912ff899d /media/base/synchronizer.cc
parent6dd72b0e175e27c261ff887e1f760649d8665136 (diff)
downloadchromium_src-7663e411f3f65fb232093cb3b078a5ef733562e6.zip
chromium_src-7663e411f3f65fb232093cb3b078a5ef733562e6.tar.gz
chromium_src-7663e411f3f65fb232093cb3b078a5ef733562e6.tar.bz2
Checking in media::Synchronizer, a utility class to facilitate A/V synchronization.
Review URL: http://codereview.chromium.org/19693 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8950 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/synchronizer.cc')
-rw-r--r--media/base/synchronizer.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/media/base/synchronizer.cc b/media/base/synchronizer.cc
new file mode 100644
index 0000000..f233c7b
--- /dev/null
+++ b/media/base/synchronizer.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2009 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/logging.h"
+#include "media/base/synchronizer.h"
+
+namespace media {
+
+const int64 Synchronizer::kMinFrameDelayUs = 0;
+const int64 Synchronizer::kMaxFrameDelayUs = 250000;
+
+Synchronizer::Synchronizer() {
+}
+
+Synchronizer::~Synchronizer() {
+}
+
+void Synchronizer::StartRendering() {
+ rendering_start_ = base::TimeTicks::Now();
+}
+
+void Synchronizer::StopRendering() {
+ rendering_stop_ = base::TimeTicks::Now();
+}
+
+void Synchronizer::CalculateDelay(base::TimeDelta time,
+ const StreamSample* now,
+ const StreamSample* next,
+ base::TimeDelta* delay_out,
+ bool* should_skip_out) {
+ // How long rendering took.
+ base::TimeDelta render_delta = rendering_stop_ - rendering_start_;
+
+ // The duration to display the sample |now|.
+ base::TimeDelta duration =
+ base::TimeDelta::FromMicroseconds(now->GetDuration());
+
+ // The presentation timestamp (pts) of the sample |now|.
+ base::TimeDelta now_pts =
+ base::TimeDelta::FromMicroseconds(now->GetTimestamp());
+
+ // The presentation timestamp (pts) of the next sample.
+ base::TimeDelta next_pts;
+
+ // If we were provided the next sample in the stream |next|, use it to
+ // calculate the actual sample duration as opposed to the expected duration
+ // provided by the current sample |now|.
+ //
+ // We also use |next| to get the exact next timestamp as opposed to assuming
+ // it will be |now| + |now|'s duration, which may not always be true.
+ if (next) {
+ next_pts = base::TimeDelta::FromMicroseconds(next->GetTimestamp());
+ duration = next_pts - now_pts;
+
+ // Timestamps appear out of order, so skip this frame.
+ if (duration.InMicroseconds() < 0) {
+ *delay_out = base::TimeDelta();
+ *should_skip_out = true;
+ return;
+ }
+ } else {
+ // Assume next presentation timestamp is |now| + |now|'s duration.
+ next_pts = now_pts + duration;
+ }
+
+ base::TimeDelta sleep;
+ if (time == last_time_) {
+ // The audio time has not changed. To avoid sudden bursts of video after
+ // we get audio timing information, we try and guess the current time
+ // using the duration of the frame.
+ sleep = duration - render_delta;
+ if (sleep.InMicroseconds() < kMinFrameDelayUs) {
+ sleep = base::TimeDelta::FromMicroseconds(kMinFrameDelayUs);
+ }
+ } else {
+ // The audio time has changed. The amount of time to delay is equal to
+ // the time until the next sample from now minus how long it takes to
+ // render, clamped to within the min/max frame delay constants.
+ sleep = next_pts - time - render_delta;
+ if (sleep.InMicroseconds() < kMinFrameDelayUs) {
+ sleep = base::TimeDelta::FromMicroseconds(kMinFrameDelayUs);
+ } else if (sleep.InMicroseconds() > kMaxFrameDelayUs) {
+ sleep = base::TimeDelta::FromMicroseconds(kMaxFrameDelayUs);
+ }
+ }
+ last_time_ = time;
+
+ *delay_out = sleep;
+ *should_skip_out = false;
+}
+
+} // namespace media