Chromium Code Reviews| 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> |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 | 154 |
| 155 // Vector of major mime types that have been rendered by this pipeline. | 155 // Vector of major mime types that have been rendered by this pipeline. |
| 156 typedef std::set<std::string> RenderedMimeTypesSet; | 156 typedef std::set<std::string> RenderedMimeTypesSet; |
| 157 RenderedMimeTypesSet rendered_mime_types_; | 157 RenderedMimeTypesSet rendered_mime_types_; |
| 158 | 158 |
| 159 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); | 159 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); |
| 160 }; | 160 }; |
| 161 | 161 |
| 162 | 162 |
| 163 // The PipelineThread contains most of the logic involved with running the | 163 // The PipelineThread contains most of the logic involved with running the |
| 164 // media pipeline. Filters are created and called on a dedicated thread owned | 164 // media pipeline. Filters are created and called on a dedicated thread owned |
| 165 // by this object. | 165 // by this object. This object works like a state machine to perform |
| 166 // asynchronous initialization. Initialization is done in multiple passes in | |
| 167 // StartTask(). In each pass a different filter is created and chained with a | |
| 168 // previously created filter. | |
| 169 // | |
| 170 // Here's a state diagram that describes the lifetime of this object. | |
| 171 // | |
| 172 // [ *Created ] -> [ InitDataSource ] -> [ InitDemuxer ] -> | |
| 173 // [ InitAudioDecoder ] -> [ InitAudioRenderer ] -> | |
| 174 // [ InitVideoDecoder ] -> [ InitVideoRenderer ] -> [ Started ] | |
| 175 // | | | | |
| 176 // .-> [ Error ] .-> [ Stopped ] <-. | |
| 177 // | |
| 178 // Initialization is a series of state transitions from "Created" to | |
| 179 // "Started". If any error happens during initialization, this object will | |
| 180 // transition to the "Error" state from any state. If Stop() is called during | |
| 181 // initialization, this object will transition to "Stopped" state. | |
| 182 | |
| 166 class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, | 183 class PipelineThread : public base::RefCountedThreadSafe<PipelineThread>, |
| 167 public MessageLoop::DestructionObserver { | 184 public MessageLoop::DestructionObserver { |
| 168 public: | 185 public: |
| 169 // Methods called by PipelineImpl object on the client's thread. These | 186 // Methods called by PipelineImpl object on the client's thread. These |
| 170 // methods post a task to call a corresponding xxxTask() method on the | 187 // methods post a task to call a corresponding xxxTask() method on the |
| 171 // pipeline thread. For example, Seek posts a task to call SeekTask. | 188 // pipeline thread. For example, Seek posts a task to call SeekTask. |
| 172 explicit PipelineThread(PipelineImpl* pipeline); | 189 explicit PipelineThread(PipelineImpl* pipeline); |
| 173 | 190 |
| 191 // After Start() is called, a task of StartTask() is posted on the pipeline | |
| 192 // thread to perform initialization. See StartTask() to learn more about | |
| 193 // initialization. | |
| 174 bool Start(FilterFactory* filter_factory, | 194 bool Start(FilterFactory* filter_factory, |
| 175 const std::string& url_media_source, | 195 const std::string& url_media_source, |
| 176 PipelineCallback* init_complete_callback); | 196 PipelineCallback* init_complete_callback); |
| 177 void Stop(); | 197 void Stop(); |
| 178 void SetPlaybackRate(float rate); | 198 void SetPlaybackRate(float rate); |
| 179 void Seek(base::TimeDelta time, PipelineCallback* seek_callback); | 199 void Seek(base::TimeDelta time, PipelineCallback* seek_callback); |
| 180 void SetVolume(float volume); | 200 void SetVolume(float volume); |
| 181 | 201 |
| 182 // Methods called by a FilterHostImpl object. These methods may be called | 202 // Methods called by a FilterHostImpl object. These methods may be called |
| 183 // on any thread, either the pipeline's thread or any other. | 203 // on any thread, either the pipeline's thread or any other. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 204 PipelineImpl* pipeline() const { return pipeline_; } | 224 PipelineImpl* pipeline() const { return pipeline_; } |
| 205 | 225 |
| 206 // Accessor used to post messages to thread's message loop. | 226 // Accessor used to post messages to thread's message loop. |
| 207 MessageLoop* message_loop() const { return thread_.message_loop(); } | 227 MessageLoop* message_loop() const { return thread_.message_loop(); } |
| 208 | 228 |
| 209 // Accessor used by PipelineImpl to check if we're executing on the pipeline | 229 // Accessor used by PipelineImpl to check if we're executing on the pipeline |
| 210 // thread. | 230 // thread. |
| 211 PlatformThreadId thread_id() const { return thread_.thread_id(); } | 231 PlatformThreadId thread_id() const { return thread_.thread_id(); } |
| 212 | 232 |
| 213 private: | 233 private: |
| 234 enum State { | |
| 235 kCreated, | |
| 236 kInitDataSource, | |
| 237 kInitDemuxer, | |
| 238 kInitAudioDecoder, | |
| 239 kInitAudioRenderer, | |
| 240 kInitVideoDecoder, | |
| 241 kInitVideoRenderer, | |
| 242 kStarted, | |
| 243 kStopped, | |
| 244 kError, | |
| 245 }; | |
| 246 | |
| 214 // Implementation of MessageLoop::DestructionObserver. StartTask registers | 247 // Implementation of MessageLoop::DestructionObserver. StartTask registers |
| 215 // this class as a destruction observer on the thread's message loop. | 248 // this class as a destruction observer on the thread's message loop. |
| 216 // It is used to destroy the list of FilterHosts | 249 // It is used to destroy the list of FilterHosts |
| 217 // (and thus destroy the associated filters) when all tasks have been | 250 // (and thus destroy the associated filters) when all tasks have been |
| 218 // processed and the message loop has been quit. | 251 // processed and the message loop has been quit. |
| 219 virtual void WillDestroyCurrentMessageLoop(); | 252 virtual void WillDestroyCurrentMessageLoop(); |
| 220 | 253 |
| 221 friend class base::RefCountedThreadSafe<PipelineThread>; | 254 friend class base::RefCountedThreadSafe<PipelineThread>; |
| 222 virtual ~PipelineThread(); | 255 virtual ~PipelineThread(); |
| 223 | 256 |
| 224 // Simple method used to make sure the pipeline is running normally. | 257 // Simple method used to make sure the pipeline is running normally. |
| 225 bool PipelineOk() { return PIPELINE_OK == pipeline_->error_; } | 258 bool IsPipelineOk() { return PIPELINE_OK == pipeline_->error_; } |
| 259 | |
| 260 // Helper method to tell whether we are in the state of initializing. | |
| 261 bool IsPipelineInitializing() { | |
| 262 return state_ == kInitDataSource || | |
| 263 state_ == kInitDemuxer || | |
| 264 state_ == kInitAudioDecoder || | |
| 265 state_ == kInitAudioRenderer || | |
| 266 state_ == kInitVideoDecoder || | |
| 267 state_ == kInitVideoRenderer; | |
| 268 } | |
| 226 | 269 |
| 227 // The following "task" methods correspond to the public methods, but these | 270 // The following "task" methods correspond to the public methods, but these |
| 228 // methods are run as the result of posting a task to the PipelineThread's | 271 // methods are run as the result of posting a task to the PipelineThread's |
| 229 // message loop. For example, the Start method posts a task to call the | 272 // message loop. |
| 230 // StartTask message on the pipeline thread. | 273 |
| 231 void StartTask(FilterFactory* filter_factory, | 274 // StartTask() is a special task that performs initialization in multiple |
| 232 const std::string& url, | 275 // passes. It is executed as a result of calling Start() or |
| 233 PipelineCallback* init_complete_callback); | 276 // InitializationComplete() that advances initialization to the next state. It |
| 277 // works as a hub of state transition for initialization. | |
| 278 void StartTask(); | |
| 234 void StopTask(); | 279 void StopTask(); |
| 235 void SetPlaybackRateTask(float rate); | 280 void SetPlaybackRateTask(float rate); |
| 236 void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); | 281 void SeekTask(base::TimeDelta time, PipelineCallback* seek_callback); |
| 237 void SetVolumeTask(float volume); | 282 void SetVolumeTask(float volume); |
| 238 void SetTimeTask(); | 283 void SetTimeTask(); |
| 239 void InitializationCompleteTask(FilterHostImpl* FilterHost); | |
| 240 | 284 |
| 241 // Internal methods used in the implementation of the pipeline thread. All | 285 // Internal methods used in the implementation of the pipeline thread. All |
| 242 // of these methods are only called on the pipeline thread. | 286 // of these methods are only called on the pipeline thread. |
| 243 | 287 |
| 244 // Calls the Stop method on every filter in the pipeline | 288 // Calls the Stop method on every filter in the pipeline |
| 245 void StopFilters(); | 289 void StopFilters(); |
| 246 | 290 |
| 247 // The following template funcions make use of the fact that media filter | 291 // The following template functions make use of the fact that media filter |
| 248 // derived interfaces are self-describing in the sense that they all contain | 292 // derived interfaces are self-describing in the sense that they all contain |
| 249 // the static method filter_type() which returns a FilterType enum that | 293 // the static method filter_type() which returns a FilterType enum that |
| 250 // uniquely identifies the filter's interface. In addition, filters that are | 294 // uniquely identifies the filter's interface. In addition, filters that are |
| 251 // specific to audio or video also support a static method major_mime_type() | 295 // specific to audio or video also support a static method major_mime_type() |
| 252 // which returns a string of "audio/" or "video/". | 296 // which returns a string of "audio/" or "video/". |
| 253 | 297 // |
| 254 // Uses the FilterFactory to create a new filter of the Filter class, and | 298 // Uses the FilterFactory to create a new filter of the Filter class, and |
| 255 // initiaializes it using the Source object. The source may be another filter | 299 // initializes it using the Source object. The source may be another filter |
| 256 // or it could be a string in the case of a DataSource. | 300 // or it could be a string in the case of a DataSource. |
| 257 // | 301 // |
| 258 // The CreateFilter method actually does much more than simply creating the | 302 // The CreateFilter() method actually does much more than simply creating the |
| 259 // filter. It creates the FilterHostImpl object, creates the filter using | 303 // filter. It creates the FilterHostImpl object, creates the filter using |
| 260 // the filter factory, calls the MediaFilter::SetHost method on the filter, | 304 // the filter factory, calls the MediaFilter::SetHost() method on the filter, |
| 261 // and then calls the filter's type-specific Initialize(source) method to | 305 // and then calls the filter's type-specific Initialize(source) method to |
| 262 // initialize the filter. It then runs the thread's message loop and waits | 306 // initialize the filter. If the required filter cannot be created, |
| 263 // until one of the following occurs: | 307 // PIPELINE_ERROR_REQUIRED_FILTER_MISSING is raised, initialization is halted |
| 264 // 1. The filter calls FilterHost::InitializationComplete() | 308 // and this object will remain in the "Error" state. |
| 265 // 2. A filter calls FilterHost::Error() | |
| 266 // 3. The client calls Pipeline::Stop() | |
| 267 // | 309 // |
| 268 // Callers can optionally use the returned Filter for further processing, | 310 // Callers can optionally use the returned Filter for further processing, |
| 269 // but since the call already placed the filter in the list of filter hosts, | 311 // but since the call already placed the filter in the list of filter hosts, |
| 270 // callers can ignore the return value. In any case, if this function can | 312 // callers can ignore the return value. In any case, if this function can |
| 271 // not create and initailze the speified Filter, then this method will return | 313 // not create and initializes the specified Filter, then this method will |
| 272 // with |pipeline_->error_| != PIPELINE_OK. | 314 // return with |pipeline_->error_| != PIPELINE_OK. |
| 273 template <class Filter, class Source> | 315 template <class Filter, class Source> |
| 274 scoped_refptr<Filter> CreateFilter(FilterFactory* filter_factory, | 316 void CreateFilter(FilterFactory* filter_factory, |
| 275 Source source, | 317 Source source, |
| 276 const MediaFormat& source_media_format); | 318 const MediaFormat& source_media_format); |
| 277 | 319 |
| 278 // Creates a Filter and initilizes it with the given |source|. If a Filter | 320 // Creates a Filter and initilizes it with the given |source|. If a Filter |
| 279 // could not be created or an error occurred, this metod returns NULL and the | 321 // could not be created or an error occurred, this metod returns NULL and the |
| 280 // pipeline's |error_| member will contain a specific error code. Note that | 322 // pipeline's |error_| member will contain a specific error code. Note that |
| 281 // the Source could be a filter or a DemuxerStream, but it must support the | 323 // the Source could be a filter or a DemuxerStream, but it must support the |
| 282 // GetMediaFormat() method. | 324 // GetMediaFormat() method. |
| 283 template <class Filter, class Source> | 325 template <class Filter, class Source> |
| 284 scoped_refptr<Filter> CreateFilter(FilterFactory* filter_factory, | 326 void CreateFilter(FilterFactory* filter_factory, Source* source) { |
| 285 Source* source) { | 327 CreateFilter<Filter, Source*>(filter_factory, |
| 286 return CreateFilter<Filter, Source*>(filter_factory, | 328 source, |
| 287 source, | 329 source->media_format()); |
| 288 source->media_format()); | |
| 289 } | 330 } |
| 290 | 331 |
| 291 // Creates a DataSource (the first filter in a pipeline), and initializes it | 332 // Creates a DataSource (the first filter in a pipeline). Returns true if |
| 292 // with the specified URL. | 333 // the asynchronous action of creating data source has started. |
| 293 scoped_refptr<DataSource> CreateDataSource(FilterFactory* filter_factory, | 334 void CreateDataSource(); |
| 294 const std::string& url); | |
| 295 | 335 |
| 296 // If the |demuxer| contains a stream that matches Decoder::major_media_type() | 336 // 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
| |
| 297 // this method creates and initializes the specified Decoder and Renderer. | 337 // demuxer has started. |
| 298 // Callers should examine the |pipeline_->error_| member to see if there was | 338 void CreateDemuxer(); |
| 299 // an error duing the call. The lack of the specified stream does not | 339 |
| 300 // constitute an error, and no Decoder or Renderer will be created if the | 340 // Creates a decoder of type Decoder. Returns true if the asynchronous action |
| 301 // data stream does not exist in the |demuxer|. If a stream is rendered, then | 341 // of creating decoder has started. Returns false if this method did nothing |
| 302 // this method will call |pipeline_|->InsertRenderedMimeType() to add the | 342 // because the corresponding audio/video stream does not exist. |
| 303 // mime type to the set of rendered major mime types for the pipeline. | 343 template <class Decoder> |
| 344 bool CreateDecoder(); | |
| 345 | |
| 346 // Creates a renderer of type Renderer and connects it with Decoder. Returns | |
| 347 // true if the asynchronous action of creating renderer has started. Returns | |
| 348 // false if this method did nothing because the corresponding audio/video | |
| 349 // stream does not exist. | |
| 304 template <class Decoder, class Renderer> | 350 template <class Decoder, class Renderer> |
| 305 void Render(FilterFactory* filter_factory, Demuxer* demuxer); | 351 bool CreateRenderer(); |
| 306 | 352 |
| 307 // Examine the list of existing filters to find one that supports the | 353 // Examine the list of existing filters to find one that supports the |
| 308 // specified Filter interface. If one exists, the |filter_out| will contain | 354 // specified Filter interface. If one exists, the |filter_out| will contain |
| 309 // the filter, |*filter_out| will be NULL. | 355 // the filter, |*filter_out| will be NULL. |
| 310 template <class Filter> | 356 template <class Filter> |
| 311 void GetFilter(scoped_refptr<Filter>* filter_out) const; | 357 void GetFilter(scoped_refptr<Filter>* filter_out) const; |
| 312 | 358 |
| 313 // Pointer to the pipeline that owns this PipelineThread. | 359 // Pointer to the pipeline that owns this PipelineThread. |
| 314 PipelineImpl* const pipeline_; | 360 PipelineImpl* const pipeline_; |
| 315 | 361 |
| 316 // The actual thread. | 362 // The actual thread. |
| 317 base::Thread thread_; | 363 base::Thread thread_; |
| 318 | 364 |
| 319 // Used to avoid scheduling multiple time update tasks. If this member is | 365 // Used to avoid scheduling multiple time update tasks. If this member is |
| 320 // true then a task that will call the SetTimeTask() method is in the message | 366 // true then a task that will call the SetTimeTask() method is in the message |
| 321 // loop's queue. | 367 // loop's queue. |
| 322 bool time_update_callback_scheduled_; | 368 bool time_update_callback_scheduled_; |
| 323 | 369 |
| 324 // During initialization of a filter, this member points to the FilterHostImpl | 370 // Member that tracks the current state. |
| 325 // that is being initialized. | 371 State state_; |
| 326 FilterHostImpl* host_initializing_; | |
| 327 | 372 |
| 328 // This lock is held through the entire StartTask method to prevent the | 373 // Filter factory as passed in by Start(). |
| 329 // Stop method from quitting the nested message loop of the StartTask method. | 374 scoped_refptr<FilterFactory> filter_factory_; |
| 330 Lock initialization_lock_; | 375 |
| 376 // URL for the data source as passed in by Start(). | |
| 377 std::string url_; | |
| 378 | |
| 379 // Initialization callback as passed in by Start(). | |
| 380 scoped_ptr<PipelineCallback> init_callback_; | |
| 331 | 381 |
| 332 // Vector of FilterHostImpl objects that contian the filters for the pipeline. | 382 // Vector of FilterHostImpl objects that contian the filters for the pipeline. |
| 333 typedef std::vector<FilterHostImpl*> FilterHostVector; | 383 typedef std::vector<FilterHostImpl*> FilterHostVector; |
| 334 FilterHostVector filter_hosts_; | 384 FilterHostVector filter_hosts_; |
| 335 | 385 |
| 336 typedef std::vector<base::Thread*> FilterThreadVector; | 386 typedef std::vector<base::Thread*> FilterThreadVector; |
| 337 FilterThreadVector filter_threads_; | 387 FilterThreadVector filter_threads_; |
| 338 | 388 |
| 339 DISALLOW_COPY_AND_ASSIGN(PipelineThread); | 389 DISALLOW_COPY_AND_ASSIGN(PipelineThread); |
| 340 }; | 390 }; |
| 341 | 391 |
| 342 } // namespace media | 392 } // namespace media |
| 343 | 393 |
| 344 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ | 394 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ |
| OLD | NEW |