Upload upstream chromium 120.0.6099.5
[platform/framework/web/chromium-efl.git] / media / renderers / renderer_impl_unittest.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 <stdint.h>
6
7 #include <memory>
8 #include <vector>
9
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_helpers.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/raw_ptr_exclusion.h"
14 #include "base/run_loop.h"
15 #include "base/task/single_thread_task_runner.h"
16 #include "base/test/gmock_callback_support.h"
17 #include "base/test/gmock_move_support.h"
18 #include "base/test/simple_test_tick_clock.h"
19 #include "base/test/task_environment.h"
20 #include "base/time/time.h"
21 #include "media/base/mock_filters.h"
22 #include "media/base/test_helpers.h"
23 #include "media/renderers/renderer_impl.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/abseil-cpp/absl/types/optional.h"
26
27 using ::base::test::RunCallback;
28 using ::base::test::RunClosure;
29 using ::base::test::RunOnceCallback;
30 using ::base::test::RunOnceClosure;
31 using ::testing::_;
32 using ::testing::DoAll;
33 using ::testing::InSequence;
34 using ::testing::Mock;
35 using ::testing::Return;
36 using ::testing::SaveArg;
37 using ::testing::StrictMock;
38 using ::testing::WithArg;
39 using ::testing::WithArgs;
40
41 namespace media {
42
43 const int64_t kStartPlayingTimeInMs = 100;
44
45 ACTION_P2(SetBool, var, value) {
46   *var = value;
47 }
48
49 ACTION_P3(SetBufferingState, renderer_client, buffering_state, reason) {
50   (*renderer_client)->OnBufferingStateChange(buffering_state, reason);
51 }
52
53 ACTION_P2(SetError, renderer_client, error) {
54   (*renderer_client)->OnError(error);
55 }
56
57 ACTION(PostCallback) {
58   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, arg0);
59 }
60
61 ACTION(PostQuitWhenIdle) {
62   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
63       FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
64 }
65
66 class RendererImplTest : public ::testing::Test {
67  public:
68   class CallbackHelper : public MockRendererClient {
69    public:
70     CallbackHelper() = default;
71
72     CallbackHelper(const CallbackHelper&) = delete;
73     CallbackHelper& operator=(const CallbackHelper&) = delete;
74
75     virtual ~CallbackHelper() = default;
76
77     // Completion callbacks.
78     MOCK_METHOD1(OnInitialize, void(PipelineStatus));
79     MOCK_METHOD0(OnFlushed, void());
80     MOCK_METHOD1(OnCdmAttached, void(bool));
81     MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration));
82     MOCK_METHOD0(OnVideoTrackChangeComplete, void());
83     MOCK_METHOD0(OnAudioTrackChangeComplete, void());
84   };
85
86   RendererImplTest()
87       : demuxer_(new StrictMock<MockDemuxer>()),
88         video_renderer_(new StrictMock<MockVideoRenderer>()),
89         audio_renderer_(new StrictMock<MockAudioRenderer>()),
90         renderer_impl_(
91             new RendererImpl(task_environment_.GetMainThreadTaskRunner(),
92                              std::unique_ptr<AudioRenderer>(audio_renderer_),
93                              std::unique_ptr<VideoRenderer>(video_renderer_))),
94         cdm_context_(new StrictMock<MockCdmContext>()),
95         video_renderer_client_(nullptr),
96         audio_renderer_client_(nullptr),
97         initialization_status_(PIPELINE_OK) {
98     // CreateAudioStream() and CreateVideoStream() overrides expectations for
99     // expected non-NULL streams.
100     EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
101   }
102
103   RendererImplTest(const RendererImplTest&) = delete;
104   RendererImplTest& operator=(const RendererImplTest&) = delete;
105
106   ~RendererImplTest() override { Destroy(); }
107
108  protected:
109   void Destroy() {
110     renderer_impl_.reset();
111     base::RunLoop().RunUntilIdle();
112   }
113
114   std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream(
115       DemuxerStream::Type type) {
116     std::unique_ptr<StrictMock<MockDemuxerStream>> stream(
117         new StrictMock<MockDemuxerStream>(type));
118     return stream;
119   }
120
121   // Sets up expectations to allow the audio renderer to initialize.
122   void SetAudioRendererInitializeExpectations(PipelineStatus status) {
123     EXPECT_CALL(*audio_renderer_, OnInitialize(audio_stream_.get(), _, _, _))
124         .WillOnce(DoAll(SaveArg<2>(&audio_renderer_client_),
125                         RunOnceCallback<3>(status)));
126   }
127
128   // Sets up expectations to allow the video renderer to initialize.
129   void SetVideoRendererInitializeExpectations(PipelineStatus status) {
130     EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _))
131         .WillOnce(DoAll(SaveArg<2>(&video_renderer_client_),
132                         RunOnceCallback<4>(status)));
133   }
134
135   void InitializeAndExpect(PipelineStatus start_status) {
136     EXPECT_CALL(callbacks_, OnInitialize(start_status))
137         .WillOnce(SaveArg<0>(&initialization_status_));
138     if (is_encrypted_ && !is_cdm_set_)
139       EXPECT_CALL(callbacks_, OnWaiting(WaitingReason::kNoCdm));
140
141     if (start_status == PIPELINE_OK && audio_stream_) {
142       EXPECT_CALL(*audio_renderer_, GetTimeSource())
143           .WillOnce(Return(&time_source_));
144     } else {
145       renderer_impl_->set_time_source_for_testing(&time_source_);
146     }
147
148     renderer_impl_->Initialize(demuxer_.get(), &callbacks_,
149                                base::BindOnce(&CallbackHelper::OnInitialize,
150                                               base::Unretained(&callbacks_)));
151     base::RunLoop().RunUntilIdle();
152
153     if (start_status == PIPELINE_OK && audio_stream_) {
154       ON_CALL(*audio_renderer_, Flush(_))
155           .WillByDefault([this](base::OnceClosure on_done) {
156             audio_renderer_client_->OnBufferingStateChange(
157                 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
158             std::move(on_done).Run();
159           });
160       ON_CALL(*audio_renderer_, StartPlaying())
161           .WillByDefault(SetBufferingState(&audio_renderer_client_,
162                                            BUFFERING_HAVE_ENOUGH,
163                                            BUFFERING_CHANGE_REASON_UNKNOWN));
164     }
165     if (start_status == PIPELINE_OK && video_stream_) {
166       ON_CALL(*video_renderer_, Flush(_))
167           .WillByDefault([this](base::OnceClosure on_done) {
168             video_renderer_client_->OnBufferingStateChange(
169                 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
170             std::move(on_done).Run();
171           });
172       ON_CALL(*video_renderer_, StartPlayingFrom(_))
173           .WillByDefault(SetBufferingState(&video_renderer_client_,
174                                            BUFFERING_HAVE_ENOUGH,
175                                            BUFFERING_CHANGE_REASON_UNKNOWN));
176     }
177   }
178
179   void CreateAudioStream() {
180     audio_stream_ = CreateStream(DemuxerStream::AUDIO);
181     streams_.push_back(audio_stream_.get());
182     EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
183   }
184
185   void CreateVideoStream(bool is_encrypted = false) {
186     is_encrypted_ = is_encrypted;
187     video_stream_ = CreateStream(DemuxerStream::VIDEO);
188     video_stream_->set_video_decoder_config(
189         is_encrypted ? TestVideoConfig::NormalEncrypted()
190                      : TestVideoConfig::Normal());
191     streams_.push_back(video_stream_.get());
192     EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
193   }
194
195   void CreateEncryptedVideoStream() { CreateVideoStream(true); }
196
197   void CreateAudioAndVideoStream() {
198     CreateAudioStream();
199     CreateVideoStream();
200   }
201
202   void InitializeWithAudio() {
203     CreateAudioStream();
204     SetAudioRendererInitializeExpectations(PIPELINE_OK);
205     // There is a potential race between HTMLMediaElement/WMPI shutdown and
206     // renderers being initialized which might result in MediaResource
207     // GetAllStreams suddenly returning fewer streams than before or even
208     // returning
209     // and empty stream collection (see crbug.com/668604). So we are going to
210     // check here that GetAllStreams will be invoked exactly 3 times during
211     // RendererImpl initialization to help catch potential issues. Currently the
212     // GetAllStreams is invoked once from the RendererImpl::Initialize via
213     // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer
214     // and once from the RendererImpl::InitializeVideoRenderer.
215     EXPECT_CALL(*demuxer_, GetAllStreams())
216         .Times(3)
217         .WillRepeatedly(Return(streams_));
218     InitializeAndExpect(PIPELINE_OK);
219   }
220
221   void InitializeWithVideo() {
222     CreateVideoStream();
223     SetVideoRendererInitializeExpectations(PIPELINE_OK);
224     // There is a potential race between HTMLMediaElement/WMPI shutdown and
225     // renderers being initialized which might result in MediaResource
226     // GetAllStreams suddenly returning fewer streams than before or even
227     // returning
228     // and empty stream collection (see crbug.com/668604). So we are going to
229     // check here that GetAllStreams will be invoked exactly 3 times during
230     // RendererImpl initialization to help catch potential issues. Currently the
231     // GetAllStreams is invoked once from the RendererImpl::Initialize via
232     // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer
233     // and once from the RendererImpl::InitializeVideoRenderer.
234     EXPECT_CALL(*demuxer_, GetAllStreams())
235         .Times(3)
236         .WillRepeatedly(Return(streams_));
237     InitializeAndExpect(PIPELINE_OK);
238   }
239
240   void InitializeWithAudioAndVideo() {
241     CreateAudioAndVideoStream();
242     SetAudioRendererInitializeExpectations(PIPELINE_OK);
243     SetVideoRendererInitializeExpectations(PIPELINE_OK);
244     InitializeAndExpect(PIPELINE_OK);
245   }
246
247   void Play() {
248     DCHECK(audio_stream_ || video_stream_);
249     EXPECT_CALL(callbacks_,
250                 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
251                                        BUFFERING_CHANGE_REASON_UNKNOWN));
252
253     base::TimeDelta start_time(base::Milliseconds(kStartPlayingTimeInMs));
254     EXPECT_CALL(time_source_, SetMediaTime(start_time));
255     EXPECT_CALL(time_source_, StartTicking());
256
257     if (audio_stream_) {
258       EXPECT_CALL(*audio_renderer_, StartPlaying());
259     }
260
261     if (video_stream_) {
262       EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time));
263     }
264
265     renderer_impl_->StartPlayingFrom(start_time);
266     base::RunLoop().RunUntilIdle();
267   }
268
269   void SetFlushExpectationsForAVRenderers() {
270     if (audio_stream_)
271       EXPECT_CALL(*audio_renderer_, Flush(_));
272
273     if (video_stream_)
274       EXPECT_CALL(*video_renderer_, Flush(_));
275   }
276
277   void Flush(bool underflowed) {
278     if (!underflowed)
279       EXPECT_CALL(time_source_, StopTicking());
280
281     SetFlushExpectationsForAVRenderers();
282     EXPECT_CALL(callbacks_, OnFlushed());
283
284     renderer_impl_->Flush(base::BindOnce(&CallbackHelper::OnFlushed,
285                                          base::Unretained(&callbacks_)));
286     base::RunLoop().RunUntilIdle();
287   }
288
289   void SetPlaybackRate(double playback_rate) {
290     EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
291     renderer_impl_->SetPlaybackRate(playback_rate);
292     base::RunLoop().RunUntilIdle();
293   }
294
295   int64_t GetMediaTimeMs() {
296     return renderer_impl_->GetMediaTime().InMilliseconds();
297   }
298
299   bool IsMediaTimeAdvancing(double playback_rate) {
300     int64_t start_time_ms = GetMediaTimeMs();
301     const int64_t time_to_advance_ms = 100;
302
303     test_tick_clock_.Advance(base::Milliseconds(time_to_advance_ms));
304
305     if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
306       return true;
307
308     DCHECK_EQ(start_time_ms, GetMediaTimeMs());
309     return false;
310   }
311
312   bool IsMediaTimeAdvancing() {
313     return IsMediaTimeAdvancing(1.0);
314   }
315
316   void SetCdmAndExpect(bool expected_result) {
317     EXPECT_CALL(callbacks_, OnCdmAttached(expected_result))
318         .WillOnce(SaveArg<0>(&is_cdm_set_));
319     renderer_impl_->SetCdm(cdm_context_.get(),
320                            base::BindOnce(&CallbackHelper::OnCdmAttached,
321                                           base::Unretained(&callbacks_)));
322     base::RunLoop().RunUntilIdle();
323   }
324
325   void SetAudioTrackSwitchExpectations() {
326     InSequence track_switch_seq;
327
328     // Called from withing OnEnabledAudioTracksChanged
329     EXPECT_CALL(time_source_, CurrentMediaTime());
330     EXPECT_CALL(time_source_, CurrentMediaTime());
331     EXPECT_CALL(time_source_, StopTicking());
332     EXPECT_CALL(*audio_renderer_, Flush(_));
333
334     // Callback into RestartAudioRenderer
335     EXPECT_CALL(*audio_renderer_, StartPlaying());
336
337     // Callback into OnBufferingStateChange
338     EXPECT_CALL(time_source_, StartTicking());
339     EXPECT_CALL(callbacks_,
340                 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
341                                        BUFFERING_CHANGE_REASON_UNKNOWN));
342   }
343
344   void SetVideoTrackSwitchExpectations() {
345     InSequence track_switch_seq;
346
347     // Called from withing OnSelectedVideoTrackChanged
348     EXPECT_CALL(time_source_, CurrentMediaTime());
349     EXPECT_CALL(*video_renderer_, Flush(_));
350
351     // Callback into RestartVideoRenderer
352     EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
353
354     // Callback into OnBufferingStateChange
355     EXPECT_CALL(callbacks_,
356                 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
357                                        BUFFERING_CHANGE_REASON_UNKNOWN));
358   }
359
360   // Fixture members.
361   base::test::SingleThreadTaskEnvironment task_environment_;
362   StrictMock<CallbackHelper> callbacks_;
363   base::SimpleTestTickClock test_tick_clock_;
364
365   std::unique_ptr<StrictMock<MockDemuxer>> demuxer_;
366   raw_ptr<StrictMock<MockVideoRenderer>, DanglingUntriaged> video_renderer_;
367   raw_ptr<StrictMock<MockAudioRenderer>, DanglingUntriaged> audio_renderer_;
368   std::unique_ptr<RendererImpl> renderer_impl_;
369   std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_;
370
371   StrictMock<MockTimeSource> time_source_;
372   std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_;
373   std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_;
374   std::vector<DemuxerStream*> streams_;
375   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
376   // #addr-of
377   RAW_PTR_EXCLUSION RendererClient* video_renderer_client_;
378   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
379   // #addr-of
380   RAW_PTR_EXCLUSION RendererClient* audio_renderer_client_;
381   VideoDecoderConfig video_decoder_config_;
382   PipelineStatus initialization_status_;
383   bool is_encrypted_ = false;
384   bool is_cdm_set_ = false;
385 };
386
387 TEST_F(RendererImplTest, NoStreams) {
388   // Ensure initialization without streams fails and doesn't crash.
389   EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
390   InitializeAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
391 }
392
393 TEST_F(RendererImplTest, Destroy_BeforeInitialize) {
394   Destroy();
395 }
396
397 TEST_F(RendererImplTest, Destroy_PendingInitialize) {
398   CreateAudioAndVideoStream();
399
400   SetAudioRendererInitializeExpectations(PIPELINE_OK);
401   // Not returning the video initialization callback.
402   EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
403
404   InitializeAndExpect(PIPELINE_ERROR_ABORT);
405   EXPECT_EQ(PIPELINE_OK, initialization_status_);
406
407   Destroy();
408 }
409
410 TEST_F(RendererImplTest, Destroy_PendingInitializeWithoutCdm) {
411   CreateAudioStream();
412   CreateEncryptedVideoStream();
413
414   // Audio is clear and video is encrypted. Initialization will not start
415   // because no CDM is set. So neither AudioRenderer::Initialize() nor
416   // VideoRenderer::Initialize() should not be called. The InitCB will be
417   // aborted when |renderer_impl_| is destructed.
418   InitializeAndExpect(PIPELINE_ERROR_ABORT);
419   EXPECT_EQ(PIPELINE_OK, initialization_status_);
420
421   Destroy();
422 }
423
424 TEST_F(RendererImplTest, Destroy_PendingInitializeAfterSetCdm) {
425   CreateAudioStream();
426   CreateEncryptedVideoStream();
427
428   // Audio is clear and video is encrypted. Initialization will not start
429   // because no CDM is set.
430   InitializeAndExpect(PIPELINE_ERROR_ABORT);
431   EXPECT_EQ(PIPELINE_OK, initialization_status_);
432
433   SetAudioRendererInitializeExpectations(PIPELINE_OK);
434   // Not returning the video initialization callback. So initialization will
435   // be pending.
436   EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
437
438   // SetCdm() will trigger the initialization to start. But it will not complete
439   // because the |video_renderer_| is not returning the initialization callback.
440   SetCdmAndExpect(true);
441   EXPECT_EQ(PIPELINE_OK, initialization_status_);
442
443   Destroy();
444 }
445
446 TEST_F(RendererImplTest, InitializeWithAudio) {
447   InitializeWithAudio();
448 }
449
450 TEST_F(RendererImplTest, InitializeWithVideo) {
451   InitializeWithVideo();
452 }
453
454 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
455   InitializeWithAudioAndVideo();
456 }
457
458 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
459   CreateAudioStream();
460   SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
461   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
462 }
463
464 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
465   CreateVideoStream();
466   SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
467   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
468 }
469
470 TEST_F(RendererImplTest, InitializeWithAudioVideo_AudioRendererFailed) {
471   CreateAudioAndVideoStream();
472   SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
473   // VideoRenderer::Initialize() should not be called.
474   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
475 }
476
477 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
478   CreateAudioAndVideoStream();
479   SetAudioRendererInitializeExpectations(PIPELINE_OK);
480   SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
481   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
482 }
483
484 TEST_F(RendererImplTest, SetCdmBeforeInitialize) {
485   // CDM will be successfully attached immediately if set before RendererImpl
486   // initialization, regardless of the later initialization result.
487   SetCdmAndExpect(true);
488 }
489
490 TEST_F(RendererImplTest, SetCdmAfterInitialize_ClearStream) {
491   InitializeWithAudioAndVideo();
492   EXPECT_EQ(PIPELINE_OK, initialization_status_);
493
494   // CDM will be successfully attached immediately since initialization is
495   // completed.
496   SetCdmAndExpect(true);
497 }
498
499 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Success) {
500   CreateAudioStream();
501   CreateEncryptedVideoStream();
502
503   SetAudioRendererInitializeExpectations(PIPELINE_OK);
504   SetVideoRendererInitializeExpectations(PIPELINE_OK);
505   InitializeAndExpect(PIPELINE_OK);
506   // Initialization is pending until CDM is set.
507   EXPECT_EQ(PIPELINE_OK, initialization_status_);
508
509   SetCdmAndExpect(true);
510   EXPECT_EQ(PIPELINE_OK, initialization_status_);
511 }
512
513 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Failure) {
514   CreateAudioStream();
515   CreateEncryptedVideoStream();
516
517   SetAudioRendererInitializeExpectations(PIPELINE_OK);
518   SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
519   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
520   // Initialization is pending until CDM is set.
521   EXPECT_EQ(PIPELINE_OK, initialization_status_);
522
523   SetCdmAndExpect(true);
524   EXPECT_EQ(PIPELINE_ERROR_INITIALIZATION_FAILED, initialization_status_);
525 }
526
527 TEST_F(RendererImplTest, SetCdmMultipleTimes) {
528   SetCdmAndExpect(true);
529   SetCdmAndExpect(false);  // Do not support switching CDM.
530 }
531
532 TEST_F(RendererImplTest, StartPlayingFrom) {
533   InitializeWithAudioAndVideo();
534   Play();
535 }
536
537 TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) {
538   InitializeWithAudioAndVideo();
539
540   // Play with a zero playback rate shouldn't start time.
541   Play();
542   Mock::VerifyAndClearExpectations(video_renderer_);
543
544   // Positive playback rate when ticking should start time.
545   EXPECT_CALL(*video_renderer_, OnTimeProgressing());
546   SetPlaybackRate(1.0);
547   Mock::VerifyAndClearExpectations(video_renderer_);
548
549   // Double notifications shouldn't be sent.
550   SetPlaybackRate(1.0);
551   Mock::VerifyAndClearExpectations(video_renderer_);
552
553   // Zero playback rate should stop time.
554   EXPECT_CALL(*video_renderer_, OnTimeStopped());
555   SetPlaybackRate(0.0);
556   Mock::VerifyAndClearExpectations(video_renderer_);
557
558   // Double notifications shouldn't be sent.
559   SetPlaybackRate(0.0);
560   Mock::VerifyAndClearExpectations(video_renderer_);
561
562   // Starting playback and flushing should cause time to stop.
563   EXPECT_CALL(*video_renderer_, OnTimeProgressing());
564   EXPECT_CALL(*video_renderer_, OnTimeStopped());
565   SetPlaybackRate(1.0);
566   Flush(false);
567
568   // A positive playback rate when playback isn't started should do nothing.
569   SetPlaybackRate(1.0);
570 }
571
572 TEST_F(RendererImplTest, FlushAfterInitialization) {
573   InitializeWithAudioAndVideo();
574   EXPECT_CALL(callbacks_, OnFlushed());
575   renderer_impl_->Flush(base::BindOnce(&CallbackHelper::OnFlushed,
576                                        base::Unretained(&callbacks_)));
577   base::RunLoop().RunUntilIdle();
578 }
579
580 TEST_F(RendererImplTest, FlushAfterPlay) {
581   InitializeWithAudioAndVideo();
582   Play();
583   Flush(false);
584 }
585
586 TEST_F(RendererImplTest, FlushAfterUnderflow) {
587   InitializeWithAudioAndVideo();
588   Play();
589
590   // Simulate underflow.
591   EXPECT_CALL(time_source_, StopTicking());
592   EXPECT_CALL(callbacks_,
593               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
594                                      BUFFERING_CHANGE_REASON_UNKNOWN));
595   audio_renderer_client_->OnBufferingStateChange(
596       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
597
598   // Flush while underflowed. We shouldn't call StopTicking() again.
599   Flush(true);
600 }
601
602 TEST_F(RendererImplTest, SetPlaybackRate) {
603   InitializeWithAudioAndVideo();
604   SetPlaybackRate(1.0);
605   SetPlaybackRate(2.0);
606 }
607
608 TEST_F(RendererImplTest, SetVolume) {
609   InitializeWithAudioAndVideo();
610   EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
611   renderer_impl_->SetVolume(2.0f);
612 }
613
614 TEST_F(RendererImplTest, AudioStreamEnded) {
615   InitializeWithAudio();
616   Play();
617
618   EXPECT_CALL(time_source_, StopTicking());
619   EXPECT_CALL(callbacks_, OnEnded());
620
621   audio_renderer_client_->OnEnded();
622   base::RunLoop().RunUntilIdle();
623 }
624
625 TEST_F(RendererImplTest, VideoStreamEnded) {
626   InitializeWithVideo();
627   Play();
628
629   EXPECT_CALL(time_source_, StopTicking());
630   EXPECT_CALL(callbacks_, OnEnded());
631   EXPECT_CALL(*video_renderer_, OnTimeStopped());
632
633   video_renderer_client_->OnEnded();
634   base::RunLoop().RunUntilIdle();
635 }
636
637 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
638   InitializeWithAudioAndVideo();
639   Play();
640
641   // OnEnded() is called only when all streams have finished.
642   audio_renderer_client_->OnEnded();
643   base::RunLoop().RunUntilIdle();
644
645   EXPECT_CALL(time_source_, StopTicking());
646   EXPECT_CALL(callbacks_, OnEnded());
647   EXPECT_CALL(*video_renderer_, OnTimeStopped());
648
649   video_renderer_client_->OnEnded();
650   base::RunLoop().RunUntilIdle();
651 }
652
653 TEST_F(RendererImplTest, ErrorAfterInitialize) {
654   InitializeWithAudio();
655   EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
656   audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
657   base::RunLoop().RunUntilIdle();
658 }
659
660 TEST_F(RendererImplTest, ErrorDuringPlaying) {
661   InitializeWithAudio();
662   Play();
663
664   EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
665   audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
666   base::RunLoop().RunUntilIdle();
667 }
668
669 TEST_F(RendererImplTest, ErrorDuringFlush) {
670   InitializeWithAudio();
671   Play();
672
673   InSequence s;
674   EXPECT_CALL(time_source_, StopTicking());
675   EXPECT_CALL(*audio_renderer_, Flush(_))
676       .WillOnce([this](base::OnceClosure on_done) {
677         audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
678         std::move(on_done).Run();
679       });
680   EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
681   EXPECT_CALL(callbacks_, OnFlushed());
682   renderer_impl_->Flush(base::BindOnce(&CallbackHelper::OnFlushed,
683                                        base::Unretained(&callbacks_)));
684   base::RunLoop().RunUntilIdle();
685 }
686
687 TEST_F(RendererImplTest, ErrorAfterFlush) {
688   InitializeWithAudio();
689   Play();
690   Flush(false);
691
692   EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
693   audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
694   base::RunLoop().RunUntilIdle();
695 }
696
697 TEST_F(RendererImplTest, ErrorDuringInitialize) {
698   CreateAudioAndVideoStream();
699   SetAudioRendererInitializeExpectations(PIPELINE_OK);
700
701   // Force an audio error to occur during video renderer initialization.
702   EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _))
703       .WillOnce(DoAll(SetError(&audio_renderer_client_, PIPELINE_ERROR_DECODE),
704                       SaveArg<2>(&video_renderer_client_),
705                       RunOnceCallback<4>(PIPELINE_OK)));
706
707   InitializeAndExpect(PIPELINE_ERROR_DECODE);
708 }
709
710 TEST_F(RendererImplTest, AudioUnderflow) {
711   InitializeWithAudio();
712   Play();
713
714   // Underflow should occur immediately with a single audio track.
715   EXPECT_CALL(time_source_, StopTicking());
716   EXPECT_CALL(callbacks_,
717               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
718                                      BUFFERING_CHANGE_REASON_UNKNOWN));
719   audio_renderer_client_->OnBufferingStateChange(
720       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
721 }
722
723 TEST_F(RendererImplTest, AudioUnderflowWithVideo) {
724   InitializeWithAudioAndVideo();
725   Play();
726
727   // Underflow should be immediate when both audio and video are present and
728   // audio underflows.
729   EXPECT_CALL(time_source_, StopTicking());
730   EXPECT_CALL(callbacks_,
731               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
732                                      BUFFERING_CHANGE_REASON_UNKNOWN));
733   audio_renderer_client_->OnBufferingStateChange(
734       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
735 }
736
737 TEST_F(RendererImplTest, VideoUnderflow) {
738   InitializeWithVideo();
739   Play();
740
741   // Underflow should occur immediately with a single video track.
742   EXPECT_CALL(time_source_, StopTicking());
743   EXPECT_CALL(callbacks_,
744               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
745                                      BUFFERING_CHANGE_REASON_UNKNOWN));
746   video_renderer_client_->OnBufferingStateChange(
747       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
748 }
749
750 TEST_F(RendererImplTest, VideoUnderflowWithAudio) {
751   InitializeWithAudioAndVideo();
752   Play();
753
754   // Set a zero threshold such that the underflow will be executed on the next
755   // run of the message loop.
756   renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
757
758   // Underflow should be delayed when both audio and video are present and video
759   // underflows.
760   EXPECT_CALL(callbacks_,
761               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
762                                      BUFFERING_CHANGE_REASON_UNKNOWN));
763   video_renderer_client_->OnBufferingStateChange(
764       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
765   Mock::VerifyAndClearExpectations(&time_source_);
766
767   EXPECT_CALL(time_source_, StopTicking());
768   base::RunLoop().RunUntilIdle();
769 }
770
771 TEST_F(RendererImplTest, VideoUnderflowWithAudioVideoRecovers) {
772   InitializeWithAudioAndVideo();
773   Play();
774
775   // Set a zero threshold such that the underflow will be executed on the next
776   // run of the message loop.
777   renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
778
779   // Underflow should be delayed when both audio and video are present and video
780   // underflows.
781   EXPECT_CALL(callbacks_,
782               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
783                                      BUFFERING_CHANGE_REASON_UNKNOWN))
784       .Times(0);
785   video_renderer_client_->OnBufferingStateChange(
786       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
787   Mock::VerifyAndClearExpectations(&time_source_);
788
789   // If video recovers, the underflow should never occur.
790   video_renderer_client_->OnBufferingStateChange(
791       BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
792   base::RunLoop().RunUntilIdle();
793 }
794
795 TEST_F(RendererImplTest, VideoAndAudioUnderflow) {
796   InitializeWithAudioAndVideo();
797   Play();
798
799   // Set a zero threshold such that the underflow will be executed on the next
800   // run of the message loop.
801   renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
802
803   // Underflow should be delayed when both audio and video are present and video
804   // underflows.
805   EXPECT_CALL(callbacks_,
806               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
807                                      BUFFERING_CHANGE_REASON_UNKNOWN))
808       .Times(0);
809   video_renderer_client_->OnBufferingStateChange(
810       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
811   Mock::VerifyAndClearExpectations(&time_source_);
812
813   EXPECT_CALL(callbacks_,
814               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
815                                      BUFFERING_CHANGE_REASON_UNKNOWN));
816   EXPECT_CALL(time_source_, StopTicking());
817   audio_renderer_client_->OnBufferingStateChange(
818       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
819
820   // Nothing else should primed on the message loop.
821   base::RunLoop().RunUntilIdle();
822 }
823
824 TEST_F(RendererImplTest, VideoUnderflowWithAudioFlush) {
825   InitializeWithAudioAndVideo();
826   Play();
827
828   // Set a massive threshold such that it shouldn't fire within this test.
829   renderer_impl_->set_video_underflow_threshold_for_testing(base::Seconds(100));
830
831   // Simulate the cases where audio underflows and then video underflows.
832   EXPECT_CALL(time_source_, StopTicking());
833   EXPECT_CALL(callbacks_,
834               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
835                                      BUFFERING_CHANGE_REASON_UNKNOWN));
836   audio_renderer_client_->OnBufferingStateChange(
837       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
838   video_renderer_client_->OnBufferingStateChange(
839       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
840   Mock::VerifyAndClearExpectations(&time_source_);
841
842   // Flush the audio and video renderers, both think they're in an underflow
843   // state, but if the video renderer underflow was deferred, RendererImpl would
844   // think it still has enough data.
845   EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunOnceClosure<0>());
846   EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunOnceClosure<0>());
847   EXPECT_CALL(callbacks_, OnFlushed());
848   renderer_impl_->Flush(base::BindOnce(&CallbackHelper::OnFlushed,
849                                        base::Unretained(&callbacks_)));
850   base::RunLoop().RunUntilIdle();
851
852   // Start playback after the flush, but never return BUFFERING_HAVE_ENOUGH from
853   // the video renderer (which simulates spool up time for the video renderer).
854   const base::TimeDelta kStartTime;
855   EXPECT_CALL(time_source_, SetMediaTime(kStartTime));
856   EXPECT_CALL(time_source_, StartTicking());
857   EXPECT_CALL(*audio_renderer_, StartPlaying());
858   EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime));
859   EXPECT_CALL(callbacks_,
860               OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
861                                      BUFFERING_CHANGE_REASON_UNKNOWN));
862   renderer_impl_->StartPlayingFrom(kStartTime);
863
864   // Nothing else should primed on the message loop.
865   base::RunLoop().RunUntilIdle();
866 }
867
868 TEST_F(RendererImplTest, AudioTrackDisableThenEnable) {
869   InitializeWithAudioAndVideo();
870   Play();
871   Mock::VerifyAndClearExpectations(&time_source_);
872
873   base::RunLoop disable_wait;
874   SetAudioTrackSwitchExpectations();
875   renderer_impl_->OnEnabledAudioTracksChanged({}, disable_wait.QuitClosure());
876   disable_wait.Run();
877
878   base::RunLoop enable_wait;
879   SetAudioTrackSwitchExpectations();
880   renderer_impl_->OnEnabledAudioTracksChanged({streams_[0]},
881                                               enable_wait.QuitClosure());
882   enable_wait.Run();
883 }
884
885 TEST_F(RendererImplTest, VideoTrackDisableThenEnable) {
886   InitializeWithAudioAndVideo();
887   Play();
888   Mock::VerifyAndClearExpectations(&time_source_);
889
890   base::RunLoop disable_wait;
891   SetVideoTrackSwitchExpectations();
892   renderer_impl_->OnSelectedVideoTracksChanged({}, disable_wait.QuitClosure());
893   disable_wait.Run();
894
895   base::RunLoop enable_wait;
896   SetVideoTrackSwitchExpectations();
897   renderer_impl_->OnSelectedVideoTracksChanged({streams_[1]},
898                                                enable_wait.QuitClosure());
899   enable_wait.Run();
900
901   base::RunLoop().RunUntilIdle();
902 }
903
904 TEST_F(RendererImplTest, AudioUnderflowDuringAudioTrackChange) {
905   InitializeWithAudioAndVideo();
906   Play();
907
908   base::RunLoop loop;
909
910   // Underflow should occur immediately with a single audio track.
911   EXPECT_CALL(time_source_, StopTicking());
912
913   // Capture the callback from the audio renderer flush.
914   base::OnceClosure audio_renderer_flush_cb;
915   EXPECT_CALL(*audio_renderer_, Flush(_))
916       .WillOnce(MoveArg(&audio_renderer_flush_cb));
917
918   EXPECT_CALL(time_source_, CurrentMediaTime()).Times(2);
919   std::vector<DemuxerStream*> tracks;
920   renderer_impl_->OnEnabledAudioTracksChanged({}, loop.QuitClosure());
921
922   EXPECT_CALL(callbacks_,
923               OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
924                                      BUFFERING_CHANGE_REASON_UNKNOWN));
925
926   EXPECT_CALL(time_source_, StartTicking());
927   EXPECT_CALL(*audio_renderer_, StartPlaying());
928   audio_renderer_client_->OnBufferingStateChange(
929       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
930   std::move(audio_renderer_flush_cb).Run();
931   loop.Run();
932 }
933
934 TEST_F(RendererImplTest, VideoUnderflowDuringVideoTrackChange) {
935   InitializeWithAudioAndVideo();
936   Play();
937
938   base::RunLoop loop;
939
940   // Capture the callback from the video renderer flush.
941   base::OnceClosure video_renderer_flush_cb;
942   {
943     InSequence track_switch_seq;
944     EXPECT_CALL(time_source_, CurrentMediaTime());
945     EXPECT_CALL(*video_renderer_, Flush(_))
946         .WillOnce(MoveArg(&video_renderer_flush_cb));
947     EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
948     EXPECT_CALL(callbacks_,
949                 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
950                                        BUFFERING_CHANGE_REASON_UNKNOWN));
951   }
952
953   renderer_impl_->OnSelectedVideoTracksChanged({}, loop.QuitClosure());
954
955   video_renderer_client_->OnBufferingStateChange(
956       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
957   std::move(video_renderer_flush_cb).Run();
958   loop.Run();
959 }
960
961 TEST_F(RendererImplTest, VideoUnderflowDuringAudioTrackChange) {
962   InitializeWithAudioAndVideo();
963   Play();
964
965   base::RunLoop loop;
966
967   // Capture the callback from the audio renderer flush.
968   base::OnceClosure audio_renderer_flush_cb;
969   EXPECT_CALL(*audio_renderer_, Flush(_))
970       .WillOnce(MoveArg(&audio_renderer_flush_cb));
971
972   EXPECT_CALL(time_source_, CurrentMediaTime()).Times(2);
973   EXPECT_CALL(time_source_, StopTicking());
974   renderer_impl_->OnEnabledAudioTracksChanged({}, loop.QuitClosure());
975
976   EXPECT_CALL(*audio_renderer_, StartPlaying());
977   video_renderer_client_->OnBufferingStateChange(
978       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
979   std::move(audio_renderer_flush_cb).Run();
980   loop.Run();
981 }
982
983 TEST_F(RendererImplTest, AudioUnderflowDuringVideoTrackChange) {
984   InitializeWithAudioAndVideo();
985   Play();
986
987   base::RunLoop loop;
988   EXPECT_CALL(callbacks_,
989               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
990                                      BUFFERING_CHANGE_REASON_UNKNOWN));
991   EXPECT_CALL(time_source_, CurrentMediaTime());
992
993   // Capture the callback from the audio renderer flush.
994   base::OnceClosure video_renderer_flush_cb;
995   EXPECT_CALL(*video_renderer_, Flush(_))
996       .WillOnce(MoveArg(&video_renderer_flush_cb));
997
998   renderer_impl_->OnSelectedVideoTracksChanged({}, loop.QuitClosure());
999
1000   EXPECT_CALL(time_source_, StopTicking());
1001   EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
1002
1003   audio_renderer_client_->OnBufferingStateChange(
1004       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
1005
1006   std::move(video_renderer_flush_cb).Run();
1007   loop.Run();
1008 }
1009
1010 TEST_F(RendererImplTest, VideoResumedFromUnderflowDuringAudioTrackChange) {
1011   InitializeWithAudioAndVideo();
1012   Play();
1013
1014   // Underflow the renderer.
1015   base::RunLoop underflow_wait;
1016   EXPECT_CALL(callbacks_,
1017               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
1018                                      BUFFERING_CHANGE_REASON_UNKNOWN))
1019       .WillOnce(RunClosure(underflow_wait.QuitClosure()));
1020   EXPECT_CALL(time_source_, StopTicking());
1021   video_renderer_client_->OnBufferingStateChange(
1022       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
1023   underflow_wait.Run();
1024
1025   // Start a track change.
1026   base::OnceClosure audio_renderer_flush_cb;
1027   base::RunLoop track_change;
1028   {
1029     InSequence track_switch_seq;
1030     EXPECT_CALL(time_source_, CurrentMediaTime()).Times(2);
1031     EXPECT_CALL(*audio_renderer_, Flush(_))
1032         .WillOnce(MoveArg(&audio_renderer_flush_cb));
1033   }
1034   renderer_impl_->OnEnabledAudioTracksChanged({}, track_change.QuitClosure());
1035
1036   // Signal that the renderer has enough data to resume from underflow.
1037   // Nothing should bubble up, since we are pending audio track change.
1038   EXPECT_CALL(callbacks_, OnBufferingStateChange(_, _)).Times(0);
1039   EXPECT_CALL(time_source_, StartTicking()).Times(0);
1040   video_renderer_client_->OnBufferingStateChange(
1041       BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
1042
1043   // Finish the track change.
1044   EXPECT_CALL(*audio_renderer_, StartPlaying());
1045   std::move(audio_renderer_flush_cb).Run();
1046   track_change.Run();
1047 }
1048
1049 TEST_F(RendererImplTest, AudioResumedFromUnderflowDuringVideoTrackChange) {
1050   InitializeWithAudioAndVideo();
1051   Play();
1052
1053   // Underflow the renderer.
1054   base::RunLoop underflow_wait;
1055   EXPECT_CALL(callbacks_,
1056               OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
1057                                      BUFFERING_CHANGE_REASON_UNKNOWN))
1058       .WillOnce(RunClosure(underflow_wait.QuitClosure()));
1059   EXPECT_CALL(time_source_, StopTicking());
1060   audio_renderer_client_->OnBufferingStateChange(
1061       BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
1062   underflow_wait.Run();
1063
1064   // Start a track change.
1065   base::OnceClosure video_renderer_flush_cb;
1066   base::RunLoop track_change;
1067   {
1068     InSequence track_switch_seq;
1069     EXPECT_CALL(time_source_, CurrentMediaTime());
1070     EXPECT_CALL(*video_renderer_, Flush(_))
1071         .WillOnce(MoveArg(&video_renderer_flush_cb));
1072   }
1073   renderer_impl_->OnSelectedVideoTracksChanged({}, track_change.QuitClosure());
1074
1075   // Signal that the renderer has enough data to resume from underflow.
1076   // Nothing should bubble up, since we are pending audio track change.
1077   EXPECT_CALL(callbacks_, OnBufferingStateChange(_, _)).Times(0);
1078   EXPECT_CALL(time_source_, StartTicking()).Times(0);
1079   audio_renderer_client_->OnBufferingStateChange(
1080       BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
1081
1082   // Finish the track change.
1083   EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
1084   std::move(video_renderer_flush_cb).Run();
1085   track_change.Run();
1086 }
1087
1088 }  // namespace media