pipeline_controller.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright 2016 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. #ifndef MEDIA_FILTERS_PIPELINE_CONTROLLER_H_
  5. #define MEDIA_FILTERS_PIPELINE_CONTROLLER_H_
  6. #include "base/callback.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "base/threading/thread_checker.h"
  10. #include "base/time/time.h"
  11. #include "media/base/media_export.h"
  12. #include "media/base/pipeline.h"
  13. #include "third_party/abseil-cpp/absl/types/optional.h"
  14. namespace media {
  15. class CdmContext;
  16. class Demuxer;
  17. // PipelineController wraps a Pipeline to expose the one-at-a-time operations
  18. // (Seek(), Suspend(), and Resume()) with a simpler API. Internally it tracks
  19. // pending operations and dispatches them when possible. Duplicate requests
  20. // (such as seeking twice to the same time) may be elided.
  21. //
  22. // TODO(sandersd/tguilbert):
  23. // - Expose an operation that replaces the Renderer (via Suspend/Resume).
  24. // - Expose an operation that replaces the Demuxer (via Start/Stop). This will
  25. // also implicitly replace the Renderer.
  26. // - Block invalid calls after an error occurs.
  27. class MEDIA_EXPORT PipelineController {
  28. public:
  29. enum class State {
  30. STOPPED,
  31. STARTING,
  32. PLAYING,
  33. PLAYING_OR_SUSPENDED,
  34. SEEKING,
  35. SWITCHING_TRACKS,
  36. SUSPENDING,
  37. SUSPENDED,
  38. RESUMING,
  39. };
  40. using SeekedCB = base::RepeatingCallback<void(bool time_updated)>;
  41. using SuspendedCB = base::RepeatingClosure;
  42. using BeforeResumeCB = base::RepeatingClosure;
  43. using ResumedCB = base::RepeatingClosure;
  44. using CdmAttachedCB = base::OnceCallback<void(bool)>;
  45. // Construct a PipelineController wrapping |pipeline_|.
  46. // The callbacks are:
  47. // - |seeked_cb| is called upon reaching a stable state if a seek occurred.
  48. // - |suspended_cb| is called immediately after suspending.
  49. // - |before_resume_cb| is called immediately before resuming.
  50. // - |resumed_cb| is called immediately after resuming.
  51. // - |error_cb| is called if any operation on |pipeline_| does not result
  52. // in PIPELINE_OK or its error callback is called.
  53. PipelineController(std::unique_ptr<Pipeline> pipeline,
  54. SeekedCB seeked_cb,
  55. SuspendedCB suspended_cb,
  56. BeforeResumeCB before_resume_cb,
  57. ResumedCB resumed_cb,
  58. PipelineStatusCB error_cb);
  59. PipelineController(const PipelineController&) = delete;
  60. PipelineController& operator=(const PipelineController&) = delete;
  61. ~PipelineController();
  62. // Start |pipeline_|. |demuxer| will be retained and StartWaitingForSeek()/
  63. // CancelPendingSeek() will be issued to it as necessary.
  64. //
  65. // When |is_streaming| is true, Resume() will always start at the
  66. // beginning of the stream, rather than attempting to seek to the current
  67. // time.
  68. //
  69. // When |is_static| is true, seeks to the current time may be elided.
  70. // Otherwise it is assumed that the media data may have changed.
  71. //
  72. // The remaining parameters are just passed directly to pipeline_.Start().
  73. void Start(Pipeline::StartType start_type,
  74. Demuxer* demuxer,
  75. Pipeline::Client* client,
  76. bool is_streaming,
  77. bool is_static);
  78. // Request a seek to |time|. If |time_updated| is true, then the eventual
  79. // |seeked_cb| callback will also have |time_updated| set to true; it
  80. // indicates that the seek was requested by Blink and a time update is
  81. // expected so that Blink can fire the seeked event.
  82. //
  83. // Note: This will not resume the pipeline if it is in the suspended state; a
  84. // call to Resume() is required. |seeked_cb_| will not be called until the
  85. // later Resume() completes. The intention is to avoid unnecessary wake-ups
  86. // for suspended players.
  87. void Seek(base::TimeDelta time, bool time_updated);
  88. // Request that |pipeline_| be suspended. This is a no-op if |pipeline_| has
  89. // been suspended.
  90. void Suspend();
  91. // Request that |pipeline_| be resumed. This is a no-op if |pipeline_| has not
  92. // been suspended.
  93. void Resume();
  94. // Called when a decoder in the pipeline lost its state. This requires a seek
  95. // so that the decoder can start from a new key frame.
  96. void OnDecoderStateLost();
  97. // Returns true if the current state is stable. This means that |state_| is
  98. // PLAYING and there are no pending operations. Requests are processed
  99. // immediately when the state is stable, otherwise they are queued.
  100. //
  101. // Exceptions to the above:
  102. // - Start() is processed immediately while in the CREATED state.
  103. // - Resume() is processed immediately while in the SUSPENDED state.
  104. bool IsStable();
  105. // Returns true if the current target state is suspended.
  106. bool IsSuspended();
  107. // Returns true if Seek() was called and there is a seek operation which has
  108. // not yet completed.
  109. bool IsPendingSeek();
  110. // Returns true if |pipeline_| is suspended.
  111. bool IsPipelineSuspended();
  112. // Subset of the Pipeline interface directly exposing |pipeline_|.
  113. void Stop();
  114. bool IsPipelineRunning() const;
  115. double GetPlaybackRate() const;
  116. void SetPlaybackRate(double playback_rate);
  117. float GetVolume() const;
  118. void SetVolume(float volume);
  119. void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint);
  120. void SetPreservesPitch(bool preserves_pitch);
  121. void SetWasPlayedWithUserActivation(bool was_played_with_user_activation);
  122. base::TimeDelta GetMediaTime() const;
  123. Ranges<base::TimeDelta> GetBufferedTimeRanges() const;
  124. base::TimeDelta GetMediaDuration() const;
  125. bool DidLoadingProgress();
  126. PipelineStatistics GetStatistics() const;
  127. void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb);
  128. void OnEnabledAudioTracksChanged(
  129. const std::vector<MediaTrack::Id>& enabled_track_ids);
  130. void OnSelectedVideoTrackChanged(
  131. absl::optional<MediaTrack::Id> selected_track_id);
  132. void OnExternalVideoFrameRequest();
  133. // Used to fire the OnTrackChangeComplete function which is captured in a
  134. // OnceCallback, and doesn't play nicely with gmock.
  135. void FireOnTrackChangeCompleteForTesting(State set_to);
  136. private:
  137. // Attempts to make progress from the current state to the target state.
  138. void Dispatch();
  139. // PipelineStaus callback that also carries the target state.
  140. void OnPipelineStatus(State state, PipelineStatus pipeline_status);
  141. void OnTrackChangeComplete();
  142. // The Pipeline we are managing state for.
  143. std::unique_ptr<Pipeline> pipeline_;
  144. // Called after seeks (which includes Start()) upon reaching a stable state.
  145. // Multiple seeks result in only one callback if no stable state occurs
  146. // between them.
  147. const SeekedCB seeked_cb_;
  148. // Called immediately when |pipeline_| completes a suspend operation.
  149. const SuspendedCB suspended_cb_;
  150. // Called immediately before |pipeline_| starts a resume operation.
  151. const BeforeResumeCB before_resume_cb_;
  152. // Called immediately when |pipeline_| completes a resume operation.
  153. const ResumedCB resumed_cb_;
  154. // Called immediately when any operation on |pipeline_| results in an error.
  155. const PipelineStatusCB error_cb_;
  156. // State for handling StartWaitingForSeek()/CancelPendingSeek().
  157. raw_ptr<Demuxer> demuxer_ = nullptr;
  158. bool waiting_for_seek_ = false;
  159. // When true, Resume() will start at time zero instead of seeking to the
  160. // current time.
  161. bool is_streaming_ = false;
  162. // When true, seeking to the current time may be elided.
  163. bool is_static_ = true;
  164. // Tracks the current state of |pipeline_|.
  165. State state_ = State::STOPPED;
  166. // The previous state of |pipeline_| if it's currently undergoing a track
  167. // change.
  168. State previous_track_change_state_ = State::STOPPED;
  169. // Indicates that a seek has occurred. When set, a seeked callback will be
  170. // issued at the next stable state.
  171. bool pending_seeked_cb_ = false;
  172. // Indicates that a seek has occurred from an explicit call to Seek() or
  173. // OnDecoderStateLost().
  174. bool pending_seek_except_start_ = false;
  175. // Indicates that time has been changed by a seek, which will be reported at
  176. // the next seeked callback.
  177. bool pending_time_updated_ = false;
  178. // The target time of the active seek; valid while SEEKING or RESUMING.
  179. base::TimeDelta seek_time_;
  180. // Target state which we will work to achieve.
  181. bool pending_seek_ = false;
  182. bool pending_suspend_ = false;
  183. bool pending_resume_ = false;
  184. bool pending_audio_track_change_ = false;
  185. bool pending_video_track_change_ = false;
  186. // |pending_seek_time_| is only valid when |pending_seek_| is true.
  187. // |pending_track_change_type_| is only valid when |pending_track_change_|.
  188. // |pending_audio_track_change_ids_| is only valid when
  189. // |pending_audio_track_change_|.
  190. // |pending_video_track_change_id_| is only valid when
  191. // |pending_video_track_change_|.
  192. base::TimeDelta pending_seek_time_;
  193. std::vector<MediaTrack::Id> pending_audio_track_change_ids_;
  194. absl::optional<MediaTrack::Id> pending_video_track_change_id_;
  195. // Set to true during Start(). Indicates that |seeked_cb_| must be fired once
  196. // we've completed startup.
  197. bool pending_startup_ = false;
  198. base::ThreadChecker thread_checker_;
  199. base::WeakPtrFactory<PipelineController> weak_factory_{this};
  200. };
  201. } // namespace media
  202. #endif // MEDIA_FILTERS_PIPELINE_CONTROLLER_H_