diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 00:12:04 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 00:12:04 +0000 |
commit | 83548cfb4900fa35d3f34a88340f10d2bcce74fc (patch) | |
tree | 4317a48420047c6c3d170d4a430743b832cc9ef9 /media | |
parent | cfdae27555853c2c57f7aa91179bc39407dc77bc (diff) | |
download | chromium_src-83548cfb4900fa35d3f34a88340f10d2bcce74fc.zip chromium_src-83548cfb4900fa35d3f34a88340f10d2bcce74fc.tar.gz chromium_src-83548cfb4900fa35d3f34a88340f10d2bcce74fc.tar.bz2 |
Big media::Pipeline cleanup.
Before I can even start refactoring, I need to remove a lot of accumulated cruft and fix some style stuff. PipelineStatus has been merged into Pipeline and I got rid of GetInterpolatedTime() as well as the ability to schedule callbacks when time has updated. We haven't found a need for these features and they introduced a good amount of code complexity.
TEST=media_unittests should still pass
BUG=16008
Review URL: http://codereview.chromium.org/149215
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/filter_host.h | 34 | ||||
-rw-r--r-- | media/base/filter_host_impl.cc | 63 | ||||
-rw-r--r-- | media/base/filter_host_impl.h | 64 | ||||
-rw-r--r-- | media/base/mock_filter_host.h | 29 | ||||
-rw-r--r-- | media/base/pipeline.h | 163 | ||||
-rw-r--r-- | media/base/pipeline_impl.cc | 293 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 71 | ||||
-rw-r--r-- | media/filters/video_renderer_base.cc | 2 | ||||
-rw-r--r-- | media/player/movie.cc | 2 |
9 files changed, 245 insertions, 476 deletions
diff --git a/media/base/filter_host.h b/media/base/filter_host.h index b911473..4907df2a 100644 --- a/media/base/filter_host.h +++ b/media/base/filter_host.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2008-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. @@ -24,31 +24,6 @@ namespace media { class FilterHost { public: - // The PipelineStatus class allows read-only access to the pipeline state. - // This is the same object that is used by the pipeline client to examine - // the state of the running pipeline. The lifetime of the PipelineStatus - // interface is the same as the lifetime of the FilterHost interface, so - // it is acceptable for filters to use the returned pointer until their - // Stop method has been called. - virtual const PipelineStatus* GetPipelineStatus() const = 0; - - // Registers a callback to receive global clock update notifications. The - // callback will be called repeatedly and filters do not need to re-register - // after each invocation of the callback. To remove the callback, filters - // may call this method passing NULL for the callback argument. - // - // Callback arguments: - // base::TimeDelta - the new pipeline time, in microseconds. - virtual void SetTimeUpdateCallback(Callback1<base::TimeDelta>::Type* cb) = 0; - - // Request that the time callback be called at the specified stream - // time. This will set a timer specific to the filter that will be fired - // no sooner than the specified time based on the interpolated time. Note - // that, becuase the callback will be made with the interpolated time, it is - // possible for time to move "backward" slightly when the audio device updates - // the pipeline time though the SetTime method. - virtual void ScheduleTimeUpdateCallback(base::TimeDelta time) = 0; - // Filters must call this method to indicate that their initialization is // complete. They may call this from within their Initialize() method or may // choose call it after processing some data. @@ -58,8 +33,11 @@ class FilterHost { // method with PIPELINE_OK or PIPELINE_STOPPING (used internally by pipeline). virtual void Error(PipelineError error) = 0; - // Sets the current time. Any filters that have registered a callback through - // the SetTimeUpdateCallback method will be notified of the change. + // Gets the current time in microseconds. + virtual base::TimeDelta GetTime() const = 0; + + // Updates the current time. Other filters should poll to examine the updated + // time. virtual void SetTime(base::TimeDelta time) = 0; // Get the duration of the media in microseconds. If the duration has not diff --git a/media/base/filter_host_impl.cc b/media/base/filter_host_impl.cc index 0cd348a..96e4e93 100644 --- a/media/base/filter_host_impl.cc +++ b/media/base/filter_host_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2008-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. @@ -6,56 +6,6 @@ namespace media { -void FilterHostImpl::SetTimeUpdateCallback( - Callback1<base::TimeDelta>::Type* callback) { - time_update_callback_.reset(callback); -} - -void FilterHostImpl::RunTimeUpdateCallback(base::TimeDelta time) { - if (time_update_callback_.get()) { - time_update_callback_->Run(time); - } -} - -// To understand why this method takes the |caller| parameter, see the comments -// of the TimeUpdatedTask in the file filter_host_impl.h. -void FilterHostImpl::RunScheduledTimeUpdateCallback(TimeUpdateTask* caller) { - time_update_lock_.Acquire(); - if (caller == scheduled_time_update_task_) { - scheduled_time_update_task_ = NULL; - } - time_update_lock_.Release(); - RunTimeUpdateCallback(pipeline()->GetInterpolatedTime()); -} - -void FilterHostImpl::ScheduleTimeUpdateCallback(base::TimeDelta time) { - time_update_lock_.Acquire(); - if (stopped_) { - time_update_lock_.Release(); - } else { - DCHECK(time_update_callback_.get()); - if (scheduled_time_update_task_) { - scheduled_time_update_task_->Cancel(); - } - scheduled_time_update_task_ = new TimeUpdateTask(this); - Task* task = scheduled_time_update_task_; - time_update_lock_.Release(); - - // Here, we compute the delta from now & adjust it by the playback rate. - time -= pipeline()->GetInterpolatedTime(); - int delay = static_cast<int>(time.InMilliseconds()); - float rate = pipeline()->GetPlaybackRate(); - if (rate > 0.0f) { - delay = static_cast<int>(delay / rate); - } - if (delay > 0) { - pipeline_thread_->message_loop()->PostDelayedTask(FROM_HERE, task, delay); - } else { - pipeline_thread_->message_loop()->PostTask(FROM_HERE, task); - } - } -} - void FilterHostImpl::InitializationComplete() { pipeline_thread_->InitializationComplete(this); } @@ -64,6 +14,10 @@ void FilterHostImpl::Error(PipelineError error) { pipeline_thread_->Error(error); } +base::TimeDelta FilterHostImpl::GetTime() const { + return pipeline()->GetTime(); +} + void FilterHostImpl::SetTime(base::TimeDelta time) { pipeline_thread_->SetTime(time); } @@ -88,18 +42,11 @@ void FilterHostImpl::SetVideoSize(size_t width, size_t height) { pipeline()->SetVideoSize(width, height); } -const PipelineStatus* FilterHostImpl::GetPipelineStatus() const { - return pipeline(); -} - void FilterHostImpl::Stop() { if (!stopped_) { filter_->Stop(); AutoLock auto_lock(time_update_lock_); stopped_ = true; - if (scheduled_time_update_task_) { - scheduled_time_update_task_->Cancel(); - } } } diff --git a/media/base/filter_host_impl.h b/media/base/filter_host_impl.h index 4ae9260..1fcb0c4 100644 --- a/media/base/filter_host_impl.h +++ b/media/base/filter_host_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2008-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. @@ -16,11 +16,9 @@ namespace media { class FilterHostImpl : public FilterHost { public: // FilterHost interface. - virtual const PipelineStatus* GetPipelineStatus() const; - virtual void SetTimeUpdateCallback(Callback1<base::TimeDelta>::Type* cb); - virtual void ScheduleTimeUpdateCallback(base::TimeDelta time); virtual void InitializationComplete(); virtual void Error(PipelineError error); + virtual base::TimeDelta GetTime() const; virtual void SetTime(base::TimeDelta time); virtual void SetDuration(base::TimeDelta duration); virtual void SetBufferedTime(base::TimeDelta buffered_time); @@ -31,7 +29,7 @@ class FilterHostImpl : public FilterHost { // These methods are public, but are intended for use by the // PipelineThread class only. - // Creates a FilterHostImpl object and populates the filter_type_ member + // Creates a FilterHostImpl object and populates the |filter_type_| member // by calling the Filter class's static filter_type() method. This ensures // that the GetFilter method can safely cast the filter interface from the // MediaFilter base class interface to the specific Filter interface. @@ -40,12 +38,11 @@ class FilterHostImpl : public FilterHost { : pipeline_thread_(pipeline_thread), filter_type_(Filter::filter_type()), filter_(filter), - scheduled_time_update_task_(NULL), stopped_(false) { } ~FilterHostImpl() {} - // If this FilterHost contains a filter of the specifed Filter class, then + // If this FilterHost contains a filter of the specified Filter class, then // this method returns a pointer to the interface, otherwise it returns NULL // in |*filter_out|. template <class Filter> @@ -54,10 +51,6 @@ class FilterHostImpl : public FilterHost { reinterpret_cast<Filter*>(media_filter()) : NULL; } - // Call the filter if it has registered a time update callback if the filter - // has registered one though the FilterHost::SetTimeUpdateCallback method. - void RunTimeUpdateCallback(base::TimeDelta time); - // Stops the filter. void Stop(); @@ -65,49 +58,6 @@ class FilterHostImpl : public FilterHost { MediaFilter* media_filter() const { return filter_; } private: - // This task class is used to schedule a time update callback for the filter. - // Because a filter may call the ScheduleTimeUpdateCallback method from any - // thread, and becuase we only want to honor the last call to that method, - // we always have only one current task. - // We are required to keep a pointer to the host and a boolean that tells - // us if the task was canceled because the cancelation could happen on one - // thread, just as the pipeline thread is calling the Run method on this task. - // So, we can't just NULL out the host_ to cancel this because it could - // fault. Once we have called the host, it needs to enter it's critical - // section and make sure that the task that has Run is, in fact, the last one - // that was scheduled. - // In the case where the filter host is Stopping (or being destroyed), it will - // be guaranteed to happen on the pipeline thread, thus making the setting - // of the |canceled_| bool thread safe since the task would only execute on - // the pipeline thread. This means that it could be possible for a task to - // hold a pointer to a |host_| that has been deleted, but it will never access - // that pointer because the task was canceled. - class TimeUpdateTask : public CancelableTask { - public: - explicit TimeUpdateTask(FilterHostImpl* host) - : host_(host), - canceled_(false) {} - - virtual void Run() { - if (!canceled_) { - host_->RunScheduledTimeUpdateCallback(this); - } - } - - virtual void Cancel() { - canceled_ = true; - } - - private: - FilterHostImpl* const host_; - bool canceled_; - - DISALLOW_COPY_AND_ASSIGN(TimeUpdateTask); - }; - - // Method used by the TimeUpdateTask to call back to the filter. - void RunScheduledTimeUpdateCallback(TimeUpdateTask* caller); - // Useful method for getting the pipeline. PipelineImpl* pipeline() const { return pipeline_thread_->pipeline(); } @@ -120,15 +70,9 @@ class FilterHostImpl : public FilterHost { // A pointer to the filter's MediaFilter base interface. scoped_refptr<MediaFilter> filter_; - // An optional callback that will be called when the time is updated. - scoped_ptr<Callback1<base::TimeDelta>::Type> time_update_callback_; - // Critical section used for scheduled time update callbacks. Lock time_update_lock_; - // Pointer to the current time update callback task. - TimeUpdateTask* scheduled_time_update_task_; - // Used to avoid calling Filter's Stop() method multiple times. bool stopped_; diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h index 0c1ae43..d6fde0b 100644 --- a/media/base/mock_filter_host.h +++ b/media/base/mock_filter_host.h @@ -40,18 +40,6 @@ class MockFilterHost : public FilterHost { virtual ~MockFilterHost() {} - virtual const PipelineStatus* GetPipelineStatus() const { - return mock_pipeline_; - } - - virtual void SetTimeUpdateCallback(Callback1<base::TimeDelta>::Type* cb) { - time_update_callback_.reset(cb); - } - - virtual void ScheduleTimeUpdateCallback(base::TimeDelta time) { - scheduled_callback_time_ = time; - } - virtual void InitializationComplete() { EXPECT_FALSE(initialized_); initialized_ = true; @@ -64,6 +52,10 @@ class MockFilterHost : public FilterHost { wait_for_error_.Signal(); } + virtual base::TimeDelta GetTime() const { + return mock_pipeline_->GetTime(); + } + virtual void SetTime(base::TimeDelta time) { mock_pipeline_->SetTime(time); } @@ -88,15 +80,6 @@ class MockFilterHost : public FilterHost { mock_pipeline_->SetVideoSize(width, height); } - // Used by unit tests to manipulate the filter. - base::TimeDelta GetScheduledCallbackTime() const { - return scheduled_callback_time_; - } - - Callback1<base::TimeDelta>::Type* GetTimeUpdateCallback() const { - return time_update_callback_.get(); - } - bool IsInitialized() const { return initialized_; } @@ -124,10 +107,6 @@ class MockFilterHost : public FilterHost { private: MockPipeline* mock_pipeline_; scoped_refptr<Filter> filter_; - scoped_ptr<Callback1<base::TimeDelta>::Type> time_update_callback_; - - // Keeps track of the time passed into ScheduleTimeUpdateCallback(). - base::TimeDelta scheduled_callback_time_; // Tracks if the filter has executed InitializationComplete(). bool initialized_; diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 66dab005..d418e4b 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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. @@ -15,7 +15,7 @@ #include "media/base/factory.h" namespace base { - class TimeDelta; +class TimeDelta; } namespace media { @@ -44,88 +44,15 @@ enum PipelineError { DEMUXER_ERROR_COULD_NOT_CREATE_THREAD, }; -// Base class for Pipeline class which allows for read-only access to members. -// Filters are allowed to access the PipelineStatus interface but are not given -// access to the client Pipeline methods. -class PipelineStatus { - public: - // Returns the current initialization state of the pipeline. Clients can - // examine this to determine if it is acceptable to call SetRate/SetVolume/ - // Seek after calling Start on the pipeline. Note that this will be - // set to true prior to a call to the client's |init_complete_callback| if - // initialization is successful. - virtual bool IsInitialized() const = 0; - - // Get the duration of the media in microseconds. If the duration has not - // been determined yet, then returns 0. - virtual base::TimeDelta GetDuration() const = 0; - - // Get the approximate amount of playable data buffered so far in micro- - // seconds. - virtual base::TimeDelta GetBufferedTime() const = 0; - - // Get the total size of the media file. If the size has not yet been - // determined or can not be determined, this value is 0. - virtual int64 GetTotalBytes() const = 0; - - // Get the total number of bytes that are buffered on the client and ready to - // be played. - virtual int64 GetBufferedBytes() const = 0; - - // Gets the size of the video output in pixel units. If there is no video - // or the video has not been rendered yet, the width and height will be 0. - virtual void GetVideoSize(size_t* width_out, size_t* height_out) const = 0; - - // Gets the current volume setting being used by the audio renderer. When - // the pipeline is started, this value will be 1.0f. Valid values range - // from 0.0f to 1.0f. - virtual float GetVolume() const = 0; - - // Gets the current playback rate of the pipeline. When the pipeline is - // started, the playback rate will be 0.0f. A rate of 1.0f indicates - // that the pipeline is rendering the media at the standard rate. Valid - // values for playback rate are >= 0.0f. - virtual float GetPlaybackRate() const = 0; - - // Gets the current pipeline time in microseconds. For a pipeline "time" - // progresses from 0 to the end of the media. This time base is updated - // by the audio renderer to allow for synchronization of audio and video. - // Note that a more accurate time may be obtained by calling the - // GetInterpolatedTime method which estimates the position of the audio - // device based on a combination of the last time the audio device reported - // it's position and the current system time. - virtual base::TimeDelta GetTime() const = 0; - - // Gets the current pipeline time in microseconds. For a pipeline "time" - // progresses from 0 to the end of the media. Becuase this method provides - // an estimated time, it is possible that subsequent calls to this method will - // actually progress backwards slightly, so callers must not assume that this - // method will always return times larger than the last one. - virtual base::TimeDelta GetInterpolatedTime() const = 0; - - // Gets the current error status for the pipeline. If the pipeline is - // operating correctly, this will return OK. - virtual PipelineError GetError() const = 0; - - // If the |major_mime_type| exists in the pipeline and is being rendered, this - // method will return true. Types are defined in media/base/media_foramt.h. - // For example, to determine if a pipeline contains video: - // bool has_video = pipeline->IsRendered(mime_type::kMajorTypeVideo); - virtual bool IsRendered(const std::string& major_mime_type) const = 0; - - protected: - virtual ~PipelineStatus() {} -}; - // Client-provided callbacks for various pipeline operations. // // TODO(scherkus): consider returning a PipelineError instead of a bool, or // perhaps a client callback interface. typedef Callback1<bool>::Type PipelineCallback; -class Pipeline : public PipelineStatus { +class Pipeline { public: - // Build a pipeline to render the given URI using the given filter factory to + // Build a pipeline to render the given URL using the given filter factory to // construct a filter chain. Returns true if successful, false otherwise // (i.e., pipeline already started). Note that a return value of true // only indicates that the initialization process has started successfully. @@ -149,42 +76,90 @@ class Pipeline : public PipelineStatus { // the pipeline class, not on the thread that originally called the Start() // method. virtual bool Start(FilterFactory* filter_factory, - const std::string& uri, + const std::string& url, PipelineCallback* start_callback) = 0; // Stops the pipeline and resets to an uninitialized state. This method // will block the calling thread until the pipeline has been completely - // torn down and reset to an uninitialized state. After calling Stop, it - // is acceptable to call Start again since Stop leaves the pipeline + // torn down and reset to an uninitialized state. After calling Stop(), it + // is acceptable to call Start() again since Stop() leaves the pipeline // in a state identical to a newly created pipeline. - // Calling this method is not strictly required because the pipeline - // destructor will stop it pipeline if it has not been stopped already. + // + // Stop() must be called before destroying the pipeline. + // + // TODO(scherkus): it shouldn't be acceptable to call Start() again after you + // Stop() a pipeline -- it should be destroyed and replaced with a new + // instance. virtual void Stop() = 0; + // Attempt to seek to the position specified by time. |seek_callback| will be + // executed when the all filters in the pipeline have processed the seek. + // The callback will return true if the seek was carried out, false otherwise + // (i.e., streaming media). + virtual void Seek(base::TimeDelta time, PipelineCallback* seek_callback) = 0; + + // Returns the current initialization state of the pipeline. Note that this + // will be set to true prior to a executing |init_complete_callback| if + // initialization is successful. + virtual bool IsInitialized() const = 0; + + // If the |major_mime_type| exists in the pipeline and is being rendered, this + // method will return true. Types are defined in media/base/media_foramt.h. + // For example, to determine if a pipeline contains video: + // bool has_video = pipeline->IsRendered(mime_type::kMajorTypeVideo); + virtual bool IsRendered(const std::string& major_mime_type) const = 0; + + // Gets the current playback rate of the pipeline. When the pipeline is + // started, the playback rate will be 0.0f. A rate of 1.0f indicates + // that the pipeline is rendering the media at the standard rate. Valid + // values for playback rate are >= 0.0f. + virtual float GetPlaybackRate() const = 0; + // Attempt to adjust the playback rate. Setting a playback rate of 0.0f pauses // all rendering of the media. A rate of 1.0f indicates a normal playback // rate. Values for the playback rate must be greater than or equal to 0.0f. - // TODO(ralphl): What about maximum rate? Does HTML5 specify a max? // - // This method must be called only after initialization has completed. + // TODO(scherkus): What about maximum rate? Does HTML5 specify a max? virtual void SetPlaybackRate(float playback_rate) = 0; - // Attempt to seek to the position specified by time. |seek_callback| will be - // executed when the all filters in the pipeline have processed the seek. - // The callback will return true if the seek was carried out, false otherwise - // (i.e., streaming media). - // - // This method must be called only after initialization has completed. - virtual void Seek(base::TimeDelta time, - PipelineCallback* seek_callback) = 0; + // Gets the current volume setting being used by the audio renderer. When + // the pipeline is started, this value will be 1.0f. Valid values range + // from 0.0f to 1.0f. + virtual float GetVolume() const = 0; // Attempt to set the volume of the audio renderer. Valid values for volume // range from 0.0f (muted) to 1.0f (full volume). This value affects all // channels proportionately for multi-channel audio streams. - // - // This method must be called only after initialization has completed. virtual void SetVolume(float volume) = 0; + // Gets the current pipeline time. For a pipeline "time" progresses from 0 to + // the end of the media. + virtual base::TimeDelta GetTime() const = 0; + + // Get the approximate amount of playable data buffered so far in micro- + // seconds. + virtual base::TimeDelta GetBufferedTime() const = 0; + + // Get the duration of the media in microseconds. If the duration has not + // been determined yet, then returns 0. + virtual base::TimeDelta GetDuration() const = 0; + + // Get the total number of bytes that are buffered on the client and ready to + // be played. + virtual int64 GetBufferedBytes() const = 0; + + // Get the total size of the media file. If the size has not yet been + // determined or can not be determined, this value is 0. + virtual int64 GetTotalBytes() const = 0; + + // Gets the size of the video output in pixel units. If there is no video + // or the video has not been rendered yet, the width and height will be 0. + virtual void GetVideoSize(size_t* width_out, size_t* height_out) const = 0; + + // Gets the current error status for the pipeline. If the pipeline is + // operating correctly, this will return OK. + virtual PipelineError GetError() const = 0; + protected: virtual ~Pipeline() {} }; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 16148d3..e9edc4f 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -54,110 +54,6 @@ PipelineImpl::~PipelineImpl() { Stop(); } -bool PipelineImpl::IsInitialized() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return initialized_; -} - -base::TimeDelta PipelineImpl::GetDuration() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return duration_; -} - -base::TimeDelta PipelineImpl::GetBufferedTime() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return buffered_time_; -} - -int64 PipelineImpl::GetTotalBytes() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return total_bytes_; -} - -int64 PipelineImpl::GetBufferedBytes() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return buffered_bytes_; -} - -void PipelineImpl::GetVideoSize(size_t* width_out, size_t* height_out) const { - DCHECK(width_out); - DCHECK(height_out); - AutoLock auto_lock(const_cast<Lock&>(lock_)); - *width_out = video_width_; - *height_out = video_height_; -} - -float PipelineImpl::GetVolume() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return volume_; -} - -float PipelineImpl::GetPlaybackRate() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return playback_rate_; -} - -base::TimeDelta PipelineImpl::GetTime() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return time_; -} - -base::TimeDelta PipelineImpl::GetInterpolatedTime() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - base::TimeDelta time = time_; - if (playback_rate_ > 0.0f) { - base::TimeDelta delta = base::TimeTicks::Now() - ticks_at_last_set_time_; - if (playback_rate_ == 1.0f) { - time += delta; - } else { - int64 adjusted_delta = static_cast<int64>(delta.InMicroseconds() * - playback_rate_); - time += base::TimeDelta::FromMicroseconds(adjusted_delta); - } - } - return time; -} - -void PipelineImpl::SetTime(base::TimeDelta time) { - AutoLock auto_lock(lock_); - time_ = time; - ticks_at_last_set_time_ = base::TimeTicks::Now(); -} - -void PipelineImpl::InternalSetPlaybackRate(float rate) { - AutoLock auto_lock(lock_); - if (playback_rate_ == 0.0f && rate > 0.0f) { - ticks_at_last_set_time_ = base::TimeTicks::Now(); - } - playback_rate_ = rate; -} - -PipelineError PipelineImpl::GetError() const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - return error_; -} - -bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { - AutoLock auto_lock(const_cast<Lock&>(lock_)); - bool is_rendered = (rendered_mime_types_.find(major_mime_type) != - rendered_mime_types_.end()); - return is_rendered; -} - - -bool PipelineImpl::InternalSetError(PipelineError error) { - // Don't want callers to set an error of "OK". STOPPING is a special value - // that should only be used internally by the StopTask() method. - DCHECK(PIPELINE_OK != error && PIPELINE_STOPPING != error); - AutoLock auto_lock(lock_); - bool changed_error = false; - if (PIPELINE_OK == error_) { - error_ = error; - changed_error = true; - } - return changed_error; -} - // Creates the PipelineThread and calls it's start method. bool PipelineImpl::Start(FilterFactory* factory, const std::string& url, @@ -192,6 +88,34 @@ void PipelineImpl::Stop() { ResetState(); } +void PipelineImpl::Seek(base::TimeDelta time, + PipelineCallback* seek_callback) { + DCHECK(!IsPipelineThread()); + + if (IsPipelineOk()) { + pipeline_thread_->Seek(time, seek_callback); + } else { + NOTREACHED(); + } +} + +bool PipelineImpl::IsInitialized() const { + AutoLock auto_lock(lock_); + return initialized_; +} + +bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { + AutoLock auto_lock(lock_); + bool is_rendered = (rendered_mime_types_.find(major_mime_type) != + rendered_mime_types_.end()); + return is_rendered; +} + +float PipelineImpl::GetPlaybackRate() const { + AutoLock auto_lock(lock_); + return playback_rate_; +} + void PipelineImpl::SetPlaybackRate(float rate) { DCHECK(!IsPipelineThread()); @@ -203,15 +127,9 @@ void PipelineImpl::SetPlaybackRate(float rate) { } } -void PipelineImpl::Seek(base::TimeDelta time, - PipelineCallback* seek_callback) { - DCHECK(!IsPipelineThread()); - - if (IsPipelineOk()) { - pipeline_thread_->Seek(time, seek_callback); - } else { - NOTREACHED(); - } +float PipelineImpl::GetVolume() const { + AutoLock auto_lock(lock_); + return volume_; } void PipelineImpl::SetVolume(float volume) { @@ -224,6 +142,44 @@ void PipelineImpl::SetVolume(float volume) { } } +base::TimeDelta PipelineImpl::GetTime() const { + AutoLock auto_lock(lock_); + return time_; +} + +base::TimeDelta PipelineImpl::GetBufferedTime() const { + AutoLock auto_lock(lock_); + return buffered_time_; +} + +base::TimeDelta PipelineImpl::GetDuration() const { + AutoLock auto_lock(lock_); + return duration_; +} + +int64 PipelineImpl::GetBufferedBytes() const { + AutoLock auto_lock(lock_); + return buffered_bytes_; +} + +int64 PipelineImpl::GetTotalBytes() const { + AutoLock auto_lock(lock_); + return total_bytes_; +} + +void PipelineImpl::GetVideoSize(size_t* width_out, size_t* height_out) const { + CHECK(width_out); + CHECK(height_out); + AutoLock auto_lock(lock_); + *width_out = video_width_; + *height_out = video_height_; +} + +PipelineError PipelineImpl::GetError() const { + AutoLock auto_lock(lock_); + return error_; +} + void PipelineImpl::ResetState() { AutoLock auto_lock(lock_); pipeline_thread_ = NULL; @@ -238,7 +194,6 @@ void PipelineImpl::ResetState() { playback_rate_ = 0.0f; error_ = PIPELINE_OK; time_ = base::TimeDelta(); - ticks_at_last_set_time_ = base::TimeTicks::Now(); rendered_mime_types_.clear(); } @@ -277,6 +232,29 @@ void PipelineImpl::SetVideoSize(size_t width, size_t height) { video_height_ = height; } +void PipelineImpl::SetTime(base::TimeDelta time) { + AutoLock auto_lock(lock_); + time_ = time; +} + +void PipelineImpl::InternalSetPlaybackRate(float rate) { + AutoLock auto_lock(lock_); + playback_rate_ = rate; +} + +bool PipelineImpl::InternalSetError(PipelineError error) { + // Don't want callers to set an error of "OK". STOPPING is a special value + // that should only be used internally by the StopTask() method. + DCHECK(PIPELINE_OK != error && PIPELINE_STOPPING != error); + AutoLock auto_lock(lock_); + bool changed_error = false; + if (PIPELINE_OK == error_) { + error_ = error; + changed_error = true; + } + return changed_error; +} + void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) { AutoLock auto_lock(lock_); rendered_mime_types_.insert(major_mime_type); @@ -288,7 +266,6 @@ void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) { PipelineThread::PipelineThread(PipelineImpl* pipeline) : pipeline_(pipeline), thread_("PipelineThread"), - time_update_callback_scheduled_(false), state_(kCreated) { } @@ -308,7 +285,8 @@ bool PipelineThread::Start(FilterFactory* filter_factory, filter_factory_ = filter_factory; url_ = url; init_callback_.reset(init_complete_callback); - PostTask(NewRunnableMethod(this, &PipelineThread::StartTask)); + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::StartTask)); return true; } return false; @@ -319,7 +297,8 @@ bool PipelineThread::Start(FilterFactory* filter_factory, // stopped. void PipelineThread::Stop() { if (thread_.IsRunning()) { - PostTask(NewRunnableMethod(this, &PipelineThread::StopTask)); + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::StopTask)); thread_.Stop(); } DCHECK(filter_hosts_.empty()); @@ -327,37 +306,36 @@ void PipelineThread::Stop() { } // Called on client's thread. -void PipelineThread::SetPlaybackRate(float rate) { - PostTask(NewRunnableMethod(this, &PipelineThread::SetPlaybackRateTask, rate)); +void PipelineThread::Seek(base::TimeDelta time, + PipelineCallback* seek_callback) { + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::SeekTask, time, seek_callback)); } // Called on client's thread. -void PipelineThread::Seek(base::TimeDelta time, - PipelineCallback* seek_callback) { - PostTask(NewRunnableMethod(this, &PipelineThread::SeekTask, time, - seek_callback)); +void PipelineThread::SetPlaybackRate(float rate) { + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::SetPlaybackRateTask, rate)); } // Called on client's thread. void PipelineThread::SetVolume(float volume) { - PostTask(NewRunnableMethod(this, &PipelineThread::SetVolumeTask, volume)); + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::SetVolumeTask, volume)); } +// Called from any thread. void PipelineThread::InitializationComplete(FilterHostImpl* host) { if (IsPipelineOk()) { // Continue the start task by proceeding to the next stage. - PostTask(NewRunnableMethod(this, &PipelineThread::StartTask)); + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::StartTask)); } } -// Called from any thread. Updates the pipeline time and schedules a task to -// call back to filters that have registered a callback for time updates. +// Called from any thread. Updates the pipeline time. void PipelineThread::SetTime(base::TimeDelta time) { pipeline()->SetTime(time); - if (!time_update_callback_scheduled_) { - time_update_callback_scheduled_ = true; - PostTask(NewRunnableMethod(this, &PipelineThread::SetTimeTask)); - } } // Called from any thread. Sets the pipeline |error_| member and schedules a @@ -368,17 +346,19 @@ void PipelineThread::Error(PipelineError error) { // If this method returns false, then an error has already happened, so no // reason to run the StopTask again. It's going to happen. if (pipeline()->InternalSetError(error)) { - PostTask(NewRunnableMethod(this, &PipelineThread::StopTask)); + message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &PipelineThread::StopTask)); } } -// This is a helper method to post task on message_loop(). This method is only -// called from this class or from Pipeline. -void PipelineThread::PostTask(Task* task) { - message_loop()->PostTask(FROM_HERE, task); +// Called as a result of destruction of the thread. +// +// TODO(scherkus): this can block the client due to synchronous Stop() API call. +void PipelineThread::WillDestroyCurrentMessageLoop() { + STLDeleteElements(&filter_hosts_); + STLDeleteElements(&filter_threads_); } - // Main initialization method called on the pipeline thread. This code attempts // to use the specified filter factory to build a pipeline. // Initialization step performed in this method depends on current state of this @@ -603,29 +583,6 @@ void PipelineThread::SetVolumeTask(float volume) { } } -void PipelineThread::SetTimeTask() { - DCHECK_EQ(PlatformThread::CurrentId(), thread_.thread_id()); - - time_update_callback_scheduled_ = false; - for (FilterHostVector::iterator iter = filter_hosts_.begin(); - iter != filter_hosts_.end(); - ++iter) { - (*iter)->RunTimeUpdateCallback(pipeline_->time_); - } -} - -template <class Filter> -void PipelineThread::GetFilter(scoped_refptr<Filter>* filter_out) const { - DCHECK_EQ(PlatformThread::CurrentId(), thread_.thread_id()); - - *filter_out = NULL; - for (FilterHostVector::const_iterator iter = filter_hosts_.begin(); - iter != filter_hosts_.end() && NULL == *filter_out; - iter++) { - (*iter)->GetFilter(filter_out); - } -} - template <class Filter, class Source> void PipelineThread::CreateFilter(FilterFactory* filter_factory, Source source, @@ -723,12 +680,16 @@ bool PipelineThread::CreateRenderer() { return false; } -// Called as a result of destruction of the thread. -// -// TODO(scherkus): this can block the client due to synchronous Stop() API call. -void PipelineThread::WillDestroyCurrentMessageLoop() { - STLDeleteElements(&filter_hosts_); - STLDeleteElements(&filter_threads_); +template <class Filter> +void PipelineThread::GetFilter(scoped_refptr<Filter>* filter_out) const { + DCHECK_EQ(PlatformThread::CurrentId(), thread_.thread_id()); + + *filter_out = NULL; + for (FilterHostVector::const_iterator iter = filter_hosts_.begin(); + iter != filter_hosts_.end() && NULL == *filter_out; + iter++) { + (*iter)->GetFilter(filter_out); + } } } // namespace media diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 5e348d5..a8e9e09 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2008-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. @@ -32,29 +32,25 @@ class PipelineImpl : public Pipeline { PipelineImpl(); virtual ~PipelineImpl(); - // Implementation of PipelineStatus methods. + // Pipeline implementation. + virtual bool Start(FilterFactory* filter_factory, + const std::string& uri, + PipelineCallback* start_callback); + virtual void Stop(); + virtual void Seek(base::TimeDelta time, PipelineCallback* seek_callback); virtual bool IsInitialized() const; - virtual base::TimeDelta GetDuration() const; + virtual bool IsRendered(const std::string& major_mime_type) const; + virtual float GetPlaybackRate() const; + virtual void SetPlaybackRate(float playback_rate); + virtual float GetVolume() const; + virtual void SetVolume(float volume); + virtual base::TimeDelta GetTime() const; virtual base::TimeDelta GetBufferedTime() const; + virtual base::TimeDelta GetDuration() const; + virtual int64 GetBufferedBytes() const; virtual int64 GetTotalBytes() const; - virtual int64 GetBufferedBytes()const; virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; - virtual float GetVolume() const; - virtual float GetPlaybackRate() const; - virtual base::TimeDelta GetTime() const; - virtual base::TimeDelta GetInterpolatedTime() const; virtual PipelineError GetError() const; - virtual bool IsRendered(const std::string& major_mime_type) const; - - // Implementation of Pipeline methods. - virtual bool Start(FilterFactory* filter_factory, - const std::string& url, - PipelineCallback* start_callback); - virtual void Stop(); - virtual void SetPlaybackRate(float rate); - virtual void Seek(base::TimeDelta time, - PipelineCallback* seek_callback); - virtual void SetVolume(float volume); private: friend class FilterHostImpl; @@ -117,7 +113,7 @@ class PipelineImpl : public Pipeline { int64 total_bytes_; // Lock used to serialize access for getter/setter methods. - Lock lock_; + mutable Lock lock_; // Video width and height. Set by a FilterHostImpl object on behalf // of a filter. The video_size_access_lock_ is used to make sure access @@ -142,10 +138,6 @@ class PipelineImpl : public Pipeline { // audio renderer filter. base::TimeDelta time_; - // Internal system timer at last time the SetTime method was called. Used to - // compute interpolated time. - base::TimeTicks ticks_at_last_set_time_; - // 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 @@ -195,8 +187,8 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, const std::string& url_media_source, PipelineCallback* init_complete_callback); void Stop(); - void SetPlaybackRate(float rate); void Seek(base::TimeDelta time, PipelineCallback* seek_callback); + void SetPlaybackRate(float rate); void SetVolume(float volume); // Methods called by a FilterHostImpl object. These methods may be called @@ -215,10 +207,6 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, // If the pipeline is running a nested message loop, it will be exited. void Error(PipelineError error); - // Called by a FilterHostImpl on behalf of a filter that calls the - // FilterHost::PostTask method. - void PostTask(Task* task); - // Simple accessor used by the FilterHostImpl class to get access to the // pipeline object. PipelineImpl* pipeline() const { return pipeline_; } @@ -231,6 +219,10 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, PlatformThreadId thread_id() const { return thread_.thread_id(); } private: + // Only allow ourselves to be destroyed via ref-counting. + friend class base::RefCountedThreadSafe<PipelineThread>; + virtual ~PipelineThread(); + enum State { kCreated, kInitDataSource, @@ -244,16 +236,6 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, kError, }; - // Implementation of MessageLoop::DestructionObserver. StartTask registers - // this class as a destruction observer on the thread's message loop. - // It is used to destroy the list of FilterHosts - // (and thus destroy the associated filters) when all tasks have been - // processed and the message loop has been quit. - virtual void WillDestroyCurrentMessageLoop(); - - friend class base::RefCountedThreadSafe<PipelineThread>; - virtual ~PipelineThread(); - // Simple method used to make sure the pipeline is running normally. bool IsPipelineOk() { return PIPELINE_OK == pipeline_->error_; } @@ -267,6 +249,13 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, state_ == kInitVideoRenderer; } + // Implementation of MessageLoop::DestructionObserver. StartTask registers + // this class as a destruction observer on the thread's message loop. + // It is used to destroy the list of FilterHosts + // (and thus destroy the associated filters) when all tasks have been + // processed and the message loop has been quit. + virtual void WillDestroyCurrentMessageLoop(); + // The following "task" methods correspond to the public methods, but these // methods are run as the result of posting a task to the PipelineThread's // message loop. @@ -280,14 +269,10 @@ class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, void SetPlaybackRateTask(float rate); void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); void SetVolumeTask(float volume); - void SetTimeTask(); // Internal methods used in the implementation of the pipeline thread. All // of these methods are only called on the pipeline thread. - // Calls the Stop method on every filter in the pipeline - void StopFilters(); - // The following template functions make use of the fact that media filter // derived interfaces are self-describing in the sense that they all contain // the static method filter_type() which returns a FilterType enum that diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index 2a9ba66..094c92a 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -188,7 +188,7 @@ void VideoRendererBase::ThreadMain() { OnFrameAvailable(); // Determine the current and next presentation timestamps. - base::TimeDelta now = host_->GetPipelineStatus()->GetTime(); + base::TimeDelta now = host_->GetTime(); base::TimeDelta this_pts = current_frame_->GetTimestamp(); base::TimeDelta next_pts; if (next_frame) { diff --git a/media/player/movie.cc b/media/player/movie.cc index 1ef840f..e37a497 100644 --- a/media/player/movie.cc +++ b/media/player/movie.cc @@ -119,7 +119,7 @@ float Movie::GetDuration() { float Movie::GetPosition() { float position = 0.f; if (pipeline_.get()) - position = (pipeline_->GetInterpolatedTime()).InMicroseconds() / 1000000.0f; + position = (pipeline_->GetTime()).InMicroseconds() / 1000000.0f; return position; } |