1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/pipeline_controller.h"
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/notreached.h"
14 #include "base/run_loop.h"
15 #include "base/test/gmock_callback_support.h"
16 #include "base/test/gmock_move_support.h"
17 #include "base/test/task_environment.h"
18 #include "base/time/time.h"
19 #include "media/base/mock_filters.h"
20 #include "media/base/pipeline.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::base::test::RunOnceClosure;
26 using ::testing::AnyNumber;
27 using ::testing::DoAll;
28 using ::testing::Mock;
29 using ::testing::NiceMock;
30 using ::testing::Return;
31 using ::testing::SaveArg;
32 using ::testing::StrictMock;
36 class PipelineControllerTest : public ::testing::Test, public Pipeline::Client {
38 PipelineControllerTest()
39 : pipeline_(new StrictMock<MockPipeline>()),
41 std::unique_ptr<Pipeline>(pipeline_),
42 base::BindRepeating(&PipelineControllerTest::OnSeeked,
43 base::Unretained(this)),
44 base::BindRepeating(&PipelineControllerTest::OnSuspended,
45 base::Unretained(this)),
46 base::BindRepeating(&PipelineControllerTest::OnBeforeResume,
47 base::Unretained(this)),
48 base::BindRepeating(&PipelineControllerTest::OnResumed,
49 base::Unretained(this)),
50 base::BindRepeating(&PipelineControllerTest::OnError,
51 base::Unretained(this))) {}
53 PipelineControllerTest(const PipelineControllerTest&) = delete;
54 PipelineControllerTest& operator=(const PipelineControllerTest&) = delete;
56 ~PipelineControllerTest() override = default;
58 PipelineStatusCallback StartPipeline(bool is_streaming, bool is_static) {
59 EXPECT_FALSE(pipeline_controller_.IsStable());
60 PipelineStatusCallback start_cb;
61 EXPECT_CALL(*pipeline_, OnStart(_, _, _, _))
62 .WillOnce(MoveArg<3>(&start_cb));
63 pipeline_controller_.Start(Pipeline::StartType::kNormal, &demuxer_, this,
64 is_streaming, is_static);
65 Mock::VerifyAndClear(pipeline_);
66 EXPECT_CALL(*pipeline_, IsSuspended())
68 .WillOnce(Return(false));
69 EXPECT_FALSE(pipeline_controller_.IsStable());
73 PipelineStatusCallback StartPipeline() { return StartPipeline(false, true); }
75 PipelineStatusCallback StartPipeline_WithDynamicData() {
76 return StartPipeline(false, false);
79 PipelineStatusCallback StartPipeline_WithStreamingData() {
80 return StartPipeline(true, false);
83 PipelineStatusCallback SeekPipeline(base::TimeDelta time) {
84 EXPECT_TRUE(pipeline_controller_.IsStable());
85 PipelineStatusCallback seek_cb;
86 EXPECT_CALL(*pipeline_, OnSeek(time, _)).WillOnce(MoveArg<1>(&seek_cb));
87 pipeline_controller_.Seek(time, true);
88 Mock::VerifyAndClear(pipeline_);
89 EXPECT_FALSE(pipeline_controller_.IsStable());
93 PipelineStatusCallback SuspendPipeline() {
94 EXPECT_TRUE(pipeline_controller_.IsStable());
95 PipelineStatusCallback suspend_cb;
96 EXPECT_CALL(*pipeline_, OnSuspend(_)).WillOnce(MoveArg<0>(&suspend_cb));
97 pipeline_controller_.Suspend();
98 Mock::VerifyAndClear(pipeline_);
99 EXPECT_CALL(*pipeline_, IsSuspended())
101 .WillOnce(Return(true));
102 EXPECT_TRUE(pipeline_controller_.IsSuspended());
103 EXPECT_FALSE(pipeline_controller_.IsStable());
104 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
108 PipelineStatusCallback ResumePipeline() {
109 EXPECT_TRUE(pipeline_controller_.IsPipelineSuspended());
110 PipelineStatusCallback resume_cb;
111 EXPECT_CALL(*pipeline_, OnResume(_, _))
113 DoAll(SaveArg<0>(&last_resume_time_), MoveArg<1>(&resume_cb)));
114 EXPECT_CALL(*pipeline_, GetMediaTime())
115 .WillRepeatedly(Return(base::TimeDelta()));
116 pipeline_controller_.Resume();
117 Mock::VerifyAndClear(pipeline_);
118 EXPECT_CALL(*pipeline_, IsSuspended())
120 .WillOnce(Return(false));
121 EXPECT_FALSE(pipeline_controller_.IsSuspended());
122 EXPECT_FALSE(pipeline_controller_.IsStable());
123 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
127 void Complete(PipelineStatusCallback cb) {
128 std::move(cb).Run(PIPELINE_OK);
129 base::RunLoop().RunUntilIdle();
133 void OnSeeked(bool time_updated) {
135 last_seeked_time_updated_ = time_updated;
138 void OnSuspended() { was_suspended_ = true; }
139 void OnBeforeResume() { was_resuming_ = true; }
140 void OnResumed() { was_resumed_ = true; }
142 // Pipeline::Client overrides
143 void OnError(PipelineStatus status) override { NOTREACHED(); }
144 void OnFallback(PipelineStatus status) override { NOTREACHED(); }
145 void OnEnded() override {}
146 void OnMetadata(const PipelineMetadata& metadata) override {}
147 void OnBufferingStateChange(BufferingState state,
148 BufferingStateChangeReason reason) override {}
149 void OnDurationChange() override {}
150 void OnWaiting(WaitingReason reason) override {}
151 void OnVideoNaturalSizeChange(const gfx::Size& size) override {}
152 void OnAudioConfigChange(const AudioDecoderConfig& config) override {}
153 void OnVideoConfigChange(const VideoDecoderConfig& config) override {}
154 void OnVideoOpacityChange(bool opaque) override {}
155 void OnVideoFrameRateChange(absl::optional<int>) override {}
156 void OnVideoAverageKeyframeDistanceUpdate() override {}
157 void OnAudioPipelineInfoChange(const AudioPipelineInfo& info) override {}
158 void OnVideoPipelineInfoChange(const VideoPipelineInfo& info) override {}
160 base::test::SingleThreadTaskEnvironment task_environment_;
162 NiceMock<MockDemuxer> demuxer_;
163 raw_ptr<StrictMock<MockPipeline>, DanglingUntriaged> pipeline_;
164 PipelineController pipeline_controller_;
166 bool was_seeked_ = false;
167 bool last_seeked_time_updated_ = false;
168 bool was_suspended_ = false;
169 bool was_resuming_ = false;
170 bool was_resumed_ = false;
171 base::TimeDelta last_resume_time_;
174 TEST_F(PipelineControllerTest, Startup) {
175 PipelineStatusCallback start_cb = StartPipeline();
176 EXPECT_FALSE(was_seeked_);
178 Complete(std::move(start_cb));
179 EXPECT_TRUE(was_seeked_);
180 EXPECT_FALSE(last_seeked_time_updated_);
181 EXPECT_FALSE(was_suspended_);
182 EXPECT_TRUE(pipeline_controller_.IsStable());
185 TEST_F(PipelineControllerTest, StartSuspendedSeekAndResume) {
186 EXPECT_FALSE(pipeline_controller_.IsStable());
187 PipelineStatusCallback start_cb;
188 EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
189 pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
190 &demuxer_, this, false, true);
191 Mock::VerifyAndClear(pipeline_);
193 // Initiate a seek before the pipeline completes suspended startup.
194 base::TimeDelta seek_time = base::Seconds(5);
195 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time));
196 pipeline_controller_.Seek(seek_time, true);
197 base::RunLoop().RunUntilIdle();
198 EXPECT_FALSE(was_seeked_);
200 PipelineStatusCallback resume_cb;
201 EXPECT_CALL(*pipeline_, OnResume(_, _))
202 .WillOnce(DoAll(MoveArg<1>(&resume_cb)));
203 EXPECT_CALL(*pipeline_, GetMediaTime())
204 .WillRepeatedly(Return(base::TimeDelta()));
206 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
207 EXPECT_FALSE(pipeline_controller_.IsStable());
208 Complete(std::move(start_cb));
210 EXPECT_FALSE(pipeline_controller_.IsStable());
211 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
212 EXPECT_FALSE(pipeline_controller_.IsSuspended());
213 Mock::VerifyAndClear(pipeline_);
215 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
216 Complete(std::move(resume_cb));
217 EXPECT_TRUE(was_seeked_);
220 EXPECT_TRUE(pipeline_controller_.IsStable());
221 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
222 EXPECT_FALSE(pipeline_controller_.IsSuspended());
223 Mock::VerifyAndClear(pipeline_);
226 TEST_F(PipelineControllerTest, StartSuspendedAndResume) {
227 EXPECT_FALSE(pipeline_controller_.IsStable());
228 PipelineStatusCallback start_cb;
229 EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
230 pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
231 &demuxer_, this, false, true);
232 Mock::VerifyAndClear(pipeline_);
233 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
234 EXPECT_FALSE(pipeline_controller_.IsStable());
235 Complete(std::move(start_cb));
236 EXPECT_TRUE(was_seeked_);
239 EXPECT_FALSE(pipeline_controller_.IsStable());
240 EXPECT_TRUE(pipeline_controller_.IsPipelineSuspended());
241 EXPECT_TRUE(pipeline_controller_.IsSuspended());
242 Mock::VerifyAndClear(pipeline_);
244 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
245 PipelineStatusCallback resume_cb = ResumePipeline();
246 EXPECT_TRUE(was_resuming_);
247 EXPECT_FALSE(was_resumed_);
249 Complete(std::move(resume_cb));
250 EXPECT_TRUE(was_resumed_);
251 EXPECT_TRUE(pipeline_controller_.IsStable());
253 // |was_seeked_| should not be affected by Suspend()/Resume() at all.
254 EXPECT_FALSE(was_seeked_);
257 TEST_F(PipelineControllerTest, SuspendResume) {
258 Complete(StartPipeline());
259 EXPECT_TRUE(was_seeked_);
262 Complete(SuspendPipeline());
263 EXPECT_TRUE(was_suspended_);
264 EXPECT_FALSE(pipeline_controller_.IsStable());
266 PipelineStatusCallback resume_cb = ResumePipeline();
267 EXPECT_TRUE(was_resuming_);
268 EXPECT_FALSE(was_resumed_);
270 Complete(std::move(resume_cb));
271 EXPECT_TRUE(was_resumed_);
272 EXPECT_TRUE(pipeline_controller_.IsStable());
274 // |was_seeked_| should not be affected by Suspend()/Resume() at all.
275 EXPECT_FALSE(was_seeked_);
278 TEST_F(PipelineControllerTest, Seek) {
279 // Normal seeking should not result in a cancel.
280 EXPECT_CALL(demuxer_, CancelPendingSeek(_)).Times(0);
282 Complete(StartPipeline());
285 base::TimeDelta seek_time = base::Seconds(5);
286 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time));
287 PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
288 base::RunLoop().RunUntilIdle();
289 EXPECT_FALSE(was_seeked_);
291 Complete(std::move(seek_cb));
292 EXPECT_TRUE(was_seeked_);
293 EXPECT_TRUE(pipeline_controller_.IsStable());
296 // Makes sure OnDecoderStateLost() triggers a seek to the current media time.
297 TEST_F(PipelineControllerTest, DecoderStateLost) {
298 Complete(StartPipeline());
300 constexpr auto kCurrentMediaTime = base::Seconds(7);
301 EXPECT_CALL(*pipeline_, GetMediaTime())
302 .WillRepeatedly(Return(kCurrentMediaTime));
304 EXPECT_CALL(demuxer_, StartWaitingForSeek(kCurrentMediaTime));
305 EXPECT_CALL(*pipeline_, OnSeek(kCurrentMediaTime, _));
307 pipeline_controller_.OnDecoderStateLost();
308 base::RunLoop().RunUntilIdle();
311 // Makes sure OnDecoderStateLost() does not trigger a seek during pending seek.
312 TEST_F(PipelineControllerTest, DecoderStateLost_DuringPendingSeek) {
313 Complete(StartPipeline());
315 // Create a pending seek.
316 base::TimeDelta kSeekTime = base::Seconds(5);
317 EXPECT_CALL(demuxer_, StartWaitingForSeek(kSeekTime));
318 PipelineStatusCallback seek_cb = SeekPipeline(kSeekTime);
319 base::RunLoop().RunUntilIdle();
320 Mock::VerifyAndClear(&demuxer_);
322 // OnDecoderStateLost() should not trigger another seek.
323 EXPECT_CALL(*pipeline_, GetMediaTime()).Times(0);
324 pipeline_controller_.OnDecoderStateLost();
325 base::RunLoop().RunUntilIdle();
327 Complete(std::move(seek_cb));
330 TEST_F(PipelineControllerTest, SuspendResumeTime) {
331 Complete(StartPipeline());
332 Complete(SuspendPipeline());
334 base::TimeDelta seek_time = base::Seconds(5);
335 pipeline_controller_.Seek(seek_time, true);
336 base::RunLoop().RunUntilIdle();
338 Complete(ResumePipeline());
339 EXPECT_EQ(seek_time, last_resume_time_);
342 TEST_F(PipelineControllerTest, SuspendResumeTime_WithStreamingData) {
343 Complete(StartPipeline_WithStreamingData());
344 Complete(SuspendPipeline());
346 base::TimeDelta seek_time = base::Seconds(5);
347 pipeline_controller_.Seek(seek_time, true);
348 base::RunLoop().RunUntilIdle();
350 Complete(ResumePipeline());
351 EXPECT_EQ(base::TimeDelta(), last_resume_time_);
354 TEST_F(PipelineControllerTest, SeekAborted) {
355 Complete(StartPipeline());
357 // Create a first pending seek.
358 base::TimeDelta seek_time_1 = base::Seconds(5);
359 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_1));
360 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
361 base::RunLoop().RunUntilIdle();
362 Mock::VerifyAndClear(&demuxer_);
364 // Create a second seek; the first should be aborted.
365 base::TimeDelta seek_time_2 = base::Seconds(10);
366 EXPECT_CALL(demuxer_, CancelPendingSeek(seek_time_2));
367 pipeline_controller_.Seek(seek_time_2, true);
368 base::RunLoop().RunUntilIdle();
369 Mock::VerifyAndClear(&demuxer_);
371 // When the first seek is completed (or aborted) the second should be issued.
372 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_2));
373 EXPECT_CALL(*pipeline_, OnSeek(seek_time_2, _));
374 Complete(std::move(seek_cb_1));
377 TEST_F(PipelineControllerTest, PendingSuspend) {
378 Complete(StartPipeline());
380 base::TimeDelta seek_time = base::Seconds(5);
381 PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
382 base::RunLoop().RunUntilIdle();
384 // While the seek is ongoing, request a suspend.
385 // It will be a mock failure if pipeline_.Suspend() is called.
386 pipeline_controller_.Suspend();
387 base::RunLoop().RunUntilIdle();
389 // Expect the suspend to trigger when the seek is completed.
390 EXPECT_CALL(*pipeline_, OnSuspend(_));
391 Complete(std::move(seek_cb));
394 TEST_F(PipelineControllerTest, SeekMergesWithResume) {
395 Complete(StartPipeline());
396 Complete(SuspendPipeline());
398 // Pipeline startup always completes with a seek.
399 EXPECT_TRUE(was_seeked_);
402 // Request a seek while suspended.
403 // It will be a mock failure if pipeline_.Seek() is called.
404 base::TimeDelta seek_time = base::Seconds(5);
405 pipeline_controller_.Seek(seek_time, true);
406 base::RunLoop().RunUntilIdle();
407 EXPECT_FALSE(was_seeked_);
409 // Resume and verify the resume time includes the seek.
410 Complete(ResumePipeline());
411 EXPECT_EQ(seek_time, last_resume_time_);
412 EXPECT_TRUE(last_seeked_time_updated_);
415 TEST_F(PipelineControllerTest, SeekMergesWithSeek) {
416 Complete(StartPipeline());
418 base::TimeDelta seek_time_1 = base::Seconds(5);
419 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
420 base::RunLoop().RunUntilIdle();
422 // Request another seek while the first is ongoing.
423 base::TimeDelta seek_time_2 = base::Seconds(10);
424 pipeline_controller_.Seek(seek_time_2, true);
425 base::RunLoop().RunUntilIdle();
427 // Request a third seek. (It should replace the second.)
428 base::TimeDelta seek_time_3 = base::Seconds(15);
429 pipeline_controller_.Seek(seek_time_3, true);
430 base::RunLoop().RunUntilIdle();
432 // Expect the third seek to trigger when the first seek completes.
433 EXPECT_CALL(*pipeline_, OnSeek(seek_time_3, _));
434 Complete(std::move(seek_cb_1));
437 TEST_F(PipelineControllerTest, SeekToSeekTimeElided) {
438 Complete(StartPipeline());
440 base::TimeDelta seek_time = base::Seconds(5);
441 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
442 base::RunLoop().RunUntilIdle();
444 // Request a seek to the same time again.
445 pipeline_controller_.Seek(seek_time, true);
446 base::RunLoop().RunUntilIdle();
448 // Complete the first seek.
449 // It would be a mock error if the second seek was dispatched here.
450 Complete(std::move(seek_cb_1));
451 EXPECT_TRUE(pipeline_controller_.IsStable());
454 TEST_F(PipelineControllerTest, SeekToSeekTimeNotElided) {
455 Complete(StartPipeline_WithDynamicData());
457 base::TimeDelta seek_time = base::Seconds(5);
458 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
459 base::RunLoop().RunUntilIdle();
461 // Request a seek to the same time again.
462 pipeline_controller_.Seek(seek_time, true);
463 base::RunLoop().RunUntilIdle();
465 // Expect the second seek to trigger when the first seek completes.
466 EXPECT_CALL(*pipeline_, OnSeek(seek_time, _));
467 Complete(std::move(seek_cb_1));
470 TEST_F(PipelineControllerTest, VideoTrackChangeWhileSuspending) {
471 Complete(StartPipeline());
472 EXPECT_CALL(*pipeline_, OnSuspend(_));
473 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _)).Times(0);
474 pipeline_controller_.Suspend();
475 pipeline_controller_.OnSelectedVideoTrackChanged({});
478 TEST_F(PipelineControllerTest, AudioTrackChangeWhileSuspending) {
479 Complete(StartPipeline());
480 EXPECT_CALL(*pipeline_, OnSuspend(_));
481 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _)).Times(0);
482 pipeline_controller_.Suspend();
483 pipeline_controller_.OnEnabledAudioTracksChanged({});
486 TEST_F(PipelineControllerTest, AudioTrackChangeDuringVideoTrackChange) {
487 Complete(StartPipeline());
489 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _));
490 pipeline_controller_.OnSelectedVideoTrackChanged({});
491 pipeline_controller_.OnEnabledAudioTracksChanged({});
492 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _));
494 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
495 PipelineController::State::PLAYING);
497 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
498 PipelineController::State::PLAYING);
501 TEST_F(PipelineControllerTest, SuspendDuringVideoTrackChange) {
502 Complete(StartPipeline());
503 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _));
504 was_resumed_ = false;
505 pipeline_controller_.OnSelectedVideoTrackChanged({});
506 pipeline_controller_.Suspend();
509 EXPECT_CALL(*pipeline_, OnSuspend(_))
510 .WillOnce(RunOnceClosure(loop.QuitClosure()));
512 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
513 PipelineController::State::PLAYING);
516 EXPECT_FALSE(was_resumed_);
519 TEST_F(PipelineControllerTest, SuspendDuringAudioTrackChange) {
520 Complete(StartPipeline());
521 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _));
522 was_resumed_ = false;
524 pipeline_controller_.OnEnabledAudioTracksChanged({});
525 pipeline_controller_.Suspend();
528 EXPECT_CALL(*pipeline_, OnSuspend(_))
529 .WillOnce(RunOnceClosure(loop.QuitClosure()));
531 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
532 PipelineController::State::PLAYING);
535 EXPECT_FALSE(was_resumed_);
538 TEST_F(PipelineControllerTest, ResumePlaybackDuringSwitchingTracksState) {
539 Complete(StartPipeline());
540 Complete(SuspendPipeline());
541 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _)).Times(1);
542 EXPECT_CALL(*pipeline_, GetMediaTime()).Times(1);
543 EXPECT_CALL(*pipeline_, OnResume(_, _)).Times(1);
545 pipeline_controller_.OnSelectedVideoTrackChanged({});
546 pipeline_controller_.Resume();
547 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
548 PipelineController::State::SUSPENDED);
551 TEST_F(PipelineControllerTest, PreservesPitch) {
552 Complete(StartPipeline());
553 EXPECT_CALL(*pipeline_, SetPreservesPitch(false));
554 pipeline_controller_.SetPreservesPitch(false);
556 EXPECT_CALL(*pipeline_, SetPreservesPitch(true));
557 pipeline_controller_.SetPreservesPitch(true);