summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
Diffstat (limited to 'media/base')
-rw-r--r--media/base/buffers.cc13
-rw-r--r--media/base/buffers.h3
-rw-r--r--media/base/clock_impl.cc5
-rw-r--r--media/base/pipeline_impl.cc47
-rw-r--r--media/base/pipeline_impl.h5
5 files changed, 66 insertions, 7 deletions
diff --git a/media/base/buffers.cc b/media/base/buffers.cc
new file mode 100644
index 0000000..4247e39
--- /dev/null
+++ b/media/base/buffers.cc
@@ -0,0 +1,13 @@
+// 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 "media/base/buffers.h"
+
+namespace media {
+
+// static
+const base::TimeDelta StreamSample::kInvalidTimestamp =
+ base::TimeDelta::FromMicroseconds(kint64min);
+
+} // namespace media
diff --git a/media/base/buffers.h b/media/base/buffers.h
index 2b4f25b..27ad130 100644
--- a/media/base/buffers.h
+++ b/media/base/buffers.h
@@ -35,6 +35,9 @@ namespace media {
class StreamSample : public base::RefCountedThreadSafe<StreamSample> {
public:
+ // Constant timestamp value to indicate an invalid or missing timestamp.
+ static const base::TimeDelta kInvalidTimestamp;
+
// Returns the timestamp of this buffer in microseconds.
base::TimeDelta GetTimestamp() const {
return timestamp_;
diff --git a/media/base/clock_impl.cc b/media/base/clock_impl.cc
index cc46568..b853742 100644
--- a/media/base/clock_impl.cc
+++ b/media/base/clock_impl.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/logging.h"
+#include "media/base/buffers.h"
#include "media/base/clock_impl.h"
namespace media {
@@ -32,6 +33,10 @@ base::TimeDelta ClockImpl::Pause() {
}
void ClockImpl::SetTime(const base::TimeDelta& time) {
+ if (time == StreamSample::kInvalidTimestamp) {
+ NOTREACHED();
+ return;
+ }
if (playing_) {
reference_ = time_provider_();
}
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index 61f6344..270347c 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -74,6 +74,7 @@ void DecrementCounter(Lock* lock, ConditionVariable* cond_var, int* count) {
PipelineImpl::PipelineImpl(MessageLoop* message_loop)
: message_loop_(message_loop),
clock_(&base::Time::Now),
+ waiting_for_clock_update_(false),
state_(kCreated),
remaining_transitions_(0) {
ResetState();
@@ -292,6 +293,7 @@ void PipelineImpl::ResetState() {
volume_ = 1.0f;
playback_rate_ = 0.0f;
error_ = PIPELINE_OK;
+ waiting_for_clock_update_ = false;
clock_.SetTime(kZero);
rendered_mime_types_.clear();
}
@@ -346,6 +348,17 @@ base::TimeDelta PipelineImpl::GetTime() const {
void PipelineImpl::SetTime(base::TimeDelta time) {
DCHECK(IsRunning());
AutoLock auto_lock(lock_);
+
+ // If we were waiting for a valid timestamp and such timestamp arrives, we
+ // need to clear the flag for waiting and start the clock.
+ if (waiting_for_clock_update_) {
+ if (time < clock_.Elapsed())
+ return;
+ waiting_for_clock_update_ = false;
+ clock_.SetTime(time);
+ clock_.Play();
+ return;
+ }
clock_.SetTime(time);
}
@@ -607,7 +620,10 @@ void PipelineImpl::ErrorChangedTask(PipelineError error) {
void PipelineImpl::PlaybackRateChangedTask(float playback_rate) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
- clock_.SetPlaybackRate(playback_rate);
+ {
+ AutoLock auto_lock(lock_);
+ clock_.SetPlaybackRate(playback_rate);
+ }
for (FilterVector::iterator iter = filters_.begin();
iter != filters_.end();
++iter) {
@@ -652,7 +668,12 @@ void PipelineImpl::SeekTask(base::TimeDelta time,
remaining_transitions_ = filters_.size();
// Kick off seeking!
- clock_.Pause();
+ {
+ AutoLock auto_lock(lock_);
+ // If we are waiting for a clock update, the clock hasn't been played yet.
+ if (!waiting_for_clock_update_)
+ clock_.Pause();
+ }
filters_.front()->Pause(
NewCallback(this, &PipelineImpl::OnFilterStateTransition));
}
@@ -688,10 +709,14 @@ void PipelineImpl::NotifyEndedTask() {
void PipelineImpl::BroadcastMessageTask(FilterMessage message) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
- // TODO(kylep): This is a horribly ugly hack, but we have no better way to log
- // that audio is not and will not be working.
- if (message == media::kMsgDisableAudio)
+ // TODO(kylep): This is a horribly ugly hack, but we have no better way to
+ // log that audio is not and will not be working.
+ if (message == media::kMsgDisableAudio) {
+ // |rendered_mime_types_| is read through public methods so we need to lock
+ // this variable.
+ AutoLock auto_lock(lock_);
rendered_mime_types_.erase(mime_type::kMajorTypeAudio);
+ }
// Broadcast the message to all filters.
for (FilterVector::iterator iter = filters_.begin();
@@ -722,9 +747,8 @@ void PipelineImpl::FilterStateTransitionTask() {
if (--remaining_transitions_ == 0) {
state_ = FindNextState(state_);
if (state_ == kSeeking) {
+ AutoLock auto_lock(lock_);
clock_.SetTime(seek_timestamp_);
- } else if (state_ == kStarting) {
- clock_.Play();
}
if (StateTransitionsToStarted(state_)) {
@@ -755,6 +779,15 @@ void PipelineImpl::FilterStateTransitionTask() {
// Finally, reset our seeking timestamp back to zero.
seek_timestamp_ = base::TimeDelta();
+
+ AutoLock auto_lock(lock_);
+ // We use audio stream to update the clock. So if there is such a stream,
+ // we pause the clock until we receive a valid timestamp.
+ waiting_for_clock_update_ =
+ rendered_mime_types_.find(mime_type::kMajorTypeAudio) !=
+ rendered_mime_types_.end();
+ if (!waiting_for_clock_update_)
+ clock_.Play();
} else {
NOTREACHED();
}
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h
index 383969d..c448106 100644
--- a/media/base/pipeline_impl.h
+++ b/media/base/pipeline_impl.h
@@ -308,6 +308,11 @@ class PipelineImpl : public Pipeline, public FilterHost {
// by filters.
ClockImpl clock_;
+ // If this value is set to true, then |clock_| is paused and we are waiting
+ // for an update of the clock greater than or equal to the elapsed time to
+ // start the clock.
+ bool waiting_for_clock_update_;
+
// Status of the pipeline. Initialized to PIPELINE_OK which indicates that
// the pipeline is operating correctly. Any other value indicates that the
// pipeline is stopped or is stopping. Clients can call the Stop() method to