| OLD | NEW |
| 1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Implementation of Pipeline. | 5 // Implementation of Pipeline. |
| 6 | 6 |
| 7 #ifndef MEDIA_BASE_PIPELINE_IMPL_H_ | 7 #ifndef MEDIA_BASE_PIPELINE_IMPL_H_ |
| 8 #define MEDIA_BASE_PIPELINE_IMPL_H_ | 8 #define MEDIA_BASE_PIPELINE_IMPL_H_ |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 #include <set> | 12 #include <set> |
| 13 | 13 |
| 14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 15 #include "base/ref_counted.h" | 15 #include "base/ref_counted.h" |
| 16 #include "base/thread.h" | 16 #include "base/thread.h" |
| 17 #include "base/time.h" | 17 #include "base/time.h" |
| 18 #include "media/base/filter_host.h" | 18 #include "media/base/filter_host.h" |
| 19 #include "media/base/pipeline.h" | 19 #include "media/base/pipeline.h" |
| 20 | 20 |
| 21 namespace media { | 21 namespace media { |
| 22 | 22 |
| 23 | 23 |
| 24 // PipelineImpl runs the media pipeline. Filters are created and called on the | 24 // PipelineImpl runs the media pipeline. Filters are created and called on the |
| 25 // message loop injected into this object. PipelineImpl works like a state | 25 // message loop injected into this object. PipelineImpl works like a state |
| 26 // machine to perform asynchronous initialization. Initialization is done in | 26 // machine to perform asynchronous initialization, pausing, seeking and playing. |
| 27 // multiple passes by InitializeTask(). In each pass a different filter is | |
| 28 // created and chained with a previously created filter. | |
| 29 // | 27 // |
| 30 // Here's a state diagram that describes the lifetime of this object. | 28 // Here's a state diagram that describes the lifetime of this object. |
| 31 // | 29 // |
| 32 // [ *Created ] -> [ InitDataSource ] -> [ InitDemuxer ] -> | 30 // [ *Created ] |
| 33 // [ InitAudioDecoder ] -> [ InitAudioRenderer ] -> | 31 // | Start() |
| 34 // [ InitVideoDecoder ] -> [ InitVideoRenderer ] -> [ Started ] | 32 // V |
| 35 // | | | | 33 // [ InitXXX (for each filter) ] |
| 36 // .-> [ Error ] .-> [ Stopped ] <-. | 34 // | |
| 35 // V |
| 36 // [ Seeking (for each filter) ] <----------------------. |
| 37 // | | |
| 38 // V | |
| 39 // [ Starting (for each filter) ] | |
| 40 // | | |
| 41 // V Seek() | |
| 42 // [ Started ] --------> [ Pausing (for each filter) ] -' |
| 37 // | 43 // |
| 38 // Initialization is a series of state transitions from "Created" to | 44 // |
| 39 // "Started". If any error happens during initialization, this object will | 45 // SetError() |
| 40 // transition to the "Error" state from any state. If Stop() is called during | 46 // [ Any State ] -------------> [ Error ] |
| 41 // initialization, this object will transition to "Stopped" state. | 47 // | Stop() |
| 48 // '--------------------> [ Stopped ] |
| 49 // |
| 50 // Initialization is a series of state transitions from "Created" through each |
| 51 // filter initialization state. When all filter initialization states have |
| 52 // completed, we are implicitly in a "Paused" state. At that point we simulate |
| 53 // a Seek() to the beginning of the media to give filters a chance to preroll. |
| 54 // From then on the normal Seek() transitions are carried out and we start |
| 55 // playing the media. |
| 56 // |
| 57 // If any error ever happens, this object will transition to the "Error" state |
| 58 // from any state. If Stop() is ever called, this object will transition to |
| 59 // "Stopped" state. |
| 42 class PipelineImpl : public Pipeline, public FilterHost { | 60 class PipelineImpl : public Pipeline, public FilterHost { |
| 43 public: | 61 public: |
| 44 explicit PipelineImpl(MessageLoop* message_loop); | 62 explicit PipelineImpl(MessageLoop* message_loop); |
| 45 | 63 |
| 46 // Pipeline implementation. | 64 // Pipeline implementation. |
| 47 virtual bool Start(FilterFactory* filter_factory, | 65 virtual bool Start(FilterFactory* filter_factory, |
| 48 const std::string& uri, | 66 const std::string& uri, |
| 49 PipelineCallback* start_callback); | 67 PipelineCallback* start_callback); |
| 50 virtual void Stop(PipelineCallback* stop_callback); | 68 virtual void Stop(PipelineCallback* stop_callback); |
| 51 virtual void Seek(base::TimeDelta time, PipelineCallback* seek_callback); | 69 virtual void Seek(base::TimeDelta time, PipelineCallback* seek_callback); |
| 52 virtual bool IsRunning() const; | 70 virtual bool IsRunning() const; |
| 53 virtual bool IsInitialized() const; | 71 virtual bool IsInitialized() const; |
| 54 virtual bool IsRendered(const std::string& major_mime_type) const; | 72 virtual bool IsRendered(const std::string& major_mime_type) const; |
| 55 virtual float GetPlaybackRate() const; | 73 virtual float GetPlaybackRate() const; |
| 56 virtual void SetPlaybackRate(float playback_rate); | 74 virtual void SetPlaybackRate(float playback_rate); |
| 57 virtual float GetVolume() const; | 75 virtual float GetVolume() const; |
| 58 virtual void SetVolume(float volume); | 76 virtual void SetVolume(float volume); |
| 59 virtual base::TimeDelta GetCurrentTime() const; | 77 virtual base::TimeDelta GetCurrentTime() const; |
| 60 virtual base::TimeDelta GetBufferedTime() const; | 78 virtual base::TimeDelta GetBufferedTime() const; |
| 61 virtual base::TimeDelta GetDuration() const; | 79 virtual base::TimeDelta GetDuration() const; |
| 62 virtual int64 GetBufferedBytes() const; | 80 virtual int64 GetBufferedBytes() const; |
| 63 virtual int64 GetTotalBytes() const; | 81 virtual int64 GetTotalBytes() const; |
| 64 virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; | 82 virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; |
| 65 virtual PipelineError GetError() const; | 83 virtual PipelineError GetError() const; |
| 66 | 84 |
| 67 private: | 85 private: |
| 86 // Pipeline states, as described above. |
| 87 enum State { |
| 88 kCreated, |
| 89 kInitDataSource, |
| 90 kInitDemuxer, |
| 91 kInitAudioDecoder, |
| 92 kInitAudioRenderer, |
| 93 kInitVideoDecoder, |
| 94 kInitVideoRenderer, |
| 95 kPausing, |
| 96 kSeeking, |
| 97 kStarting, |
| 98 kStarted, |
| 99 kStopped, |
| 100 kError, |
| 101 }; |
| 102 |
| 68 virtual ~PipelineImpl(); | 103 virtual ~PipelineImpl(); |
| 69 | 104 |
| 70 // Reset the state of the pipeline object to the initial state. This method | 105 // Reset the state of the pipeline object to the initial state. This method |
| 71 // is used by the constructor, and the Stop() method. | 106 // is used by the constructor, and the Stop() method. |
| 72 void ResetState(); | 107 void ResetState(); |
| 73 | 108 |
| 74 // Simple method used to make sure the pipeline is running normally. | 109 // Simple method used to make sure the pipeline is running normally. |
| 75 bool IsPipelineOk(); | 110 bool IsPipelineOk(); |
| 76 | 111 |
| 77 // Helper method to tell whether we are in the state of initializing. | 112 // Helper method to tell whether we are in the state of initializing. |
| 78 bool IsPipelineInitializing(); | 113 bool IsPipelineInitializing(); |
| 79 | 114 |
| 115 // Returns true if the given state is one that transitions to the started |
| 116 // state. |
| 117 static bool StateTransitionsToStarted(State state); |
| 118 |
| 119 // Given the current state, returns the next state. |
| 120 static State FindNextState(State current); |
| 121 |
| 80 // FilterHost implementation. | 122 // FilterHost implementation. |
| 81 virtual void SetError(PipelineError error); | 123 virtual void SetError(PipelineError error); |
| 82 virtual base::TimeDelta GetTime() const; | 124 virtual base::TimeDelta GetTime() const; |
| 83 virtual void SetTime(base::TimeDelta time); | 125 virtual void SetTime(base::TimeDelta time); |
| 84 virtual void SetDuration(base::TimeDelta duration); | 126 virtual void SetDuration(base::TimeDelta duration); |
| 85 virtual void SetBufferedTime(base::TimeDelta buffered_time); | 127 virtual void SetBufferedTime(base::TimeDelta buffered_time); |
| 86 virtual void SetTotalBytes(int64 total_bytes); | 128 virtual void SetTotalBytes(int64 total_bytes); |
| 87 virtual void SetBufferedBytes(int64 buffered_bytes); | 129 virtual void SetBufferedBytes(int64 buffered_bytes); |
| 88 virtual void SetVideoSize(size_t width, size_t height); | 130 virtual void SetVideoSize(size_t width, size_t height); |
| 89 | 131 |
| 90 // Method called during initialization to insert a mime type into the | 132 // Method called during initialization to insert a mime type into the |
| 91 // |rendered_mime_types_| set. | 133 // |rendered_mime_types_| set. |
| 92 void InsertRenderedMimeType(const std::string& major_mime_type); | 134 void InsertRenderedMimeType(const std::string& major_mime_type); |
| 93 | 135 |
| 94 // Method called during initialization to determine if we rendered anything. | 136 // Method called during initialization to determine if we rendered anything. |
| 95 bool HasRenderedMimeTypes() const; | 137 bool HasRenderedMimeTypes() const; |
| 96 | 138 |
| 97 // Callback executed by filters upon completing initialization and seeking. | 139 // Callback executed by filters upon completing initialization. |
| 98 void OnFilterInitialize(); | 140 void OnFilterInitialize(); |
| 99 void OnFilterSeek(); | 141 |
| 142 // Callback executed by filters upon completing Play(), Pause() or Seek(). |
| 143 void OnFilterStateTransition(); |
| 100 | 144 |
| 101 // The following "task" methods correspond to the public methods, but these | 145 // The following "task" methods correspond to the public methods, but these |
| 102 // methods are run as the result of posting a task to the PipelineInternal's | 146 // methods are run as the result of posting a task to the PipelineInternal's |
| 103 // message loop. | 147 // message loop. |
| 104 void StartTask(FilterFactory* filter_factory, | 148 void StartTask(FilterFactory* filter_factory, |
| 105 const std::string& url, | 149 const std::string& url, |
| 106 PipelineCallback* start_callback); | 150 PipelineCallback* start_callback); |
| 107 | 151 |
| 108 // InitializeTask() performs initialization in multiple passes. It is executed | 152 // InitializeTask() performs initialization in multiple passes. It is executed |
| 109 // as a result of calling Start() or InitializationComplete() that advances | 153 // as a result of calling Start() or InitializationComplete() that advances |
| (...skipping 11 matching lines...) Expand all Loading... |
| 121 | 165 |
| 122 // Carries out notifying filters that the playback rate has changed. | 166 // Carries out notifying filters that the playback rate has changed. |
| 123 void PlaybackRateChangedTask(float playback_rate); | 167 void PlaybackRateChangedTask(float playback_rate); |
| 124 | 168 |
| 125 // Carries out notifying filters that the volume has changed. | 169 // Carries out notifying filters that the volume has changed. |
| 126 void VolumeChangedTask(float volume); | 170 void VolumeChangedTask(float volume); |
| 127 | 171 |
| 128 // Carries out notifying filters that we are seeking to a new timestamp. | 172 // Carries out notifying filters that we are seeking to a new timestamp. |
| 129 void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); | 173 void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); |
| 130 | 174 |
| 175 // Carries out advancing to the next filter during Play()/Pause()/Seek(). |
| 176 void FilterStateTransitionTask(); |
| 177 |
| 131 // Internal methods used in the implementation of the pipeline thread. All | 178 // Internal methods used in the implementation of the pipeline thread. All |
| 132 // of these methods are only called on the pipeline thread. | 179 // of these methods are only called on the pipeline thread. |
| 133 | 180 |
| 134 // The following template functions make use of the fact that media filter | 181 // The following template functions make use of the fact that media filter |
| 135 // derived interfaces are self-describing in the sense that they all contain | 182 // derived interfaces are self-describing in the sense that they all contain |
| 136 // the static method filter_type() which returns a FilterType enum that | 183 // the static method filter_type() which returns a FilterType enum that |
| 137 // uniquely identifies the filter's interface. In addition, filters that are | 184 // uniquely identifies the filter's interface. In addition, filters that are |
| 138 // specific to audio or video also support a static method major_mime_type() | 185 // specific to audio or video also support a static method major_mime_type() |
| 139 // which returns a string of "audio/" or "video/". | 186 // which returns a string of "audio/" or "video/". |
| 140 // | 187 // |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 PipelineError error_; | 286 PipelineError error_; |
| 240 | 287 |
| 241 // Vector of major mime types that have been rendered by this pipeline. | 288 // Vector of major mime types that have been rendered by this pipeline. |
| 242 typedef std::set<std::string> RenderedMimeTypesSet; | 289 typedef std::set<std::string> RenderedMimeTypesSet; |
| 243 RenderedMimeTypesSet rendered_mime_types_; | 290 RenderedMimeTypesSet rendered_mime_types_; |
| 244 | 291 |
| 245 // The following data members are only accessed by tasks posted to | 292 // The following data members are only accessed by tasks posted to |
| 246 // |message_loop_|. | 293 // |message_loop_|. |
| 247 | 294 |
| 248 // Member that tracks the current state. | 295 // Member that tracks the current state. |
| 249 enum State { | |
| 250 kCreated, | |
| 251 kInitDataSource, | |
| 252 kInitDemuxer, | |
| 253 kInitAudioDecoder, | |
| 254 kInitAudioRenderer, | |
| 255 kInitVideoDecoder, | |
| 256 kInitVideoRenderer, | |
| 257 kStarted, | |
| 258 kStopped, | |
| 259 kError, | |
| 260 }; | |
| 261 State state_; | 296 State state_; |
| 262 | 297 |
| 298 // For kPausing, kSeeking and kStarting, we need to track how many filters |
| 299 // have completed transitioning to the destination state. When |
| 300 // |remaining_transitions_| reaches 0 the pipeline can transition out |
| 301 // of the current state. |
| 302 size_t remaining_transitions_; |
| 303 |
| 304 // For kSeeking we need to remember where we're seeking between filter |
| 305 // replies. |
| 306 base::TimeDelta seek_timestamp_; |
| 307 |
| 263 // Filter factory as passed in by Start(). | 308 // Filter factory as passed in by Start(). |
| 264 scoped_refptr<FilterFactory> filter_factory_; | 309 scoped_refptr<FilterFactory> filter_factory_; |
| 265 | 310 |
| 266 // URL for the data source as passed in by Start(). | 311 // URL for the data source as passed in by Start(). |
| 267 std::string url_; | 312 std::string url_; |
| 268 | 313 |
| 269 // Callbacks for various pipeline operations. | 314 // Callbacks for various pipeline operations. |
| 270 scoped_ptr<PipelineCallback> start_callback_; | |
| 271 scoped_ptr<PipelineCallback> seek_callback_; | 315 scoped_ptr<PipelineCallback> seek_callback_; |
| 272 scoped_ptr<PipelineCallback> stop_callback_; | 316 scoped_ptr<PipelineCallback> stop_callback_; |
| 273 | 317 |
| 274 // Vector of our filters and map maintaining the relationship between the | 318 // Vector of our filters and map maintaining the relationship between the |
| 275 // FilterType and the filter itself. | 319 // FilterType and the filter itself. |
| 276 typedef std::vector<scoped_refptr<MediaFilter> > FilterVector; | 320 typedef std::vector<scoped_refptr<MediaFilter> > FilterVector; |
| 277 FilterVector filters_; | 321 FilterVector filters_; |
| 278 | 322 |
| 279 typedef std::map<FilterType, scoped_refptr<MediaFilter> > FilterTypeMap; | 323 typedef std::map<FilterType, scoped_refptr<MediaFilter> > FilterTypeMap; |
| 280 FilterTypeMap filter_types_; | 324 FilterTypeMap filter_types_; |
| 281 | 325 |
| 282 // Vector of threads owned by the pipeline and being used by filters. | 326 // Vector of threads owned by the pipeline and being used by filters. |
| 283 typedef std::vector<base::Thread*> FilterThreadVector; | 327 typedef std::vector<base::Thread*> FilterThreadVector; |
| 284 FilterThreadVector filter_threads_; | 328 FilterThreadVector filter_threads_; |
| 285 | 329 |
| 286 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); | 330 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); |
| 287 }; | 331 }; |
| 288 | 332 |
| 289 } // namespace media | 333 } // namespace media |
| 290 | 334 |
| 291 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ | 335 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ |
| OLD | NEW |