Chromium Code Reviews| Index: media/base/pipeline_impl.h |
| =================================================================== |
| --- media/base/pipeline_impl.h (revision 19701) |
| +++ media/base/pipeline_impl.h (working copy) |
| @@ -161,8 +161,25 @@ |
| // 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. |
| +// media pipeline. Filters are created and called on a dedicated thread owned |
| +// by this object. This object works like a state machine to perform |
| +// asynchronous initialization. Initialization is done in multiple passes in |
| +// StartTask(). In each pass a different filter is created and chained with a |
| +// previously created filter. |
| +// |
| +// Here's a state diagram that describes the lifetime of this object. |
| +// |
| +// [ *Created ] -> [ InitDataSource ] -> [ InitDemuxer ] -> |
| +// [ InitAudioDecoder ] -> [ InitAudioRenderer ] -> |
| +// [ InitVideoDecoder ] -> [ InitVideoRenderer ] -> [ Started ] |
| +// | | | |
| +// .-> [ Error ] .-> [ Stopped ] <-. |
| +// |
| +// Initialization is a series of state transitions from "Created" to |
| +// "Started". If any error happens during initialization, this object will |
| +// transition to the "Error" state from any state. If Stop() is called during |
| +// initialization, this object will transition to "Stopped" state. |
| + |
| class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, |
| public MessageLoop::DestructionObserver { |
| public: |
| @@ -171,6 +188,9 @@ |
| // pipeline thread. For example, Seek posts a task to call SeekTask. |
| explicit PipelineThread(PipelineImpl* pipeline); |
| + // After Start() is called, a task of StartTask() is posted on the pipeline |
| + // thread to perform initialization. See StartTask() to learn more about |
| + // initialization. |
| bool Start(FilterFactory* filter_factory, |
| const std::string& url_media_source, |
| PipelineCallback* init_complete_callback); |
| @@ -211,6 +231,19 @@ |
| PlatformThreadId thread_id() const { return thread_.thread_id(); } |
| private: |
| + enum State { |
| + kCreated, |
| + kInitDataSource, |
| + kInitDemuxer, |
| + kInitAudioDecoder, |
| + kInitAudioRenderer, |
| + kInitVideoDecoder, |
| + kInitVideoRenderer, |
| + kStarted, |
| + kStopped, |
| + 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 |
| @@ -222,21 +255,32 @@ |
| virtual ~PipelineThread(); |
| // Simple method used to make sure the pipeline is running normally. |
| - bool PipelineOk() { return PIPELINE_OK == pipeline_->error_; } |
| + bool IsPipelineOk() { return PIPELINE_OK == pipeline_->error_; } |
| + // Helper method to tell whether we are in the state of initializing. |
| + bool IsPipelineInitializing() { |
| + return state_ == kInitDataSource || |
| + state_ == kInitDemuxer || |
| + state_ == kInitAudioDecoder || |
| + state_ == kInitAudioRenderer || |
| + state_ == kInitVideoDecoder || |
| + state_ == kInitVideoRenderer; |
| + } |
| + |
| // 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, |
| - PipelineCallback* init_complete_callback); |
| + // message loop. |
| + |
| + // StartTask() is a special task that performs initialization in multiple |
| + // passes. It is executed as a result of calling Start() or |
| + // InitializationComplete() that advances initialization to the next state. It |
| + // works as a hub of state transition for initialization. |
| + void StartTask(); |
| void StopTask(); |
| void SetPlaybackRateTask(float rate); |
| void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); |
| 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. |
| @@ -244,36 +288,34 @@ |
| // Calls the Stop method on every filter in the pipeline |
| void StopFilters(); |
| - // The following template funcions make use of the fact that media filter |
| + // 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 |
| // uniquely identifies the filter'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 Filter class, and |
| - // initiaializes it using the Source object. The source may be another filter |
| + // initializes 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 |
| + // 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, |
| + // 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() |
| + // initialize the filter. If the required filter cannot be created, |
| + // PIPELINE_ERROR_REQUIRED_FILTER_MISSING is raised, initialization is halted |
| + // and this object will remain in the "Error" state. |
| // |
| // Callers can optionally use the returned Filter for further processing, |
| // but since the call already placed the filter in the list of filter hosts, |
| // callers can ignore the return value. In any case, if this function can |
| - // not create and initailze the speified Filter, then this method will return |
| - // with |pipeline_->error_| != PIPELINE_OK. |
| + // not create and initializes the specified Filter, then this method will |
| + // return with |pipeline_->error_| != PIPELINE_OK. |
| template <class Filter, class Source> |
| - scoped_refptr<Filter> CreateFilter(FilterFactory* filter_factory, |
| - Source source, |
| - const MediaFormat& source_media_format); |
| + void CreateFilter(FilterFactory* filter_factory, |
| + Source source, |
| + const MediaFormat& source_media_format); |
| // Creates a Filter and initilizes it with the given |source|. If a Filter |
| // could not be created or an error occurred, this metod returns NULL and the |
| @@ -281,28 +323,32 @@ |
| // the Source could be a filter or a DemuxerStream, but it must support the |
| // GetMediaFormat() method. |
| template <class Filter, class Source> |
| - scoped_refptr<Filter> CreateFilter(FilterFactory* filter_factory, |
| - Source* source) { |
| - return CreateFilter<Filter, Source*>(filter_factory, |
| - source, |
| - source->media_format()); |
| + void CreateFilter(FilterFactory* filter_factory, Source* source) { |
| + CreateFilter<Filter, Source*>(filter_factory, |
| + source, |
| + source->media_format()); |
| } |
| - // Creates a DataSource (the first filter in a pipeline), and initializes it |
| - // with the specified URL. |
| - scoped_refptr<DataSource> CreateDataSource(FilterFactory* filter_factory, |
| - const std::string& url); |
| + // Creates a DataSource (the first filter in a pipeline). Returns true if |
| + // the asynchronous action of creating data source has started. |
| + void CreateDataSource(); |
| - // If the |demuxer| contains a stream that matches Decoder::major_media_type() |
| - // this method creates and initializes the specified Decoder and Renderer. |
| - // Callers should examine the |pipeline_->error_| member to see if there was |
| - // an error duing the call. The lack of the specified stream does not |
| - // constitute an error, and no Decoder or Renderer will be created if the |
| - // data stream does not exist in the |demuxer|. If a stream is rendered, then |
| - // this method will call |pipeline_|->InsertRenderedMimeType() to add the |
| - // mime type to the set of rendered major mime types for the pipeline. |
| + // Creates a Demuxer. Returns true if the asynchronous action of creating |
|
awong
2009/07/01 23:39:46
void function's done return...same elsewhere in fi
|
| + // demuxer has started. |
| + void CreateDemuxer(); |
| + |
| + // Creates a decoder of type Decoder. Returns true if the asynchronous action |
| + // of creating decoder has started. Returns false if this method did nothing |
| + // because the corresponding audio/video stream does not exist. |
| + template <class Decoder> |
| + bool CreateDecoder(); |
| + |
| + // Creates a renderer of type Renderer and connects it with Decoder. Returns |
| + // true if the asynchronous action of creating renderer has started. Returns |
| + // false if this method did nothing because the corresponding audio/video |
| + // stream does not exist. |
| template <class Decoder, class Renderer> |
| - void Render(FilterFactory* filter_factory, Demuxer* demuxer); |
| + bool CreateRenderer(); |
| // Examine the list of existing filters to find one that supports the |
| // specified Filter interface. If one exists, the |filter_out| will contain |
| @@ -321,14 +367,18 @@ |
| // 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_; |
| + // Member that tracks the current state. |
| + State state_; |
| - // 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_; |
| + // Filter factory as passed in by Start(). |
| + scoped_refptr<FilterFactory> filter_factory_; |
| + // URL for the data source as passed in by Start(). |
| + std::string url_; |
| + |
| + // Initialization callback as passed in by Start(). |
| + scoped_ptr<PipelineCallback> init_callback_; |
| + |
| // Vector of FilterHostImpl objects that contian the filters for the pipeline. |
| typedef std::vector<FilterHostImpl*> FilterHostVector; |
| FilterHostVector filter_hosts_; |