| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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 | 12 |
| 13 #include "base/message_loop.h" |
| 14 #include "base/ref_counted.h" |
| 15 #include "base/thread.h" |
| 16 #include "base/time.h" |
| 12 #include "media/base/pipeline.h" | 17 #include "media/base/pipeline.h" |
| 13 | 18 |
| 14 namespace media { | 19 namespace media { |
| 15 | 20 |
| 21 class FilterHostImpl; |
| 22 class PipelineThread; |
| 23 |
| 24 // Class which implements the Media::Pipeline contract. The majority of the |
| 25 // actual code for this object lives in the PipelineThread class, which is |
| 26 // responsible for actually building and running the pipeline. This object |
| 27 // is basically a simple container for state information, and is responsible |
| 28 // for creating and communicating with the PipelineThread object. |
| 16 class PipelineImpl : public Pipeline { | 29 class PipelineImpl : public Pipeline { |
| 17 public: | 30 public: |
| 18 PipelineImpl(); | 31 PipelineImpl(); |
| 19 ~PipelineImpl(); | 32 ~PipelineImpl(); |
| 20 | 33 |
| 21 // Implementation of PipelineStatus methods. | 34 // Implementation of PipelineStatus methods. |
| 22 virtual bool IsInitialized() const; | 35 virtual bool IsInitialized() const; |
| 23 virtual int64 GetDuration() const; | 36 virtual base::TimeDelta GetDuration() const; |
| 24 virtual int64 GetBufferedTime() const; | 37 virtual base::TimeDelta GetBufferedTime() const; |
| 25 virtual int64 GetTotalBytes() const; | 38 virtual int64 GetTotalBytes() const; |
| 26 virtual int64 GetBufferedBytes()const; | 39 virtual int64 GetBufferedBytes()const; |
| 27 virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; | 40 virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; |
| 28 virtual float GetVolume() const; | 41 virtual float GetVolume() const; |
| 29 virtual float GetPlaybackRate() const; | 42 virtual float GetPlaybackRate() const; |
| 30 virtual int64 GetTime() const; | 43 virtual base::TimeDelta GetTime() const; |
| 31 virtual PipelineError GetError() const; | 44 virtual PipelineError GetError() const; |
| 32 | 45 |
| 33 // Impementation of Pipeline methods. | 46 // Impementation of Pipeline methods. |
| 34 virtual bool Start(FilterFactory* filter_factory, | 47 virtual bool Start(FilterFactory* filter_factory, |
| 35 const std::string& uri, | 48 const std::string& url, |
| 36 Callback1<bool>::Type* init_complete_callback); | 49 Callback1<bool>::Type* init_complete_callback); |
| 37 virtual void Stop(); | 50 virtual void Stop(); |
| 38 virtual bool SetPlaybackRate(float rate); | 51 virtual void SetPlaybackRate(float rate); |
| 39 virtual bool Seek(int64 time); | 52 virtual void Seek(base::TimeDelta time); |
| 40 virtual bool SetVolume(float volume); | 53 virtual void SetVolume(float volume); |
| 41 | 54 |
| 42 private: | 55 private: |
| 56 friend class FilterHostImpl; |
| 57 friend class PipelineThread; |
| 58 |
| 59 // Reset the state of the pipline object to the initial state. This method |
| 60 // is used by the constructor, and the Stop method. |
| 61 void ResetState(); |
| 62 |
| 63 // Used internally to make sure that the thread is in a state that is |
| 64 // acceptable to post a task to. It must exist, be initialized, and there |
| 65 // must not be an error. |
| 66 bool OkToCallThread() const { |
| 67 return (pipeline_thread_ && initialized_ && PIPELINE_OK == error_); |
| 68 } |
| 69 |
| 70 // Called directly by the FilterHostImpl object to set the video size. |
| 71 void SetVideoSize(size_t width, size_t height); |
| 72 |
| 73 // Holds a ref counted reference to the PipelineThread object associated |
| 74 // with this pipeline. Prior to the call to the Start method, this member |
| 75 // will be NULL, since no thread is running. |
| 76 scoped_refptr<PipelineThread> pipeline_thread_; |
| 77 |
| 78 // After calling Start, if all of the required filters are created and |
| 79 // initialized, this member will be set to true by the pipeline thread. |
| 80 bool initialized_; |
| 81 |
| 82 // Duration of the media in microseconds. Set by a FilterHostImpl object on |
| 83 // behalf of a filter. |
| 84 base::TimeDelta duration_; |
| 85 |
| 86 // Amount of available buffered data in microseconds. Set by a |
| 87 // FilterHostImpl object on behalf of a filter. |
| 88 base::TimeDelta buffered_time_; |
| 89 |
| 90 // Amount of available buffered data. Set by a FilterHostImpl object |
| 91 // on behalf of a filter. |
| 92 int64 buffered_bytes_; |
| 93 |
| 94 // Total size of the media. Set by a FilterHostImpl object on behalf |
| 95 // of a filter. |
| 96 int64 total_bytes_; |
| 97 |
| 98 // Video width and height. Set by a FilterHostImpl object on behalf |
| 99 // of a filter. The video_size_access_lock_ is used to make sure access |
| 100 // to the pair of width and height are modified or read in thread safe way. |
| 101 Lock video_size_access_lock_; |
| 102 size_t video_width_; |
| 103 size_t video_height_; |
| 104 |
| 105 // Current volume level (from 0.0f to 1.0f). The volume reflects the last |
| 106 // value the audio filter was called with SetVolume, so there will be a short |
| 107 // period of time between the client calling SetVolume on the pipeline and |
| 108 // this value being updated. Set by the PipelineThread just prior to calling |
| 109 // the audio renderer. |
| 110 float volume_; |
| 111 |
| 112 // Current playback rate (>= 0.0f). This member reflects the last value |
| 113 // that the filters in the pipeline were called with, so there will be a short |
| 114 // period of time between the client calling SetPlaybackRate and this value |
| 115 // being updated. Set by the PipelineThread just prior to calling filters. |
| 116 float playback_rate_; |
| 117 |
| 118 // Current playback time. Set by a FilterHostImpl object on behalf of the |
| 119 // audio renderer filter. |
| 120 base::TimeDelta time_; |
| 121 |
| 122 // Status of the pipeline. Initialized to PIPELINE_OK which indicates that |
| 123 // the pipeline is operating correctly. Any other value indicates that the |
| 124 // pipeline is stopped or is stopping. Clients can call the Stop method to |
| 125 // reset the pipeline state, and restore this to PIPELINE_OK. |
| 126 PipelineError error_; |
| 127 |
| 43 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); | 128 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); |
| 44 }; | 129 }; |
| 45 | 130 |
| 131 |
| 132 // The PipelineThread contains most of the logic involved with running the |
| 133 // media pipeline. Filters are created and called on a dedicated thread owned |
| 134 // by this object. |
| 135 class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, |
| 136 public MessageLoop::DestructionObserver { |
| 137 public: |
| 138 // Methods called by PipelineImpl object on the client's thread. These |
| 139 // methods post a task to call a corresponding xxxTask() method on the |
| 140 // pipeline thread. For example, Seek posts a task to call SeekTask. |
| 141 explicit PipelineThread(PipelineImpl* pipeline); |
| 142 |
| 143 bool Start(FilterFactory* filter_factory, |
| 144 const std::string& url_media_source, |
| 145 Callback1<bool>::Type* init_complete_callback); |
| 146 void Stop(); |
| 147 void SetPlaybackRate(float rate); |
| 148 void Seek(base::TimeDelta time); |
| 149 void SetVolume(float volume); |
| 150 |
| 151 // Methods called by a FilterHostImpl object. These methods may be called |
| 152 // on any thread, either the pipeline's thread or any other. |
| 153 |
| 154 // When a filter calls it's FilterHost, the filter host calls back to the |
| 155 // pipeline thread. If the pipeline thread is running a nested message loop |
| 156 // then it will be exited. |
| 157 void InitializationComplete(FilterHostImpl* host); |
| 158 |
| 159 // Sets the pipeline time and schedules a task to call back to any filters |
| 160 // that have registered a time update callback. |
| 161 void SetTime(base::TimeDelta time); |
| 162 |
| 163 // Called by a FilterHostImpl on behalf of a filter calling FilerHost::Error. |
| 164 // If the pipeline is running a nested message loop, it will be exited. |
| 165 void Error(PipelineError error); |
| 166 |
| 167 // Called by a FilterHostImpl on behalf of a filter that calls the |
| 168 // FilterHost::PostTask method. |
| 169 void PostTask(Task* task); |
| 170 |
| 171 // Simple accessor used by the FilterHostImpl class to get access to the |
| 172 // pipeline object. |
| 173 PipelineImpl* pipeline() const { return pipeline_; } |
| 174 |
| 175 private: |
| 176 // Implementation of MessageLoop::DestructionObserver. StartTask registers |
| 177 // this class as a destruction observer on the thread's message loop. |
| 178 // It is used to destroy the list of FilterHosts |
| 179 // (and thus destroy the associated filters) when all tasks have been |
| 180 // processed and the message loop has been quit. |
| 181 virtual void WillDestroyCurrentMessageLoop(); |
| 182 |
| 183 friend class base::RefCountedThreadSafe<PipelineThread>; |
| 184 virtual ~PipelineThread(); |
| 185 |
| 186 MessageLoop* message_loop() const { return thread_.message_loop(); } |
| 187 |
| 188 // The following "task" methods correspond to the public methods, but these |
| 189 // methods are run as the result of posting a task to the PipelineThread's |
| 190 // message loop. For example, the Start method posts a task to call the |
| 191 // StartTask message on the pipeline thread. |
| 192 void StartTask(FilterFactory* filter_factory, |
| 193 const std::string& url, |
| 194 Callback1<bool>::Type* init_complete_callback); |
| 195 void StopTask(); |
| 196 void SetPlaybackRateTask(float rate); |
| 197 void SeekTask(base::TimeDelta time); |
| 198 void SetVolumeTask(float volume); |
| 199 void SetTimeTask(); |
| 200 void InitializationCompleteTask(FilterHostImpl* FilterHost); |
| 201 |
| 202 // Internal methods used in the implementation of the pipeline thread. All |
| 203 // of these methods are only called on the pipeline thread. |
| 204 |
| 205 // Calls the Stop method on every filter in the pipeline |
| 206 void StopFilters(); |
| 207 |
| 208 // Examines the demuxer filter output streams. If one contains video then |
| 209 // returns true. |
| 210 bool HasVideo() const; |
| 211 |
| 212 // The following template funcions make use of the fact that media filter |
| 213 // derived interfaces are self-describing in the sense that they all contain |
| 214 // the static method filter_type() which returns a FilterType enum that |
| 215 // uniquely identifies the filer's interface. In addition, filters that are |
| 216 // specific to audio or video also support a static method major_mime_type() |
| 217 // which returns a string of "audio/" or "video/". |
| 218 |
| 219 // Uses the FilterFactory to create a new filter of the NewFilter class, and |
| 220 // initiaializes it using the Source object. The source may be another filter |
| 221 // or it could be a string in the case of a DataSource. |
| 222 // |
| 223 // The CreateFilter method actually does much more than simply creating the |
| 224 // filter. It creates the FilterHostImpl object, creates the filter using |
| 225 // the filter factory, calls the MediaFilter::SetHost method on the filter, |
| 226 // and then calls the filter's type-specific Initialize(source) method to |
| 227 // initialize the filter. It then runs the thread's message loop and waits |
| 228 // until one of the following occurs: |
| 229 // 1. The filter calls FilterHost::InitializationComplete() |
| 230 // 2. A filter calls FilterHost::Error() |
| 231 // 3. The client calls Pipeline::Stop() |
| 232 template <class NewFilter, class Source> |
| 233 bool CreateFilter(FilterFactory* filter_factory, |
| 234 Source source, |
| 235 const MediaFormat* source_media_format); |
| 236 |
| 237 // Creates a DataSource (the first filter in a pipeline), and initializes it |
| 238 // with the specified URL. |
| 239 bool CreateDataSource(FilterFactory* filter_factory, |
| 240 const std::string& url); |
| 241 |
| 242 // Examines the list of existing filters to find a Source, then creates a |
| 243 // NewFilter, and initializes it with the Source filter. |
| 244 template <class NewFilter, class Source> |
| 245 bool CreateAndConnect(FilterFactory* filter_factory); |
| 246 |
| 247 // Creates and initiaializes a decoder. |
| 248 template <class Decoder> |
| 249 bool CreateDecoder(FilterFactory* filter_factory); |
| 250 |
| 251 // Examine the list of existing filters to find one that supports the |
| 252 // specified Filter interface. If one exists, the specified Filter interface |
| 253 // is returned otherwise the method retuns NULL. |
| 254 template <class Filter> |
| 255 Filter* GetFilter() const; |
| 256 |
| 257 // Simple function that returns true if the specified MediaFormat object |
| 258 // has a mime type that matches the major_mime_type. Examples of major mime |
| 259 // types are "audio/" and "video/" |
| 260 bool IsMajorMimeType(const MediaFormat* media_format, |
| 261 const std::string& major_mime_type) const; |
| 262 |
| 263 // Pointer to the pipeline that owns this PipelineThread. |
| 264 PipelineImpl* const pipeline_; |
| 265 |
| 266 // The actual thread. |
| 267 base::Thread thread_; |
| 268 |
| 269 // Used to avoid scheduling multiple time update tasks. If this member is |
| 270 // true then a task that will call the SetTimeTask() method is in the message |
| 271 // loop's queue. |
| 272 bool time_update_callback_scheduled_; |
| 273 |
| 274 // During initialization of a filter, this member points to the FilterHostImpl |
| 275 // that is being initialized. |
| 276 FilterHostImpl* host_initializing_; |
| 277 |
| 278 // This lock is held through the entire StartTask method to prevent the |
| 279 // Stop method from quitting the nested message loop of the StartTask method. |
| 280 Lock initialization_lock_; |
| 281 |
| 282 // Vector of FilterHostImpl objects that contian the filters for the pipeline. |
| 283 typedef std::vector<FilterHostImpl*> FilterHostVector; |
| 284 FilterHostVector filter_hosts_; |
| 285 |
| 286 DISALLOW_COPY_AND_ASSIGN(PipelineThread); |
| 287 }; |
| 288 |
| 46 } // namespace media | 289 } // namespace media |
| 47 | 290 |
| 48 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ | 291 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ |
| OLD | NEW |