12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MEDIA_BASE_PIPELINE_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MEDIA_BASE_PIPELINE_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/gtest_prod_util.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/weak_ptr.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/lock.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_checker.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/time/default_tick_clock.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/buffering_state.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/demuxer.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_export.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/pipeline_status.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/ranges.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/serial_runner.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/text_track.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/video_rotation.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SingleThreadTaskRunner;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TimeDelta;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30class MediaLog;
31class Renderer;
32class TextRenderer;
33class TextTrackConfig;
34class TimeDeltaInterpolator;
35
36// Metadata describing a pipeline once it has been initialized.
37struct PipelineMetadata {
38  PipelineMetadata()
39      : has_audio(false), has_video(false), video_rotation(VIDEO_ROTATION_0) {}
40
41  bool has_audio;
42  bool has_video;
43  gfx::Size natural_size;
44  VideoRotation video_rotation;
45  base::Time timeline_offset;
46};
47
48typedef base::Callback<void(PipelineMetadata)> PipelineMetadataCB;
49
50// Pipeline runs the media pipeline.  Filters are created and called on the
51// task runner injected into this object. Pipeline works like a state
52// machine to perform asynchronous initialization, pausing, seeking and playing.
53//
54// Here's a state diagram that describes the lifetime of this object.
55//
56//   [ *Created ]                       [ Any State ]
57//         | Start()                         | Stop() / SetError()
58//         V                                 V
59//   [ InitXXX (for each filter) ]      [ Stopping ]
60//         |                                 |
61//         V                                 V
62//   [ Playing ] <-- [ Seeking ]        [ Stopped ]
63//         |               ^
64//         `---------------'
65//              Seek()
66//
67// Initialization is a series of state transitions from "Created" through each
68// filter initialization state.  When all filter initialization states have
69// completed, we are implicitly in a "Paused" state.  At that point we simulate
70// a Seek() to the beginning of the media to give filters a chance to preroll.
71// From then on the normal Seek() transitions are carried out and we start
72// playing the media.
73//
74// If any error ever happens, this object will transition to the "Error" state
75// from any state. If Stop() is ever called, this object will transition to
76// "Stopped" state.
77class MEDIA_EXPORT Pipeline : public DemuxerHost {
78 public:
79  // Constructs a media pipeline that will execute on |task_runner|.
80  Pipeline(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
81           MediaLog* media_log);
82  virtual ~Pipeline();
83
84  // Build a pipeline to using the given |demuxer| and |renderer| to construct
85  // a filter chain, executing |seek_cb| when the initial seek has completed.
86  //
87  // The following permanent callbacks will be executed as follows up until
88  // Stop() has completed:
89  //   |ended_cb| will be executed whenever the media reaches the end.
90  //   |error_cb| will be executed whenever an error occurs but hasn't been
91  //              reported already through another callback.
92  //   |metadata_cb| will be executed when the content duration, container video
93  //                 size, start time, and whether the content has audio and/or
94  //                 video in supported formats are known.
95  //   |buffering_state_cb| will be executed whenever there are changes in the
96  //                        overall buffering state of the pipeline.
97  //   |duration_change_cb| optional callback that will be executed whenever the
98  //                        presentation duration changes.
99  //   |add_text_track_cb| will be executed whenever a text track is added.
100  // It is an error to call this method after the pipeline has already started.
101  void Start(Demuxer* demuxer,
102             scoped_ptr<Renderer> renderer,
103             const base::Closure& ended_cb,
104             const PipelineStatusCB& error_cb,
105             const PipelineStatusCB& seek_cb,
106             const PipelineMetadataCB& metadata_cb,
107             const BufferingStateCB& buffering_state_cb,
108             const base::Closure& duration_change_cb,
109             const AddTextTrackCB& add_text_track_cb);
110
111  // Asynchronously stops the pipeline, executing |stop_cb| when the pipeline
112  // teardown has completed.
113  //
114  // Stop() must complete before destroying the pipeline. It it permissible to
115  // call Stop() at any point during the lifetime of the pipeline.
116  //
117  // It is safe to delete the pipeline during the execution of |stop_cb|.
118  void Stop(const base::Closure& stop_cb);
119
120  // Attempt to seek to the position specified by time.  |seek_cb| will be
121  // executed when the all filters in the pipeline have processed the seek.
122  //
123  // Clients are expected to call GetMediaTime() to check whether the seek
124  // succeeded.
125  //
126  // It is an error to call this method if the pipeline has not started.
127  void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb);
128
129  // Returns true if the pipeline has been started via Start().  If IsRunning()
130  // returns true, it is expected that Stop() will be called before destroying
131  // the pipeline.
132  bool IsRunning() const;
133
134  // Gets the current playback rate of the pipeline.  When the pipeline is
135  // started, the playback rate will be 0.0f.  A rate of 1.0f indicates
136  // that the pipeline is rendering the media at the standard rate.  Valid
137  // values for playback rate are >= 0.0f.
138  float GetPlaybackRate() const;
139
140  // Attempt to adjust the playback rate. Setting a playback rate of 0.0f pauses
141  // all rendering of the media.  A rate of 1.0f indicates a normal playback
142  // rate.  Values for the playback rate must be greater than or equal to 0.0f.
143  //
144  // TODO(scherkus): What about maximum rate?  Does HTML5 specify a max?
145  void SetPlaybackRate(float playback_rate);
146
147  // Gets the current volume setting being used by the audio renderer.  When
148  // the pipeline is started, this value will be 1.0f.  Valid values range
149  // from 0.0f to 1.0f.
150  float GetVolume() const;
151
152  // Attempt to set the volume of the audio renderer.  Valid values for volume
153  // range from 0.0f (muted) to 1.0f (full volume).  This value affects all
154  // channels proportionately for multi-channel audio streams.
155  void SetVolume(float volume);
156
157  // Returns the current media playback time, which progresses from 0 until
158  // GetMediaDuration().
159  base::TimeDelta GetMediaTime() const;
160
161  // Get approximate time ranges of buffered media.
162  Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
163
164  // Get the duration of the media in microseconds.  If the duration has not
165  // been determined yet, then returns 0.
166  base::TimeDelta GetMediaDuration() const;
167
168  // Return true if loading progress has been made since the last time this
169  // method was called.
170  bool DidLoadingProgress();
171
172  // Gets the current pipeline statistics.
173  PipelineStatistics GetStatistics() const;
174
175  void SetErrorForTesting(PipelineStatus status);
176  bool HasWeakPtrsForTesting() const;
177
178 private:
179  FRIEND_TEST_ALL_PREFIXES(PipelineTest, GetBufferedTimeRanges);
180  FRIEND_TEST_ALL_PREFIXES(PipelineTest, EndedCallback);
181  FRIEND_TEST_ALL_PREFIXES(PipelineTest, AudioStreamShorterThanVideo);
182  friend class MediaLog;
183
184  // Pipeline states, as described above.
185  enum State {
186    kCreated,
187    kInitDemuxer,
188    kInitRenderer,
189    kSeeking,
190    kPlaying,
191    kStopping,
192    kStopped,
193  };
194
195  // Updates |state_|. All state transitions should use this call.
196  void SetState(State next_state);
197
198  static const char* GetStateString(State state);
199  State GetNextState() const;
200
201  // Helper method that runs & resets |seek_cb_| and resets |seek_timestamp_|
202  // and |seek_pending_|.
203  void FinishSeek();
204
205  // DemuxerHost implementaion.
206  virtual void AddBufferedTimeRange(base::TimeDelta start,
207                                    base::TimeDelta end) OVERRIDE;
208  virtual void SetDuration(base::TimeDelta duration) OVERRIDE;
209  virtual void OnDemuxerError(PipelineStatus error) OVERRIDE;
210  virtual void AddTextStream(DemuxerStream* text_stream,
211                             const TextTrackConfig& config) OVERRIDE;
212  virtual void RemoveTextStream(DemuxerStream* text_stream) OVERRIDE;
213
214  // Callback executed when a rendering error happened, initiating the teardown
215  // sequence.
216  void OnError(PipelineStatus error);
217
218  // Callback executed by filters to update statistics.
219  void OnUpdateStatistics(const PipelineStatistics& stats);
220
221  // The following "task" methods correspond to the public methods, but these
222  // methods are run as the result of posting a task to the Pipeline's
223  // task runner.
224  void StartTask();
225
226  // Stops and destroys all filters, placing the pipeline in the kStopped state.
227  void StopTask(const base::Closure& stop_cb);
228
229  // Carries out stopping and destroying all filters, placing the pipeline in
230  // the kStopped state.
231  void ErrorChangedTask(PipelineStatus error);
232
233  // Carries out notifying filters that the playback rate has changed.
234  void PlaybackRateChangedTask(float playback_rate);
235
236  // Carries out notifying filters that the volume has changed.
237  void VolumeChangedTask(float volume);
238
239  // Carries out notifying filters that we are seeking to a new timestamp.
240  void SeekTask(base::TimeDelta time, const PipelineStatusCB& seek_cb);
241
242  // Callbacks executed when a renderer has ended.
243  void OnRendererEnded();
244  void OnTextRendererEnded();
245  void RunEndedCallbackIfNeeded();
246
247  scoped_ptr<TextRenderer> CreateTextRenderer();
248
249  // Carries out adding a new text stream to the text renderer.
250  void AddTextStreamTask(DemuxerStream* text_stream,
251                         const TextTrackConfig& config);
252
253  // Carries out removing a text stream from the text renderer.
254  void RemoveTextStreamTask(DemuxerStream* text_stream);
255
256  // Callbacks executed when a text track is added.
257  void OnAddTextTrack(const TextTrackConfig& config,
258                      const AddTextTrackDoneCB& done_cb);
259
260  // Kicks off initialization for each media object, executing |done_cb| with
261  // the result when completed.
262  void InitializeDemuxer(const PipelineStatusCB& done_cb);
263  void InitializeRenderer(const base::Closure& done_cb);
264
265  void OnStateTransition(PipelineStatus status);
266  void StateTransitionTask(PipelineStatus status);
267
268  // Initiates an asynchronous pause-flush-seek-preroll call sequence
269  // executing |done_cb| with the final status when completed.
270  void DoSeek(base::TimeDelta seek_timestamp, const PipelineStatusCB& done_cb);
271
272  // Initiates an asynchronous pause-flush-stop call sequence executing
273  // |done_cb| when completed.
274  void DoStop(const PipelineStatusCB& done_cb);
275  void OnStopCompleted(PipelineStatus status);
276
277  void ReportMetadata();
278
279  void BufferingStateChanged(BufferingState new_buffering_state);
280
281  // Task runner used to execute pipeline tasks.
282  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
283
284  // MediaLog to which to log events.
285  scoped_refptr<MediaLog> media_log_;
286
287  // Lock used to serialize access for the following data members.
288  mutable base::Lock lock_;
289
290  // Whether or not the pipeline is running.
291  bool running_;
292
293  // Amount of available buffered data as reported by |demuxer_|.
294  Ranges<base::TimeDelta> buffered_time_ranges_;
295
296  // True when AddBufferedTimeRange() has been called more recently than
297  // DidLoadingProgress().
298  bool did_loading_progress_;
299
300  // Current volume level (from 0.0f to 1.0f).  This value is set immediately
301  // via SetVolume() and a task is dispatched on the task runner to notify the
302  // filters.
303  float volume_;
304
305  // Current playback rate (>= 0.0f).  This value is set immediately via
306  // SetPlaybackRate() and a task is dispatched on the task runner to notify
307  // the filters.
308  float playback_rate_;
309
310  // Current duration as reported by |demuxer_|.
311  base::TimeDelta duration_;
312
313  // Status of the pipeline.  Initialized to PIPELINE_OK which indicates that
314  // the pipeline is operating correctly. Any other value indicates that the
315  // pipeline is stopped or is stopping.  Clients can call the Stop() method to
316  // reset the pipeline state, and restore this to PIPELINE_OK.
317  PipelineStatus status_;
318
319  // The following data members are only accessed by tasks posted to
320  // |task_runner_|.
321
322  bool is_initialized_;
323
324  // Member that tracks the current state.
325  State state_;
326
327  // The timestamp to start playback from after starting/seeking has completed.
328  base::TimeDelta start_timestamp_;
329
330  // Whether we've received the audio/video/text ended events.
331  bool renderer_ended_;
332  bool text_renderer_ended_;
333
334  // Temporary callback used for Start() and Seek().
335  PipelineStatusCB seek_cb_;
336
337  // Temporary callback used for Stop().
338  base::Closure stop_cb_;
339
340  // Permanent callbacks passed in via Start().
341  base::Closure ended_cb_;
342  PipelineStatusCB error_cb_;
343  PipelineMetadataCB metadata_cb_;
344  BufferingStateCB buffering_state_cb_;
345  base::Closure duration_change_cb_;
346  AddTextTrackCB add_text_track_cb_;
347
348  // Holds the initialized demuxer. Used for seeking. Owned by client.
349  Demuxer* demuxer_;
350
351  // Holds the initialized renderers. Used for setting the volume,
352  // playback rate, and determining when playback has finished.
353  scoped_ptr<Renderer> renderer_;
354  scoped_ptr<TextRenderer> text_renderer_;
355
356  PipelineStatistics statistics_;
357
358  scoped_ptr<SerialRunner> pending_callbacks_;
359
360  base::ThreadChecker thread_checker_;
361
362  // NOTE: Weak pointers must be invalidated before all other member variables.
363  base::WeakPtrFactory<Pipeline> weak_factory_;
364
365  DISALLOW_COPY_AND_ASSIGN(Pipeline);
366};
367
368}  // namespace media
369
370#endif  // MEDIA_BASE_PIPELINE_H_
371