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() |
(...skipping 22 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 kInitDemuxer, |
124 kInitRenderer, | 109 kInitRenderer, |
125 kSeeking, | 110 kSeeking, |
126 kPlaying, | 111 kPlaying, |
127 kStopping, | 112 kStopping, |
128 kStopped, | 113 kStopped, |
129 kSuspending, | 114 kSuspending, |
130 kSuspended, | 115 kSuspended, |
131 kResuming, | 116 kResuming, |
132 }; | 117 }; |
| 118 static const char* GetStateString(State state); |
133 | 119 |
134 // Updates |state_|. All state transitions should use this call. | 120 // Notifications from RendererWrapper. |
135 void SetState(State next_state); | 121 void OnError(PipelineStatus error); |
136 | 122 void OnEnded(); |
137 static const char* GetStateString(State state); | 123 void OnMetadata(PipelineMetadata metadata); |
138 State GetNextState() const; | 124 void OnBufferingStateChange(BufferingState state); |
139 | 125 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, | 126 void OnAddTextTrack(const TextTrackConfig& config, |
216 const AddTextTrackDoneCB& done_cb); | 127 const AddTextTrackDoneCB& done_cb); |
| 128 void OnWaitingForDecryptionKey(); |
| 129 void OnVideoNaturalSizeChange(const gfx::Size& size); |
| 130 void OnVideoOpacityChange(bool opaque); |
| 131 void OnBufferedTimeRangesChange(const Ranges<base::TimeDelta>& ranges); |
| 132 void OnStatisticsUpdate(const PipelineStatistics& stats); |
217 | 133 |
218 // Kicks off initialization for each media object, executing |done_cb| with | 134 // Task completion callbacks from RendererWrapper. |
219 // the result when completed. | 135 void OnSeekDone(base::TimeDelta start_time); |
220 void InitializeDemuxer(const PipelineStatusCB& done_cb); | 136 void OnSuspendDone(base::TimeDelta suspend_time); |
221 void InitializeRenderer(const PipelineStatusCB& done_cb); | |
222 | 137 |
223 void StateTransitionTask(PipelineStatus status); | 138 // Parameters passed in the constructor. |
| 139 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; |
| 140 const scoped_refptr<MediaLog> media_log_; |
224 | 141 |
225 // Initiates an asynchronous pause-flush-seek-preroll call sequence | 142 // Pipeline client. Valid only while the pipeline is running. |
226 // executing |done_cb| with the final status when completed. | 143 Client* client_; |
227 void DoSeek(base::TimeDelta seek_timestamp, const PipelineStatusCB& done_cb); | |
228 | 144 |
229 // Stops media rendering and executes |stop_cb_| when done. | 145 // RendererWrapper instance that runs on the media thread. |
230 void DoStop(); | 146 std::unique_ptr<RendererWrapper> renderer_wrapper_; |
231 | 147 |
232 void ReportMetadata(); | 148 // Temporary callback used for Start(), Seek(), and Resume(). |
| 149 PipelineStatusCB seek_cb_; |
233 | 150 |
234 // Task runner of the thread on which this class is constructed. | 151 // Temporary callback used for Suspend(). |
235 // Also used to post notifications on Pipeline::Client object. | 152 PipelineStatusCB suspend_cb_; |
236 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | |
237 | 153 |
238 // Task runner used to execute pipeline tasks. | 154 // Current playback rate (>= 0.0). This value is set immediately via |
239 const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | 155 // SetPlaybackRate() and a task is dispatched on the task runner to notify |
| 156 // the filters. |
| 157 double playback_rate_; |
240 | 158 |
241 // MediaLog to which to log events. | 159 // 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 | 160 // via SetVolume() and a task is dispatched on the task runner to notify the |
259 // filters. | 161 // filters. |
260 float volume_; | 162 float volume_; |
261 | 163 |
262 // Current playback rate (>= 0.0). This value is set immediately via | 164 // The media timestamp to return while the pipeline is suspended. |
263 // SetPlaybackRate() and a task is dispatched on the task runner to notify | 165 // Otherwise set to kNoTimestamp(). |
264 // the filters. | 166 base::TimeDelta suspend_time_; |
265 double playback_rate_; | |
266 | 167 |
267 // Current duration as reported by |demuxer_|. | 168 // Amount of available buffered data as reported by Demuxer. |
| 169 Ranges<base::TimeDelta> buffered_time_ranges_; |
| 170 |
| 171 // Current duration as reported by Demuxer. |
268 base::TimeDelta duration_; | 172 base::TimeDelta duration_; |
269 | 173 |
270 // Status of the pipeline. Initialized to PIPELINE_OK which indicates that | 174 // True when OnBufferedTimeRangesChange() has been called more recently than |
271 // the pipeline is operating correctly. Any other value indicates that the | 175 // DidLoadingProgress(). |
272 // pipeline is stopped or is stopping. Clients can call the Stop() method to | 176 bool did_loading_progress_; |
273 // reset the pipeline state, and restore this to PIPELINE_OK. | |
274 PipelineStatus status_; | |
275 | 177 |
276 // The following data members are only accessed by tasks posted to | 178 // 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_; | 179 PipelineStatistics statistics_; |
319 | 180 |
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_; | 181 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_; | 182 base::WeakPtrFactory<PipelineImpl> weak_factory_; |
340 | 183 |
341 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); | 184 DISALLOW_COPY_AND_ASSIGN(PipelineImpl); |
342 }; | 185 }; |
343 | 186 |
344 } // namespace media | 187 } // namespace media |
345 | 188 |
346 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ | 189 #endif // MEDIA_BASE_PIPELINE_IMPL_H_ |
OLD | NEW |