summaryrefslogtreecommitdiffstats
path: root/media/base/pipeline_impl.h
diff options
context:
space:
mode:
authorralphl@chromium.org <ralphl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-28 17:21:23 +0000
committerralphl@chromium.org <ralphl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-28 17:21:23 +0000
commitb026f4aeb159244e47d3b55c5faad7bb3247fd55 (patch)
treeefda81548664ea009160ded8588904185b384ca4 /media/base/pipeline_impl.h
parentabc659b6d95cf197c2b96a544351a667e8b96f95 (diff)
downloadchromium_src-b026f4aeb159244e47d3b55c5faad7bb3247fd55.zip
chromium_src-b026f4aeb159244e47d3b55c5faad7bb3247fd55.tar.gz
chromium_src-b026f4aeb159244e47d3b55c5faad7bb3247fd55.tar.bz2
Implementation of Pipeline and FilterHost interfaces. This is a large change, but all of the objects are interrelated.
I am also checking in a basic unit test that creates pipeline, and the data source hangs during initialization. The test sleeps one second and then stops the pipeline. Andrew has already done a first pass on this, and the code has come largely from our working experimental branch. Review URL: http://codereview.chromium.org/18546 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8805 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/pipeline_impl.h')
-rw-r--r--media/base/pipeline_impl.h257
1 files changed, 250 insertions, 7 deletions
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h
index 7c920e9..dc46c02 100644
--- a/media/base/pipeline_impl.h
+++ b/media/base/pipeline_impl.h
@@ -8,11 +8,24 @@
#define MEDIA_BASE_PIPELINE_IMPL_H_
#include <string>
+#include <vector>
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/thread.h"
+#include "base/time.h"
#include "media/base/pipeline.h"
namespace media {
+class FilterHostImpl;
+class PipelineThread;
+
+// Class which implements the Media::Pipeline contract. The majority of the
+// actual code for this object lives in the PipelineThread class, which is
+// responsible for actually building and running the pipeline. This object
+// is basically a simple container for state information, and is responsible
+// for creating and communicating with the PipelineThread object.
class PipelineImpl : public Pipeline {
public:
PipelineImpl();
@@ -20,29 +33,259 @@ class PipelineImpl : public Pipeline {
// Implementation of PipelineStatus methods.
virtual bool IsInitialized() const;
- virtual int64 GetDuration() const;
- virtual int64 GetBufferedTime() const;
+ virtual base::TimeDelta GetDuration() const;
+ virtual base::TimeDelta GetBufferedTime() 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 int64 GetTime() const;
+ virtual base::TimeDelta GetTime() const;
virtual PipelineError GetError() const;
// Impementation of Pipeline methods.
virtual bool Start(FilterFactory* filter_factory,
- const std::string& uri,
+ const std::string& url,
Callback1<bool>::Type* init_complete_callback);
virtual void Stop();
- virtual bool SetPlaybackRate(float rate);
- virtual bool Seek(int64 time);
- virtual bool SetVolume(float volume);
+ virtual void SetPlaybackRate(float rate);
+ virtual void Seek(base::TimeDelta time);
+ virtual void SetVolume(float volume);
private:
+ friend class FilterHostImpl;
+ friend class PipelineThread;
+
+ // Reset the state of the pipline object to the initial state. This method
+ // is used by the constructor, and the Stop method.
+ void ResetState();
+
+ // Used internally to make sure that the thread is in a state that is
+ // acceptable to post a task to. It must exist, be initialized, and there
+ // must not be an error.
+ bool OkToCallThread() const {
+ return (pipeline_thread_ && initialized_ && PIPELINE_OK == error_);
+ }
+
+ // Called directly by the FilterHostImpl object to set the video size.
+ void SetVideoSize(size_t width, size_t height);
+
+ // Holds a ref counted reference to the PipelineThread object associated
+ // with this pipeline. Prior to the call to the Start method, this member
+ // will be NULL, since no thread is running.
+ scoped_refptr<PipelineThread> pipeline_thread_;
+
+ // After calling Start, if all of the required filters are created and
+ // initialized, this member will be set to true by the pipeline thread.
+ bool initialized_;
+
+ // Duration of the media in microseconds. Set by a FilterHostImpl object on
+ // behalf of a filter.
+ base::TimeDelta duration_;
+
+ // Amount of available buffered data in microseconds. Set by a
+ // FilterHostImpl object on behalf of a filter.
+ base::TimeDelta buffered_time_;
+
+ // Amount of available buffered data. Set by a FilterHostImpl object
+ // on behalf of a filter.
+ int64 buffered_bytes_;
+
+ // Total size of the media. Set by a FilterHostImpl object on behalf
+ // of a filter.
+ int64 total_bytes_;
+
+ // 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
+ // to the pair of width and height are modified or read in thread safe way.
+ Lock video_size_access_lock_;
+ size_t video_width_;
+ size_t video_height_;
+
+ // Current volume level (from 0.0f to 1.0f). The volume reflects the last
+ // value the audio filter was called with SetVolume, so there will be a short
+ // period of time between the client calling SetVolume on the pipeline and
+ // this value being updated. Set by the PipelineThread just prior to calling
+ // the audio renderer.
+ float volume_;
+
+ // Current playback rate (>= 0.0f). This member reflects the last value
+ // that the filters in the pipeline were called with, so there will be a short
+ // period of time between the client calling SetPlaybackRate and this value
+ // being updated. Set by the PipelineThread just prior to calling filters.
+ float playback_rate_;
+
+ // Current playback time. Set by a FilterHostImpl object on behalf of the
+ // audio renderer filter.
+ base::TimeDelta 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
+ // reset the pipeline state, and restore this to PIPELINE_OK.
+ PipelineError error_;
+
DISALLOW_COPY_AND_ASSIGN(PipelineImpl);
};
+
+// The PipelineThread contains most of the logic involved with running the
+// media pipeline. Filters are created and called on a dedicated thread owned
+// by this object.
+class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>,
+ public MessageLoop::DestructionObserver {
+ public:
+ // Methods called by PipelineImpl object on the client's thread. These
+ // methods post a task to call a corresponding xxxTask() method on the
+ // pipeline thread. For example, Seek posts a task to call SeekTask.
+ explicit PipelineThread(PipelineImpl* pipeline);
+
+ bool Start(FilterFactory* filter_factory,
+ const std::string& url_media_source,
+ Callback1<bool>::Type* init_complete_callback);
+ void Stop();
+ void SetPlaybackRate(float rate);
+ void Seek(base::TimeDelta time);
+ void SetVolume(float volume);
+
+ // Methods called by a FilterHostImpl object. These methods may be called
+ // on any thread, either the pipeline's thread or any other.
+
+ // When a filter calls it's FilterHost, the filter host calls back to the
+ // pipeline thread. If the pipeline thread is running a nested message loop
+ // then it will be exited.
+ void InitializationComplete(FilterHostImpl* host);
+
+ // Sets the pipeline time and schedules a task to call back to any filters
+ // that have registered a time update callback.
+ void SetTime(base::TimeDelta time);
+
+ // Called by a FilterHostImpl on behalf of a filter calling FilerHost::Error.
+ // 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_; }
+
+ private:
+ // 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();
+
+ MessageLoop* message_loop() const { return thread_.message_loop(); }
+
+ // 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. For example, the Start method posts a task to call the
+ // StartTask message on the pipeline thread.
+ void StartTask(FilterFactory* filter_factory,
+ const std::string& url,
+ Callback1<bool>::Type* init_complete_callback);
+ void StopTask();
+ void SetPlaybackRateTask(float rate);
+ void SeekTask(base::TimeDelta time);
+ void SetVolumeTask(float volume);
+ void SetTimeTask();
+ void InitializationCompleteTask(FilterHostImpl* FilterHost);
+
+ // 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();
+
+ // Examines the demuxer filter output streams. If one contains video then
+ // returns true.
+ bool HasVideo() const;
+
+ // The following template funcions 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
+ // uniquely identifies the filer's interface. In addition, filters that are
+ // specific to audio or video also support a static method major_mime_type()
+ // which returns a string of "audio/" or "video/".
+
+ // Uses the FilterFactory to create a new filter of the NewFilter class, and
+ // initiaializes it using the Source object. The source may be another filter
+ // or it could be a string in the case of a DataSource.
+ //
+ // The CreateFilter method actually does much more than simply creating the
+ // filter. It creates the FilterHostImpl object, creates the filter using
+ // the filter factory, calls the MediaFilter::SetHost method on the filter,
+ // and then calls the filter's type-specific Initialize(source) method to
+ // initialize the filter. It then runs the thread's message loop and waits
+ // until one of the following occurs:
+ // 1. The filter calls FilterHost::InitializationComplete()
+ // 2. A filter calls FilterHost::Error()
+ // 3. The client calls Pipeline::Stop()
+ template <class NewFilter, class Source>
+ bool CreateFilter(FilterFactory* filter_factory,
+ Source source,
+ const MediaFormat* source_media_format);
+
+ // Creates a DataSource (the first filter in a pipeline), and initializes it
+ // with the specified URL.
+ bool CreateDataSource(FilterFactory* filter_factory,
+ const std::string& url);
+
+ // Examines the list of existing filters to find a Source, then creates a
+ // NewFilter, and initializes it with the Source filter.
+ template <class NewFilter, class Source>
+ bool CreateAndConnect(FilterFactory* filter_factory);
+
+ // Creates and initiaializes a decoder.
+ template <class Decoder>
+ bool CreateDecoder(FilterFactory* filter_factory);
+
+ // Examine the list of existing filters to find one that supports the
+ // specified Filter interface. If one exists, the specified Filter interface
+ // is returned otherwise the method retuns NULL.
+ template <class Filter>
+ Filter* GetFilter() const;
+
+ // Simple function that returns true if the specified MediaFormat object
+ // has a mime type that matches the major_mime_type. Examples of major mime
+ // types are "audio/" and "video/"
+ bool IsMajorMimeType(const MediaFormat* media_format,
+ const std::string& major_mime_type) const;
+
+ // Pointer to the pipeline that owns this PipelineThread.
+ PipelineImpl* const pipeline_;
+
+ // The actual thread.
+ base::Thread thread_;
+
+ // Used to avoid scheduling multiple time update tasks. If this member is
+ // true then a task that will call the SetTimeTask() method is in the message
+ // loop's queue.
+ bool time_update_callback_scheduled_;
+
+ // During initialization of a filter, this member points to the FilterHostImpl
+ // that is being initialized.
+ FilterHostImpl* host_initializing_;
+
+ // This lock is held through the entire StartTask method to prevent the
+ // Stop method from quitting the nested message loop of the StartTask method.
+ Lock initialization_lock_;
+
+ // Vector of FilterHostImpl objects that contian the filters for the pipeline.
+ typedef std::vector<FilterHostImpl*> FilterHostVector;
+ FilterHostVector filter_hosts_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipelineThread);
+};
+
} // namespace media
#endif // MEDIA_BASE_PIPELINE_IMPL_H_