Upload upstream chromium 120.0.6099.5
[platform/framework/web/chromium-efl.git] / media / renderers / renderer_impl.cc
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.
4
5 #include "media/renderers/renderer_impl.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/command_line.h"
11 #include "base/compiler_specific.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/functional/callback_helpers.h"
15 #include "base/location.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/task/bind_post_task.h"
19 #include "base/task/sequenced_task_runner.h"
20 #include "base/task/single_thread_task_runner.h"
21 #include "base/trace_event/trace_event.h"
22 #include "media/base/audio_decoder_config.h"
23 #include "media/base/audio_renderer.h"
24 #include "media/base/media_log.h"
25 #include "media/base/media_resource.h"
26 #include "media/base/media_switches.h"
27 #include "media/base/renderer_client.h"
28 #include "media/base/time_source.h"
29 #include "media/base/video_decoder_config.h"
30 #include "media/base/video_renderer.h"
31 #include "media/base/wall_clock_time_source.h"
32
33 namespace media {
34
35 class RendererImpl::RendererClientInternal final : public RendererClient {
36  public:
37   RendererClientInternal(DemuxerStream::Type type,
38                          RendererImpl* renderer,
39                          MediaResource* media_resource)
40       : type_(type), renderer_(renderer), media_resource_(media_resource) {
41     DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO));
42   }
43
44   void OnError(PipelineStatus error) override { renderer_->OnError(error); }
45   void OnFallback(PipelineStatus error) override {
46     renderer_->OnFallback(std::move(error).AddHere());
47   }
48   void OnEnded() override { renderer_->OnRendererEnded(type_); }
49   void OnStatisticsUpdate(const PipelineStatistics& stats) override {
50     renderer_->OnStatisticsUpdate(stats);
51   }
52   void OnBufferingStateChange(BufferingState state,
53                               BufferingStateChangeReason reason) override {
54     renderer_->OnBufferingStateChange(type_, state, reason);
55   }
56   void OnWaiting(WaitingReason reason) override {
57     renderer_->OnWaiting(reason);
58   }
59   void OnAudioConfigChange(const AudioDecoderConfig& config) override {
60     renderer_->OnAudioConfigChange(config);
61   }
62   void OnVideoConfigChange(const VideoDecoderConfig& config) override {
63     renderer_->OnVideoConfigChange(config);
64   }
65   void OnVideoNaturalSizeChange(const gfx::Size& size) override {
66     DCHECK(type_ == DemuxerStream::VIDEO);
67     renderer_->OnVideoNaturalSizeChange(size);
68   }
69   void OnVideoOpacityChange(bool opaque) override {
70     DCHECK(type_ == DemuxerStream::VIDEO);
71     renderer_->OnVideoOpacityChange(opaque);
72   }
73   void OnVideoFrameRateChange(absl::optional<int> fps) override {
74     DCHECK(type_ == DemuxerStream::VIDEO);
75     renderer_->OnVideoFrameRateChange(fps);
76   }
77
78   bool IsVideoStreamAvailable() override {
79     return media_resource_->GetFirstStream(::media::DemuxerStream::VIDEO);
80   }
81
82  private:
83   DemuxerStream::Type type_;
84   raw_ptr<RendererImpl> renderer_;
85   raw_ptr<MediaResource> media_resource_;
86 };
87
88 RendererImpl::RendererImpl(
89     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
90     std::unique_ptr<AudioRenderer> audio_renderer,
91     std::unique_ptr<VideoRenderer> video_renderer)
92     : state_(STATE_UNINITIALIZED),
93       task_runner_(task_runner),
94       audio_renderer_(std::move(audio_renderer)),
95       video_renderer_(std::move(video_renderer)),
96       current_audio_stream_(nullptr),
97       current_video_stream_(nullptr),
98       time_source_(nullptr),
99       time_ticking_(false),
100       playback_rate_(0.0),
101       audio_buffering_state_(BUFFERING_HAVE_NOTHING),
102       video_buffering_state_(BUFFERING_HAVE_NOTHING),
103       audio_ended_(false),
104       video_ended_(false),
105       audio_playing_(false),
106       video_playing_(false),
107       cdm_context_(nullptr),
108       underflow_disabled_for_testing_(false),
109       clockless_video_playback_enabled_for_testing_(false),
110       pending_audio_track_change_(false),
111       pending_video_track_change_(false) {
112   weak_this_ = weak_factory_.GetWeakPtr();
113   DVLOG(1) << __func__;
114 }
115
116 RendererImpl::~RendererImpl() {
117   DVLOG(1) << __func__;
118   DCHECK(task_runner_->RunsTasksInCurrentSequence());
119
120   // RendererImpl is being destroyed, so invalidate weak pointers right away to
121   // avoid getting callbacks which might try to access fields that has been
122   // destroyed, e.g. audio_renderer_/video_renderer_ below (crbug.com/668963).
123   weak_factory_.InvalidateWeakPtrs();
124
125   // Tear down in opposite order of construction as |video_renderer_| can still
126   // need |time_source_| (which can be |audio_renderer_|) to be alive.
127   video_renderer_.reset();
128   audio_renderer_.reset();
129
130   if (init_cb_)
131     FinishInitialization(PIPELINE_ERROR_ABORT);
132   else if (flush_cb_)
133     FinishFlush();
134 }
135
136 void RendererImpl::Initialize(MediaResource* media_resource,
137                               RendererClient* client,
138                               PipelineStatusCallback init_cb) {
139   DVLOG(1) << __func__;
140   DCHECK(task_runner_->RunsTasksInCurrentSequence());
141   DCHECK_EQ(state_, STATE_UNINITIALIZED);
142   DCHECK(init_cb);
143   DCHECK(client);
144   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "RendererImpl::Initialize",
145                                     TRACE_ID_LOCAL(this));
146
147   client_ = client;
148   media_resource_ = media_resource;
149   init_cb_ = std::move(init_cb);
150
151   if (HasEncryptedStream() && !cdm_context_) {
152     DVLOG(1) << __func__ << ": Has encrypted stream but CDM is not set.";
153     state_ = STATE_INIT_PENDING_CDM;
154     OnWaiting(WaitingReason::kNoCdm);
155     return;
156   }
157
158   state_ = STATE_INITIALIZING;
159   InitializeAudioRenderer();
160 }
161
162 void RendererImpl::SetCdm(CdmContext* cdm_context,
163                           CdmAttachedCB cdm_attached_cb) {
164   DVLOG(1) << __func__;
165   DCHECK(task_runner_->RunsTasksInCurrentSequence());
166   DCHECK(cdm_context);
167   TRACE_EVENT0("media", "RendererImpl::SetCdm");
168
169   if (cdm_context_) {
170     DVLOG(1) << "Switching CDM not supported.";
171     std::move(cdm_attached_cb).Run(false);
172     return;
173   }
174
175   cdm_context_ = cdm_context;
176   std::move(cdm_attached_cb).Run(true);
177
178   if (state_ != STATE_INIT_PENDING_CDM)
179     return;
180
181   DCHECK(init_cb_);
182   state_ = STATE_INITIALIZING;
183   InitializeAudioRenderer();
184 }
185
186 void RendererImpl::SetLatencyHint(
187     absl::optional<base::TimeDelta> latency_hint) {
188   DVLOG(1) << __func__;
189   DCHECK(!latency_hint || (*latency_hint >= base::TimeDelta()));
190   DCHECK(task_runner_->RunsTasksInCurrentSequence());
191
192   if (video_renderer_)
193     video_renderer_->SetLatencyHint(latency_hint);
194
195   if (audio_renderer_)
196     audio_renderer_->SetLatencyHint(latency_hint);
197 }
198
199 void RendererImpl::SetPreservesPitch(bool preserves_pitch) {
200   DVLOG(1) << __func__;
201   DCHECK(task_runner_->RunsTasksInCurrentSequence());
202
203   if (audio_renderer_)
204     audio_renderer_->SetPreservesPitch(preserves_pitch);
205 }
206
207 void RendererImpl::SetWasPlayedWithUserActivation(
208     bool was_played_with_user_activation) {
209   DVLOG(1) << __func__;
210   DCHECK(task_runner_->RunsTasksInCurrentSequence());
211
212   if (audio_renderer_)
213     audio_renderer_->SetWasPlayedWithUserActivation(
214         was_played_with_user_activation);
215 }
216
217 void RendererImpl::Flush(base::OnceClosure flush_cb) {
218   DVLOG(1) << __func__;
219   DCHECK(task_runner_->RunsTasksInCurrentSequence());
220   DCHECK(!flush_cb_);
221   DCHECK(!(pending_audio_track_change_ || pending_video_track_change_));
222   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", "RendererImpl::Flush",
223                                     TRACE_ID_LOCAL(this));
224
225   if (state_ == STATE_FLUSHED) {
226     flush_cb_ = base::BindPostTaskToCurrentDefault(std::move(flush_cb));
227     FinishFlush();
228     return;
229   }
230
231   if (state_ != STATE_PLAYING) {
232     DCHECK_EQ(state_, STATE_ERROR);
233     return;
234   }
235
236   flush_cb_ = std::move(flush_cb);
237   state_ = STATE_FLUSHING;
238
239   // If a stream restart is pending, this Flush() will complete it. Upon flush
240   // completion any pending actions will be executed as well.
241   FlushInternal();
242 }
243
244 void RendererImpl::StartPlayingFrom(base::TimeDelta time) {
245   DVLOG(1) << __func__;
246   DCHECK(task_runner_->RunsTasksInCurrentSequence());
247   TRACE_EVENT1("media", "RendererImpl::StartPlayingFrom", "time_us",
248                time.InMicroseconds());
249
250   if (state_ != STATE_FLUSHED) {
251     DCHECK_EQ(state_, STATE_ERROR);
252     return;
253   }
254
255   time_source_->SetMediaTime(time);
256
257   state_ = STATE_PLAYING;
258   if (audio_renderer_) {
259     audio_playing_ = true;
260     audio_renderer_->StartPlaying();
261   }
262   if (video_renderer_) {
263     video_playing_ = true;
264     video_renderer_->StartPlayingFrom(time);
265   }
266 }
267
268 void RendererImpl::SetPlaybackRate(double playback_rate) {
269   DVLOG(1) << __func__ << "(" << playback_rate << ")";
270   DCHECK(task_runner_->RunsTasksInCurrentSequence());
271   TRACE_EVENT1("media", "RendererImpl::SetPlaybackRate", "rate", playback_rate);
272
273   // Playback rate changes are only carried out while playing.
274   if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED)
275     return;
276
277   time_source_->SetPlaybackRate(playback_rate);
278
279   const double old_rate = playback_rate_;
280   playback_rate_ = playback_rate;
281   if (!time_ticking_ || !video_renderer_)
282     return;
283
284   if (old_rate == 0 && playback_rate > 0)
285     video_renderer_->OnTimeProgressing();
286   else if (old_rate > 0 && playback_rate == 0)
287     video_renderer_->OnTimeStopped();
288 }
289
290 void RendererImpl::SetVolume(float volume) {
291   DVLOG(1) << __func__;
292   DCHECK(task_runner_->RunsTasksInCurrentSequence());
293
294   if (audio_renderer_)
295     audio_renderer_->SetVolume(volume);
296 }
297
298 base::TimeDelta RendererImpl::GetMediaTime() {
299   // No BelongsToCurrentThread() checking because this can be called from other
300   // threads.
301   {
302     base::AutoLock lock(restarting_audio_lock_);
303     if (pending_audio_track_change_) {
304       DCHECK_NE(kNoTimestamp, restarting_audio_time_);
305       return restarting_audio_time_;
306     }
307   }
308
309   return time_source_->CurrentMediaTime();
310 }
311
312 void RendererImpl::DisableUnderflowForTesting() {
313   DVLOG(1) << __func__;
314   DCHECK(task_runner_->RunsTasksInCurrentSequence());
315   DCHECK_EQ(state_, STATE_UNINITIALIZED);
316
317   underflow_disabled_for_testing_ = true;
318 }
319
320 void RendererImpl::EnableClocklessVideoPlaybackForTesting() {
321   DVLOG(1) << __func__;
322   DCHECK(task_runner_->RunsTasksInCurrentSequence());
323   DCHECK_EQ(state_, STATE_UNINITIALIZED);
324   DCHECK(underflow_disabled_for_testing_)
325       << "Underflow must be disabled for clockless video playback";
326
327   clockless_video_playback_enabled_for_testing_ = true;
328 }
329
330 bool RendererImpl::GetWallClockTimes(
331     const std::vector<base::TimeDelta>& media_timestamps,
332     std::vector<base::TimeTicks>* wall_clock_times) {
333   // No BelongsToCurrentThread() checking because this can be called from other
334   // threads.
335   //
336   // TODO(scherkus): Currently called from VideoRendererImpl's internal thread,
337   // which should go away at some point http://crbug.com/110814
338   if (clockless_video_playback_enabled_for_testing_) {
339     if (media_timestamps.empty()) {
340       *wall_clock_times = std::vector<base::TimeTicks>(1,
341                                                        base::TimeTicks::Now());
342     } else {
343       *wall_clock_times = std::vector<base::TimeTicks>();
344       for (auto const &media_time : media_timestamps) {
345         wall_clock_times->push_back(base::TimeTicks() + media_time);
346       }
347     }
348     return true;
349   }
350
351   return time_source_->GetWallClockTimes(media_timestamps, wall_clock_times);
352 }
353
354 bool RendererImpl::HasEncryptedStream() {
355   std::vector<DemuxerStream*> demuxer_streams =
356       media_resource_->GetAllStreams();
357
358   for (auto* stream : demuxer_streams) {
359     if (stream->type() == DemuxerStream::AUDIO &&
360         stream->audio_decoder_config().is_encrypted())
361       return true;
362     if (stream->type() == DemuxerStream::VIDEO &&
363         stream->video_decoder_config().is_encrypted())
364       return true;
365   }
366
367   return false;
368 }
369
370 void RendererImpl::FinishInitialization(PipelineStatus status) {
371   DCHECK(init_cb_);
372   TRACE_EVENT_NESTABLE_ASYNC_END1("media", "RendererImpl::Initialize",
373                                   TRACE_ID_LOCAL(this), "status",
374                                   PipelineStatusToString(status));
375   std::move(init_cb_).Run(status);
376 }
377
378 void RendererImpl::FinishFlush() {
379   DCHECK(flush_cb_);
380   TRACE_EVENT_NESTABLE_ASYNC_END0("media", "RendererImpl::Flush",
381                                   TRACE_ID_LOCAL(this));
382   std::move(flush_cb_).Run();
383 }
384
385 void RendererImpl::InitializeAudioRenderer() {
386   DVLOG(1) << __func__;
387   DCHECK(task_runner_->RunsTasksInCurrentSequence());
388   DCHECK_EQ(state_, STATE_INITIALIZING);
389   DCHECK(init_cb_);
390
391   // TODO(servolk): Implement proper support for multiple streams. But for now
392   // pick the first enabled stream to preserve the existing behavior.
393   DemuxerStream* audio_stream =
394       media_resource_->GetFirstStream(DemuxerStream::AUDIO);
395
396   if (!audio_stream) {
397     audio_renderer_.reset();
398     task_runner_->PostTask(
399         FROM_HERE, base::BindOnce(&RendererImpl::OnAudioRendererInitializeDone,
400                                   weak_this_, PIPELINE_OK));
401     return;
402   }
403
404   current_audio_stream_ = audio_stream;
405
406   audio_renderer_client_ = std::make_unique<RendererClientInternal>(
407       DemuxerStream::AUDIO, this, media_resource_);
408   // Note: After the initialization of a renderer, error events from it may
409   // happen at any time and all future calls must guard against STATE_ERROR.
410   audio_renderer_->Initialize(
411       audio_stream, cdm_context_, audio_renderer_client_.get(),
412       base::BindOnce(&RendererImpl::OnAudioRendererInitializeDone, weak_this_));
413 }
414
415 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
416   DVLOG(1) << __func__ << ": " << status;
417   DCHECK(task_runner_->RunsTasksInCurrentSequence());
418
419   // OnError() may be fired at any time by the renderers, even if they thought
420   // they initialized successfully (due to delayed output device setup).
421   if (state_ != STATE_INITIALIZING) {
422     DCHECK(!init_cb_);
423     audio_renderer_.reset();
424     return;
425   }
426
427   if (status != PIPELINE_OK) {
428     FinishInitialization(status);
429     return;
430   }
431
432   DCHECK(init_cb_);
433   InitializeVideoRenderer();
434 }
435
436 void RendererImpl::InitializeVideoRenderer() {
437   DVLOG(1) << __func__;
438   DCHECK(task_runner_->RunsTasksInCurrentSequence());
439   DCHECK_EQ(state_, STATE_INITIALIZING);
440   DCHECK(init_cb_);
441
442   // TODO(servolk): Implement proper support for multiple streams. But for now
443   // pick the first enabled stream to preserve the existing behavior.
444   DemuxerStream* video_stream =
445       media_resource_->GetFirstStream(DemuxerStream::VIDEO);
446
447   if (!video_stream) {
448     video_renderer_.reset();
449
450     // Something has disabled all audio and video streams, so fail
451     // initialization.
452     if (!audio_renderer_) {
453       FinishInitialization(PIPELINE_ERROR_COULD_NOT_RENDER);
454       return;
455     }
456
457     task_runner_->PostTask(
458         FROM_HERE, base::BindOnce(&RendererImpl::OnVideoRendererInitializeDone,
459                                   weak_this_, PIPELINE_OK));
460     return;
461   }
462
463   current_video_stream_ = video_stream;
464
465   video_renderer_client_ = std::make_unique<RendererClientInternal>(
466       DemuxerStream::VIDEO, this, media_resource_);
467   video_renderer_->Initialize(
468       video_stream, cdm_context_, video_renderer_client_.get(),
469       base::BindRepeating(&RendererImpl::GetWallClockTimes,
470                           base::Unretained(this)),
471       base::BindOnce(&RendererImpl::OnVideoRendererInitializeDone, weak_this_));
472 }
473
474 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
475   DVLOG(1) << __func__ << ": " << status;
476   DCHECK(task_runner_->RunsTasksInCurrentSequence());
477
478   // OnError() may be fired at any time by the renderers, even if they thought
479   // they initialized successfully (due to delayed output device setup).
480   if (state_ != STATE_INITIALIZING) {
481     DCHECK(!init_cb_);
482     audio_renderer_.reset();
483     video_renderer_.reset();
484     return;
485   }
486
487   DCHECK(init_cb_);
488
489   if (status != PIPELINE_OK) {
490     FinishInitialization(status);
491     return;
492   }
493
494   if (audio_renderer_) {
495     time_source_ = audio_renderer_->GetTimeSource();
496   } else if (!time_source_) {
497     wall_clock_time_source_ = std::make_unique<WallClockTimeSource>();
498     time_source_ = wall_clock_time_source_.get();
499   }
500
501   state_ = STATE_FLUSHED;
502   DCHECK(time_source_);
503   DCHECK(audio_renderer_ || video_renderer_);
504
505   FinishInitialization(PIPELINE_OK);
506 }
507
508 void RendererImpl::FlushInternal() {
509   DVLOG(1) << __func__;
510   DCHECK(task_runner_->RunsTasksInCurrentSequence());
511   DCHECK_EQ(state_, STATE_FLUSHING);
512   DCHECK(flush_cb_);
513
514   if (time_ticking_)
515     PausePlayback();
516
517   FlushAudioRenderer();
518 }
519
520 // TODO(tmathmeyer) Combine this functionality with track switching flushing.
521 void RendererImpl::FlushAudioRenderer() {
522   DVLOG(1) << __func__;
523   DCHECK(task_runner_->RunsTasksInCurrentSequence());
524   DCHECK_EQ(state_, STATE_FLUSHING);
525   DCHECK(flush_cb_);
526
527   if (!audio_renderer_ || !audio_playing_) {
528     OnAudioRendererFlushDone();
529   } else {
530     audio_renderer_->Flush(
531         base::BindOnce(&RendererImpl::OnAudioRendererFlushDone, weak_this_));
532   }
533 }
534
535 void RendererImpl::OnAudioRendererFlushDone() {
536   DVLOG(1) << __func__;
537   DCHECK(task_runner_->RunsTasksInCurrentSequence());
538
539   if (state_ == STATE_ERROR) {
540     DCHECK(!flush_cb_);
541     return;
542   }
543
544   DCHECK_EQ(state_, STATE_FLUSHING);
545   DCHECK(flush_cb_);
546
547   // If we had a deferred video renderer underflow prior to the flush, it should
548   // have been cleared by the audio renderer changing to BUFFERING_HAVE_NOTHING.
549   DCHECK(!has_deferred_buffering_state_change_);
550   DCHECK_EQ(audio_buffering_state_, BUFFERING_HAVE_NOTHING);
551   audio_ended_ = false;
552   audio_playing_ = false;
553
554   FlushVideoRenderer();
555 }
556
557 void RendererImpl::FlushVideoRenderer() {
558   DVLOG(1) << __func__;
559   DCHECK(task_runner_->RunsTasksInCurrentSequence());
560   DCHECK_EQ(state_, STATE_FLUSHING);
561   DCHECK(flush_cb_);
562
563   if (!video_renderer_ || !video_playing_) {
564     OnVideoRendererFlushDone();
565   } else {
566     video_renderer_->Flush(
567         base::BindOnce(&RendererImpl::OnVideoRendererFlushDone, weak_this_));
568   }
569 }
570
571 void RendererImpl::OnVideoRendererFlushDone() {
572   DVLOG(1) << __func__;
573   DCHECK(task_runner_->RunsTasksInCurrentSequence());
574
575   if (state_ == STATE_ERROR) {
576     DCHECK(!flush_cb_);
577     return;
578   }
579
580   DCHECK_EQ(state_, STATE_FLUSHING);
581   DCHECK(flush_cb_);
582
583   DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING);
584   video_ended_ = false;
585   video_playing_ = false;
586   state_ = STATE_FLUSHED;
587   FinishFlush();
588 }
589
590 void RendererImpl::ReinitializeAudioRenderer(
591     DemuxerStream* stream,
592     base::TimeDelta time,
593     base::OnceClosure reinitialize_completed_cb) {
594   DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
595   DCHECK(task_runner_->RunsTasksInCurrentSequence());
596   DCHECK_NE(stream, current_audio_stream_);
597
598   current_audio_stream_ = stream;
599   audio_renderer_->Initialize(
600       stream, cdm_context_, audio_renderer_client_.get(),
601       base::BindOnce(&RendererImpl::OnAudioRendererReinitialized, weak_this_,
602                      stream, time, std::move(reinitialize_completed_cb)));
603 }
604
605 void RendererImpl::OnAudioRendererReinitialized(
606     DemuxerStream* stream,
607     base::TimeDelta time,
608     base::OnceClosure reinitialize_completed_cb,
609     PipelineStatus status) {
610   DVLOG(2) << __func__ << ": status=" << status;
611   DCHECK_EQ(stream, current_audio_stream_);
612
613   if (status != PIPELINE_OK) {
614     std::move(reinitialize_completed_cb).Run();
615     OnError(status);
616     return;
617   }
618   RestartAudioRenderer(stream, time, std::move(reinitialize_completed_cb));
619 }
620
621 void RendererImpl::ReinitializeVideoRenderer(
622     DemuxerStream* stream,
623     base::TimeDelta time,
624     base::OnceClosure reinitialize_completed_cb) {
625   DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
626   DCHECK(task_runner_->RunsTasksInCurrentSequence());
627   DCHECK_NE(stream, current_video_stream_);
628
629   current_video_stream_ = stream;
630   video_renderer_->OnTimeStopped();
631   video_renderer_->Initialize(
632       stream, cdm_context_, video_renderer_client_.get(),
633       base::BindRepeating(&RendererImpl::GetWallClockTimes,
634                           base::Unretained(this)),
635       base::BindOnce(&RendererImpl::OnVideoRendererReinitialized, weak_this_,
636                      stream, time, std::move(reinitialize_completed_cb)));
637 }
638
639 void RendererImpl::OnVideoRendererReinitialized(
640     DemuxerStream* stream,
641     base::TimeDelta time,
642     base::OnceClosure reinitialize_completed_cb,
643     PipelineStatus status) {
644   DVLOG(2) << __func__ << ": status=" << status;
645   DCHECK_EQ(stream, current_video_stream_);
646
647   if (status != PIPELINE_OK) {
648     std::move(reinitialize_completed_cb).Run();
649     OnError(status);
650     return;
651   }
652   RestartVideoRenderer(stream, time, std::move(reinitialize_completed_cb));
653 }
654
655 void RendererImpl::RestartAudioRenderer(
656     DemuxerStream* stream,
657     base::TimeDelta time,
658     base::OnceClosure restart_completed_cb) {
659   DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
660   DCHECK(task_runner_->RunsTasksInCurrentSequence());
661   DCHECK(audio_renderer_);
662   DCHECK_EQ(stream, current_audio_stream_);
663   DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED ||
664          state_ == STATE_FLUSHING);
665
666   if (state_ == STATE_FLUSHED) {
667     // If we are in the FLUSHED state, then we are done. The audio renderer will
668     // be restarted by a subsequent RendererImpl::StartPlayingFrom call.
669     std::move(restart_completed_cb).Run();
670     return;
671   }
672
673   {
674     base::AutoLock lock(restarting_audio_lock_);
675     audio_playing_ = true;
676     pending_audio_track_change_ = false;
677   }
678   audio_renderer_->StartPlaying();
679   std::move(restart_completed_cb).Run();
680 }
681
682 void RendererImpl::RestartVideoRenderer(
683     DemuxerStream* stream,
684     base::TimeDelta time,
685     base::OnceClosure restart_completed_cb) {
686   DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
687   DCHECK(task_runner_->RunsTasksInCurrentSequence());
688   DCHECK(video_renderer_);
689   DCHECK_EQ(stream, current_video_stream_);
690   DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED ||
691          state_ == STATE_FLUSHING);
692
693   if (state_ == STATE_FLUSHED) {
694     // If we are in the FLUSHED state, then we are done. The video renderer will
695     // be restarted by a subsequent RendererImpl::StartPlayingFrom call.
696     std::move(restart_completed_cb).Run();
697     return;
698   }
699
700   video_playing_ = true;
701   pending_video_track_change_ = false;
702   video_renderer_->StartPlayingFrom(time);
703   std::move(restart_completed_cb).Run();
704 }
705
706 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
707   DCHECK(task_runner_->RunsTasksInCurrentSequence());
708   client_->OnStatisticsUpdate(stats);
709 }
710
711 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type,
712                                           BufferingState new_buffering_state,
713                                           BufferingStateChangeReason reason) {
714   DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
715   BufferingState* buffering_state = type == DemuxerStream::AUDIO
716                                         ? &audio_buffering_state_
717                                         : &video_buffering_state_;
718
719   const auto* type_string = DemuxerStream::GetTypeName(type);
720   DVLOG(1) << __func__ << " " << type_string << " "
721            << BufferingStateToString(*buffering_state) << " -> "
722            << BufferingStateToString(new_buffering_state, reason);
723   DCHECK(task_runner_->RunsTasksInCurrentSequence());
724   TRACE_EVENT2("media", "RendererImpl::OnBufferingStateChange", "type",
725                type_string, "state",
726                BufferingStateToString(new_buffering_state, reason));
727
728   bool was_waiting_for_enough_data = WaitingForEnoughData();
729
730   if (new_buffering_state == BUFFERING_HAVE_NOTHING) {
731     if ((pending_audio_track_change_ && type == DemuxerStream::AUDIO) ||
732         (pending_video_track_change_ && type == DemuxerStream::VIDEO)) {
733       // Don't pass up a nothing event if it was triggered by a track change.
734       // This would cause the renderer to effectively lie about underflow state.
735       // Even though this might cause an immediate video underflow due to
736       // changing an audio track, all playing is paused when audio is disabled.
737       *buffering_state = new_buffering_state;
738       return;
739     }
740   }
741
742   // When audio is present and has enough data, defer video underflow callbacks
743   // for some time to avoid unnecessary glitches in audio; see
744   // http://crbug.com/144683#c53.
745   if (audio_renderer_ && type == DemuxerStream::VIDEO &&
746       state_ == STATE_PLAYING) {
747     if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
748         audio_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
749         new_buffering_state == BUFFERING_HAVE_NOTHING &&
750         !has_deferred_buffering_state_change_) {
751       DVLOG(4) << __func__ << " Deferring HAVE_NOTHING for video stream.";
752       deferred_video_underflow_cb_.Reset(
753           base::BindOnce(&RendererImpl::OnBufferingStateChange, weak_this_,
754                          type, new_buffering_state, reason));
755       has_deferred_buffering_state_change_ = true;
756       task_runner_->PostDelayedTask(FROM_HERE,
757                                     deferred_video_underflow_cb_.callback(),
758                                     video_underflow_threshold_.value());
759       return;
760     }
761
762     DVLOG(4) << "deferred_video_underflow_cb_.Cancel()";
763     deferred_video_underflow_cb_.Cancel();
764     has_deferred_buffering_state_change_ = false;
765   } else if (has_deferred_buffering_state_change_ &&
766              type == DemuxerStream::AUDIO &&
767              new_buffering_state == BUFFERING_HAVE_NOTHING) {
768     // If audio underflows while we have a deferred video underflow in progress
769     // we want to mark video as underflowed immediately and cancel the deferral.
770     deferred_video_underflow_cb_.Cancel();
771     has_deferred_buffering_state_change_ = false;
772     video_buffering_state_ = BUFFERING_HAVE_NOTHING;
773   }
774
775   *buffering_state = new_buffering_state;
776
777   // Disable underflow by ignoring updates that renderers have ran out of data.
778   if (state_ == STATE_PLAYING && underflow_disabled_for_testing_ &&
779       time_ticking_) {
780     DVLOG(1) << "Update ignored because underflow is disabled for testing.";
781     return;
782   }
783
784   // Renderer underflowed.
785   if (!was_waiting_for_enough_data && WaitingForEnoughData()) {
786     PausePlayback();
787     client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING, reason);
788     return;
789   }
790
791   // Renderer prerolled.
792   if (was_waiting_for_enough_data && !WaitingForEnoughData()) {
793     // Prevent condition where audio or video is sputtering and flipping back
794     // and forth between NOTHING and ENOUGH mixing with a track change, causing
795     // a StartPlayback to be called while the audio renderer is being flushed.
796     if (!pending_audio_track_change_ && !pending_video_track_change_) {
797       StartPlayback();
798       client_->OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, reason);
799       return;
800     }
801   }
802 }
803
804 bool RendererImpl::WaitingForEnoughData() const {
805   DCHECK(task_runner_->RunsTasksInCurrentSequence());
806   if (state_ != STATE_PLAYING)
807     return false;
808   if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH)
809     return true;
810   if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH)
811     return true;
812   return false;
813 }
814
815 void RendererImpl::PausePlayback() {
816   DVLOG(1) << __func__;
817   DCHECK(task_runner_->RunsTasksInCurrentSequence());
818   TRACE_EVENT0("media", "RendererImpl::PausePlayback");
819
820   switch (state_) {
821     case STATE_PLAYING:
822       DCHECK(PlaybackHasEnded() || WaitingForEnoughData() ||
823              pending_audio_track_change_)
824           << "Playback should only pause due to ending or underflowing or"
825              " when restarting audio stream";
826
827       break;
828
829     case STATE_FLUSHING:
830     case STATE_FLUSHED:
831       // It's OK to pause playback when flushing.
832       break;
833
834     case STATE_UNINITIALIZED:
835     case STATE_INIT_PENDING_CDM:
836     case STATE_INITIALIZING:
837       NOTREACHED() << "Invalid state: " << state_;
838       break;
839
840     case STATE_ERROR:
841       // An error state may occur at any time.
842       break;
843   }
844   if (time_ticking_) {
845     time_ticking_ = false;
846     time_source_->StopTicking();
847   }
848
849   if (playback_rate_ > 0 && video_renderer_)
850     video_renderer_->OnTimeStopped();
851 }
852
853 void RendererImpl::StartPlayback() {
854   DVLOG(1) << __func__;
855   DCHECK(task_runner_->RunsTasksInCurrentSequence());
856   DCHECK_EQ(state_, STATE_PLAYING);
857   DCHECK(!WaitingForEnoughData());
858   TRACE_EVENT0("media", "RendererImpl::StartPlayback");
859
860   if (!time_ticking_) {
861     time_ticking_ = true;
862     audio_playing_ = true;
863     time_source_->StartTicking();
864   }
865   if (playback_rate_ > 0 && video_renderer_) {
866     video_playing_ = true;
867     video_renderer_->OnTimeProgressing();
868   }
869 }
870
871 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) {
872   const auto* type_string = DemuxerStream::GetTypeName(type);
873   DVLOG(1) << __func__ << ": " << type_string;
874   DCHECK(task_runner_->RunsTasksInCurrentSequence());
875   DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
876   TRACE_EVENT1("media", "RendererImpl::OnRendererEnded", "type", type_string);
877
878   // If all streams are ended, do not propagate a redundant ended event.
879   if (state_ != STATE_PLAYING || PlaybackHasEnded())
880     return;
881
882   if (type == DemuxerStream::AUDIO) {
883     DCHECK(audio_renderer_);
884     audio_ended_ = true;
885   } else {
886     DCHECK(video_renderer_);
887     video_ended_ = true;
888     video_renderer_->OnTimeStopped();
889   }
890
891   RunEndedCallbackIfNeeded();
892 }
893
894 bool RendererImpl::PlaybackHasEnded() const {
895   DCHECK(task_runner_->RunsTasksInCurrentSequence());
896
897   if (audio_renderer_ && !audio_ended_)
898     return false;
899
900   if (video_renderer_ && !video_ended_)
901     return false;
902
903   return true;
904 }
905
906 void RendererImpl::RunEndedCallbackIfNeeded() {
907   DVLOG(1) << __func__;
908   DCHECK(task_runner_->RunsTasksInCurrentSequence());
909
910   if (!PlaybackHasEnded())
911     return;
912
913   if (time_ticking_)
914     PausePlayback();
915
916   client_->OnEnded();
917 }
918
919 void RendererImpl::OnFallback(PipelineStatus fallback) {
920   client_->OnFallback(std::move(fallback).AddHere());
921 }
922
923 void RendererImpl::OnError(PipelineStatus error) {
924   DVLOG(1) << __func__ << "(" << error << ")";
925   DCHECK(task_runner_->RunsTasksInCurrentSequence());
926   DCHECK(error != PIPELINE_OK) << "PIPELINE_OK isn't an error!";
927   TRACE_EVENT1("media", "RendererImpl::OnError", "error",
928                PipelineStatusToString(error));
929
930   // An error has already been delivered.
931   if (state_ == STATE_ERROR)
932     return;
933
934   const State old_state = state_;
935   state_ = STATE_ERROR;
936
937   if (init_cb_) {
938     DCHECK(old_state == STATE_INITIALIZING ||
939            old_state == STATE_INIT_PENDING_CDM);
940     FinishInitialization(error);
941     return;
942   }
943
944   // After OnError() returns, the pipeline may destroy |this|.
945   client_->OnError(error);
946
947   if (flush_cb_)
948     FinishFlush();
949 }
950
951 void RendererImpl::OnWaiting(WaitingReason reason) {
952   DCHECK(task_runner_->RunsTasksInCurrentSequence());
953   client_->OnWaiting(reason);
954 }
955
956 void RendererImpl::OnAudioConfigChange(const AudioDecoderConfig& config) {
957   DCHECK(task_runner_->RunsTasksInCurrentSequence());
958   client_->OnAudioConfigChange(config);
959 }
960
961 void RendererImpl::OnVideoConfigChange(const VideoDecoderConfig& config) {
962   DCHECK(task_runner_->RunsTasksInCurrentSequence());
963   client_->OnVideoConfigChange(config);
964 }
965
966 void RendererImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
967   DCHECK(task_runner_->RunsTasksInCurrentSequence());
968   client_->OnVideoNaturalSizeChange(size);
969 }
970
971 void RendererImpl::OnVideoOpacityChange(bool opaque) {
972   DCHECK(task_runner_->RunsTasksInCurrentSequence());
973   client_->OnVideoOpacityChange(opaque);
974 }
975
976 void RendererImpl::OnVideoFrameRateChange(absl::optional<int> fps) {
977   DCHECK(task_runner_->RunsTasksInCurrentSequence());
978   client_->OnVideoFrameRateChange(fps);
979 }
980
981 void RendererImpl::CleanUpTrackChange(base::OnceClosure on_finished,
982                                       bool* ended,
983                                       bool* playing) {
984   *playing = false;
985   // If either stream is alive (i.e. hasn't reached ended state), ended can be
986   // set to false. If both streams are dead, keep ended=true.
987   if ((audio_renderer_ && !audio_ended_) || (video_renderer_ && !video_ended_))
988     *ended = false;
989   std::move(on_finished).Run();
990 }
991
992 void RendererImpl::OnSelectedVideoTracksChanged(
993     const std::vector<DemuxerStream*>& enabled_tracks,
994     base::OnceClosure change_completed_cb) {
995   DCHECK(task_runner_->RunsTasksInCurrentSequence());
996   TRACE_EVENT0("media", "RendererImpl::OnSelectedVideoTracksChanged");
997
998   DCHECK_LT(enabled_tracks.size(), 2u);
999   DemuxerStream* stream = enabled_tracks.empty() ? nullptr : enabled_tracks[0];
1000
1001   if (!stream && !video_playing_) {
1002     std::move(change_completed_cb).Run();
1003     return;
1004   }
1005
1006   // 'fixing' the stream -> restarting if its the same stream,
1007   //                        reinitializing if it is different.
1008   base::OnceClosure fix_stream_cb;
1009   if (stream && stream != current_video_stream_) {
1010     fix_stream_cb =
1011         base::BindOnce(&RendererImpl::ReinitializeVideoRenderer, weak_this_,
1012                        stream, GetMediaTime(), std::move(change_completed_cb));
1013   } else {
1014     fix_stream_cb = base::BindOnce(
1015         &RendererImpl::RestartVideoRenderer, weak_this_, current_video_stream_,
1016         GetMediaTime(), std::move(change_completed_cb));
1017   }
1018
1019   pending_video_track_change_ = true;
1020   video_renderer_->Flush(base::BindOnce(&RendererImpl::CleanUpTrackChange,
1021                                         weak_this_, std::move(fix_stream_cb),
1022                                         &video_ended_, &video_playing_));
1023 }
1024
1025 void RendererImpl::OnEnabledAudioTracksChanged(
1026     const std::vector<DemuxerStream*>& enabled_tracks,
1027     base::OnceClosure change_completed_cb) {
1028   DCHECK(task_runner_->RunsTasksInCurrentSequence());
1029   TRACE_EVENT0("media", "RendererImpl::OnEnabledAudioTracksChanged");
1030
1031   DCHECK_LT(enabled_tracks.size(), 2u);
1032   DemuxerStream* stream = enabled_tracks.empty() ? nullptr : enabled_tracks[0];
1033
1034   if (!stream && !audio_playing_) {
1035     std::move(change_completed_cb).Run();
1036     return;
1037   }
1038
1039   // 'fixing' the stream -> restarting if its the same stream,
1040   //                        reinitializing if it is different.
1041   base::OnceClosure fix_stream_cb;
1042
1043   if (stream && stream != current_audio_stream_) {
1044     fix_stream_cb =
1045         base::BindOnce(&RendererImpl::ReinitializeAudioRenderer, weak_this_,
1046                        stream, GetMediaTime(), std::move(change_completed_cb));
1047   } else {
1048     fix_stream_cb = base::BindOnce(
1049         &RendererImpl::RestartAudioRenderer, weak_this_, current_audio_stream_,
1050         GetMediaTime(), std::move(change_completed_cb));
1051   }
1052
1053   {
1054     base::AutoLock lock(restarting_audio_lock_);
1055     pending_audio_track_change_ = true;
1056     restarting_audio_time_ = time_source_->CurrentMediaTime();
1057   }
1058
1059   if (audio_playing_)
1060     PausePlayback();
1061
1062   audio_renderer_->Flush(base::BindOnce(&RendererImpl::CleanUpTrackChange,
1063                                         weak_this_, std::move(fix_stream_cb),
1064                                         &audio_ended_, &audio_playing_));
1065 }
1066
1067 RendererType RendererImpl::GetRendererType() {
1068   return RendererType::kRendererImpl;
1069 }
1070
1071 }  // namespace media