| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #ifndef MEDIA_BASE_PIPELINE_H_ | 5 #ifndef MEDIA_BASE_PIPELINE_H_ |
| 6 #define MEDIA_BASE_PIPELINE_H_ | 6 #define MEDIA_BASE_PIPELINE_H_ |
| 7 | 7 |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/gtest_prod_util.h" | 10 #include "base/gtest_prod_util.h" |
| 11 #include "base/synchronization/condition_variable.h" | 11 #include "base/synchronization/condition_variable.h" |
| 12 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
| 13 #include "media/base/audio_renderer.h" | 13 #include "media/base/audio_renderer.h" |
| 14 #include "media/base/demuxer.h" | 14 #include "media/base/demuxer.h" |
| 15 #include "media/base/filter_host.h" | |
| 16 #include "media/base/media_export.h" | 15 #include "media/base/media_export.h" |
| 17 #include "media/base/pipeline_status.h" | 16 #include "media/base/pipeline_status.h" |
| 18 #include "media/base/ranges.h" | 17 #include "media/base/ranges.h" |
| 19 #include "ui/gfx/size.h" | 18 #include "ui/gfx/size.h" |
| 20 | 19 |
| 21 class MessageLoop; | 20 class MessageLoop; |
| 22 | 21 |
| 23 namespace base { | 22 namespace base { |
| 24 class MessageLoopProxy; | 23 class MessageLoopProxy; |
| 25 class TimeDelta; | 24 class TimeDelta; |
| 26 } | 25 } |
| 27 | 26 |
| 28 namespace media { | 27 namespace media { |
| 29 | 28 |
| 30 class AudioDecoder; | 29 class AudioDecoder; |
| 31 class Clock; | 30 class Clock; |
| 32 class Filter; | |
| 33 class FilterCollection; | 31 class FilterCollection; |
| 34 class MediaLog; | 32 class MediaLog; |
| 35 class VideoDecoder; | 33 class VideoDecoder; |
| 36 class VideoRenderer; | 34 class VideoRenderer; |
| 37 | 35 |
| 38 // Adapter for using asynchronous Pipeline methods in code that wants to run | 36 // Adapter for using asynchronous Pipeline methods in code that wants to run |
| 39 // synchronously. To use, construct an instance of this class and pass the | 37 // synchronously. To use, construct an instance of this class and pass the |
| 40 // |Callback()| to the Pipeline method requiring a callback. Then Wait() for | 38 // |Callback()| to the Pipeline method requiring a callback. Then Wait() for |
| 41 // the callback to get fired and call status() to see what the callback's | 39 // the callback to get fired and call status() to see what the callback's |
| 42 // argument was. This object is for one-time use; call |Callback()| exactly | 40 // argument was. This object is for one-time use; call |Callback()| exactly |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // | ^ | 73 // | ^ |
| 76 // V | if Stop | 74 // V | if Stop |
| 77 // [ Seeking (for each filter) ] <--------[ Flushing (for each filter) ] | 75 // [ Seeking (for each filter) ] <--------[ Flushing (for each filter) ] |
| 78 // | if Seek ^ | 76 // | if Seek ^ |
| 79 // V | | 77 // V | |
| 80 // [ Starting (for each filter) ] | | 78 // [ Starting (for each filter) ] | |
| 81 // | | | 79 // | | |
| 82 // V Seek()/Stop() | | 80 // V Seek()/Stop() | |
| 83 // [ Started ] -------------------------> [ Pausing (for each filter) ] | 81 // [ Started ] -------------------------> [ Pausing (for each filter) ] |
| 84 // | ^ | 82 // | ^ |
| 85 // | NotifyEnded() Seek()/Stop() | | 83 // | OnRendererEnded() Seek()/Stop() | |
| 86 // `-------------> [ Ended ] ---------------------' | 84 // `-------------> [ Ended ] ---------------------' |
| 87 // ^ SetError() | 85 // ^ SetError() |
| 88 // | | 86 // | |
| 89 // [ Any State Other Than InitXXX ] | 87 // [ Any State Other Than InitXXX ] |
| 90 | 88 |
| 91 // | 89 // |
| 92 // Initialization is a series of state transitions from "Created" through each | 90 // Initialization is a series of state transitions from "Created" through each |
| 93 // filter initialization state. When all filter initialization states have | 91 // filter initialization state. When all filter initialization states have |
| 94 // completed, we are implicitly in a "Paused" state. At that point we simulate | 92 // completed, we are implicitly in a "Paused" state. At that point we simulate |
| 95 // a Seek() to the beginning of the media to give filters a chance to preroll. | 93 // a Seek() to the beginning of the media to give filters a chance to preroll. |
| 96 // From then on the normal Seek() transitions are carried out and we start | 94 // From then on the normal Seek() transitions are carried out and we start |
| 97 // playing the media. | 95 // playing the media. |
| 98 // | 96 // |
| 99 // If any error ever happens, this object will transition to the "Error" state | 97 // If any error ever happens, this object will transition to the "Error" state |
| 100 // from any state. If Stop() is ever called, this object will transition to | 98 // from any state. If Stop() is ever called, this object will transition to |
| 101 // "Stopped" state. | 99 // "Stopped" state. |
| 102 class MEDIA_EXPORT Pipeline | 100 class MEDIA_EXPORT Pipeline |
| 103 : public base::RefCountedThreadSafe<Pipeline>, | 101 : public base::RefCountedThreadSafe<Pipeline>, |
| 104 public FilterHost, | |
| 105 public DemuxerHost { | 102 public DemuxerHost { |
| 106 public: | 103 public: |
| 107 // Constructs a media pipeline that will execute on |message_loop|. | 104 // Constructs a media pipeline that will execute on |message_loop|. |
| 108 Pipeline(MessageLoop* message_loop, MediaLog* media_log); | 105 Pipeline(MessageLoop* message_loop, MediaLog* media_log); |
| 109 | 106 |
| 110 // Build a pipeline to using the given filter collection to construct a filter | 107 // Build a pipeline to using the given filter collection to construct a filter |
| 111 // chain. | 108 // chain. |
| 112 // | 109 // |
| 113 // Pipeline initialization is an inherently asynchronous process. Clients can | 110 // Pipeline initialization is an inherently asynchronous process. Clients can |
| 114 // either poll the IsInitialized() method (discouraged) or optionally pass in | 111 // either poll the IsInitialized() method (discouraged) or optionally pass in |
| (...skipping 27 matching lines...) Expand all Loading... |
| 142 // | 139 // |
| 143 // It is an error to call this method if the pipeline has not started. | 140 // It is an error to call this method if the pipeline has not started. |
| 144 // | 141 // |
| 145 // TODO(scherkus): ideally clients would destroy the pipeline after calling | 142 // TODO(scherkus): ideally clients would destroy the pipeline after calling |
| 146 // Stop() and create a new pipeline as needed. | 143 // Stop() and create a new pipeline as needed. |
| 147 void Stop(const base::Closure& stop_cb); | 144 void Stop(const base::Closure& stop_cb); |
| 148 | 145 |
| 149 // Attempt to seek to the position specified by time. |seek_cb| will be | 146 // Attempt to seek to the position specified by time. |seek_cb| will be |
| 150 // executed when the all filters in the pipeline have processed the seek. | 147 // executed when the all filters in the pipeline have processed the seek. |
| 151 // | 148 // |
| 152 // Clients are expected to call GetCurrentTime() to check whether the seek | 149 // Clients are expected to call GetMediaTime() to check whether the seek |
| 153 // succeeded. | 150 // succeeded. |
| 154 // | 151 // |
| 155 // It is an error to call this method if the pipeline has not started. | 152 // It is an error to call this method if the pipeline has not started. |
| 156 void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb); | 153 void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb); |
| 157 | 154 |
| 158 // Returns true if the pipeline has been started via Start(). If IsRunning() | 155 // Returns true if the pipeline has been started via Start(). If IsRunning() |
| 159 // returns true, it is expected that Stop() will be called before destroying | 156 // returns true, it is expected that Stop() will be called before destroying |
| 160 // the pipeline. | 157 // the pipeline. |
| 161 bool IsRunning() const; | 158 bool IsRunning() const; |
| 162 | 159 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 187 // Gets the current volume setting being used by the audio renderer. When | 184 // Gets the current volume setting being used by the audio renderer. When |
| 188 // the pipeline is started, this value will be 1.0f. Valid values range | 185 // the pipeline is started, this value will be 1.0f. Valid values range |
| 189 // from 0.0f to 1.0f. | 186 // from 0.0f to 1.0f. |
| 190 float GetVolume() const; | 187 float GetVolume() const; |
| 191 | 188 |
| 192 // Attempt to set the volume of the audio renderer. Valid values for volume | 189 // Attempt to set the volume of the audio renderer. Valid values for volume |
| 193 // range from 0.0f (muted) to 1.0f (full volume). This value affects all | 190 // range from 0.0f (muted) to 1.0f (full volume). This value affects all |
| 194 // channels proportionately for multi-channel audio streams. | 191 // channels proportionately for multi-channel audio streams. |
| 195 void SetVolume(float volume); | 192 void SetVolume(float volume); |
| 196 | 193 |
| 197 // Gets the current pipeline time. For a pipeline "time" progresses from 0 to | 194 // Returns the current media playback time, which progresses from 0 until |
| 198 // the end of the media. | 195 // GetMediaDuration(). |
| 199 base::TimeDelta GetCurrentTime() const; | 196 base::TimeDelta GetMediaTime() const; |
| 200 | 197 |
| 201 // Get approximate time ranges of buffered media. | 198 // Get approximate time ranges of buffered media. |
| 202 Ranges<base::TimeDelta> GetBufferedTimeRanges(); | 199 Ranges<base::TimeDelta> GetBufferedTimeRanges(); |
| 203 | 200 |
| 204 // Get the duration of the media in microseconds. If the duration has not | 201 // Get the duration of the media in microseconds. If the duration has not |
| 205 // been determined yet, then returns 0. | 202 // been determined yet, then returns 0. |
| 206 base::TimeDelta GetMediaDuration() const; | 203 base::TimeDelta GetMediaDuration() const; |
| 207 | 204 |
| 208 // Get the total size of the media file. If the size has not yet been | 205 // Get the total size of the media file. If the size has not yet been |
| 209 // determined or can not be determined, this value is 0. | 206 // determined or can not be determined, this value is 0. |
| 210 int64 GetTotalBytes() const; | 207 int64 GetTotalBytes() const; |
| 211 | 208 |
| 212 // Gets the natural size of the video output in pixel units. If there is no | 209 // Gets the natural size of the video output in pixel units. If there is no |
| 213 // video or the video has not been rendered yet, the width and height will | 210 // video or the video has not been rendered yet, the width and height will |
| 214 // be 0. | 211 // be 0. |
| 215 void GetNaturalVideoSize(gfx::Size* out_size) const; | 212 void GetNaturalVideoSize(gfx::Size* out_size) const; |
| 216 | 213 |
| 217 // Return true if loading progress has been made since the last time this | 214 // Return true if loading progress has been made since the last time this |
| 218 // method was called. | 215 // method was called. |
| 219 bool DidLoadingProgress() const; | 216 bool DidLoadingProgress() const; |
| 220 | 217 |
| 221 // Gets the current pipeline statistics. | 218 // Gets the current pipeline statistics. |
| 222 PipelineStatistics GetStatistics() const; | 219 PipelineStatistics GetStatistics() const; |
| 223 | 220 |
| 224 void SetClockForTesting(Clock* clock); | 221 void SetClockForTesting(Clock* clock); |
| 225 | 222 |
| 226 private: | 223 private: |
| 227 FRIEND_TEST_ALL_PREFIXES(PipelineTest, GetBufferedTimeRanges); | 224 FRIEND_TEST_ALL_PREFIXES(PipelineTest, GetBufferedTimeRanges); |
| 228 FRIEND_TEST_ALL_PREFIXES(PipelineTest, DisableAudioRenderer); | 225 FRIEND_TEST_ALL_PREFIXES(PipelineTest, DisableAudioRenderer); |
| 226 FRIEND_TEST_ALL_PREFIXES(PipelineTest, DisableAudioRendererDuringInit); |
| 227 FRIEND_TEST_ALL_PREFIXES(PipelineTest, EndedCallback); |
| 228 FRIEND_TEST_ALL_PREFIXES(PipelineTest, AudioStreamShorterThanVideo); |
| 229 friend class MediaLog; | 229 friend class MediaLog; |
| 230 | 230 |
| 231 // Only allow ourselves to be deleted by reference counting. | 231 // Only allow ourselves to be deleted by reference counting. |
| 232 friend class base::RefCountedThreadSafe<Pipeline>; | 232 friend class base::RefCountedThreadSafe<Pipeline>; |
| 233 virtual ~Pipeline(); | 233 virtual ~Pipeline(); |
| 234 | 234 |
| 235 // Pipeline states, as described above. | 235 // Pipeline states, as described above. |
| 236 enum State { | 236 enum State { |
| 237 kCreated, | 237 kCreated, |
| 238 kInitDemuxer, | 238 kInitDemuxer, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 // DataSourceHost (by way of DemuxerHost) implementation. | 289 // DataSourceHost (by way of DemuxerHost) implementation. |
| 290 virtual void SetTotalBytes(int64 total_bytes) OVERRIDE; | 290 virtual void SetTotalBytes(int64 total_bytes) OVERRIDE; |
| 291 virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE; | 291 virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE; |
| 292 virtual void AddBufferedTimeRange(base::TimeDelta start, | 292 virtual void AddBufferedTimeRange(base::TimeDelta start, |
| 293 base::TimeDelta end) OVERRIDE; | 293 base::TimeDelta end) OVERRIDE; |
| 294 | 294 |
| 295 // DemuxerHost implementaion. | 295 // DemuxerHost implementaion. |
| 296 virtual void SetDuration(base::TimeDelta duration) OVERRIDE; | 296 virtual void SetDuration(base::TimeDelta duration) OVERRIDE; |
| 297 virtual void OnDemuxerError(PipelineStatus error) OVERRIDE; | 297 virtual void OnDemuxerError(PipelineStatus error) OVERRIDE; |
| 298 | 298 |
| 299 // FilterHost implementation. | 299 // Initiates teardown sequence in response to a runtime error. |
| 300 virtual void SetError(PipelineStatus error) OVERRIDE; | 300 // |
| 301 virtual base::TimeDelta GetTime() const OVERRIDE; | 301 // Safe to call from any thread. |
| 302 virtual base::TimeDelta GetDuration() const OVERRIDE; | 302 void SetError(PipelineStatus error); |
| 303 virtual void SetNaturalVideoSize(const gfx::Size& size) OVERRIDE; | 303 |
| 304 virtual void NotifyEnded() OVERRIDE; | 304 // Callback executed when the natural size of the video has changed. |
| 305 void OnNaturalVideoSizeChanged(const gfx::Size& size); |
| 306 |
| 307 // Callback executed when either of the renderers have ended. |
| 308 void OnRendererEnded(); |
| 305 | 309 |
| 306 // Callbacks executed by filters upon completing initialization. | 310 // Callbacks executed by filters upon completing initialization. |
| 307 void OnFilterInitialize(PipelineStatus status); | 311 void OnFilterInitialize(PipelineStatus status); |
| 308 | 312 |
| 309 // Callback executed by filters upon completing Play(), Pause(), or Stop(). | 313 // Callback executed by filters upon completing Play(), Pause(), or Stop(). |
| 310 void OnFilterStateTransition(); | 314 void OnFilterStateTransition(); |
| 311 | 315 |
| 312 // Callback executed by filters upon completing Seek(). | 316 // Callback executed by filters upon completing Seek(). |
| 313 void OnFilterStateTransitionWithStatus(PipelineStatus status); | 317 void OnFilterStateTransitionWithStatus(PipelineStatus status); |
| 314 | 318 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 355 |
| 352 // Carries out notifying filters that the playback rate has changed. | 356 // Carries out notifying filters that the playback rate has changed. |
| 353 void PlaybackRateChangedTask(float playback_rate); | 357 void PlaybackRateChangedTask(float playback_rate); |
| 354 | 358 |
| 355 // Carries out notifying filters that the volume has changed. | 359 // Carries out notifying filters that the volume has changed. |
| 356 void VolumeChangedTask(float volume); | 360 void VolumeChangedTask(float volume); |
| 357 | 361 |
| 358 // Carries out notifying filters that we are seeking to a new timestamp. | 362 // Carries out notifying filters that we are seeking to a new timestamp. |
| 359 void SeekTask(base::TimeDelta time, const PipelineStatusCB& seek_cb); | 363 void SeekTask(base::TimeDelta time, const PipelineStatusCB& seek_cb); |
| 360 | 364 |
| 361 // Carries out handling a notification from a filter that it has ended. | 365 // Carries out handling a notification from a renderer that it has ended. |
| 362 void NotifyEndedTask(); | 366 void OnRendererEndedTask(); |
| 363 | 367 |
| 364 // Carries out disabling the audio renderer. | 368 // Carries out disabling the audio renderer. |
| 365 void AudioDisabledTask(); | 369 void AudioDisabledTask(); |
| 366 | 370 |
| 367 // Carries out advancing to the next filter during Play()/Pause()/Seek(). | 371 // Carries out advancing to the next filter during Play()/Pause()/Seek(). |
| 368 void FilterStateTransitionTask(); | 372 void FilterStateTransitionTask(); |
| 369 | 373 |
| 370 // Carries out advancing to the next teardown operation. | 374 // Carries out advancing to the next teardown operation. |
| 371 void TeardownStateTransitionTask(); | 375 void TeardownStateTransitionTask(); |
| 372 | 376 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 399 | 403 |
| 400 // Kicks off destroying filters. Called by StopTask() and ErrorChangedTask(). | 404 // Kicks off destroying filters. Called by StopTask() and ErrorChangedTask(). |
| 401 // When we start to tear down the pipeline, we will consider two cases: | 405 // When we start to tear down the pipeline, we will consider two cases: |
| 402 // 1. when pipeline has not been initialized, we will transit to stopping | 406 // 1. when pipeline has not been initialized, we will transit to stopping |
| 403 // state first. | 407 // state first. |
| 404 // 2. when pipeline has been initialized, we will first transit to pausing | 408 // 2. when pipeline has been initialized, we will first transit to pausing |
| 405 // => flushing => stopping => stopped state. | 409 // => flushing => stopping => stopped state. |
| 406 // This will remove the race condition during stop between filters. | 410 // This will remove the race condition during stop between filters. |
| 407 void TearDownPipeline(); | 411 void TearDownPipeline(); |
| 408 | 412 |
| 409 // Compute the current time. Assumes that the lock has been acquired by the | |
| 410 // caller. | |
| 411 base::TimeDelta GetCurrentTime_Locked() const; | |
| 412 | |
| 413 // Compute the time corresponding to a byte offset. | 413 // Compute the time corresponding to a byte offset. |
| 414 base::TimeDelta TimeForByteOffset_Locked(int64 byte_offset) const; | 414 base::TimeDelta TimeForByteOffset_Locked(int64 byte_offset) const; |
| 415 | 415 |
| 416 // Initiates an asynchronous Pause/Seek/Play/Stop() call sequence executing | 416 // Initiates an asynchronous Pause/Seek/Play/Stop() call sequence executing |
| 417 // |done_cb| when completed. | 417 // |done_cb| when completed. |
| 418 void DoPause(const base::Closure& done_cb); | 418 void DoPause(const base::Closure& done_cb); |
| 419 void DoFlush(const base::Closure& done_cb); | 419 void DoFlush(const base::Closure& done_cb); |
| 420 void DoPlay(const base::Closure& done_cb); | 420 void DoPlay(const base::Closure& done_cb); |
| 421 void DoStop(const base::Closure& done_cb); | 421 void DoStop(const base::Closure& done_cb); |
| 422 | 422 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 | 529 |
| 530 // Filter collection as passed in by Start(). | 530 // Filter collection as passed in by Start(). |
| 531 scoped_ptr<FilterCollection> filter_collection_; | 531 scoped_ptr<FilterCollection> filter_collection_; |
| 532 | 532 |
| 533 // Callbacks for various pipeline operations. | 533 // Callbacks for various pipeline operations. |
| 534 PipelineStatusCB seek_cb_; | 534 PipelineStatusCB seek_cb_; |
| 535 base::Closure stop_cb_; | 535 base::Closure stop_cb_; |
| 536 PipelineStatusCB ended_cb_; | 536 PipelineStatusCB ended_cb_; |
| 537 PipelineStatusCB error_cb_; | 537 PipelineStatusCB error_cb_; |
| 538 | 538 |
| 539 // Reference to the filter(s) that constitute the pipeline. | |
| 540 // | |
| 541 // TODO(scherkus): At this point in time this is a CompositeFilter that | |
| 542 // contains |video_renderer_|. Remove when CompositeFilter is gone, see | |
| 543 // http://crbug.com/126069 | |
| 544 scoped_refptr<Filter> pipeline_filter_; | |
| 545 | |
| 546 // Decoder reference used for signalling imminent shutdown. | 539 // Decoder reference used for signalling imminent shutdown. |
| 547 // This is a HACK necessary because WebMediaPlayerImpl::Destroy() holds the | 540 // This is a HACK necessary because WebMediaPlayerImpl::Destroy() holds the |
| 548 // renderer thread loop hostage for until PipelineImpl::Stop() calls its | 541 // renderer thread loop hostage for until PipelineImpl::Stop() calls its |
| 549 // callback. | 542 // callback. |
| 550 // This reference should only be used for this hack and no other purposes. | 543 // This reference should only be used for this hack and no other purposes. |
| 551 // http://crbug.com/110228 tracks removing this hack. | 544 // http://crbug.com/110228 tracks removing this hack. |
| 552 scoped_refptr<VideoDecoder> video_decoder_; | 545 scoped_refptr<VideoDecoder> video_decoder_; |
| 553 | 546 |
| 554 // Renderer references used for setting the volume and determining | 547 // Renderer references used for setting the volume and determining |
| 555 // when playback has finished. | 548 // when playback has finished. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 569 // Time of pipeline creation; is non-zero only until the pipeline first | 562 // Time of pipeline creation; is non-zero only until the pipeline first |
| 570 // reaches "kStarted", at which point it is used & zeroed out. | 563 // reaches "kStarted", at which point it is used & zeroed out. |
| 571 base::Time creation_time_; | 564 base::Time creation_time_; |
| 572 | 565 |
| 573 DISALLOW_COPY_AND_ASSIGN(Pipeline); | 566 DISALLOW_COPY_AND_ASSIGN(Pipeline); |
| 574 }; | 567 }; |
| 575 | 568 |
| 576 } // namespace media | 569 } // namespace media |
| 577 | 570 |
| 578 #endif // MEDIA_BASE_PIPELINE_H_ | 571 #endif // MEDIA_BASE_PIPELINE_H_ |
| OLD | NEW |