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
3 // found in the LICENSE file.
4 
5 #ifndef MEDIA_BASE_PIPELINE_H_
6 #define MEDIA_BASE_PIPELINE_H_
7 
8 #include <memory>
9 
10 #include "base/memory/ref_counted.h"
11 #include "base/optional.h"
12 #include "base/time/time.h"
13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/buffering_state.h"
15 #include "media/base/media_export.h"
16 #include "media/base/media_status.h"
17 #include "media/base/media_track.h"
18 #include "media/base/pipeline_metadata.h"
19 #include "media/base/pipeline_status.h"
20 #include "media/base/ranges.h"
21 #include "media/base/text_track.h"
22 #include "media/base/video_decoder_config.h"
23 #include "media/base/video_transformation.h"
24 #include "media/base/waiting.h"
25 #include "ui/gfx/geometry/size.h"
26 
27 namespace media {
28 
29 class CdmContext;
30 class Demuxer;
31 
32 class MEDIA_EXPORT Pipeline {
33  public:
34   class Client {
35    public:
36     // Executed whenever an error occurs except when the error occurs during
37     // Start/Seek/Resume or Suspend. Those errors are reported via |seek_cb|
38     // and |suspend_cb| respectively.
39     // NOTE: The client is responsible for calling Pipeline::Stop().
40     virtual void OnError(PipelineStatus status) = 0;
41 
42     // Executed whenever the media reaches the end.
43     virtual void OnEnded() = 0;
44 
45     // Executed when the content duration, container video size, start time,
46     // and whether the content has audio and/or video in supported formats are
47     // known.
48     virtual void OnMetadata(const PipelineMetadata& metadata) = 0;
49 
50     // Executed whenever there are changes in the buffering state of the
51     // pipeline. |reason| indicates the cause of the state change, when known.
52     virtual void OnBufferingStateChange(BufferingState state,
53                                         BufferingStateChangeReason reason) = 0;
54 
55     // Executed whenever the presentation duration changes.
56     virtual void OnDurationChange() = 0;
57 
58     // Executed whenever a text track is added.
59     // The client is expected to create a TextTrack and call |done_cb|.
60     virtual void OnAddTextTrack(const TextTrackConfig& config,
61                                 AddTextTrackDoneCB done_cb) = 0;
62 
63     // Executed whenever the pipeline is waiting because of |reason|.
64     virtual void OnWaiting(WaitingReason reason) = 0;
65 
66     // Executed for the first video frame and whenever natural size changes.
67     virtual void OnVideoNaturalSizeChange(const gfx::Size& size) = 0;
68 
69     // Executed for the first video frame and whenever opacity changes.
70     virtual void OnVideoOpacityChange(bool opaque) = 0;
71 
72     // Executed when the average keyframe distance for the video changes.
73     virtual void OnVideoAverageKeyframeDistanceUpdate() = 0;
74 
75     // Executed whenever DemuxerStream status returns kConfigChange. Initial
76     // configs provided by OnMetadata.
77     virtual void OnAudioConfigChange(const AudioDecoderConfig& config) = 0;
78     virtual void OnVideoConfigChange(const VideoDecoderConfig& config) = 0;
79 
80     // Executed whenever the underlying AudioDecoder or VideoDecoder changes
81     // during playback.
82     virtual void OnAudioDecoderChange(const PipelineDecoderInfo& info) = 0;
83     virtual void OnVideoDecoderChange(const PipelineDecoderInfo& info) = 0;
84 
85     // Executed whenever the video frame rate changes.  |fps| will be unset if
86     // the frame rate is unstable.  The duration used for the frame rate is
87     // based on wall clock time, not media time.
88     virtual void OnVideoFrameRateChange(base::Optional<int> fps) = 0;
89   };
90 
~Pipeline()91   virtual ~Pipeline() {}
92 
93   // StartType provides the option to start the pipeline without a renderer;
94   // pipeline initialization will stop once metadata has been retrieved. The
95   // flags below indicate when suspended start will be invoked.
96   enum class StartType {
97     kNormal,                            // Follow the normal startup path.
98     kSuspendAfterMetadataForAudioOnly,  // Suspend after metadata for audio
99                                         // only.
100     kSuspendAfterMetadata,              // Always suspend after metadata.
101   };
102 
103   // Build a pipeline to using the given |demuxer| to construct a filter chain,
104   // executing |seek_cb| when the initial seek has completed. Methods on
105   // PipelineClient may be called up until Stop() has completed. It is an error
106   // to call this method after the pipeline has already started.
107   //
108   // If a |start_type| is specified which allows suspension, pipeline startup
109   // will halt after metadata has been retrieved and the pipeline will be in a
110   // suspended state.
111   virtual void Start(StartType start_type,
112                      Demuxer* demuxer,
113                      Client* client,
114                      PipelineStatusCallback seek_cb) = 0;
115 
116   // Track switching works similarly for both audio and video. Callbacks are
117   // used to notify when it is time to procede to the next step, since many of
118   // the operations are asynchronous.
119   // ──────────────────── Track Switch Control Flow ───────────────────────
120   //  pipeline | demuxer | demuxer_stream | renderer | video/audio_renderer
121   //           |         |                |          |
122   //           |         |                |          |
123   //           |         |                |          |
124   //     switch track    |                |          |
125   //      --------->     |                |          |
126   //           | disable/enable stream    |          |
127   //           |      ----------->        |          |
128   //    active streams   |                |          |
129   //      <---------     |                |          |
130   //           |        switch track      |          |
131   //      -------------------------------------->    |
132   //           |         |                |    Flush/Restart/Reset
133   //           |         |                |     --------------->
134   //     Notify pipeline of completed track change (via callback)
135   //      <-----------------------------------------------------
136   // ──────────────────── Sometime in the future ──────────────────────────
137   //           |         |                | OnBufferingStateChange
138   //           |         |                |    <----------------
139   //           | OnBufferingStateChange   |          |
140   //     <--------------------------------------     |
141   //           |         |                |          |
142   //           |         |                |          |
143   // |enabled_track_ids| contains track ids of enabled audio tracks.
144   virtual void OnEnabledAudioTracksChanged(
145       const std::vector<MediaTrack::Id>& enabled_track_ids,
146       base::OnceClosure change_completed_cb) = 0;
147 
148   // |selected_track_id| is either empty, which means no video track is
149   // selected, or contains the selected video track id.
150   virtual void OnSelectedVideoTrackChanged(
151       base::Optional<MediaTrack::Id> selected_track_id,
152       base::OnceClosure change_completed_cb) = 0;
153 
154   // Stops the pipeline. This is a blocking function.
155   // If the pipeline is started, it must be stopped before destroying it.
156   // It it permissible to call Stop() at any point during the lifetime of the
157   // pipeline.
158   //
159   // Once Stop is called any outstanding completion callbacks
160   // for Start/Seek/Suspend/Resume or Client methods will *not* be called.
161   virtual void Stop() = 0;
162 
163   // Attempt to seek to the position specified by time.  |seek_cb| will be
164   // executed when the all filters in the pipeline have processed the seek.
165   //
166   // Clients are expected to call GetMediaTime() to check whether the seek
167   // succeeded.
168   //
169   // It is an error to call this method if the pipeline has not started or
170   // has been suspended.
171   virtual void Seek(base::TimeDelta time, PipelineStatusCallback seek_cb) = 0;
172 
173   // Suspends the pipeline, discarding the current renderer.
174   //
175   // While suspended, GetMediaTime() returns the presentation timestamp of the
176   // last rendered frame.
177   //
178   // It is an error to call this method if the pipeline has not started or is
179   // seeking.
180   virtual void Suspend(PipelineStatusCallback suspend_cb) = 0;
181 
182   // Resume the pipeline and seek to |timestamp|.
183   //
184   // It is an error to call this method if the pipeline has not finished
185   // suspending.
186   virtual void Resume(base::TimeDelta timestamp,
187                       PipelineStatusCallback seek_cb) = 0;
188 
189   // Returns true if the pipeline has been started via Start().  If IsRunning()
190   // returns true, it is expected that Stop() will be called before destroying
191   // the pipeline.
192   virtual bool IsRunning() const = 0;
193 
194   // Returns true if the pipeline has been suspended via Suspend() or during
195   // Start(). If IsSuspended() returns true, it is expected that Resume() will
196   // be called to resume playback.
197   virtual bool IsSuspended() const = 0;
198 
199   // Gets the current playback rate of the pipeline.  When the pipeline is
200   // started, the playback rate will be 0.0.  A rate of 1.0 indicates
201   // that the pipeline is rendering the media at the standard rate.  Valid
202   // values for playback rate are >= 0.0.
203   virtual double GetPlaybackRate() const = 0;
204 
205   // Attempt to adjust the playback rate. Setting a playback rate of 0.0 pauses
206   // all rendering of the media.  A rate of 1.0 indicates a normal playback
207   // rate.  Values for the playback rate must be greater than or equal to 0.0.
208   //
209   // TODO(scherkus): What about maximum rate?  Does HTML5 specify a max?
210   virtual void SetPlaybackRate(double playback_rate) = 0;
211 
212   // Gets the current volume setting being used by the audio renderer.  When
213   // the pipeline is started, this value will be 1.0f.  Valid values range
214   // from 0.0f to 1.0f.
215   virtual float GetVolume() const = 0;
216 
217   // Attempt to set the volume of the audio renderer.  Valid values for volume
218   // range from 0.0f (muted) to 1.0f (full volume).  This value affects all
219   // channels proportionately for multi-channel audio streams.
220   virtual void SetVolume(float volume) = 0;
221 
222   // Hint from player about target latency as a guide for the desired amount of
223   // post-decode buffering required to start playback or resume from
224   // seek/underflow. A null option indicates the hint is unset and the pipeline
225   // can choose its own default.
226   virtual void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) = 0;
227 
228   // Sets whether pitch adjustment should be applied when the playback rate is
229   // different than 1.0.
230   virtual void SetPreservesPitch(bool preserves_pitch) = 0;
231 
232   // Returns the current media playback time, which progresses from 0 until
233   // GetMediaDuration().
234   virtual base::TimeDelta GetMediaTime() const = 0;
235 
236   // Get approximate time ranges of buffered media.
237   virtual Ranges<base::TimeDelta> GetBufferedTimeRanges() const = 0;
238 
239   // Get the duration of the media in microseconds.  If the duration has not
240   // been determined yet, then returns 0.
241   virtual base::TimeDelta GetMediaDuration() const = 0;
242 
243   // Return true if loading progress has been made since the last time this
244   // method was called.
245   virtual bool DidLoadingProgress() = 0;
246 
247   // Gets the current pipeline statistics.
248   virtual PipelineStatistics GetStatistics() const = 0;
249 
250   using CdmAttachedCB = base::OnceCallback<void(bool)>;
251   virtual void SetCdm(CdmContext* cdm_context,
252                       CdmAttachedCB cdm_attached_cb) = 0;
253 };
254 
255 }  // namespace media
256 
257 #endif  // MEDIA_BASE_PIPELINE_H_
258