| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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_IMPL_H_ | 5 #ifndef MEDIA_BASE_PIPELINE_IMPL_H_ |
| 6 #define MEDIA_BASE_PIPELINE_IMPL_H_ | 6 #define MEDIA_BASE_PIPELINE_IMPL_H_ |
| 7 | 7 |
| 8 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "base/gtest_prod_util.h" | |
| 11 #include "base/macros.h" | 10 #include "base/macros.h" |
| 12 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
| 13 #include "base/memory/weak_ptr.h" | 12 #include "base/memory/weak_ptr.h" |
| 14 #include "base/synchronization/lock.h" | |
| 15 #include "base/threading/thread_checker.h" | 13 #include "base/threading/thread_checker.h" |
| 16 #include "base/time/time.h" | |
| 17 #include "media/base/buffering_state.h" | |
| 18 #include "media/base/cdm_context.h" | |
| 19 #include "media/base/demuxer.h" | |
| 20 #include "media/base/media_export.h" | 14 #include "media/base/media_export.h" |
| 21 #include "media/base/pipeline.h" | 15 #include "media/base/pipeline.h" |
| 22 #include "media/base/pipeline_status.h" | |
| 23 #include "media/base/ranges.h" | |
| 24 #include "media/base/renderer_client.h" | |
| 25 #include "media/base/serial_runner.h" | |
| 26 #include "media/base/text_track.h" | |
| 27 | 16 |
| 28 namespace base { | 17 namespace base { |
| 29 class SingleThreadTaskRunner; | 18 class SingleThreadTaskRunner; |
| 30 } | 19 } |
| 31 | 20 |
| 32 namespace media { | 21 namespace media { |
| 33 | 22 |
| 34 class MediaLog; | 23 class MediaLog; |
| 35 class Renderer; | |
| 36 class TextRenderer; | 24 class TextRenderer; |
| 37 | 25 |
| 38 // Pipeline runs the media pipeline. Filters are created and called on the | 26 // Pipeline runs the media pipeline. Filters are created and called on the |
| 39 // task runner injected into this object. Pipeline works like a state | 27 // task runner injected into this object. Pipeline works like a state |
| 40 // machine to perform asynchronous initialization, pausing, seeking and playing. | 28 // machine to perform asynchronous initialization, pausing, seeking and playing. |
| 41 // | 29 // |
| 42 // Here's a state diagram that describes the lifetime of this object. | 30 // Here's a state diagram that describes the lifetime of this object. |
| 43 // | 31 // |
| 44 // [ *Created ] [ Any State ] | 32 // [ Created ] [ Any State ] |
| 45 // | Start() | Stop() / SetError() | 33 // | Start() | Stop() / SetError() |
| 46 // V V | 34 // V V |
| 47 // [ InitXXX (for each filter) ] [ Stopping ] | 35 // [ Starting ] [ Stopping ] |
| 48 // | | | 36 // | | |
| 49 // V V | 37 // V V |
| 50 // [ Playing ] <---------. [ Stopped ] | 38 // [ Playing ] <---------. [ Stopped ] |
| 51 // | | Seek() | | 39 // | | Seek() | |
| 52 // | V | | 40 // | V | |
| 53 // | [ Seeking ] ----' | 41 // | [ Seeking ] ----' |
| 54 // | ^ | 42 // | ^ |
| 55 // | Suspend() | | 43 // | Suspend() | |
| 56 // V | | 44 // V | |
| 57 // [ Suspending ] | | 45 // [ Suspending ] | |
| (...skipping 10 matching lines...) Expand all Loading... |
| 68 // a chance to preroll. From then on the normal Seek() transitions are carried | 56 // a chance to preroll. From then on the normal Seek() transitions are carried |
| 69 // out and we start playing the media. | 57 // out and we start playing the media. |
| 70 // | 58 // |
| 71 // If any error ever happens, this object will transition to the "Error" state | 59 // If any error ever happens, this object will transition to the "Error" state |
| 72 // from any state. If Stop() is ever called, this object will transition to | 60 // from any state. If Stop() is ever called, this object will transition to |
| 73 // "Stopped" state. | 61 // "Stopped" state. |
| 74 // | 62 // |
| 75 // TODO(sandersd): It should be possible to pass through Suspended when going | 63 // TODO(sandersd): It should be possible to pass through Suspended when going |
| 76 // from InitDemuxer to InitRenderer, thereby eliminating the Resuming state. | 64 // from InitDemuxer to InitRenderer, thereby eliminating the Resuming state. |
| 77 // Some annoying differences between the two paths need to be removed first. | 65 // Some annoying differences between the two paths need to be removed first. |
| 78 class MEDIA_EXPORT PipelineImpl : public Pipeline, | 66 class MEDIA_EXPORT PipelineImpl : public Pipeline { |
| 79 public DemuxerHost, | |
| 80 public RendererClient { | |
| 81 public: | 67 public: |
| 82 // Constructs a media pipeline that will execute media tasks on | 68 // Constructs a media pipeline that will execute media tasks on |
| 83 // |media_task_runner|. | 69 // |media_task_runner|. |
| 84 PipelineImpl( | 70 PipelineImpl( |
| 85 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 71 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 86 MediaLog* media_log); | 72 MediaLog* media_log); |
| 87 ~PipelineImpl() override; | 73 ~PipelineImpl() override; |
| 88 | 74 |
| 89 void SetErrorForTesting(PipelineStatus status); | |
| 90 bool HasWeakPtrsForTesting() const; | |
| 91 | |
| 92 // Pipeline implementation. | 75 // Pipeline implementation. |
| 93 void Start(Demuxer* demuxer, | 76 void Start(Demuxer* demuxer, |
| 94 std::unique_ptr<Renderer> renderer, | 77 std::unique_ptr<Renderer> renderer, |
| 95 Client* client, | 78 Client* client, |
| 96 const PipelineStatusCB& seek_cb) override; | 79 const PipelineStatusCB& seek_cb) override; |
| 97 void Stop() override; | 80 void Stop() override; |
| 98 void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) override; | 81 void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) override; |
| 82 void Suspend(const PipelineStatusCB& suspend_cb) override; |
| 83 void Resume(std::unique_ptr<Renderer> renderer, |
| 84 base::TimeDelta time, |
| 85 const PipelineStatusCB& seek_cb) override; |
| 99 bool IsRunning() const override; | 86 bool IsRunning() const override; |
| 100 double GetPlaybackRate() const override; | 87 double GetPlaybackRate() const override; |
| 101 void SetPlaybackRate(double playback_rate) override; | 88 void SetPlaybackRate(double playback_rate) override; |
| 102 void Suspend(const PipelineStatusCB& suspend_cb) override; | |
| 103 void Resume(std::unique_ptr<Renderer> renderer, | |
| 104 base::TimeDelta timestamp, | |
| 105 const PipelineStatusCB& seek_cb) override; | |
| 106 float GetVolume() const override; | 89 float GetVolume() const override; |
| 107 void SetVolume(float volume) override; | 90 void SetVolume(float volume) override; |
| 108 base::TimeDelta GetMediaTime() const override; | 91 base::TimeDelta GetMediaTime() const override; |
| 109 Ranges<base::TimeDelta> GetBufferedTimeRanges() const override; | 92 Ranges<base::TimeDelta> GetBufferedTimeRanges() const override; |
| 110 base::TimeDelta GetMediaDuration() const override; | 93 base::TimeDelta GetMediaDuration() const override; |
| 111 bool DidLoadingProgress() override; | 94 bool DidLoadingProgress() override; |
| 112 PipelineStatistics GetStatistics() const override; | 95 PipelineStatistics GetStatistics() const override; |
| 113 void SetCdm(CdmContext* cdm_context, | 96 void SetCdm(CdmContext* cdm_context, |
| 114 const CdmAttachedCB& cdm_attached_cb) override; | 97 const CdmAttachedCB& cdm_attached_cb) override; |
| 115 | 98 |
| 116 private: | 99 private: |
| 117 friend class MediaLog; | 100 friend class MediaLog; |
| 118 friend class PipelineImplTest; | 101 class RendererWrapper; |
| 119 | 102 |
| 120 // Pipeline states, as described above. | 103 // Pipeline states, as described above. |
| 104 // TODO(alokp): Move this to RendererWrapper after removing the references |
| 105 // from MediaLog. |
| 121 enum State { | 106 enum State { |
| 122 kCreated, | 107 kCreated, |
| 123 kInitDemuxer, | 108 kStarting, |
| 124 kInitRenderer, | |
| 125 kSeeking, | 109 kSeeking, |
| 126 kPlaying, | 110 kPlaying, |
| 127 kStopping, | 111 kStopping, |
| 128 kStopped, | 112 kStopped, |
| 129 kSuspending, | 113 kSuspending, |
| 130 kSuspended, | 114 kSuspended, |
| 131 kResuming, | 115 kResuming, |
| 132 }; | 116 }; |
| 117 static const char* GetStateString(State state); |
| 133 | 118 |
| 134 // Updates |state_|. All state transitions should use this call. | 119 // Notifications from RendererWrapper. |
| 135 void SetState(State next_state); | 120 void OnError(PipelineStatus error); |
| 136 | 121 void OnEnded(); |
| 137 static const char* GetStateString(State state); | 122 void OnMetadata(PipelineMetadata metadata); |
| 138 State GetNextState() const; | 123 void OnBufferingStateChange(BufferingState state); |
| 139 | 124 void OnDurationChange(base::TimeDelta duration); |
| 140 // Helper method that runs & resets |seek_cb_| and resets |seek_timestamp_| | |
| 141 // and |seek_pending_|. | |
| 142 void FinishSeek(); | |
| 143 | |
| 144 // DemuxerHost implementaion. | |
| 145 void OnBufferedTimeRangesChanged( | |
| 146 const Ranges<base::TimeDelta>& ranges) override; | |
| 147 void SetDuration(base::TimeDelta duration) override; | |
| 148 void OnDemuxerError(PipelineStatus error) override; | |
| 149 void AddTextStream(DemuxerStream* text_stream, | |
| 150 const TextTrackConfig& config) override; | |
| 151 void RemoveTextStream(DemuxerStream* text_stream) override; | |
| 152 | |
| 153 // RendererClient implementation. | |
| 154 void OnError(PipelineStatus error) override; | |
| 155 void OnEnded() override; | |
| 156 void OnStatisticsUpdate(const PipelineStatistics& stats) override; | |
| 157 void OnBufferingStateChange(BufferingState state) override; | |
| 158 void OnWaitingForDecryptionKey() override; | |
| 159 void OnVideoNaturalSizeChange(const gfx::Size& size) override; | |
| 160 void OnVideoOpacityChange(bool opaque) override; | |
| 161 | |
| 162 // The following "task" methods correspond to the public methods, but these | |
| 163 // methods are run as the result of posting a task to the Pipeline's | |
| 164 // task runner. | |
| 165 void StartTask(); | |
| 166 | |
| 167 // Suspends the pipeline, discarding the current renderer. | |
| 168 void SuspendTask(const PipelineStatusCB& suspend_cb); | |
| 169 | |
| 170 // Resumes the pipeline with a new renderer, and initializes it with a seek. | |
| 171 void ResumeTask(std::unique_ptr<Renderer> renderer, | |
| 172 base::TimeDelta timestamp, | |
| 173 const PipelineStatusCB& seek_sb); | |
| 174 | |
| 175 // Stops and destroys all filters, placing the pipeline in the kStopped state. | |
| 176 void StopTask(const base::Closure& stop_cb); | |
| 177 | |
| 178 // Carries out stopping and destroying all filters, placing the pipeline in | |
| 179 // the kStopped state. | |
| 180 void ErrorChangedTask(PipelineStatus error); | |
| 181 | |
| 182 // Carries out notifying filters that the playback rate has changed. | |
| 183 void PlaybackRateChangedTask(double playback_rate); | |
| 184 | |
| 185 // Carries out notifying filters that the volume has changed. | |
| 186 void VolumeChangedTask(float volume); | |
| 187 | |
| 188 // Carries out notifying filters that we are seeking to a new timestamp. | |
| 189 void SeekTask(base::TimeDelta time, const PipelineStatusCB& seek_cb); | |
| 190 | |
| 191 // Carries out setting the |cdm_context| in |renderer_|, and then fires | |
| 192 // |cdm_attached_cb| with the result. If |renderer_| is null, | |
| 193 // |cdm_attached_cb| will be fired immediately with true, and |cdm_context| | |
| 194 // will be set in |renderer_| later when |renderer_| is created. | |
| 195 void SetCdmTask(CdmContext* cdm_context, | |
| 196 const CdmAttachedCB& cdm_attached_cb); | |
| 197 void OnCdmAttached(const CdmAttachedCB& cdm_attached_cb, | |
| 198 CdmContext* cdm_context, | |
| 199 bool success); | |
| 200 | |
| 201 // Callbacks executed when text renderer has ended. | |
| 202 void OnTextRendererEnded(); | |
| 203 void RunEndedCallbackIfNeeded(); | |
| 204 | |
| 205 std::unique_ptr<TextRenderer> CreateTextRenderer(); | |
| 206 | |
| 207 // Carries out adding a new text stream to the text renderer. | |
| 208 void AddTextStreamTask(DemuxerStream* text_stream, | |
| 209 const TextTrackConfig& config); | |
| 210 | |
| 211 // Carries out removing a text stream from the text renderer. | |
| 212 void RemoveTextStreamTask(DemuxerStream* text_stream); | |
| 213 | |
| 214 // Callbacks executed when a text track is added. | |
| 215 void OnAddTextTrack(const TextTrackConfig& config, | 125 void OnAddTextTrack(const TextTrackConfig& config, |
| 216 const AddTextTrackDoneCB& done_cb); | 126 const AddTextTrackDoneCB& done_cb); |
| 127 void OnWaitingForDecryptionKey(); |
| 128 void OnVideoNaturalSizeChange(const gfx::Size& size); |
| 129 void OnVideoOpacityChange(bool opaque); |
| 130 void OnBufferedTimeRangesChange(const Ranges<base::TimeDelta>& ranges); |
| 131 void OnStatisticsUpdate(const PipelineStatistics& stats); |
| 217 | 132 |
| 218 // Kicks off initialization for each media object, executing |done_cb| with | 133 // Task completion callbacks from RendererWrapper. |
| 219 // the result when completed. | 134 void OnSeekDone(base::TimeDelta start_time); |
| 220 void InitializeDemuxer(const PipelineStatusCB& done_cb); | 135 void OnSuspendDone(base::TimeDelta suspend_time); |
| 221 void InitializeRenderer(const PipelineStatusCB& done_cb); | |
| 222 | 136 |
| 223 void StateTransitionTask(PipelineStatus status); | 137 // Parameters passed in the constructor. |
| 138 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 139 const scoped_refptr<MediaLog> media_log_; |
| 224 | 140 |
| 225 // Initiates an asynchronous pause-flush-seek-preroll call sequence | 141 // Pipeline client. Valid only while the pipeline is running. |
| 226 // executing |done_cb| with the final status when completed. | 142 Client* client_; |
| 227 void DoSeek(base::TimeDelta seek_timestamp, const PipelineStatusCB& done_cb); | |
| 228 | 143 |
| 229 // Stops media rendering and executes |stop_cb_| when done. | 144 // RendererWrapper instance that runs on the media thread. |
| 230 void DoStop(); | 145 std::unique_ptr<RendererWrapper> renderer_wrapper_; |
| 231 | 146 |
| 232 void ReportMetadata(); | 147 // Temporary callback used for Start(), Seek(), and Resume(). |
| 148 PipelineStatusCB seek_cb_; |
| 233 | 149 |
| 234 // Task runner of the thread on which this class is constructed. | 150 // Temporary callback used for Suspend(). |
| 235 // Also used to post notifications on Pipeline::Client object. | 151 PipelineStatusCB suspend_cb_; |
| 236 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | |
| 237 | 152 |
| 238 // Task runner used to execute pipeline tasks. | 153 // Current playback rate (>= 0.0). This value is set immediately via |
| 239 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | 154 // SetPlaybackRate() and a task is dispatched on the task runner to notify |
| 155 // the filters. |
| 156 double playback_rate_; |
| 240 | 157 |
| 241 // MediaLog to which to log events. | 158 // Current volume level (from 0.0f to 1.0f). This value is set immediately |
| 242 scoped_refptr<MediaLog> media_log_; | |
| 243 | |
| 244 // Lock used to serialize access for the following data members. | |
| 245 mutable base::Lock lock_; | |
| 246 | |
| 247 // Whether or not the pipeline is running. | |
| 248 bool running_; | |
| 249 | |
| 250 // Amount of available buffered data as reported by |demuxer_|. | |
| 251 Ranges<base::TimeDelta> buffered_time_ranges_; | |
| 252 | |
| 253 // True when OnBufferedTimeRangesChanged() has been called more recently than | |
| 254 // DidLoadingProgress(). | |
| 255 bool did_loading_progress_; | |
| 256 | |
| 257 // Current volume level (from 0.0f to 1.0f). This value is set immediately | |
| 258 // via SetVolume() and a task is dispatched on the task runner to notify the | 159 // via SetVolume() and a task is dispatched on the task runner to notify the |
| 259 // filters. | 160 // filters. |
| 260 float volume_; | 161 float volume_; |
| 261 | 162 |
| 262 // Current playback rate (>= 0.0). This value is set immediately via | 163 // The media timestamp to return while the pipeline is suspended. |
| 263 // SetPlaybackRate() and a task is dispatched on the task runner to notify | 164 // Otherwise set to kNoTimestamp(). |
| 264 // the filters. | 165 base::TimeDelta suspend_time_; |
| 265 double playback_rate_; | |
| 266 | 166 |
| 267 // Current duration as reported by |demuxer_|. | 167 // Amount of available buffered data as reported by Demuxer. |
| 168 Ranges<base::TimeDelta> buffered_time_ranges_; |
| 169 |
| 170 // Current duration as reported by Demuxer. |
| 268 base::TimeDelta duration_; | 171 base::TimeDelta duration_; |
| 269 | 172 |
| 270 // Status of the pipeline. Initialized to PIPELINE_OK which indicates that | 173 // True when OnBufferedTimeRangesChange() has been called more recently than |
| 271 // the pipeline is operating correctly. Any other value indicates that the | 174 // DidLoadingProgress(). |
| 272 // pipeline is stopped or is stopping. Clients can call the Stop() method to | 175 bool did_loading_progress_; |
| 273 // reset the pipeline state, and restore this to PIPELINE_OK. | |
| 274 PipelineStatus status_; | |
| 275 | 176 |
| 276 // The following data members are only accessed by tasks posted to | 177 // Accumulated statistics reported by the renderer. |
| 277 // |task_runner_|. | |
| 278 | |
| 279 // Member that tracks the current state. | |
| 280 State state_; | |
| 281 | |
| 282 // The timestamp to start playback from after starting/seeking/resuming has | |
| 283 // completed. | |
| 284 base::TimeDelta start_timestamp_; | |
| 285 | |
| 286 // The media timestamp to return while the pipeline is suspended. Otherwise | |
| 287 // set to kNoTimestamp(). | |
| 288 base::TimeDelta suspend_timestamp_; | |
| 289 | |
| 290 // Whether we've received the audio/video/text ended events. | |
| 291 bool renderer_ended_; | |
| 292 bool text_renderer_ended_; | |
| 293 | |
| 294 // Temporary callback used for Start(), Seek(), and Resume(). | |
| 295 PipelineStatusCB seek_cb_; | |
| 296 | |
| 297 // Temporary callback used for Stop(). | |
| 298 base::Closure stop_cb_; | |
| 299 | |
| 300 // Temporary callback used for Suspend(). | |
| 301 PipelineStatusCB suspend_cb_; | |
| 302 | |
| 303 // Holds the initialized demuxer. Used for seeking. Owned by client. | |
| 304 Demuxer* demuxer_; | |
| 305 | |
| 306 // Holds the initialized renderers. Used for setting the volume, | |
| 307 // playback rate, and determining when playback has finished. | |
| 308 std::unique_ptr<Renderer> renderer_; | |
| 309 std::unique_ptr<TextRenderer> text_renderer_; | |
| 310 | |
| 311 // Holds the client passed on Start(). | |
| 312 // Initialized, Dereferenced, and Invalidated on |main_task_runner_|. | |
| 313 // Used on |media_task_runner_| to post tasks on |main_task_runner_|. | |
| 314 base::WeakPtr<Client> weak_client_; | |
| 315 // Created and destroyed on |main_task_runner_|. | |
| 316 std::unique_ptr<base::WeakPtrFactory<Client>> client_weak_factory_; | |
| 317 | |
| 318 PipelineStatistics statistics_; | 178 PipelineStatistics statistics_; |
| 319 | 179 |
| 320 std::unique_ptr<SerialRunner> pending_callbacks_; | |
| 321 | |
| 322 // The CdmContext to be used to decrypt (and decode) encrypted stream in this | |
| 323 // pipeline. It is set when SetCdm() succeeds on the renderer (or when | |
| 324 // SetCdm() is called before Start()), after which it is guaranteed to outlive | |
| 325 // this pipeline. The saved value will be used to configure new renderers, | |
| 326 // when starting or resuming. | |
| 327 CdmContext* cdm_context_; | |
| 328 | |
| 329 base::ThreadChecker thread_checker_; | 180 base::ThreadChecker thread_checker_; |
| 330 | |
| 331 // A weak pointer that can be safely copied on the media thread. | |
| 332 base::WeakPtr<PipelineImpl> weak_this_; | |
| 333 | |
| 334 // Weak pointers must be created on the main thread, and must be dereferenced | |
| 335 // on the media thread. | |
| 336 // | |
| 337 // Declared last so that weak pointers will be invalidated before all other | |
| 338 // member variables. | |
| 339 base::WeakPtrFactory<PipelineImpl> weak_factory_; | 181 base::WeakPtrFactory<PipelineImpl> weak_factory_; |
| 340 | 182 |
| 341 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); | 183 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); |
| 342 }; | 184 }; |
| 343 | 185 |
| 344 } // namespace media | 186 } // namespace media |
| 345 | 187 |
| 346 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ | 188 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ |
| OLD | NEW |