1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/base/pipeline_impl.h"
6
7 #include <stddef.h>
8 #include <memory>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/location.h"
14 #include "base/macros.h"
15 #include "base/run_loop.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/stl_util.h"
18 #include "base/test/gmock_callback_support.h"
19 #include "base/test/simple_test_tick_clock.h"
20 #include "base/test/task_environment.h"
21 #include "base/threading/simple_thread.h"
22 #include "base/threading/thread_task_runner_handle.h"
23 #include "base/time/clock.h"
24 #include "media/base/fake_text_track_stream.h"
25 #include "media/base/media_util.h"
26 #include "media/base/mock_filters.h"
27 #include "media/base/test_helpers.h"
28 #include "media/base/text_renderer.h"
29 #include "media/base/text_track_config.h"
30 #include "media/base/time_delta_interpolator.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/gfx/geometry/size.h"
33
34 using ::base::test::RunClosure;
35 using ::base::test::RunOnceCallback;
36 using ::base::test::RunOnceClosure;
37 using ::testing::_;
38 using ::testing::AnyNumber;
39 using ::testing::DeleteArg;
40 using ::testing::DoAll;
41 using ::testing::Invoke;
42 using ::testing::InvokeWithoutArgs;
43 using ::testing::Mock;
44 using ::testing::NiceMock;
45 using ::testing::NotNull;
46 using ::testing::Return;
47 using ::testing::SaveArg;
48 using ::testing::StrictMock;
49 using ::testing::WithArg;
50
51 namespace media {
52
ACTION_P(SetDemuxerProperties,duration)53 ACTION_P(SetDemuxerProperties, duration) {
54 arg0->SetDuration(duration);
55 }
56
ACTION_P(Stop,pipeline)57 ACTION_P(Stop, pipeline) {
58 pipeline->Stop();
59 }
60
ACTION_P(PostStop,pipeline)61 ACTION_P(PostStop, pipeline) {
62 base::ThreadTaskRunnerHandle::Get()->PostTask(
63 FROM_HERE, base::BindOnce(&Pipeline::Stop, base::Unretained(pipeline)));
64 }
65
ACTION_P2(SetError,renderer_client,status)66 ACTION_P2(SetError, renderer_client, status) {
67 (*renderer_client)->OnError(status);
68 }
69
ACTION_P3(SetBufferingState,renderer_client,buffering_state,reason)70 ACTION_P3(SetBufferingState, renderer_client, buffering_state, reason) {
71 (*renderer_client)->OnBufferingStateChange(buffering_state, reason);
72 }
73
ACTION_TEMPLATE(PostCallback,HAS_1_TEMPLATE_PARAMS (int,k),AND_1_VALUE_PARAMS (p0))74 ACTION_TEMPLATE(PostCallback,
75 HAS_1_TEMPLATE_PARAMS(int, k),
76 AND_1_VALUE_PARAMS(p0)) {
77 base::ThreadTaskRunnerHandle::Get()->PostTask(
78 FROM_HERE, base::BindOnce(std::move(std::get<k>(args)), p0));
79 }
80
81 // TODO(scherkus): even though some filters are initialized on separate
82 // threads these test aren't flaky... why? It's because filters' Initialize()
83 // is executed on |message_loop_| and the mock filters instantly call
84 // InitializationComplete(), which keeps the pipeline humming along. If
85 // either filters don't call InitializationComplete() immediately or filter
86 // initialization is moved to a separate thread this test will become flaky.
87 class PipelineImplTest : public ::testing::Test {
88 public:
89 // Used for setting expectations on pipeline callbacks. Using a StrictMock
90 // also lets us test for missing callbacks.
91 class CallbackHelper : public MockPipelineClient {
92 public:
93 CallbackHelper() = default;
94 virtual ~CallbackHelper() = default;
95
96 MOCK_METHOD1(OnStart, void(PipelineStatus));
97 MOCK_METHOD1(OnSeek, void(PipelineStatus));
98 MOCK_METHOD1(OnSuspend, void(PipelineStatus));
99 MOCK_METHOD1(OnResume, void(PipelineStatus));
100 MOCK_METHOD1(OnCdmAttached, void(bool));
101
102 private:
103 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
104 };
105
PipelineImplTest()106 PipelineImplTest()
107 : demuxer_(new StrictMock<MockDemuxer>()),
108 demuxer_host_(nullptr),
109 scoped_renderer_(new StrictMock<MockRenderer>()),
110 renderer_(scoped_renderer_.get()),
111 renderer_client_(nullptr) {
112 pipeline_ = std::make_unique<PipelineImpl>(
113 task_environment_.GetMainThreadTaskRunner(),
114 task_environment_.GetMainThreadTaskRunner(),
115 base::BindRepeating(&PipelineImplTest::CreateRenderer,
116 base::Unretained(this)),
117 &media_log_);
118
119 // SetDemuxerExpectations() adds overriding expectations for expected
120 // non-NULL streams.
121 std::vector<DemuxerStream*> empty;
122 EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(empty));
123
124 EXPECT_CALL(*demuxer_, GetTimelineOffset())
125 .WillRepeatedly(Return(base::Time()));
126
127 EXPECT_CALL(*renderer_, GetMediaTime())
128 .WillRepeatedly(Return(base::TimeDelta()));
129
130 EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
131
132 EXPECT_CALL(*renderer_, SetPreservesPitch(true)).Times(AnyNumber());
133 }
134
~PipelineImplTest()135 ~PipelineImplTest() override {
136 if (pipeline_->IsRunning()) {
137 ExpectDemuxerStop();
138
139 pipeline_->Stop();
140 }
141
142 pipeline_.reset();
143 base::RunLoop().RunUntilIdle();
144 }
145
OnDemuxerError()146 void OnDemuxerError() { demuxer_host_->OnDemuxerError(PIPELINE_ERROR_ABORT); }
147
148 protected:
149 // Sets up expectations to allow the demuxer to initialize.
SetDemuxerExpectations(base::TimeDelta duration)150 void SetDemuxerExpectations(base::TimeDelta duration) {
151 EXPECT_CALL(callbacks_, OnDurationChange());
152 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
153 .WillOnce(DoAll(SaveArg<0>(&demuxer_host_),
154 SetDemuxerProperties(duration),
155 PostCallback<1>(PIPELINE_OK)));
156 EXPECT_CALL(*demuxer_, GetAllStreams()).WillRepeatedly(Return(streams_));
157 }
158
SetDemuxerExpectations()159 void SetDemuxerExpectations() {
160 // Initialize with a default non-zero duration.
161 SetDemuxerExpectations(base::TimeDelta::FromSeconds(10));
162 }
163
CreateStream(DemuxerStream::Type type)164 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream(
165 DemuxerStream::Type type) {
166 std::unique_ptr<StrictMock<MockDemuxerStream>> stream(
167 new StrictMock<MockDemuxerStream>(type));
168 return stream;
169 }
170
171 // Sets up expectations to allow the renderer to initialize.
ExpectRendererInitialization()172 void ExpectRendererInitialization() {
173 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
174 .WillOnce(
175 DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK)));
176 }
177
StartPipeline(Pipeline::StartType start_type=Pipeline::StartType::kNormal)178 void StartPipeline(
179 Pipeline::StartType start_type = Pipeline::StartType::kNormal) {
180 EXPECT_CALL(callbacks_, OnWaiting(_)).Times(0);
181 pipeline_->Start(start_type, demuxer_.get(), &callbacks_,
182 base::BindOnce(&CallbackHelper::OnStart,
183 base::Unretained(&callbacks_)));
184 }
185
SetRendererPostStartExpectations()186 void SetRendererPostStartExpectations() {
187 EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
188 EXPECT_CALL(*renderer_, SetVolume(1.0f));
189 EXPECT_CALL(*renderer_, StartPlayingFrom(start_time_))
190 .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH,
191 BUFFERING_CHANGE_REASON_UNKNOWN));
192 EXPECT_CALL(callbacks_,
193 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
194 BUFFERING_CHANGE_REASON_UNKNOWN));
195 }
196
197 // Suspension status of the pipeline post Start().
198 enum class PostStartStatus {
199 kNormal,
200 kSuspended,
201 };
202
203 // Sets up expectations on the callback and initializes the pipeline. Called
204 // after tests have set expectations any filters they wish to use.
StartPipelineAndExpect(PipelineStatus start_status,Pipeline::StartType start_type=Pipeline::StartType::kNormal,PostStartStatus post_start_status=PostStartStatus::kNormal)205 void StartPipelineAndExpect(
206 PipelineStatus start_status,
207 Pipeline::StartType start_type = Pipeline::StartType::kNormal,
208 PostStartStatus post_start_status = PostStartStatus::kNormal) {
209 EXPECT_CALL(callbacks_, OnStart(start_status));
210
211 if (start_status == PIPELINE_OK) {
212 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
213
214 if (start_type == Pipeline::StartType::kNormal)
215 ExpectRendererInitialization();
216
217 if (post_start_status == PostStartStatus::kNormal)
218 SetRendererPostStartExpectations();
219 }
220
221 StartPipeline(start_type);
222 base::RunLoop().RunUntilIdle();
223
224 if (start_status == PIPELINE_OK)
225 EXPECT_TRUE(pipeline_->IsRunning());
226
227 if (post_start_status != PostStartStatus::kNormal)
228 EXPECT_TRUE(pipeline_->IsSuspended());
229 }
230
CreateAudioStream()231 void CreateAudioStream() {
232 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
233 streams_.push_back(audio_stream_.get());
234 }
235
CreateVideoStream(bool is_encrypted=false)236 void CreateVideoStream(bool is_encrypted = false) {
237 video_stream_ = CreateStream(DemuxerStream::VIDEO);
238 video_stream_->set_video_decoder_config(
239 is_encrypted ? TestVideoConfig::NormalEncrypted()
240 : TestVideoConfig::Normal());
241 streams_.push_back(video_stream_.get());
242 }
243
CreateAudioAndVideoStream()244 void CreateAudioAndVideoStream() {
245 CreateAudioStream();
246 CreateVideoStream();
247 }
248
CreateEncryptedVideoStream()249 void CreateEncryptedVideoStream() { CreateVideoStream(true); }
250
SetCdmAndExpect(bool expected_result)251 void SetCdmAndExpect(bool expected_result) {
252 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
253 EXPECT_CALL(callbacks_, OnCdmAttached(expected_result));
254 pipeline_->SetCdm(&cdm_context_,
255 base::BindOnce(&CallbackHelper::OnCdmAttached,
256 base::Unretained(&callbacks_)));
257 base::RunLoop().RunUntilIdle();
258 }
259
ExpectSeek(const base::TimeDelta & seek_time,bool underflowed)260 void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
261 EXPECT_CALL(*demuxer_, AbortPendingReads());
262 EXPECT_CALL(*demuxer_, OnSeek(seek_time, _))
263 .WillOnce(RunOnceCallback<1>(PIPELINE_OK));
264
265 EXPECT_CALL(*renderer_, OnFlush(_)).WillOnce(RunOnceClosure<0>());
266 EXPECT_CALL(*renderer_, SetPlaybackRate(_));
267 EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
268 .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH,
269 BUFFERING_CHANGE_REASON_UNKNOWN));
270
271 // We expect a successful seek callback followed by a buffering update.
272 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
273 EXPECT_CALL(callbacks_,
274 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
275 BUFFERING_CHANGE_REASON_UNKNOWN));
276 }
277
DoSeek(const base::TimeDelta & seek_time)278 void DoSeek(const base::TimeDelta& seek_time) {
279 pipeline_->Seek(seek_time, base::BindOnce(&CallbackHelper::OnSeek,
280 base::Unretained(&callbacks_)));
281 base::RunLoop().RunUntilIdle();
282 }
283
ExpectSuspend()284 void ExpectSuspend() {
285 EXPECT_CALL(*demuxer_, AbortPendingReads());
286 EXPECT_CALL(*renderer_, SetPlaybackRate(0));
287 EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
288 }
289
DoSuspend()290 void DoSuspend() {
291 pipeline_->Suspend(base::BindOnce(&CallbackHelper::OnSuspend,
292 base::Unretained(&callbacks_)));
293 base::RunLoop().RunUntilIdle();
294 ResetRenderer();
295 }
296
CreateRenderer(base::Optional<RendererFactoryType>)297 std::unique_ptr<Renderer> CreateRenderer(
298 base::Optional<RendererFactoryType> /* factory_type */) {
299 return std::move(scoped_renderer_);
300 }
301
ResetRenderer()302 void ResetRenderer() {
303 // |renderer_| has been deleted, replace it.
304 scoped_renderer_.reset(new StrictMock<MockRenderer>());
305 renderer_ = scoped_renderer_.get();
306 EXPECT_CALL(*renderer_, SetPreservesPitch(_)).Times(AnyNumber());
307 }
308
ExpectResume(const base::TimeDelta & seek_time)309 void ExpectResume(const base::TimeDelta& seek_time) {
310 ExpectRendererInitialization();
311 EXPECT_CALL(*demuxer_, OnSeek(seek_time, _))
312 .WillOnce(RunOnceCallback<1>(PIPELINE_OK));
313 EXPECT_CALL(*renderer_, SetPlaybackRate(_));
314 EXPECT_CALL(*renderer_, SetVolume(_));
315 EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
316 .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH,
317 BUFFERING_CHANGE_REASON_UNKNOWN));
318 EXPECT_CALL(callbacks_,
319 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
320 BUFFERING_CHANGE_REASON_UNKNOWN));
321 EXPECT_CALL(callbacks_, OnResume(PIPELINE_OK));
322 }
323
DoResume(const base::TimeDelta & seek_time)324 void DoResume(const base::TimeDelta& seek_time) {
325 pipeline_->Resume(seek_time, base::BindOnce(&CallbackHelper::OnResume,
326 base::Unretained(&callbacks_)));
327 base::RunLoop().RunUntilIdle();
328 }
329
ExpectDemuxerStop()330 void ExpectDemuxerStop() {
331 if (demuxer_)
332 EXPECT_CALL(*demuxer_, Stop());
333 }
334
RunBufferedTimeRangesTest(const base::TimeDelta duration)335 void RunBufferedTimeRangesTest(const base::TimeDelta duration) {
336 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
337 EXPECT_FALSE(pipeline_->DidLoadingProgress());
338
339 Ranges<base::TimeDelta> ranges;
340 ranges.Add(base::TimeDelta(), duration);
341 demuxer_host_->OnBufferedTimeRangesChanged(ranges);
342 base::RunLoop().RunUntilIdle();
343
344 EXPECT_TRUE(pipeline_->DidLoadingProgress());
345 EXPECT_FALSE(pipeline_->DidLoadingProgress());
346 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
347 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
348 EXPECT_EQ(duration, pipeline_->GetBufferedTimeRanges().end(0));
349 }
350
351 // Fixture members.
352 StrictMock<CallbackHelper> callbacks_;
353 base::SimpleTestTickClock test_tick_clock_;
354 base::test::SingleThreadTaskEnvironment task_environment_;
355 NullMediaLog media_log_;
356 std::unique_ptr<PipelineImpl> pipeline_;
357 NiceMock<MockCdmContext> cdm_context_;
358
359 std::unique_ptr<StrictMock<MockDemuxer>> demuxer_;
360 DemuxerHost* demuxer_host_;
361 std::unique_ptr<StrictMock<MockRenderer>> scoped_renderer_;
362 StrictMock<MockRenderer>* renderer_;
363 std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_;
364 std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_;
365 std::vector<DemuxerStream*> streams_;
366 RendererClient* renderer_client_;
367 VideoDecoderConfig video_decoder_config_;
368 PipelineMetadata metadata_;
369 base::TimeDelta start_time_;
370
371 private:
372 DISALLOW_COPY_AND_ASSIGN(PipelineImplTest);
373 };
374
375 // Test that playback controls methods can be set even before the pipeline is
376 // started.
TEST_F(PipelineImplTest,ControlMethods)377 TEST_F(PipelineImplTest, ControlMethods) {
378 const base::TimeDelta kZero;
379
380 EXPECT_FALSE(pipeline_->IsRunning());
381
382 // Initial value.
383 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
384 // Invalid values cannot be set.
385 pipeline_->SetPlaybackRate(-1.0);
386 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
387 // Valid settings should work.
388 pipeline_->SetPlaybackRate(1.0);
389 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
390
391 // Initial value.
392 EXPECT_EQ(1.0f, pipeline_->GetVolume());
393 // Invalid values cannot be set.
394 pipeline_->SetVolume(-1.0f);
395 EXPECT_EQ(1.0f, pipeline_->GetVolume());
396 // Valid settings should work.
397 pipeline_->SetVolume(0.0f);
398 EXPECT_EQ(0.0f, pipeline_->GetVolume());
399
400 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
401 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
402 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
403 }
404
TEST_F(PipelineImplTest,NeverInitializes)405 TEST_F(PipelineImplTest, NeverInitializes) {
406 // Don't execute the callback passed into Initialize().
407 EXPECT_CALL(*demuxer_, OnInitialize(_, _));
408
409 // This test hangs during initialization by never calling
410 // InitializationComplete(). StrictMock<> will ensure that the callback is
411 // never executed.
412 StartPipeline();
413 base::RunLoop().RunUntilIdle();
414
415 // Because our callback will get executed when the test tears down, we'll
416 // verify that nothing has been called, then set our expectation for the call
417 // made during tear down.
418 Mock::VerifyAndClear(&callbacks_);
419 }
420
TEST_F(PipelineImplTest,StopWithoutStart)421 TEST_F(PipelineImplTest, StopWithoutStart) {
422 pipeline_->Stop();
423 base::RunLoop().RunUntilIdle();
424 }
425
TEST_F(PipelineImplTest,StartThenStopImmediately)426 TEST_F(PipelineImplTest, StartThenStopImmediately) {
427 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
428 .WillOnce(PostCallback<1>(PIPELINE_OK));
429 EXPECT_CALL(*demuxer_, Stop());
430 EXPECT_CALL(callbacks_, OnMetadata(_));
431
432 EXPECT_CALL(callbacks_, OnStart(_));
433 StartPipeline();
434 base::RunLoop().RunUntilIdle();
435
436 pipeline_->Stop();
437 }
438
TEST_F(PipelineImplTest,StartSuspendedAndResumeAudioOnly)439 TEST_F(PipelineImplTest, StartSuspendedAndResumeAudioOnly) {
440 CreateAudioStream();
441 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
442
443 StartPipelineAndExpect(PIPELINE_OK,
444 Pipeline::StartType::kSuspendAfterMetadataForAudioOnly,
445 PostStartStatus::kSuspended);
446 ASSERT_TRUE(pipeline_->IsSuspended());
447
448 ResetRenderer();
449 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
450 ExpectResume(expected);
451 DoResume(expected);
452 }
453
TEST_F(PipelineImplTest,StartSuspendedAndResumeAudioVideo)454 TEST_F(PipelineImplTest, StartSuspendedAndResumeAudioVideo) {
455 CreateAudioAndVideoStream();
456 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
457
458 StartPipelineAndExpect(PIPELINE_OK,
459 Pipeline::StartType::kSuspendAfterMetadata,
460 PostStartStatus::kSuspended);
461 ASSERT_TRUE(pipeline_->IsSuspended());
462
463 ResetRenderer();
464 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
465 ExpectResume(expected);
466 DoResume(expected);
467 }
468
TEST_F(PipelineImplTest,StartSuspendedFailsOnVideoWithAudioOnlyExpectation)469 TEST_F(PipelineImplTest, StartSuspendedFailsOnVideoWithAudioOnlyExpectation) {
470 CreateAudioAndVideoStream();
471 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
472
473 // StartType kSuspendAfterMetadataForAudioOnly only applies to AudioOnly.
474 // Since this playback has video, renderer will be initialized and the
475 // pipeline is not suspended.
476 ExpectRendererInitialization();
477 StartPipelineAndExpect(PIPELINE_OK,
478 Pipeline::StartType::kSuspendAfterMetadataForAudioOnly,
479 PostStartStatus::kNormal);
480 ASSERT_FALSE(pipeline_->IsSuspended());
481 }
482
TEST_F(PipelineImplTest,DemuxerErrorDuringStop)483 TEST_F(PipelineImplTest, DemuxerErrorDuringStop) {
484 CreateAudioStream();
485 SetDemuxerExpectations();
486
487 StartPipelineAndExpect(PIPELINE_OK);
488 base::RunLoop().RunUntilIdle();
489
490 EXPECT_CALL(*demuxer_, Stop())
491 .WillOnce(InvokeWithoutArgs(this, &PipelineImplTest::OnDemuxerError));
492 pipeline_->Stop();
493 base::RunLoop().RunUntilIdle();
494 }
495
TEST_F(PipelineImplTest,NoStreams)496 TEST_F(PipelineImplTest, NoStreams) {
497 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
498 .WillOnce(PostCallback<1>(PIPELINE_OK));
499 EXPECT_CALL(callbacks_, OnMetadata(_));
500
501 StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
502 }
503
TEST_F(PipelineImplTest,AudioStream)504 TEST_F(PipelineImplTest, AudioStream) {
505 CreateAudioStream();
506 SetDemuxerExpectations();
507
508 StartPipelineAndExpect(PIPELINE_OK);
509 EXPECT_TRUE(metadata_.has_audio);
510 EXPECT_FALSE(metadata_.has_video);
511 }
512
TEST_F(PipelineImplTest,VideoStream)513 TEST_F(PipelineImplTest, VideoStream) {
514 CreateVideoStream();
515 SetDemuxerExpectations();
516
517 StartPipelineAndExpect(PIPELINE_OK);
518 EXPECT_FALSE(metadata_.has_audio);
519 EXPECT_TRUE(metadata_.has_video);
520 }
521
TEST_F(PipelineImplTest,AudioVideoStream)522 TEST_F(PipelineImplTest, AudioVideoStream) {
523 CreateAudioAndVideoStream();
524 SetDemuxerExpectations();
525
526 StartPipelineAndExpect(PIPELINE_OK);
527 EXPECT_TRUE(metadata_.has_audio);
528 EXPECT_TRUE(metadata_.has_video);
529 }
530
TEST_F(PipelineImplTest,EncryptedStream_SetCdmBeforeStart)531 TEST_F(PipelineImplTest, EncryptedStream_SetCdmBeforeStart) {
532 CreateEncryptedVideoStream();
533 SetDemuxerExpectations();
534
535 SetCdmAndExpect(true);
536 StartPipelineAndExpect(PIPELINE_OK);
537 }
538
TEST_F(PipelineImplTest,EncryptedStream_SetCdmAfterStart)539 TEST_F(PipelineImplTest, EncryptedStream_SetCdmAfterStart) {
540 CreateEncryptedVideoStream();
541 SetDemuxerExpectations();
542
543 // Demuxer initialization and metadata reporting don't wait for CDM.
544 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
545
546 base::RunLoop run_loop;
547 EXPECT_CALL(callbacks_, OnWaiting(_))
548 .WillOnce(RunClosure(run_loop.QuitClosure()));
549 pipeline_->Start(
550 Pipeline::StartType::kNormal, demuxer_.get(), &callbacks_,
551 base::BindOnce(&CallbackHelper::OnStart, base::Unretained(&callbacks_)));
552 run_loop.Run();
553
554 ExpectRendererInitialization();
555 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
556 SetRendererPostStartExpectations();
557 SetCdmAndExpect(true);
558 }
559
TEST_F(PipelineImplTest,Seek)560 TEST_F(PipelineImplTest, Seek) {
561 CreateAudioAndVideoStream();
562 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
563
564 // Initialize then seek!
565 StartPipelineAndExpect(PIPELINE_OK);
566
567 // Every filter should receive a call to Seek().
568 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
569 ExpectSeek(expected, false);
570 DoSeek(expected);
571 }
572
TEST_F(PipelineImplTest,SeekAfterError)573 TEST_F(PipelineImplTest, SeekAfterError) {
574 CreateAudioStream();
575 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
576
577 // Initialize then seek!
578 StartPipelineAndExpect(PIPELINE_OK);
579
580 // Pipeline::Client is supposed to call Pipeline::Stop() after errors.
581 EXPECT_CALL(callbacks_, OnError(_)).WillOnce(Stop(pipeline_.get()));
582 EXPECT_CALL(*demuxer_, Stop());
583 OnDemuxerError();
584 base::RunLoop().RunUntilIdle();
585
586 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_INVALID_STATE));
587 pipeline_->Seek(
588 base::TimeDelta::FromMilliseconds(100),
589 base::BindOnce(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
590 base::RunLoop().RunUntilIdle();
591 }
592
TEST_F(PipelineImplTest,SuspendResume)593 TEST_F(PipelineImplTest, SuspendResume) {
594 CreateAudioAndVideoStream();
595 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
596
597 StartPipelineAndExpect(PIPELINE_OK);
598
599 // Inject some fake memory usage to verify its cleared after suspend.
600 PipelineStatistics stats;
601 stats.audio_memory_usage = 12345;
602 stats.video_memory_usage = 67890;
603 renderer_client_->OnStatisticsUpdate(stats);
604 base::RunLoop().RunUntilIdle();
605
606 EXPECT_EQ(stats.audio_memory_usage,
607 pipeline_->GetStatistics().audio_memory_usage);
608 EXPECT_EQ(stats.video_memory_usage,
609 pipeline_->GetStatistics().video_memory_usage);
610
611 // Make sure the preserves pitch flag is preserved between after resuming.
612 EXPECT_CALL(*renderer_, SetPreservesPitch(false)).Times(1);
613 pipeline_->SetPreservesPitch(false);
614
615 ExpectSuspend();
616 DoSuspend();
617
618 EXPECT_EQ(0, pipeline_->GetStatistics().audio_memory_usage);
619 EXPECT_EQ(0, pipeline_->GetStatistics().video_memory_usage);
620
621 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
622 ExpectResume(expected);
623 EXPECT_CALL(*renderer_, SetPreservesPitch(false)).Times(1);
624
625 DoResume(expected);
626 }
627
TEST_F(PipelineImplTest,SetVolume)628 TEST_F(PipelineImplTest, SetVolume) {
629 CreateAudioStream();
630 SetDemuxerExpectations();
631
632 // The audio renderer should receive a call to SetVolume().
633 float expected = 0.5f;
634 EXPECT_CALL(*renderer_, SetVolume(expected));
635
636 // Initialize then set volume!
637 StartPipelineAndExpect(PIPELINE_OK);
638 pipeline_->SetVolume(expected);
639 base::RunLoop().RunUntilIdle();
640 }
641
TEST_F(PipelineImplTest,SetVolumeDuringStartup)642 TEST_F(PipelineImplTest, SetVolumeDuringStartup) {
643 CreateAudioStream();
644 SetDemuxerExpectations();
645
646 // The audio renderer should receive two calls to SetVolume().
647 float expected = 0.5f;
648 EXPECT_CALL(*renderer_, SetVolume(expected)).Times(2);
649 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
650 EXPECT_CALL(callbacks_, OnMetadata(_))
651 .WillOnce(RunOnceClosure(base::BindOnce(&PipelineImpl::SetVolume,
652 base::Unretained(pipeline_.get()),
653 expected)));
654 ExpectRendererInitialization();
655 EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
656 EXPECT_CALL(*renderer_, StartPlayingFrom(start_time_))
657 .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH,
658 BUFFERING_CHANGE_REASON_UNKNOWN));
659 EXPECT_CALL(callbacks_,
660 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
661 BUFFERING_CHANGE_REASON_UNKNOWN));
662 StartPipeline();
663 base::RunLoop().RunUntilIdle();
664 }
665
TEST_F(PipelineImplTest,SetPreservesPitch)666 TEST_F(PipelineImplTest, SetPreservesPitch) {
667 CreateAudioStream();
668 SetDemuxerExpectations();
669
670 // The audio renderer preserve pitch by default.
671 EXPECT_CALL(*renderer_, SetPreservesPitch(true));
672 StartPipelineAndExpect(PIPELINE_OK);
673 base::RunLoop().RunUntilIdle();
674
675 // Changes to the preservesPitch flag should be propagated.
676 EXPECT_CALL(*renderer_, SetPreservesPitch(false));
677 pipeline_->SetPreservesPitch(false);
678 base::RunLoop().RunUntilIdle();
679 }
680
TEST_F(PipelineImplTest,Properties)681 TEST_F(PipelineImplTest, Properties) {
682 CreateVideoStream();
683 const auto kDuration = base::TimeDelta::FromSeconds(100);
684 SetDemuxerExpectations(kDuration);
685
686 StartPipelineAndExpect(PIPELINE_OK);
687 EXPECT_EQ(kDuration.ToInternalValue(),
688 pipeline_->GetMediaDuration().ToInternalValue());
689 EXPECT_FALSE(pipeline_->DidLoadingProgress());
690 }
691
TEST_F(PipelineImplTest,GetBufferedTimeRanges)692 TEST_F(PipelineImplTest, GetBufferedTimeRanges) {
693 CreateVideoStream();
694 const auto kDuration = base::TimeDelta::FromSeconds(100);
695 SetDemuxerExpectations(kDuration);
696
697 StartPipelineAndExpect(PIPELINE_OK);
698 RunBufferedTimeRangesTest(kDuration / 8);
699
700 base::TimeDelta kSeekTime = kDuration / 2;
701 ExpectSeek(kSeekTime, false);
702 DoSeek(kSeekTime);
703
704 EXPECT_FALSE(pipeline_->DidLoadingProgress());
705 }
706
TEST_F(PipelineImplTest,BufferedTimeRangesCanChangeAfterStop)707 TEST_F(PipelineImplTest, BufferedTimeRangesCanChangeAfterStop) {
708 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
709 .WillOnce(
710 DoAll(SaveArg<0>(&demuxer_host_), PostCallback<1>(PIPELINE_OK)));
711 EXPECT_CALL(*demuxer_, Stop());
712 EXPECT_CALL(callbacks_, OnMetadata(_));
713 EXPECT_CALL(callbacks_, OnStart(_));
714 StartPipeline();
715 base::RunLoop().RunUntilIdle();
716
717 pipeline_->Stop();
718 RunBufferedTimeRangesTest(base::TimeDelta::FromSeconds(5));
719 }
720
TEST_F(PipelineImplTest,OnStatisticsUpdate)721 TEST_F(PipelineImplTest, OnStatisticsUpdate) {
722 CreateAudioAndVideoStream();
723 SetDemuxerExpectations();
724 StartPipelineAndExpect(PIPELINE_OK);
725
726 PipelineStatistics stats;
727 stats.audio_decoder_info.decoder_name = "TestAudioDecoderName";
728 stats.audio_decoder_info.is_platform_decoder = false;
729 EXPECT_CALL(callbacks_, OnAudioDecoderChange(_));
730 renderer_client_->OnStatisticsUpdate(stats);
731 base::RunLoop().RunUntilIdle();
732
733 // VideoDecoderInfo changed and we expect OnVideoDecoderChange() to be called.
734 stats.video_decoder_info.decoder_name = "TestVideoDecoderName";
735 stats.video_decoder_info.is_platform_decoder = true;
736 EXPECT_CALL(callbacks_, OnVideoDecoderChange(_));
737 renderer_client_->OnStatisticsUpdate(stats);
738 base::RunLoop().RunUntilIdle();
739
740 // OnStatisticsUpdate() with the same |stats| should not cause new
741 // PipelineClient calls.
742 renderer_client_->OnStatisticsUpdate(stats);
743 base::RunLoop().RunUntilIdle();
744
745 // AudioDecoderInfo changed and we expect OnAudioDecoderChange() to be called.
746 stats.audio_decoder_info.is_platform_decoder = true;
747 EXPECT_CALL(callbacks_, OnAudioDecoderChange(_));
748 renderer_client_->OnStatisticsUpdate(stats);
749 base::RunLoop().RunUntilIdle();
750
751 // Both info changed.
752 stats.audio_decoder_info.decoder_name = "NewTestAudioDecoderName";
753 stats.video_decoder_info.has_decrypting_demuxer_stream = true;
754 EXPECT_CALL(callbacks_, OnAudioDecoderChange(_));
755 EXPECT_CALL(callbacks_, OnVideoDecoderChange(_));
756 renderer_client_->OnStatisticsUpdate(stats);
757 base::RunLoop().RunUntilIdle();
758 }
759
TEST_F(PipelineImplTest,EndedCallback)760 TEST_F(PipelineImplTest, EndedCallback) {
761 CreateAudioAndVideoStream();
762 SetDemuxerExpectations();
763 StartPipelineAndExpect(PIPELINE_OK);
764
765 // The ended callback shouldn't run until all renderers have ended.
766 EXPECT_CALL(callbacks_, OnEnded());
767 renderer_client_->OnEnded();
768 base::RunLoop().RunUntilIdle();
769 }
770
TEST_F(PipelineImplTest,ErrorDuringSeek)771 TEST_F(PipelineImplTest, ErrorDuringSeek) {
772 CreateAudioStream();
773 SetDemuxerExpectations();
774 StartPipelineAndExpect(PIPELINE_OK);
775
776 double playback_rate = 1.0;
777 EXPECT_CALL(*renderer_, SetPlaybackRate(playback_rate));
778 pipeline_->SetPlaybackRate(playback_rate);
779 base::RunLoop().RunUntilIdle();
780
781 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
782
783 EXPECT_CALL(*renderer_, OnFlush(_)).WillOnce(RunOnceClosure<0>());
784
785 EXPECT_CALL(*demuxer_, AbortPendingReads());
786 EXPECT_CALL(*demuxer_, OnSeek(seek_time, _))
787 .WillOnce(RunOnceCallback<1>(PIPELINE_ERROR_READ));
788 EXPECT_CALL(*demuxer_, Stop());
789
790 pipeline_->Seek(seek_time, base::BindOnce(&CallbackHelper::OnSeek,
791 base::Unretained(&callbacks_)));
792 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ))
793 .WillOnce(Stop(pipeline_.get()));
794 base::RunLoop().RunUntilIdle();
795 }
796
TEST_F(PipelineImplTest,DestroyAfterStop)797 TEST_F(PipelineImplTest, DestroyAfterStop) {
798 CreateAudioStream();
799 SetDemuxerExpectations();
800 StartPipelineAndExpect(PIPELINE_OK);
801
802 ExpectDemuxerStop();
803 pipeline_->Stop();
804 base::RunLoop().RunUntilIdle();
805 }
806
TEST_F(PipelineImplTest,Underflow)807 TEST_F(PipelineImplTest, Underflow) {
808 CreateAudioAndVideoStream();
809 SetDemuxerExpectations();
810 StartPipelineAndExpect(PIPELINE_OK);
811
812 // Simulate underflow.
813 EXPECT_CALL(callbacks_,
814 OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
815 BUFFERING_CHANGE_REASON_UNKNOWN));
816 renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING,
817 BUFFERING_CHANGE_REASON_UNKNOWN);
818 base::RunLoop().RunUntilIdle();
819
820 // Seek while underflowed.
821 base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
822 ExpectSeek(expected, true);
823 DoSeek(expected);
824 }
825
TEST_F(PipelineImplTest,PositiveStartTime)826 TEST_F(PipelineImplTest, PositiveStartTime) {
827 start_time_ = base::TimeDelta::FromSeconds(1);
828 EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
829 CreateAudioStream();
830 SetDemuxerExpectations();
831 StartPipelineAndExpect(PIPELINE_OK);
832 ExpectDemuxerStop();
833 pipeline_->Stop();
834 base::RunLoop().RunUntilIdle();
835 }
836
TEST_F(PipelineImplTest,GetMediaTime)837 TEST_F(PipelineImplTest, GetMediaTime) {
838 CreateAudioStream();
839 SetDemuxerExpectations();
840 StartPipelineAndExpect(PIPELINE_OK);
841
842 // Pipeline should report the same media time returned by the renderer.
843 base::TimeDelta kMediaTime = base::TimeDelta::FromSeconds(2);
844 EXPECT_CALL(*renderer_, GetMediaTime()).WillRepeatedly(Return(kMediaTime));
845 EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
846
847 // Media time should not go backwards even if the renderer returns an
848 // errorneous value. PipelineImpl should clamp it to last reported value.
849 EXPECT_CALL(*renderer_, GetMediaTime())
850 .WillRepeatedly(Return(base::TimeDelta::FromSeconds(1)));
851 EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
852 }
853
854 // Seeking posts a task from main thread to media thread to seek the renderer,
855 // resetting its internal clock. Calling GetMediaTime() should be safe even
856 // when the renderer has not performed the seek (simulated by its continuing
857 // to return the pre-seek time). Verifies fix for http://crbug.com/675556
TEST_F(PipelineImplTest,GetMediaTimeAfterSeek)858 TEST_F(PipelineImplTest, GetMediaTimeAfterSeek) {
859 CreateAudioStream();
860 SetDemuxerExpectations();
861 StartPipelineAndExpect(PIPELINE_OK);
862
863 // Pipeline should report the same media time returned by the renderer.
864 base::TimeDelta kMediaTime = base::TimeDelta::FromSeconds(2);
865 EXPECT_CALL(*renderer_, GetMediaTime()).WillRepeatedly(Return(kMediaTime));
866 EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
867
868 // Seek backward 1 second. Do not run RunLoop to ensure renderer is not yet
869 // notified of the seek (via media thread).
870 base::TimeDelta kSeekTime = kMediaTime - base::TimeDelta::FromSeconds(1);
871 ExpectSeek(kSeekTime, false);
872 pipeline_->Seek(kSeekTime, base::BindOnce(&CallbackHelper::OnSeek,
873 base::Unretained(&callbacks_)));
874
875 // Verify pipeline returns the seek time in spite of renderer returning the
876 // stale media time.
877 EXPECT_EQ(kSeekTime, pipeline_->GetMediaTime());
878 EXPECT_EQ(kMediaTime, renderer_->GetMediaTime());
879
880 // Allow seek task to post to the renderer.
881 base::RunLoop().RunUntilIdle();
882
883 // With seek completed, pipeline should again return the renderer's media time
884 // (as long as media time is moving forward).
885 EXPECT_EQ(kMediaTime, pipeline_->GetMediaTime());
886 }
887
888 // This test makes sure that, after receiving an error, stopping and starting
889 // the pipeline clears all internal error state, and allows errors to be
890 // propagated again.
TEST_F(PipelineImplTest,RendererErrorsReset)891 TEST_F(PipelineImplTest, RendererErrorsReset) {
892 // Basic setup
893 CreateAudioStream();
894 SetDemuxerExpectations();
895 StartPipelineAndExpect(PIPELINE_OK);
896
897 // Trigger two errors. The second error will be ignored.
898 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)).Times(1);
899 renderer_client_->OnError(PIPELINE_ERROR_READ);
900 renderer_client_->OnError(PIPELINE_ERROR_READ);
901
902 base::RunLoop().RunUntilIdle();
903
904 // Stopping the demuxer should clear internal state.
905 EXPECT_CALL(*demuxer_, Stop());
906 pipeline_->Stop();
907
908 base::RunLoop().RunUntilIdle();
909
910 ResetRenderer();
911 SetDemuxerExpectations();
912 StartPipelineAndExpect(PIPELINE_OK);
913
914 // New errors should propagate and not be ignored.
915 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)).Times(1);
916 renderer_client_->OnError(PIPELINE_ERROR_READ);
917
918 base::RunLoop().RunUntilIdle();
919 }
920
921 class PipelineTeardownTest : public PipelineImplTest {
922 public:
923 enum TeardownState {
924 kInitDemuxer,
925 kInitRenderer,
926 kFlushing,
927 kSeeking,
928 kPlaying,
929 kSuspending,
930 kSuspended,
931 kResuming,
932 };
933
934 enum StopOrError {
935 kStop,
936 kError,
937 kErrorAndStop,
938 };
939
940 PipelineTeardownTest() = default;
941 ~PipelineTeardownTest() override = default;
942
RunTest(TeardownState state,StopOrError stop_or_error)943 void RunTest(TeardownState state, StopOrError stop_or_error) {
944 switch (state) {
945 case kInitDemuxer:
946 case kInitRenderer:
947 DoInitialize(state, stop_or_error);
948 break;
949
950 case kFlushing:
951 case kSeeking:
952 DoInitialize(state, stop_or_error);
953 DoSeek(state, stop_or_error);
954 break;
955
956 case kPlaying:
957 DoInitialize(state, stop_or_error);
958 DoStopOrError(stop_or_error, true);
959 break;
960
961 case kSuspending:
962 case kSuspended:
963 case kResuming:
964 DoInitialize(state, stop_or_error);
965 DoSuspend(state, stop_or_error);
966 break;
967 }
968 }
969
970 private:
971 // TODO(scherkus): We do radically different things whether teardown is
972 // invoked via stop vs error. The teardown path should be the same,
973 // see http://crbug.com/110228
DoInitialize(TeardownState state,StopOrError stop_or_error)974 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
975 SetInitializeExpectations(state, stop_or_error);
976 StartPipeline();
977 base::RunLoop().RunUntilIdle();
978 }
979
SetInitializeExpectations(TeardownState state,StopOrError stop_or_error)980 void SetInitializeExpectations(TeardownState state,
981 StopOrError stop_or_error) {
982 if (state == kInitDemuxer) {
983 if (stop_or_error == kStop) {
984 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
985 .WillOnce(
986 DoAll(PostStop(pipeline_.get()), PostCallback<1>(PIPELINE_OK)));
987 // Note: OnStart callback is not called after pipeline is stopped.
988 } else {
989 EXPECT_CALL(*demuxer_, OnInitialize(_, _))
990 .WillOnce(PostCallback<1>(DEMUXER_ERROR_COULD_NOT_OPEN));
991 EXPECT_CALL(callbacks_, OnStart(DEMUXER_ERROR_COULD_NOT_OPEN))
992 .WillOnce(Stop(pipeline_.get()));
993 }
994
995 EXPECT_CALL(*demuxer_, Stop());
996 return;
997 }
998
999 CreateAudioStream();
1000 CreateVideoStream();
1001 SetDemuxerExpectations(base::TimeDelta::FromSeconds(3000));
1002 EXPECT_CALL(*renderer_, SetVolume(1.0f));
1003
1004 if (state == kInitRenderer) {
1005 if (stop_or_error == kStop) {
1006 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
1007 .WillOnce(
1008 DoAll(PostStop(pipeline_.get()), PostCallback<2>(PIPELINE_OK)));
1009 // Note: OnStart is not callback after pipeline is stopped.
1010 } else {
1011 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
1012 .WillOnce(PostCallback<2>(PIPELINE_ERROR_INITIALIZATION_FAILED));
1013 EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_INITIALIZATION_FAILED))
1014 .WillOnce(Stop(pipeline_.get()));
1015 }
1016
1017 EXPECT_CALL(callbacks_, OnMetadata(_));
1018 EXPECT_CALL(*demuxer_, Stop());
1019 return;
1020 }
1021
1022 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
1023 .WillOnce(
1024 DoAll(SaveArg<1>(&renderer_client_), PostCallback<2>(PIPELINE_OK)));
1025
1026 // If we get here it's a successful initialization.
1027 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
1028 EXPECT_CALL(callbacks_, OnMetadata(_));
1029
1030 EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
1031 EXPECT_CALL(*renderer_, StartPlayingFrom(base::TimeDelta()))
1032 .WillOnce(SetBufferingState(&renderer_client_, BUFFERING_HAVE_ENOUGH,
1033 BUFFERING_CHANGE_REASON_UNKNOWN));
1034 EXPECT_CALL(callbacks_,
1035 OnBufferingStateChange(BUFFERING_HAVE_ENOUGH,
1036 BUFFERING_CHANGE_REASON_UNKNOWN));
1037 }
1038
DoSeek(TeardownState state,StopOrError stop_or_error)1039 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1040 SetSeekExpectations(state, stop_or_error);
1041
1042 EXPECT_CALL(*demuxer_, AbortPendingReads());
1043 EXPECT_CALL(*demuxer_, Stop());
1044
1045 pipeline_->Seek(
1046 base::TimeDelta::FromSeconds(10),
1047 base::BindOnce(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1048 base::RunLoop().RunUntilIdle();
1049 }
1050
SetSeekExpectations(TeardownState state,StopOrError stop_or_error)1051 void SetSeekExpectations(TeardownState state, StopOrError stop_or_error) {
1052 if (state == kFlushing) {
1053 EXPECT_CALL(*demuxer_, OnSeek(_, _));
1054 if (stop_or_error == kStop) {
1055 EXPECT_CALL(*renderer_, OnFlush(_))
1056 .WillOnce(DoAll(Stop(pipeline_.get()), RunOnceClosure<0>()));
1057 // Note: OnSeek callbacks are not called
1058 // after pipeline is stopped.
1059 } else {
1060 EXPECT_CALL(*renderer_, OnFlush(_))
1061 .WillOnce(DoAll(SetError(&renderer_client_, PIPELINE_ERROR_READ),
1062 RunOnceClosure<0>()));
1063 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ))
1064 .WillOnce(Stop(pipeline_.get()));
1065 }
1066 return;
1067 }
1068
1069 EXPECT_CALL(*renderer_, OnFlush(_)).WillOnce(RunOnceClosure<0>());
1070
1071 if (state == kSeeking) {
1072 if (stop_or_error == kStop) {
1073 EXPECT_CALL(*demuxer_, OnSeek(_, _))
1074 .WillOnce(DoAll(PostStop(pipeline_.get()),
1075 RunOnceCallback<1>(PIPELINE_OK)));
1076 // Note: OnSeek callback is not called after pipeline is stopped.
1077 } else {
1078 EXPECT_CALL(*demuxer_, OnSeek(_, _))
1079 .WillOnce(RunOnceCallback<1>(PIPELINE_ERROR_READ));
1080 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ))
1081 .WillOnce(Stop(pipeline_.get()));
1082 }
1083 return;
1084 }
1085
1086 NOTREACHED() << "State not supported: " << state;
1087 }
1088
DoSuspend(TeardownState state,StopOrError stop_or_error)1089 void DoSuspend(TeardownState state, StopOrError stop_or_error) {
1090 SetSuspendExpectations(state, stop_or_error);
1091
1092 if (state == kResuming) {
1093 EXPECT_CALL(*demuxer_, Stop());
1094 }
1095
1096 PipelineImplTest::DoSuspend();
1097
1098 if (state == kResuming) {
1099 PipelineImplTest::DoResume(base::TimeDelta());
1100 return;
1101 }
1102
1103 // kSuspended, kSuspending never throw errors, since Resume() is always able
1104 // to restore the pipeline to a pristine state.
1105 DoStopOrError(stop_or_error, false);
1106 }
1107
SetSuspendExpectations(TeardownState state,StopOrError stop_or_error)1108 void SetSuspendExpectations(TeardownState state, StopOrError stop_or_error) {
1109 EXPECT_CALL(*renderer_, SetPlaybackRate(0));
1110 EXPECT_CALL(*demuxer_, AbortPendingReads());
1111 EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
1112 if (state == kResuming) {
1113 if (stop_or_error == kStop) {
1114 EXPECT_CALL(*demuxer_, OnSeek(_, _))
1115 .WillOnce(DoAll(PostStop(pipeline_.get()),
1116 RunOnceCallback<1>(PIPELINE_OK)));
1117 // Note: OnResume callback is not called after pipeline is stopped.
1118 } else {
1119 EXPECT_CALL(*demuxer_, OnSeek(_, _))
1120 .WillOnce(RunOnceCallback<1>(PIPELINE_ERROR_READ));
1121 EXPECT_CALL(callbacks_, OnResume(PIPELINE_ERROR_READ))
1122 .WillOnce(Stop(pipeline_.get()));
1123 }
1124 } else if (state != kSuspended && state != kSuspending) {
1125 NOTREACHED() << "State not supported: " << state;
1126 }
1127 }
1128
DoStopOrError(StopOrError stop_or_error,bool expect_errors)1129 void DoStopOrError(StopOrError stop_or_error, bool expect_errors) {
1130 switch (stop_or_error) {
1131 case kStop:
1132 EXPECT_CALL(*demuxer_, Stop());
1133 pipeline_->Stop();
1134 break;
1135
1136 case kError:
1137 if (expect_errors) {
1138 EXPECT_CALL(*demuxer_, Stop());
1139 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ))
1140 .WillOnce(Stop(pipeline_.get()));
1141 }
1142 renderer_client_->OnError(PIPELINE_ERROR_READ);
1143 break;
1144
1145 case kErrorAndStop:
1146 EXPECT_CALL(*demuxer_, Stop());
1147 if (expect_errors)
1148 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1149 renderer_client_->OnError(PIPELINE_ERROR_READ);
1150 base::RunLoop().RunUntilIdle();
1151 pipeline_->Stop();
1152 break;
1153 }
1154
1155 base::RunLoop().RunUntilIdle();
1156 }
1157
1158 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1159 };
1160
1161 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1162 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1163 RunTest(k##state, k##stop_or_error); \
1164 }
1165
1166 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer)
1167 INSTANTIATE_TEARDOWN_TEST(Stop, InitRenderer)
1168 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing)
1169 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking)
1170 INSTANTIATE_TEARDOWN_TEST(Stop, Playing)
1171 INSTANTIATE_TEARDOWN_TEST(Stop, Suspending)
1172 INSTANTIATE_TEARDOWN_TEST(Stop, Suspended)
1173 INSTANTIATE_TEARDOWN_TEST(Stop, Resuming)
1174
1175 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer)
1176 INSTANTIATE_TEARDOWN_TEST(Error, InitRenderer)
1177 INSTANTIATE_TEARDOWN_TEST(Error, Flushing)
1178 INSTANTIATE_TEARDOWN_TEST(Error, Seeking)
1179 INSTANTIATE_TEARDOWN_TEST(Error, Playing)
1180 INSTANTIATE_TEARDOWN_TEST(Error, Suspending)
1181 INSTANTIATE_TEARDOWN_TEST(Error, Suspended)
1182 INSTANTIATE_TEARDOWN_TEST(Error, Resuming)
1183
1184 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing)
1185 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Suspended)
1186
1187 } // namespace media
1188