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.
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"
27 using ::base::test::RunCallback;
28 using ::base::test::RunClosure;
29 using ::base::test::RunOnceCallback;
30 using ::base::test::RunOnceClosure;
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;
43 const int64_t kStartPlayingTimeInMs = 100;
45 ACTION_P2(SetBool, var, value) {
49 ACTION_P3(SetBufferingState, renderer_client, buffering_state, reason) {
50 (*renderer_client)->OnBufferingStateChange(buffering_state, reason);
53 ACTION_P2(SetError, renderer_client, error) {
54 (*renderer_client)->OnError(error);
57 ACTION(PostCallback) {
58 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, arg0);
61 ACTION(PostQuitWhenIdle) {
62 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
63 FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
66 class RendererImplTest : public ::testing::Test {
68 class CallbackHelper : public MockRendererClient {
70 CallbackHelper() = default;
72 CallbackHelper(const CallbackHelper&) = delete;
73 CallbackHelper& operator=(const CallbackHelper&) = delete;
75 virtual ~CallbackHelper() = default;
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());
87 : demuxer_(new StrictMock<MockDemuxer>()),
88 video_renderer_(new StrictMock<MockVideoRenderer>()),
89 audio_renderer_(new StrictMock<MockAudioRenderer>()),
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_));
103 RendererImplTest(const RendererImplTest&) = delete;
104 RendererImplTest& operator=(const RendererImplTest&) = delete;
106 ~RendererImplTest() override { Destroy(); }
110 renderer_impl_.reset();
111 base::RunLoop().RunUntilIdle();
114 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream(
115 DemuxerStream::Type type) {
116 std::unique_ptr<StrictMock<MockDemuxerStream>> stream(
117 new StrictMock<MockDemuxerStream>(type));
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)));
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)));
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));
141 if (start_status == PIPELINE_OK && audio_stream_) {
142 EXPECT_CALL(*audio_renderer_, GetTimeSource())
143 .WillOnce(Return(&time_source_));
145 renderer_impl_->set_time_source_for_testing(&time_source_);
148 renderer_impl_->Initialize(demuxer_.get(), &callbacks_,
149 base::BindOnce(&CallbackHelper::OnInitialize,
150 base::Unretained(&callbacks_)));
151 base::RunLoop().RunUntilIdle();
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();
160 ON_CALL(*audio_renderer_, StartPlaying())
161 .WillByDefault(SetBufferingState(&audio_renderer_client_,
162 BUFFERING_HAVE_ENOUGH,
163 BUFFERING_CHANGE_REASON_UNKNOWN));
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();
172 ON_CALL(*video_renderer_, StartPlayingFrom(_))
173 .WillByDefault(SetBufferingState(&video_renderer_client_,
174 BUFFERING_HAVE_ENOUGH,
175 BUFFERING_CHANGE_REASON_UNKNOWN));
179 void CreateAudioStream() {
180 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
181 streams_.push_back(audio_stream_.get());
182 EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
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_));
195 void CreateEncryptedVideoStream() { CreateVideoStream(true); }
197 void CreateAudioAndVideoStream() {
202 void InitializeWithAudio() {
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
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())
217 .WillRepeatedly(Return(streams_));
218 InitializeAndExpect(PIPELINE_OK);
221 void InitializeWithVideo() {
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
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())
236 .WillRepeatedly(Return(streams_));
237 InitializeAndExpect(PIPELINE_OK);
240 void InitializeWithAudioAndVideo() {
241 CreateAudioAndVideoStream();
242 SetAudioRendererInitializeExpectations(PIPELINE_OK);
243 SetVideoRendererInitializeExpectations(PIPELINE_OK);
244 InitializeAndExpect(PIPELINE_OK);
248 DCHECK(audio_stream_ || video_stream_);
249 EXPECT_CALL(callbacks_,
250 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
251 BUFFERING_CHANGE_REASON_UNKNOWN));
253 base::TimeDelta start_time(base::Milliseconds(kStartPlayingTimeInMs));
254 EXPECT_CALL(time_source_, SetMediaTime(start_time));
255 EXPECT_CALL(time_source_, StartTicking());
258 EXPECT_CALL(*audio_renderer_, StartPlaying());
262 EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time));
265 renderer_impl_->StartPlayingFrom(start_time);
266 base::RunLoop().RunUntilIdle();
269 void SetFlushExpectationsForAVRenderers() {
271 EXPECT_CALL(*audio_renderer_, Flush(_));
274 EXPECT_CALL(*video_renderer_, Flush(_));
277 void Flush(bool underflowed) {
279 EXPECT_CALL(time_source_, StopTicking());
281 SetFlushExpectationsForAVRenderers();
282 EXPECT_CALL(callbacks_, OnFlushed());
284 renderer_impl_->Flush(base::BindOnce(&CallbackHelper::OnFlushed,
285 base::Unretained(&callbacks_)));
286 base::RunLoop().RunUntilIdle();
289 void SetPlaybackRate(double playback_rate) {
290 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
291 renderer_impl_->SetPlaybackRate(playback_rate);
292 base::RunLoop().RunUntilIdle();
295 int64_t GetMediaTimeMs() {
296 return renderer_impl_->GetMediaTime().InMilliseconds();
299 bool IsMediaTimeAdvancing(double playback_rate) {
300 int64_t start_time_ms = GetMediaTimeMs();
301 const int64_t time_to_advance_ms = 100;
303 test_tick_clock_.Advance(base::Milliseconds(time_to_advance_ms));
305 if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
308 DCHECK_EQ(start_time_ms, GetMediaTimeMs());
312 bool IsMediaTimeAdvancing() {
313 return IsMediaTimeAdvancing(1.0);
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();
325 void SetAudioTrackSwitchExpectations() {
326 InSequence track_switch_seq;
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(_));
334 // Callback into RestartAudioRenderer
335 EXPECT_CALL(*audio_renderer_, StartPlaying());
337 // Callback into OnBufferingStateChange
338 EXPECT_CALL(time_source_, StartTicking());
339 EXPECT_CALL(callbacks_,
340 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
341 BUFFERING_CHANGE_REASON_UNKNOWN));
344 void SetVideoTrackSwitchExpectations() {
345 InSequence track_switch_seq;
347 // Called from withing OnSelectedVideoTrackChanged
348 EXPECT_CALL(time_source_, CurrentMediaTime());
349 EXPECT_CALL(*video_renderer_, Flush(_));
351 // Callback into RestartVideoRenderer
352 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
354 // Callback into OnBufferingStateChange
355 EXPECT_CALL(callbacks_,
356 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
357 BUFFERING_CHANGE_REASON_UNKNOWN));
361 base::test::SingleThreadTaskEnvironment task_environment_;
362 StrictMock<CallbackHelper> callbacks_;
363 base::SimpleTestTickClock test_tick_clock_;
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_;
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:
377 RAW_PTR_EXCLUSION RendererClient* video_renderer_client_;
378 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
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;
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);
393 TEST_F(RendererImplTest, Destroy_BeforeInitialize) {
397 TEST_F(RendererImplTest, Destroy_PendingInitialize) {
398 CreateAudioAndVideoStream();
400 SetAudioRendererInitializeExpectations(PIPELINE_OK);
401 // Not returning the video initialization callback.
402 EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
404 InitializeAndExpect(PIPELINE_ERROR_ABORT);
405 EXPECT_EQ(PIPELINE_OK, initialization_status_);
410 TEST_F(RendererImplTest, Destroy_PendingInitializeWithoutCdm) {
412 CreateEncryptedVideoStream();
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_);
424 TEST_F(RendererImplTest, Destroy_PendingInitializeAfterSetCdm) {
426 CreateEncryptedVideoStream();
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_);
433 SetAudioRendererInitializeExpectations(PIPELINE_OK);
434 // Not returning the video initialization callback. So initialization will
436 EXPECT_CALL(*video_renderer_, OnInitialize(video_stream_.get(), _, _, _, _));
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_);
446 TEST_F(RendererImplTest, InitializeWithAudio) {
447 InitializeWithAudio();
450 TEST_F(RendererImplTest, InitializeWithVideo) {
451 InitializeWithVideo();
454 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
455 InitializeWithAudioAndVideo();
458 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
460 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
461 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
464 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
466 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
467 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
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);
477 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
478 CreateAudioAndVideoStream();
479 SetAudioRendererInitializeExpectations(PIPELINE_OK);
480 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
481 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
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);
490 TEST_F(RendererImplTest, SetCdmAfterInitialize_ClearStream) {
491 InitializeWithAudioAndVideo();
492 EXPECT_EQ(PIPELINE_OK, initialization_status_);
494 // CDM will be successfully attached immediately since initialization is
496 SetCdmAndExpect(true);
499 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Success) {
501 CreateEncryptedVideoStream();
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_);
509 SetCdmAndExpect(true);
510 EXPECT_EQ(PIPELINE_OK, initialization_status_);
513 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Failure) {
515 CreateEncryptedVideoStream();
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_);
523 SetCdmAndExpect(true);
524 EXPECT_EQ(PIPELINE_ERROR_INITIALIZATION_FAILED, initialization_status_);
527 TEST_F(RendererImplTest, SetCdmMultipleTimes) {
528 SetCdmAndExpect(true);
529 SetCdmAndExpect(false); // Do not support switching CDM.
532 TEST_F(RendererImplTest, StartPlayingFrom) {
533 InitializeWithAudioAndVideo();
537 TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) {
538 InitializeWithAudioAndVideo();
540 // Play with a zero playback rate shouldn't start time.
542 Mock::VerifyAndClearExpectations(video_renderer_);
544 // Positive playback rate when ticking should start time.
545 EXPECT_CALL(*video_renderer_, OnTimeProgressing());
546 SetPlaybackRate(1.0);
547 Mock::VerifyAndClearExpectations(video_renderer_);
549 // Double notifications shouldn't be sent.
550 SetPlaybackRate(1.0);
551 Mock::VerifyAndClearExpectations(video_renderer_);
553 // Zero playback rate should stop time.
554 EXPECT_CALL(*video_renderer_, OnTimeStopped());
555 SetPlaybackRate(0.0);
556 Mock::VerifyAndClearExpectations(video_renderer_);
558 // Double notifications shouldn't be sent.
559 SetPlaybackRate(0.0);
560 Mock::VerifyAndClearExpectations(video_renderer_);
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);
568 // A positive playback rate when playback isn't started should do nothing.
569 SetPlaybackRate(1.0);
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();
580 TEST_F(RendererImplTest, FlushAfterPlay) {
581 InitializeWithAudioAndVideo();
586 TEST_F(RendererImplTest, FlushAfterUnderflow) {
587 InitializeWithAudioAndVideo();
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);
598 // Flush while underflowed. We shouldn't call StopTicking() again.
602 TEST_F(RendererImplTest, SetPlaybackRate) {
603 InitializeWithAudioAndVideo();
604 SetPlaybackRate(1.0);
605 SetPlaybackRate(2.0);
608 TEST_F(RendererImplTest, SetVolume) {
609 InitializeWithAudioAndVideo();
610 EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
611 renderer_impl_->SetVolume(2.0f);
614 TEST_F(RendererImplTest, AudioStreamEnded) {
615 InitializeWithAudio();
618 EXPECT_CALL(time_source_, StopTicking());
619 EXPECT_CALL(callbacks_, OnEnded());
621 audio_renderer_client_->OnEnded();
622 base::RunLoop().RunUntilIdle();
625 TEST_F(RendererImplTest, VideoStreamEnded) {
626 InitializeWithVideo();
629 EXPECT_CALL(time_source_, StopTicking());
630 EXPECT_CALL(callbacks_, OnEnded());
631 EXPECT_CALL(*video_renderer_, OnTimeStopped());
633 video_renderer_client_->OnEnded();
634 base::RunLoop().RunUntilIdle();
637 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
638 InitializeWithAudioAndVideo();
641 // OnEnded() is called only when all streams have finished.
642 audio_renderer_client_->OnEnded();
643 base::RunLoop().RunUntilIdle();
645 EXPECT_CALL(time_source_, StopTicking());
646 EXPECT_CALL(callbacks_, OnEnded());
647 EXPECT_CALL(*video_renderer_, OnTimeStopped());
649 video_renderer_client_->OnEnded();
650 base::RunLoop().RunUntilIdle();
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();
660 TEST_F(RendererImplTest, ErrorDuringPlaying) {
661 InitializeWithAudio();
664 EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
665 audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
666 base::RunLoop().RunUntilIdle();
669 TEST_F(RendererImplTest, ErrorDuringFlush) {
670 InitializeWithAudio();
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();
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();
687 TEST_F(RendererImplTest, ErrorAfterFlush) {
688 InitializeWithAudio();
692 EXPECT_CALL(callbacks_, OnError(HasStatusCode(PIPELINE_ERROR_DECODE)));
693 audio_renderer_client_->OnError(PIPELINE_ERROR_DECODE);
694 base::RunLoop().RunUntilIdle();
697 TEST_F(RendererImplTest, ErrorDuringInitialize) {
698 CreateAudioAndVideoStream();
699 SetAudioRendererInitializeExpectations(PIPELINE_OK);
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)));
707 InitializeAndExpect(PIPELINE_ERROR_DECODE);
710 TEST_F(RendererImplTest, AudioUnderflow) {
711 InitializeWithAudio();
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);
723 TEST_F(RendererImplTest, AudioUnderflowWithVideo) {
724 InitializeWithAudioAndVideo();
727 // Underflow should be immediate when both audio and video are present and
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);
737 TEST_F(RendererImplTest, VideoUnderflow) {
738 InitializeWithVideo();
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);
750 TEST_F(RendererImplTest, VideoUnderflowWithAudio) {
751 InitializeWithAudioAndVideo();
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());
758 // Underflow should be delayed when both audio and video are present and video
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_);
767 EXPECT_CALL(time_source_, StopTicking());
768 base::RunLoop().RunUntilIdle();
771 TEST_F(RendererImplTest, VideoUnderflowWithAudioVideoRecovers) {
772 InitializeWithAudioAndVideo();
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());
779 // Underflow should be delayed when both audio and video are present and video
781 EXPECT_CALL(callbacks_,
782 OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
783 BUFFERING_CHANGE_REASON_UNKNOWN))
785 video_renderer_client_->OnBufferingStateChange(
786 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
787 Mock::VerifyAndClearExpectations(&time_source_);
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();
795 TEST_F(RendererImplTest, VideoAndAudioUnderflow) {
796 InitializeWithAudioAndVideo();
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());
803 // Underflow should be delayed when both audio and video are present and video
805 EXPECT_CALL(callbacks_,
806 OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
807 BUFFERING_CHANGE_REASON_UNKNOWN))
809 video_renderer_client_->OnBufferingStateChange(
810 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
811 Mock::VerifyAndClearExpectations(&time_source_);
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);
820 // Nothing else should primed on the message loop.
821 base::RunLoop().RunUntilIdle();
824 TEST_F(RendererImplTest, VideoUnderflowWithAudioFlush) {
825 InitializeWithAudioAndVideo();
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));
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_);
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();
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);
864 // Nothing else should primed on the message loop.
865 base::RunLoop().RunUntilIdle();
868 TEST_F(RendererImplTest, AudioTrackDisableThenEnable) {
869 InitializeWithAudioAndVideo();
871 Mock::VerifyAndClearExpectations(&time_source_);
873 base::RunLoop disable_wait;
874 SetAudioTrackSwitchExpectations();
875 renderer_impl_->OnEnabledAudioTracksChanged({}, disable_wait.QuitClosure());
878 base::RunLoop enable_wait;
879 SetAudioTrackSwitchExpectations();
880 renderer_impl_->OnEnabledAudioTracksChanged({streams_[0]},
881 enable_wait.QuitClosure());
885 TEST_F(RendererImplTest, VideoTrackDisableThenEnable) {
886 InitializeWithAudioAndVideo();
888 Mock::VerifyAndClearExpectations(&time_source_);
890 base::RunLoop disable_wait;
891 SetVideoTrackSwitchExpectations();
892 renderer_impl_->OnSelectedVideoTracksChanged({}, disable_wait.QuitClosure());
895 base::RunLoop enable_wait;
896 SetVideoTrackSwitchExpectations();
897 renderer_impl_->OnSelectedVideoTracksChanged({streams_[1]},
898 enable_wait.QuitClosure());
901 base::RunLoop().RunUntilIdle();
904 TEST_F(RendererImplTest, AudioUnderflowDuringAudioTrackChange) {
905 InitializeWithAudioAndVideo();
910 // Underflow should occur immediately with a single audio track.
911 EXPECT_CALL(time_source_, StopTicking());
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));
918 EXPECT_CALL(time_source_, CurrentMediaTime()).Times(2);
919 std::vector<DemuxerStream*> tracks;
920 renderer_impl_->OnEnabledAudioTracksChanged({}, loop.QuitClosure());
922 EXPECT_CALL(callbacks_,
923 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
924 BUFFERING_CHANGE_REASON_UNKNOWN));
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();
934 TEST_F(RendererImplTest, VideoUnderflowDuringVideoTrackChange) {
935 InitializeWithAudioAndVideo();
940 // Capture the callback from the video renderer flush.
941 base::OnceClosure video_renderer_flush_cb;
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));
953 renderer_impl_->OnSelectedVideoTracksChanged({}, loop.QuitClosure());
955 video_renderer_client_->OnBufferingStateChange(
956 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
957 std::move(video_renderer_flush_cb).Run();
961 TEST_F(RendererImplTest, VideoUnderflowDuringAudioTrackChange) {
962 InitializeWithAudioAndVideo();
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));
972 EXPECT_CALL(time_source_, CurrentMediaTime()).Times(2);
973 EXPECT_CALL(time_source_, StopTicking());
974 renderer_impl_->OnEnabledAudioTracksChanged({}, loop.QuitClosure());
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();
983 TEST_F(RendererImplTest, AudioUnderflowDuringVideoTrackChange) {
984 InitializeWithAudioAndVideo();
988 EXPECT_CALL(callbacks_,
989 OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
990 BUFFERING_CHANGE_REASON_UNKNOWN));
991 EXPECT_CALL(time_source_, CurrentMediaTime());
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));
998 renderer_impl_->OnSelectedVideoTracksChanged({}, loop.QuitClosure());
1000 EXPECT_CALL(time_source_, StopTicking());
1001 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
1003 audio_renderer_client_->OnBufferingStateChange(
1004 BUFFERING_HAVE_NOTHING, BUFFERING_CHANGE_REASON_UNKNOWN);
1006 std::move(video_renderer_flush_cb).Run();
1010 TEST_F(RendererImplTest, VideoResumedFromUnderflowDuringAudioTrackChange) {
1011 InitializeWithAudioAndVideo();
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();
1025 // Start a track change.
1026 base::OnceClosure audio_renderer_flush_cb;
1027 base::RunLoop track_change;
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));
1034 renderer_impl_->OnEnabledAudioTracksChanged({}, track_change.QuitClosure());
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);
1043 // Finish the track change.
1044 EXPECT_CALL(*audio_renderer_, StartPlaying());
1045 std::move(audio_renderer_flush_cb).Run();
1049 TEST_F(RendererImplTest, AudioResumedFromUnderflowDuringVideoTrackChange) {
1050 InitializeWithAudioAndVideo();
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();
1064 // Start a track change.
1065 base::OnceClosure video_renderer_flush_cb;
1066 base::RunLoop track_change;
1068 InSequence track_switch_seq;
1069 EXPECT_CALL(time_source_, CurrentMediaTime());
1070 EXPECT_CALL(*video_renderer_, Flush(_))
1071 .WillOnce(MoveArg(&video_renderer_flush_cb));
1073 renderer_impl_->OnSelectedVideoTracksChanged({}, track_change.QuitClosure());
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);
1082 // Finish the track change.
1083 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_));
1084 std::move(video_renderer_flush_cb).Run();
1088 } // namespace media