1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_RENDERERS_RENDERER_IMPL_H_
6 #define MEDIA_RENDERERS_RENDERER_IMPL_H_
11 #include "base/cancelable_callback.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/scoped_refptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/synchronization/lock.h"
16 #include "base/task/sequenced_task_runner.h"
17 #include "base/time/clock.h"
18 #include "base/time/default_tick_clock.h"
19 #include "base/time/time.h"
20 #include "media/base/audio_decoder_config.h"
21 #include "media/base/buffering_state.h"
22 #include "media/base/decryptor.h"
23 #include "media/base/demuxer_stream.h"
24 #include "media/base/media_export.h"
25 #include "media/base/pipeline_status.h"
26 #include "media/base/renderer.h"
27 #include "media/base/tuneable.h"
28 #include "media/base/video_decoder_config.h"
29 #include "media/base/waiting.h"
30 #include "ui/gfx/geometry/size.h"
38 class WallClockTimeSource;
40 class MEDIA_EXPORT RendererImpl final : public Renderer {
42 // Renders audio/video streams using |audio_renderer| and |video_renderer|
43 // provided. All methods except for GetMediaTime() run on the |task_runner|.
44 // GetMediaTime() runs on the render main thread because it's part of JS sync
46 RendererImpl(const scoped_refptr<base::SequencedTaskRunner>& task_runner,
47 std::unique_ptr<AudioRenderer> audio_renderer,
48 std::unique_ptr<VideoRenderer> video_renderer);
50 RendererImpl(const RendererImpl&) = delete;
51 RendererImpl& operator=(const RendererImpl&) = delete;
53 ~RendererImpl() final;
55 // Renderer implementation.
56 void Initialize(MediaResource* media_resource,
57 RendererClient* client,
58 PipelineStatusCallback init_cb) final;
59 void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb) final;
60 void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) final;
61 void SetPreservesPitch(bool preserves_pitch) final;
62 void SetWasPlayedWithUserActivation(
63 bool was_played_with_user_activation) final;
64 void Flush(base::OnceClosure flush_cb) final;
65 #if defined(TIZEN_MULTIMEDIA)
66 void Seek(base::TimeDelta time, base::OnceClosure seek_cb) final {}
68 void StartPlayingFrom(base::TimeDelta time) final;
69 void SetPlaybackRate(double playback_rate) final;
70 void SetVolume(float volume) final;
71 base::TimeDelta GetMediaTime() final;
72 void OnSelectedVideoTracksChanged(
73 const std::vector<DemuxerStream*>& enabled_tracks,
74 base::OnceClosure change_completed_cb) final;
75 void OnEnabledAudioTracksChanged(
76 const std::vector<DemuxerStream*>& enabled_tracks,
77 base::OnceClosure change_completed_cb) final;
78 RendererType GetRendererType() final;
80 // Helper functions for testing purposes. Must be called before Initialize().
81 void DisableUnderflowForTesting();
82 void EnableClocklessVideoPlaybackForTesting();
83 void set_time_source_for_testing(TimeSource* time_source) {
84 time_source_ = time_source;
86 void set_video_underflow_threshold_for_testing(base::TimeDelta threshold) {
87 video_underflow_threshold_.set_for_testing(threshold);
91 class RendererClientInternal;
95 STATE_INIT_PENDING_CDM, // Initialization is waiting for the CDM to be set.
96 STATE_INITIALIZING, // Initializing audio/video renderers.
97 STATE_FLUSHING, // Flushing is in progress.
98 STATE_FLUSHED, // After initialization or after flush completed.
99 STATE_PLAYING, // After StartPlayingFrom has been called.
103 bool GetWallClockTimes(const std::vector<base::TimeDelta>& media_timestamps,
104 std::vector<base::TimeTicks>* wall_clock_times);
106 bool HasEncryptedStream();
108 void FinishInitialization(PipelineStatus status);
111 // Helper functions and callbacks for Initialize().
112 void InitializeAudioRenderer();
113 void OnAudioRendererInitializeDone(PipelineStatus status);
114 void InitializeVideoRenderer();
115 void OnVideoRendererInitializeDone(PipelineStatus status);
117 // Helper functions and callbacks for Flush().
118 void FlushInternal();
119 void FlushAudioRenderer();
120 void OnAudioRendererFlushDone();
121 void FlushVideoRenderer();
122 void OnVideoRendererFlushDone();
124 // Reinitialize audio/video renderer during a demuxer stream switching. The
125 // renderer must be flushed first, and when the re-init is completed the
126 // corresponding callback will be invoked to restart playback.
127 // The |stream| parameter specifies the new demuxer stream, and the |time|
128 // parameter specifies the time on media timeline where the switch occured.
129 void ReinitializeAudioRenderer(DemuxerStream* stream,
130 base::TimeDelta time,
131 base::OnceClosure reinitialize_completed_cb);
132 void OnAudioRendererReinitialized(DemuxerStream* stream,
133 base::TimeDelta time,
134 base::OnceClosure reinitialize_completed_cb,
135 PipelineStatus status);
136 void ReinitializeVideoRenderer(DemuxerStream* stream,
137 base::TimeDelta time,
138 base::OnceClosure restart_completed_cb);
139 void OnVideoRendererReinitialized(DemuxerStream* stream,
140 base::TimeDelta time,
141 base::OnceClosure restart_completed_cb,
142 PipelineStatus status);
144 // Restart audio/video renderer playback after a demuxer stream switch or
145 // after a demuxer stream has been disabled and re-enabled. The |stream|
146 // parameter specifies which stream needs to be restarted. The |time|
147 // parameter specifies the position on the media timeline where the playback
148 // needs to be restarted. It is necessary for demuxers with independent
149 // streams (e.g. MSE / ChunkDemuxer) to synchronize data reading between those
151 void RestartAudioRenderer(DemuxerStream* stream,
152 base::TimeDelta time,
153 base::OnceClosure restart_completed_cb);
154 void RestartVideoRenderer(DemuxerStream* stream,
155 base::TimeDelta time,
156 base::OnceClosure restart_completed_cb);
158 // Fix state booleans after the stream switching is finished.
159 void CleanUpTrackChange(base::OnceClosure on_finished,
163 // Callback executed by filters to update statistics.
164 void OnStatisticsUpdate(const PipelineStatistics& stats);
166 // Collection of callback methods and helpers for tracking changes in
167 // buffering state and transition from paused/underflow states and playing
170 // While in the kPlaying state:
171 // - A waiting to non-waiting transition indicates preroll has completed
172 // and StartPlayback() should be called
173 // - A non-waiting to waiting transition indicates underflow has occurred
174 // and PausePlayback() should be called
175 void OnBufferingStateChange(DemuxerStream::Type type,
176 BufferingState new_buffering_state,
177 BufferingStateChangeReason reason);
179 // Handles the buffering notifications that we might get while an audio or a
180 // video stream is being restarted. In those cases we don't want to report
181 // underflows immediately and instead give decoders a chance to catch up with
182 // currently playing stream. Returns true if the buffering nofication has been
183 // handled and no further processing is necessary, returns false to indicate
184 // that we should fall back to the regular OnBufferingStateChange logic.
185 bool HandleRestartedStreamBufferingChanges(
186 DemuxerStream::Type type,
187 BufferingState new_buffering_state);
189 bool WaitingForEnoughData() const;
190 void PausePlayback();
191 void StartPlayback();
193 // Callbacks executed when a renderer has ended.
194 void OnRendererEnded(DemuxerStream::Type type);
195 bool PlaybackHasEnded() const;
196 void RunEndedCallbackIfNeeded();
198 // Callback executed when a runtime error happens.
199 void OnError(PipelineStatus error);
201 // Callback executed when there is a fallback somewhere in the pipeline which
202 // should be recorded for metrics analysis.
203 void OnFallback(PipelineStatus fallback);
205 void OnWaiting(WaitingReason reason);
206 void OnVideoNaturalSizeChange(const gfx::Size& size);
207 void OnAudioConfigChange(const AudioDecoderConfig& config);
208 void OnVideoConfigChange(const VideoDecoderConfig& config);
209 void OnVideoOpacityChange(bool opaque);
210 void OnVideoFrameRateChange(absl::optional<int> fps);
212 void OnStreamRestartCompleted();
216 // Task runner used to execute pipeline tasks.
217 scoped_refptr<base::SequencedTaskRunner> task_runner_;
219 raw_ptr<MediaResource> media_resource_;
220 raw_ptr<RendererClient> client_;
222 // Temporary callback used for Initialize() and Flush().
223 PipelineStatusCallback init_cb_;
224 base::OnceClosure flush_cb_;
226 std::unique_ptr<RendererClientInternal> audio_renderer_client_;
227 std::unique_ptr<RendererClientInternal> video_renderer_client_;
228 std::unique_ptr<AudioRenderer> audio_renderer_;
229 std::unique_ptr<VideoRenderer> video_renderer_;
231 raw_ptr<DemuxerStream> current_audio_stream_;
232 raw_ptr<DemuxerStream> current_video_stream_;
234 // Renderer-provided time source used to control playback.
235 raw_ptr<TimeSource, DanglingUntriaged> time_source_;
236 std::unique_ptr<WallClockTimeSource> wall_clock_time_source_;
238 double playback_rate_;
240 // The time to start playback from after starting/seeking has completed.
241 base::TimeDelta start_time_;
243 BufferingState audio_buffering_state_;
244 BufferingState video_buffering_state_;
246 // Whether we've received the audio/video ended events.
252 raw_ptr<CdmContext> cdm_context_;
254 bool underflow_disabled_for_testing_;
255 bool clockless_video_playback_enabled_for_testing_;
257 // Used to defer underflow for video when audio is present.
258 base::CancelableOnceClosure deferred_video_underflow_cb_;
260 // We cannot use `!deferred_video_underflow_cb_.IsCancelled()` as that changes
261 // when the callback is run, even if not explicitly cancelled.
262 bool has_deferred_buffering_state_change_ = false;
264 // The amount of time to wait before declaring underflow if the video renderer
265 // runs out of data but the audio renderer still has enough.
266 Tuneable<base::TimeDelta> video_underflow_threshold_ = {
267 "MediaVideoUnderflowThreshold", base::Milliseconds(1000),
268 base::Milliseconds(3000), base::Milliseconds(8000)};
270 // Lock used to protect access to the |restarting_audio_| flag and
271 // |restarting_audio_time_|.
272 // TODO(servolk): Get rid of the lock and replace restarting_audio_ with
273 // std::atomic<bool> when atomics are unbanned in Chromium.
274 base::Lock restarting_audio_lock_;
275 bool pending_audio_track_change_ = false;
276 base::TimeDelta restarting_audio_time_ = kNoTimestamp;
278 bool pending_video_track_change_ = false;
280 base::WeakPtr<RendererImpl> weak_this_;
281 base::WeakPtrFactory<RendererImpl> weak_factory_{this};
286 #endif // MEDIA_RENDERERS_RENDERER_IMPL_H_