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"
10 #include "base/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 OnAddTextTrack(const TextTrackConfig& config,
151 AddTextTrackDoneCB done_cb) override {}
152 void OnWaiting(WaitingReason reason) override {}
153 void OnVideoNaturalSizeChange(const gfx::Size& size) override {}
154 void OnAudioConfigChange(const AudioDecoderConfig& config) override {}
155 void OnVideoConfigChange(const VideoDecoderConfig& config) override {}
156 void OnVideoOpacityChange(bool opaque) override {}
157 void OnVideoFrameRateChange(absl::optional<int>) override {}
158 void OnVideoAverageKeyframeDistanceUpdate() override {}
159 void OnAudioPipelineInfoChange(const AudioPipelineInfo& info) override {}
160 void OnVideoPipelineInfoChange(const VideoPipelineInfo& info) override {}
162 base::test::SingleThreadTaskEnvironment task_environment_;
164 NiceMock<MockDemuxer> demuxer_;
165 raw_ptr<StrictMock<MockPipeline>> pipeline_;
166 PipelineController pipeline_controller_;
168 bool was_seeked_ = false;
169 bool last_seeked_time_updated_ = false;
170 bool was_suspended_ = false;
171 bool was_resuming_ = false;
172 bool was_resumed_ = false;
173 base::TimeDelta last_resume_time_;
176 TEST_F(PipelineControllerTest, Startup) {
177 PipelineStatusCallback start_cb = StartPipeline();
178 EXPECT_FALSE(was_seeked_);
180 Complete(std::move(start_cb));
181 EXPECT_TRUE(was_seeked_);
182 EXPECT_FALSE(last_seeked_time_updated_);
183 EXPECT_FALSE(was_suspended_);
184 EXPECT_TRUE(pipeline_controller_.IsStable());
187 TEST_F(PipelineControllerTest, StartSuspendedSeekAndResume) {
188 EXPECT_FALSE(pipeline_controller_.IsStable());
189 PipelineStatusCallback start_cb;
190 EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
191 pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
192 &demuxer_, this, false, true);
193 Mock::VerifyAndClear(pipeline_);
195 // Initiate a seek before the pipeline completes suspended startup.
196 base::TimeDelta seek_time = base::Seconds(5);
197 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time));
198 pipeline_controller_.Seek(seek_time, true);
199 base::RunLoop().RunUntilIdle();
200 EXPECT_FALSE(was_seeked_);
202 PipelineStatusCallback resume_cb;
203 EXPECT_CALL(*pipeline_, OnResume(_, _))
204 .WillOnce(DoAll(MoveArg<1>(&resume_cb)));
205 EXPECT_CALL(*pipeline_, GetMediaTime())
206 .WillRepeatedly(Return(base::TimeDelta()));
208 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
209 EXPECT_FALSE(pipeline_controller_.IsStable());
210 Complete(std::move(start_cb));
212 EXPECT_FALSE(pipeline_controller_.IsStable());
213 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
214 EXPECT_FALSE(pipeline_controller_.IsSuspended());
215 Mock::VerifyAndClear(pipeline_);
217 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
218 Complete(std::move(resume_cb));
219 EXPECT_TRUE(was_seeked_);
222 EXPECT_TRUE(pipeline_controller_.IsStable());
223 EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended());
224 EXPECT_FALSE(pipeline_controller_.IsSuspended());
225 Mock::VerifyAndClear(pipeline_);
228 TEST_F(PipelineControllerTest, StartSuspendedAndResume) {
229 EXPECT_FALSE(pipeline_controller_.IsStable());
230 PipelineStatusCallback start_cb;
231 EXPECT_CALL(*pipeline_, OnStart(_, _, _, _)).WillOnce(MoveArg<3>(&start_cb));
232 pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata,
233 &demuxer_, this, false, true);
234 Mock::VerifyAndClear(pipeline_);
235 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true));
236 EXPECT_FALSE(pipeline_controller_.IsStable());
237 Complete(std::move(start_cb));
238 EXPECT_TRUE(was_seeked_);
241 EXPECT_FALSE(pipeline_controller_.IsStable());
242 EXPECT_TRUE(pipeline_controller_.IsPipelineSuspended());
243 EXPECT_TRUE(pipeline_controller_.IsSuspended());
244 Mock::VerifyAndClear(pipeline_);
246 EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false));
247 PipelineStatusCallback resume_cb = ResumePipeline();
248 EXPECT_TRUE(was_resuming_);
249 EXPECT_FALSE(was_resumed_);
251 Complete(std::move(resume_cb));
252 EXPECT_TRUE(was_resumed_);
253 EXPECT_TRUE(pipeline_controller_.IsStable());
255 // |was_seeked_| should not be affected by Suspend()/Resume() at all.
256 EXPECT_FALSE(was_seeked_);
259 TEST_F(PipelineControllerTest, SuspendResume) {
260 Complete(StartPipeline());
261 EXPECT_TRUE(was_seeked_);
264 Complete(SuspendPipeline());
265 EXPECT_TRUE(was_suspended_);
266 EXPECT_FALSE(pipeline_controller_.IsStable());
268 PipelineStatusCallback resume_cb = ResumePipeline();
269 EXPECT_TRUE(was_resuming_);
270 EXPECT_FALSE(was_resumed_);
272 Complete(std::move(resume_cb));
273 EXPECT_TRUE(was_resumed_);
274 EXPECT_TRUE(pipeline_controller_.IsStable());
276 // |was_seeked_| should not be affected by Suspend()/Resume() at all.
277 EXPECT_FALSE(was_seeked_);
280 TEST_F(PipelineControllerTest, Seek) {
281 // Normal seeking should not result in a cancel.
282 EXPECT_CALL(demuxer_, CancelPendingSeek(_)).Times(0);
284 Complete(StartPipeline());
287 base::TimeDelta seek_time = base::Seconds(5);
288 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time));
289 PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
290 base::RunLoop().RunUntilIdle();
291 EXPECT_FALSE(was_seeked_);
293 Complete(std::move(seek_cb));
294 EXPECT_TRUE(was_seeked_);
295 EXPECT_TRUE(pipeline_controller_.IsStable());
298 // Makes sure OnDecoderStateLost() triggers a seek to the current media time.
299 TEST_F(PipelineControllerTest, DecoderStateLost) {
300 Complete(StartPipeline());
302 constexpr auto kCurrentMediaTime = base::Seconds(7);
303 EXPECT_CALL(*pipeline_, GetMediaTime())
304 .WillRepeatedly(Return(kCurrentMediaTime));
306 EXPECT_CALL(demuxer_, StartWaitingForSeek(kCurrentMediaTime));
307 EXPECT_CALL(*pipeline_, OnSeek(kCurrentMediaTime, _));
309 pipeline_controller_.OnDecoderStateLost();
310 base::RunLoop().RunUntilIdle();
313 // Makes sure OnDecoderStateLost() does not trigger a seek during pending seek.
314 TEST_F(PipelineControllerTest, DecoderStateLost_DuringPendingSeek) {
315 Complete(StartPipeline());
317 // Create a pending seek.
318 base::TimeDelta kSeekTime = base::Seconds(5);
319 EXPECT_CALL(demuxer_, StartWaitingForSeek(kSeekTime));
320 PipelineStatusCallback seek_cb = SeekPipeline(kSeekTime);
321 base::RunLoop().RunUntilIdle();
322 Mock::VerifyAndClear(&demuxer_);
324 // OnDecoderStateLost() should not trigger another seek.
325 EXPECT_CALL(*pipeline_, GetMediaTime()).Times(0);
326 pipeline_controller_.OnDecoderStateLost();
327 base::RunLoop().RunUntilIdle();
329 Complete(std::move(seek_cb));
332 TEST_F(PipelineControllerTest, SuspendResumeTime) {
333 Complete(StartPipeline());
334 Complete(SuspendPipeline());
336 base::TimeDelta seek_time = base::Seconds(5);
337 pipeline_controller_.Seek(seek_time, true);
338 base::RunLoop().RunUntilIdle();
340 Complete(ResumePipeline());
341 EXPECT_EQ(seek_time, last_resume_time_);
344 TEST_F(PipelineControllerTest, SuspendResumeTime_WithStreamingData) {
345 Complete(StartPipeline_WithStreamingData());
346 Complete(SuspendPipeline());
348 base::TimeDelta seek_time = base::Seconds(5);
349 pipeline_controller_.Seek(seek_time, true);
350 base::RunLoop().RunUntilIdle();
352 Complete(ResumePipeline());
353 EXPECT_EQ(base::TimeDelta(), last_resume_time_);
356 TEST_F(PipelineControllerTest, SeekAborted) {
357 Complete(StartPipeline());
359 // Create a first pending seek.
360 base::TimeDelta seek_time_1 = base::Seconds(5);
361 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_1));
362 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
363 base::RunLoop().RunUntilIdle();
364 Mock::VerifyAndClear(&demuxer_);
366 // Create a second seek; the first should be aborted.
367 base::TimeDelta seek_time_2 = base::Seconds(10);
368 EXPECT_CALL(demuxer_, CancelPendingSeek(seek_time_2));
369 pipeline_controller_.Seek(seek_time_2, true);
370 base::RunLoop().RunUntilIdle();
371 Mock::VerifyAndClear(&demuxer_);
373 // When the first seek is completed (or aborted) the second should be issued.
374 EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time_2));
375 EXPECT_CALL(*pipeline_, OnSeek(seek_time_2, _));
376 Complete(std::move(seek_cb_1));
379 TEST_F(PipelineControllerTest, PendingSuspend) {
380 Complete(StartPipeline());
382 base::TimeDelta seek_time = base::Seconds(5);
383 PipelineStatusCallback seek_cb = SeekPipeline(seek_time);
384 base::RunLoop().RunUntilIdle();
386 // While the seek is ongoing, request a suspend.
387 // It will be a mock failure if pipeline_.Suspend() is called.
388 pipeline_controller_.Suspend();
389 base::RunLoop().RunUntilIdle();
391 // Expect the suspend to trigger when the seek is completed.
392 EXPECT_CALL(*pipeline_, OnSuspend(_));
393 Complete(std::move(seek_cb));
396 TEST_F(PipelineControllerTest, SeekMergesWithResume) {
397 Complete(StartPipeline());
398 Complete(SuspendPipeline());
400 // Pipeline startup always completes with a seek.
401 EXPECT_TRUE(was_seeked_);
404 // Request a seek while suspended.
405 // It will be a mock failure if pipeline_.Seek() is called.
406 base::TimeDelta seek_time = base::Seconds(5);
407 pipeline_controller_.Seek(seek_time, true);
408 base::RunLoop().RunUntilIdle();
409 EXPECT_FALSE(was_seeked_);
411 // Resume and verify the resume time includes the seek.
412 Complete(ResumePipeline());
413 EXPECT_EQ(seek_time, last_resume_time_);
414 EXPECT_TRUE(last_seeked_time_updated_);
417 TEST_F(PipelineControllerTest, SeekMergesWithSeek) {
418 Complete(StartPipeline());
420 base::TimeDelta seek_time_1 = base::Seconds(5);
421 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time_1);
422 base::RunLoop().RunUntilIdle();
424 // Request another seek while the first is ongoing.
425 base::TimeDelta seek_time_2 = base::Seconds(10);
426 pipeline_controller_.Seek(seek_time_2, true);
427 base::RunLoop().RunUntilIdle();
429 // Request a third seek. (It should replace the second.)
430 base::TimeDelta seek_time_3 = base::Seconds(15);
431 pipeline_controller_.Seek(seek_time_3, true);
432 base::RunLoop().RunUntilIdle();
434 // Expect the third seek to trigger when the first seek completes.
435 EXPECT_CALL(*pipeline_, OnSeek(seek_time_3, _));
436 Complete(std::move(seek_cb_1));
439 TEST_F(PipelineControllerTest, SeekToSeekTimeElided) {
440 Complete(StartPipeline());
442 base::TimeDelta seek_time = base::Seconds(5);
443 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
444 base::RunLoop().RunUntilIdle();
446 // Request a seek to the same time again.
447 pipeline_controller_.Seek(seek_time, true);
448 base::RunLoop().RunUntilIdle();
450 // Complete the first seek.
451 // It would be a mock error if the second seek was dispatched here.
452 Complete(std::move(seek_cb_1));
453 EXPECT_TRUE(pipeline_controller_.IsStable());
456 TEST_F(PipelineControllerTest, SeekToSeekTimeNotElided) {
457 Complete(StartPipeline_WithDynamicData());
459 base::TimeDelta seek_time = base::Seconds(5);
460 PipelineStatusCallback seek_cb_1 = SeekPipeline(seek_time);
461 base::RunLoop().RunUntilIdle();
463 // Request a seek to the same time again.
464 pipeline_controller_.Seek(seek_time, true);
465 base::RunLoop().RunUntilIdle();
467 // Expect the second seek to trigger when the first seek completes.
468 EXPECT_CALL(*pipeline_, OnSeek(seek_time, _));
469 Complete(std::move(seek_cb_1));
472 TEST_F(PipelineControllerTest, VideoTrackChangeWhileSuspending) {
473 Complete(StartPipeline());
474 EXPECT_CALL(*pipeline_, OnSuspend(_));
475 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _)).Times(0);
476 pipeline_controller_.Suspend();
477 pipeline_controller_.OnSelectedVideoTrackChanged({});
480 TEST_F(PipelineControllerTest, AudioTrackChangeWhileSuspending) {
481 Complete(StartPipeline());
482 EXPECT_CALL(*pipeline_, OnSuspend(_));
483 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _)).Times(0);
484 pipeline_controller_.Suspend();
485 pipeline_controller_.OnEnabledAudioTracksChanged({});
488 TEST_F(PipelineControllerTest, AudioTrackChangeDuringVideoTrackChange) {
489 Complete(StartPipeline());
491 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _));
492 pipeline_controller_.OnSelectedVideoTrackChanged({});
493 pipeline_controller_.OnEnabledAudioTracksChanged({});
494 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _));
496 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
497 PipelineController::State::PLAYING);
499 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
500 PipelineController::State::PLAYING);
503 TEST_F(PipelineControllerTest, SuspendDuringVideoTrackChange) {
504 Complete(StartPipeline());
505 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _));
506 was_resumed_ = false;
507 pipeline_controller_.OnSelectedVideoTrackChanged({});
508 pipeline_controller_.Suspend();
511 EXPECT_CALL(*pipeline_, OnSuspend(_))
512 .WillOnce(RunOnceClosure(loop.QuitClosure()));
514 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
515 PipelineController::State::PLAYING);
518 EXPECT_FALSE(was_resumed_);
521 TEST_F(PipelineControllerTest, SuspendDuringAudioTrackChange) {
522 Complete(StartPipeline());
523 EXPECT_CALL(*pipeline_, OnEnabledAudioTracksChanged(_, _));
524 was_resumed_ = false;
526 pipeline_controller_.OnEnabledAudioTracksChanged({});
527 pipeline_controller_.Suspend();
530 EXPECT_CALL(*pipeline_, OnSuspend(_))
531 .WillOnce(RunOnceClosure(loop.QuitClosure()));
533 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
534 PipelineController::State::PLAYING);
537 EXPECT_FALSE(was_resumed_);
540 TEST_F(PipelineControllerTest, ResumePlaybackDuringSwitchingTracksState) {
541 Complete(StartPipeline());
542 Complete(SuspendPipeline());
543 EXPECT_CALL(*pipeline_, OnSelectedVideoTrackChanged(_, _)).Times(1);
544 EXPECT_CALL(*pipeline_, GetMediaTime()).Times(1);
545 EXPECT_CALL(*pipeline_, OnResume(_, _)).Times(1);
547 pipeline_controller_.OnSelectedVideoTrackChanged({});
548 pipeline_controller_.Resume();
549 pipeline_controller_.FireOnTrackChangeCompleteForTesting(
550 PipelineController::State::SUSPENDED);
553 TEST_F(PipelineControllerTest, PreservesPitch) {
554 Complete(StartPipeline());
555 EXPECT_CALL(*pipeline_, SetPreservesPitch(false));
556 pipeline_controller_.SetPreservesPitch(false);
558 EXPECT_CALL(*pipeline_, SetPreservesPitch(true));
559 pipeline_controller_.SetPreservesPitch(true);