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 <vector> 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/stl_util.h" 10 #include "base/test/simple_test_tick_clock.h" 11 #include "base/threading/simple_thread.h" 12 #include "base/time/clock.h" 13 #include "media/base/clock.h" 14 #include "media/base/fake_text_track_stream.h" 15 #include "media/base/gmock_callback_support.h" 16 #include "media/base/media_log.h" 17 #include "media/base/mock_filters.h" 18 #include "media/base/pipeline.h" 19 #include "media/base/test_helpers.h" 20 #include "media/base/text_renderer.h" 21 #include "media/base/text_track_config.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "ui/gfx/size.h" 24 25 using ::testing::_; 26 using ::testing::DeleteArg; 27 using ::testing::DoAll; 28 // TODO(scherkus): Remove InSequence after refactoring Pipeline. 29 using ::testing::InSequence; 30 using ::testing::Invoke; 31 using ::testing::InvokeWithoutArgs; 32 using ::testing::Mock; 33 using ::testing::NotNull; 34 using ::testing::Return; 35 using ::testing::SaveArg; 36 using ::testing::StrictMock; 37 using ::testing::WithArg; 38 39 namespace media { 40 41 // Demuxer properties. 42 const int kTotalBytes = 1024; 43 44 ACTION_P(SetDemuxerProperties, duration) { 45 arg0->SetTotalBytes(kTotalBytes); 46 arg0->SetDuration(duration); 47 } 48 49 ACTION_P2(Stop, pipeline, stop_cb) { 50 pipeline->Stop(stop_cb); 51 } 52 53 ACTION_P2(SetError, pipeline, status) { 54 pipeline->SetErrorForTesting(status); 55 } 56 57 // Used for setting expectations on pipeline callbacks. Using a StrictMock 58 // also lets us test for missing callbacks. 59 class CallbackHelper { 60 public: 61 CallbackHelper() {} 62 virtual ~CallbackHelper() {} 63 64 MOCK_METHOD1(OnStart, void(PipelineStatus)); 65 MOCK_METHOD1(OnSeek, void(PipelineStatus)); 66 MOCK_METHOD0(OnStop, void()); 67 MOCK_METHOD0(OnEnded, void()); 68 MOCK_METHOD1(OnError, void(PipelineStatus)); 69 MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState)); 70 MOCK_METHOD0(OnDurationChange, void()); 71 72 private: 73 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); 74 }; 75 76 // TODO(scherkus): even though some filters are initialized on separate 77 // threads these test aren't flaky... why? It's because filters' Initialize() 78 // is executed on |message_loop_| and the mock filters instantly call 79 // InitializationComplete(), which keeps the pipeline humming along. If 80 // either filters don't call InitializationComplete() immediately or filter 81 // initialization is moved to a separate thread this test will become flaky. 82 class PipelineTest : public ::testing::Test { 83 public: 84 PipelineTest() 85 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(), 86 new MediaLog())), 87 filter_collection_(new FilterCollection()), 88 demuxer_(new MockDemuxer()) { 89 filter_collection_->SetDemuxer(demuxer_.get()); 90 91 video_renderer_ = new MockVideoRenderer(); 92 scoped_ptr<VideoRenderer> video_renderer(video_renderer_); 93 filter_collection_->SetVideoRenderer(video_renderer.Pass()); 94 95 audio_renderer_ = new MockAudioRenderer(); 96 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_); 97 filter_collection_->SetAudioRenderer(audio_renderer.Pass()); 98 99 text_renderer_ = new TextRenderer( 100 message_loop_.message_loop_proxy(), 101 base::Bind(&PipelineTest::OnAddTextTrack, 102 base::Unretained(this))); 103 scoped_ptr<TextRenderer> text_renderer(text_renderer_); 104 filter_collection_->SetTextRenderer(text_renderer.Pass()); 105 106 // InitializeDemuxer() adds overriding expectations for expected non-NULL 107 // streams. 108 DemuxerStream* null_pointer = NULL; 109 EXPECT_CALL(*demuxer_, GetStream(_)) 110 .WillRepeatedly(Return(null_pointer)); 111 112 EXPECT_CALL(*demuxer_, GetStartTime()) 113 .WillRepeatedly(Return(base::TimeDelta())); 114 } 115 116 virtual ~PipelineTest() { 117 if (!pipeline_ || !pipeline_->IsRunning()) 118 return; 119 120 ExpectStop(); 121 122 // The mock demuxer doesn't stop the fake text track stream, 123 // so just stop it manually. 124 if (text_stream_) { 125 text_stream_->Stop(); 126 message_loop_.RunUntilIdle(); 127 } 128 129 // Expect a stop callback if we were started. 130 EXPECT_CALL(callbacks_, OnStop()); 131 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop, 132 base::Unretained(&callbacks_))); 133 message_loop_.RunUntilIdle(); 134 } 135 136 protected: 137 // Sets up expectations to allow the demuxer to initialize. 138 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; 139 void InitializeDemuxer(MockDemuxerStreamVector* streams, 140 const base::TimeDelta& duration) { 141 EXPECT_CALL(callbacks_, OnDurationChange()); 142 EXPECT_CALL(*demuxer_, Initialize(_, _, _)) 143 .WillOnce(DoAll(SetDemuxerProperties(duration), 144 RunCallback<1>(PIPELINE_OK))); 145 146 // Configure the demuxer to return the streams. 147 for (size_t i = 0; i < streams->size(); ++i) { 148 DemuxerStream* stream = (*streams)[i]; 149 EXPECT_CALL(*demuxer_, GetStream(stream->type())) 150 .WillRepeatedly(Return(stream)); 151 } 152 } 153 154 void InitializeDemuxer(MockDemuxerStreamVector* streams) { 155 // Initialize with a default non-zero duration. 156 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10)); 157 } 158 159 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream( 160 DemuxerStream::Type type) { 161 scoped_ptr<StrictMock<MockDemuxerStream> > stream( 162 new StrictMock<MockDemuxerStream>(type)); 163 return stream.Pass(); 164 } 165 166 // Sets up expectations to allow the video renderer to initialize. 167 void InitializeVideoRenderer(DemuxerStream* stream) { 168 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _)) 169 .WillOnce(RunCallback<1>(PIPELINE_OK)); 170 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f)); 171 172 // Startup sequence. 173 EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _)) 174 .WillOnce(RunCallback<1>(PIPELINE_OK)); 175 EXPECT_CALL(*video_renderer_, Play(_)) 176 .WillOnce(RunClosure<0>()); 177 } 178 179 // Sets up expectations to allow the audio renderer to initialize. 180 void InitializeAudioRenderer(DemuxerStream* stream, 181 bool disable_after_init_cb) { 182 if (disable_after_init_cb) { 183 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _)) 184 .WillOnce(DoAll(RunCallback<1>(PIPELINE_OK), 185 WithArg<6>(RunClosure<0>()))); // |disabled_cb|. 186 } else { 187 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _)) 188 .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_), 189 RunCallback<1>(PIPELINE_OK))); 190 } 191 } 192 193 void AddTextStream() { 194 EXPECT_CALL(*this, OnAddTextTrack(_,_)) 195 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack)); 196 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(), 197 TextTrackConfig(kTextSubtitles, "", "", "")); 198 } 199 200 // Sets up expectations on the callback and initializes the pipeline. Called 201 // after tests have set expectations any filters they wish to use. 202 void InitializePipeline(PipelineStatus start_status) { 203 EXPECT_CALL(callbacks_, OnStart(start_status)); 204 205 if (start_status == PIPELINE_OK) { 206 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata)); 207 208 if (audio_stream_) { 209 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f)); 210 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f)); 211 212 // Startup sequence. 213 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _)) 214 .WillOnce(RunCallback<1>(PIPELINE_OK)); 215 EXPECT_CALL(*audio_renderer_, Play(_)) 216 .WillOnce(RunClosure<0>()); 217 } 218 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted)); 219 } 220 221 pipeline_->Start( 222 filter_collection_.Pass(), 223 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), 224 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), 225 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)), 226 base::Bind(&CallbackHelper::OnBufferingState, 227 base::Unretained(&callbacks_)), 228 base::Bind(&CallbackHelper::OnDurationChange, 229 base::Unretained(&callbacks_))); 230 message_loop_.RunUntilIdle(); 231 } 232 233 void CreateAudioStream() { 234 audio_stream_ = CreateStream(DemuxerStream::AUDIO); 235 } 236 237 void CreateVideoStream() { 238 video_stream_ = CreateStream(DemuxerStream::VIDEO); 239 video_stream_->set_video_decoder_config(video_decoder_config_); 240 } 241 242 void CreateTextStream() { 243 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream); 244 text_stream_ = text_stream.Pass(); 245 } 246 247 MockDemuxerStream* audio_stream() { 248 return audio_stream_.get(); 249 } 250 251 MockDemuxerStream* video_stream() { 252 return video_stream_.get(); 253 } 254 255 FakeTextTrackStream* text_stream() { 256 return text_stream_.get(); 257 } 258 259 void ExpectSeek(const base::TimeDelta& seek_time) { 260 // Every filter should receive a call to Seek(). 261 EXPECT_CALL(*demuxer_, Seek(seek_time, _)) 262 .WillOnce(RunCallback<1>(PIPELINE_OK)); 263 264 if (audio_stream_) { 265 EXPECT_CALL(*audio_renderer_, Pause(_)) 266 .WillOnce(RunClosure<0>()); 267 EXPECT_CALL(*audio_renderer_, Flush(_)) 268 .WillOnce(RunClosure<0>()); 269 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _)) 270 .WillOnce(RunCallback<1>(PIPELINE_OK)); 271 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_)); 272 EXPECT_CALL(*audio_renderer_, SetVolume(_)); 273 EXPECT_CALL(*audio_renderer_, Play(_)) 274 .WillOnce(RunClosure<0>()); 275 } 276 277 if (video_stream_) { 278 EXPECT_CALL(*video_renderer_, Pause(_)) 279 .WillOnce(RunClosure<0>()); 280 EXPECT_CALL(*video_renderer_, Flush(_)) 281 .WillOnce(RunClosure<0>()); 282 EXPECT_CALL(*video_renderer_, Preroll(seek_time, _)) 283 .WillOnce(RunCallback<1>(PIPELINE_OK)); 284 EXPECT_CALL(*video_renderer_, SetPlaybackRate(_)); 285 EXPECT_CALL(*video_renderer_, Play(_)) 286 .WillOnce(RunClosure<0>()); 287 } 288 289 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted)); 290 291 // We expect a successful seek callback. 292 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); 293 } 294 295 void DoSeek(const base::TimeDelta& seek_time) { 296 pipeline_->Seek(seek_time, 297 base::Bind(&CallbackHelper::OnSeek, 298 base::Unretained(&callbacks_))); 299 300 // We expect the time to be updated only after the seek has completed. 301 EXPECT_NE(seek_time, pipeline_->GetMediaTime()); 302 message_loop_.RunUntilIdle(); 303 EXPECT_EQ(seek_time, pipeline_->GetMediaTime()); 304 } 305 306 void ExpectStop() { 307 if (demuxer_) 308 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 309 310 if (audio_stream_) 311 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 312 313 if (video_stream_) 314 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 315 } 316 317 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&, 318 const AddTextTrackDoneCB&)); 319 320 void DoOnAddTextTrack(const TextTrackConfig& config, 321 const AddTextTrackDoneCB& done_cb) { 322 scoped_ptr<TextTrack> text_track(new MockTextTrack); 323 done_cb.Run(text_track.Pass()); 324 } 325 326 // Fixture members. 327 StrictMock<CallbackHelper> callbacks_; 328 base::SimpleTestTickClock test_tick_clock_; 329 base::MessageLoop message_loop_; 330 scoped_ptr<Pipeline> pipeline_; 331 332 scoped_ptr<FilterCollection> filter_collection_; 333 scoped_ptr<MockDemuxer> demuxer_; 334 MockVideoRenderer* video_renderer_; 335 MockAudioRenderer* audio_renderer_; 336 StrictMock<CallbackHelper> text_renderer_callbacks_; 337 TextRenderer* text_renderer_; 338 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_; 339 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_; 340 scoped_ptr<FakeTextTrackStream> text_stream_; 341 AudioRenderer::TimeCB audio_time_cb_; 342 VideoDecoderConfig video_decoder_config_; 343 344 private: 345 DISALLOW_COPY_AND_ASSIGN(PipelineTest); 346 }; 347 348 // Test that playback controls methods no-op when the pipeline hasn't been 349 // started. 350 TEST_F(PipelineTest, NotStarted) { 351 const base::TimeDelta kZero; 352 353 EXPECT_FALSE(pipeline_->IsRunning()); 354 EXPECT_FALSE(pipeline_->HasAudio()); 355 EXPECT_FALSE(pipeline_->HasVideo()); 356 357 // Setting should still work. 358 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); 359 pipeline_->SetPlaybackRate(-1.0f); 360 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); 361 pipeline_->SetPlaybackRate(1.0f); 362 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate()); 363 364 // Setting should still work. 365 EXPECT_EQ(1.0f, pipeline_->GetVolume()); 366 pipeline_->SetVolume(-1.0f); 367 EXPECT_EQ(1.0f, pipeline_->GetVolume()); 368 pipeline_->SetVolume(0.0f); 369 EXPECT_EQ(0.0f, pipeline_->GetVolume()); 370 371 EXPECT_TRUE(kZero == pipeline_->GetMediaTime()); 372 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size()); 373 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration()); 374 375 EXPECT_EQ(0, pipeline_->GetTotalBytes()); 376 377 // Should always get set to zero. 378 gfx::Size size(1, 1); 379 pipeline_->GetNaturalVideoSize(&size); 380 EXPECT_EQ(0, size.width()); 381 EXPECT_EQ(0, size.height()); 382 } 383 384 TEST_F(PipelineTest, NeverInitializes) { 385 // Don't execute the callback passed into Initialize(). 386 EXPECT_CALL(*demuxer_, Initialize(_, _, _)); 387 388 // This test hangs during initialization by never calling 389 // InitializationComplete(). StrictMock<> will ensure that the callback is 390 // never executed. 391 pipeline_->Start( 392 filter_collection_.Pass(), 393 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), 394 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), 395 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)), 396 base::Bind(&CallbackHelper::OnBufferingState, 397 base::Unretained(&callbacks_)), 398 base::Bind(&CallbackHelper::OnDurationChange, 399 base::Unretained(&callbacks_))); 400 message_loop_.RunUntilIdle(); 401 402 403 // Because our callback will get executed when the test tears down, we'll 404 // verify that nothing has been called, then set our expectation for the call 405 // made during tear down. 406 Mock::VerifyAndClear(&callbacks_); 407 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK)); 408 } 409 410 TEST_F(PipelineTest, URLNotFound) { 411 EXPECT_CALL(*demuxer_, Initialize(_, _, _)) 412 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND)); 413 EXPECT_CALL(*demuxer_, Stop(_)) 414 .WillOnce(RunClosure<0>()); 415 416 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND); 417 } 418 419 TEST_F(PipelineTest, NoStreams) { 420 EXPECT_CALL(*demuxer_, Initialize(_, _, _)) 421 .WillOnce(RunCallback<1>(PIPELINE_OK)); 422 EXPECT_CALL(*demuxer_, Stop(_)) 423 .WillOnce(RunClosure<0>()); 424 425 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER); 426 } 427 428 TEST_F(PipelineTest, AudioStream) { 429 CreateAudioStream(); 430 MockDemuxerStreamVector streams; 431 streams.push_back(audio_stream()); 432 433 InitializeDemuxer(&streams); 434 InitializeAudioRenderer(audio_stream(), false); 435 436 InitializePipeline(PIPELINE_OK); 437 EXPECT_TRUE(pipeline_->HasAudio()); 438 EXPECT_FALSE(pipeline_->HasVideo()); 439 } 440 441 TEST_F(PipelineTest, VideoStream) { 442 CreateVideoStream(); 443 MockDemuxerStreamVector streams; 444 streams.push_back(video_stream()); 445 446 InitializeDemuxer(&streams); 447 InitializeVideoRenderer(video_stream()); 448 449 InitializePipeline(PIPELINE_OK); 450 EXPECT_FALSE(pipeline_->HasAudio()); 451 EXPECT_TRUE(pipeline_->HasVideo()); 452 } 453 454 TEST_F(PipelineTest, AudioVideoStream) { 455 CreateAudioStream(); 456 CreateVideoStream(); 457 MockDemuxerStreamVector streams; 458 streams.push_back(audio_stream()); 459 streams.push_back(video_stream()); 460 461 InitializeDemuxer(&streams); 462 InitializeAudioRenderer(audio_stream(), false); 463 InitializeVideoRenderer(video_stream()); 464 465 InitializePipeline(PIPELINE_OK); 466 EXPECT_TRUE(pipeline_->HasAudio()); 467 EXPECT_TRUE(pipeline_->HasVideo()); 468 } 469 470 TEST_F(PipelineTest, VideoTextStream) { 471 CreateVideoStream(); 472 CreateTextStream(); 473 MockDemuxerStreamVector streams; 474 streams.push_back(video_stream()); 475 476 InitializeDemuxer(&streams); 477 InitializeVideoRenderer(video_stream()); 478 479 InitializePipeline(PIPELINE_OK); 480 EXPECT_FALSE(pipeline_->HasAudio()); 481 EXPECT_TRUE(pipeline_->HasVideo()); 482 483 AddTextStream(); 484 message_loop_.RunUntilIdle(); 485 } 486 487 TEST_F(PipelineTest, VideoAudioTextStream) { 488 CreateVideoStream(); 489 CreateAudioStream(); 490 CreateTextStream(); 491 MockDemuxerStreamVector streams; 492 streams.push_back(video_stream()); 493 streams.push_back(audio_stream()); 494 495 InitializeDemuxer(&streams); 496 InitializeVideoRenderer(video_stream()); 497 InitializeAudioRenderer(audio_stream(), false); 498 499 InitializePipeline(PIPELINE_OK); 500 EXPECT_TRUE(pipeline_->HasAudio()); 501 EXPECT_TRUE(pipeline_->HasVideo()); 502 503 AddTextStream(); 504 message_loop_.RunUntilIdle(); 505 } 506 507 TEST_F(PipelineTest, Seek) { 508 CreateAudioStream(); 509 CreateVideoStream(); 510 CreateTextStream(); 511 MockDemuxerStreamVector streams; 512 streams.push_back(audio_stream()); 513 streams.push_back(video_stream()); 514 515 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000)); 516 InitializeAudioRenderer(audio_stream(), false); 517 InitializeVideoRenderer(video_stream()); 518 519 // Initialize then seek! 520 InitializePipeline(PIPELINE_OK); 521 522 AddTextStream(); 523 message_loop_.RunUntilIdle(); 524 525 // Every filter should receive a call to Seek(). 526 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000); 527 ExpectSeek(expected); 528 DoSeek(expected); 529 } 530 531 TEST_F(PipelineTest, SetVolume) { 532 CreateAudioStream(); 533 MockDemuxerStreamVector streams; 534 streams.push_back(audio_stream()); 535 536 InitializeDemuxer(&streams); 537 InitializeAudioRenderer(audio_stream(), false); 538 539 // The audio renderer should receive a call to SetVolume(). 540 float expected = 0.5f; 541 EXPECT_CALL(*audio_renderer_, SetVolume(expected)); 542 543 // Initialize then set volume! 544 InitializePipeline(PIPELINE_OK); 545 pipeline_->SetVolume(expected); 546 } 547 548 TEST_F(PipelineTest, Properties) { 549 CreateVideoStream(); 550 MockDemuxerStreamVector streams; 551 streams.push_back(video_stream()); 552 553 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); 554 InitializeDemuxer(&streams, kDuration); 555 InitializeVideoRenderer(video_stream()); 556 557 InitializePipeline(PIPELINE_OK); 558 EXPECT_EQ(kDuration.ToInternalValue(), 559 pipeline_->GetMediaDuration().ToInternalValue()); 560 EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes()); 561 EXPECT_FALSE(pipeline_->DidLoadingProgress()); 562 } 563 564 TEST_F(PipelineTest, GetBufferedTimeRanges) { 565 CreateVideoStream(); 566 MockDemuxerStreamVector streams; 567 streams.push_back(video_stream()); 568 569 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); 570 InitializeDemuxer(&streams, kDuration); 571 InitializeVideoRenderer(video_stream()); 572 573 InitializePipeline(PIPELINE_OK); 574 575 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size()); 576 577 EXPECT_FALSE(pipeline_->DidLoadingProgress()); 578 pipeline_->AddBufferedByteRange(0, kTotalBytes / 8); 579 EXPECT_TRUE(pipeline_->DidLoadingProgress()); 580 EXPECT_FALSE(pipeline_->DidLoadingProgress()); 581 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); 582 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); 583 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); 584 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8); 585 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); 586 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); 587 588 base::TimeDelta kSeekTime = kDuration / 2; 589 ExpectSeek(kSeekTime); 590 DoSeek(kSeekTime); 591 592 EXPECT_TRUE(pipeline_->DidLoadingProgress()); 593 EXPECT_FALSE(pipeline_->DidLoadingProgress()); 594 pipeline_->AddBufferedByteRange(kTotalBytes / 2, 595 kTotalBytes / 2 + kTotalBytes / 8); 596 EXPECT_TRUE(pipeline_->DidLoadingProgress()); 597 EXPECT_FALSE(pipeline_->DidLoadingProgress()); 598 EXPECT_EQ(2u, pipeline_->GetBufferedTimeRanges().size()); 599 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); 600 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); 601 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(1)); 602 EXPECT_EQ(kDuration / 2 + kDuration / 8, 603 pipeline_->GetBufferedTimeRanges().end(1)); 604 605 pipeline_->AddBufferedTimeRange(kDuration / 4, 3 * kDuration / 8); 606 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); 607 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); 608 EXPECT_EQ(kDuration / 4, pipeline_->GetBufferedTimeRanges().start(1)); 609 EXPECT_EQ(3* kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1)); 610 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(2)); 611 EXPECT_EQ(kDuration / 2 + kDuration / 8, 612 pipeline_->GetBufferedTimeRanges().end(2)); 613 } 614 615 TEST_F(PipelineTest, DisableAudioRenderer) { 616 CreateAudioStream(); 617 CreateVideoStream(); 618 MockDemuxerStreamVector streams; 619 streams.push_back(audio_stream()); 620 streams.push_back(video_stream()); 621 622 InitializeDemuxer(&streams); 623 InitializeAudioRenderer(audio_stream(), false); 624 InitializeVideoRenderer(video_stream()); 625 626 InitializePipeline(PIPELINE_OK); 627 EXPECT_TRUE(pipeline_->HasAudio()); 628 EXPECT_TRUE(pipeline_->HasVideo()); 629 630 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled()); 631 pipeline_->OnAudioDisabled(); 632 633 // Verify that ended event is fired when video ends. 634 EXPECT_CALL(callbacks_, OnEnded()); 635 pipeline_->OnVideoRendererEnded(); 636 } 637 638 TEST_F(PipelineTest, DisableAudioRendererDuringInit) { 639 CreateAudioStream(); 640 CreateVideoStream(); 641 MockDemuxerStreamVector streams; 642 streams.push_back(audio_stream()); 643 streams.push_back(video_stream()); 644 645 InitializeDemuxer(&streams); 646 InitializeAudioRenderer(audio_stream(), true); 647 InitializeVideoRenderer(video_stream()); 648 649 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled()); 650 651 InitializePipeline(PIPELINE_OK); 652 EXPECT_FALSE(pipeline_->HasAudio()); 653 EXPECT_TRUE(pipeline_->HasVideo()); 654 655 // Verify that ended event is fired when video ends. 656 EXPECT_CALL(callbacks_, OnEnded()); 657 pipeline_->OnVideoRendererEnded(); 658 } 659 660 TEST_F(PipelineTest, EndedCallback) { 661 CreateAudioStream(); 662 CreateVideoStream(); 663 CreateTextStream(); 664 MockDemuxerStreamVector streams; 665 streams.push_back(audio_stream()); 666 streams.push_back(video_stream()); 667 668 InitializeDemuxer(&streams); 669 InitializeAudioRenderer(audio_stream(), false); 670 InitializeVideoRenderer(video_stream()); 671 InitializePipeline(PIPELINE_OK); 672 673 AddTextStream(); 674 675 // The ended callback shouldn't run until all renderers have ended. 676 pipeline_->OnAudioRendererEnded(); 677 message_loop_.RunUntilIdle(); 678 679 pipeline_->OnVideoRendererEnded(); 680 message_loop_.RunUntilIdle(); 681 682 EXPECT_CALL(callbacks_, OnEnded()); 683 text_stream()->SendEosNotification(); 684 message_loop_.RunUntilIdle(); 685 } 686 687 TEST_F(PipelineTest, AudioStreamShorterThanVideo) { 688 base::TimeDelta duration = base::TimeDelta::FromSeconds(10); 689 690 CreateAudioStream(); 691 CreateVideoStream(); 692 MockDemuxerStreamVector streams; 693 streams.push_back(audio_stream()); 694 streams.push_back(video_stream()); 695 696 // Replace the clock so we can simulate wallclock time advancing w/o using 697 // Sleep(). 698 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_)); 699 700 InitializeDemuxer(&streams, duration); 701 InitializeAudioRenderer(audio_stream(), false); 702 InitializeVideoRenderer(video_stream()); 703 InitializePipeline(PIPELINE_OK); 704 705 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue()); 706 707 float playback_rate = 1.0f; 708 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate)); 709 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate)); 710 pipeline_->SetPlaybackRate(playback_rate); 711 message_loop_.RunUntilIdle(); 712 713 InSequence s; 714 715 // Verify that the clock doesn't advance since it hasn't been started by 716 // a time update from the audio stream. 717 int64 start_time = pipeline_->GetMediaTime().ToInternalValue(); 718 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); 719 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time); 720 721 // Signal end of audio stream. 722 pipeline_->OnAudioRendererEnded(); 723 message_loop_.RunUntilIdle(); 724 725 // Verify that the clock advances. 726 start_time = pipeline_->GetMediaTime().ToInternalValue(); 727 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); 728 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time); 729 730 // Signal end of video stream and make sure OnEnded() callback occurs. 731 EXPECT_CALL(callbacks_, OnEnded()); 732 pipeline_->OnVideoRendererEnded(); 733 } 734 735 TEST_F(PipelineTest, ErrorDuringSeek) { 736 CreateAudioStream(); 737 MockDemuxerStreamVector streams; 738 streams.push_back(audio_stream()); 739 740 InitializeDemuxer(&streams); 741 InitializeAudioRenderer(audio_stream(), false); 742 InitializePipeline(PIPELINE_OK); 743 744 float playback_rate = 1.0f; 745 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate)); 746 pipeline_->SetPlaybackRate(playback_rate); 747 message_loop_.RunUntilIdle(); 748 749 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); 750 751 // Preroll() isn't called as the demuxer errors out first. 752 EXPECT_CALL(*audio_renderer_, Pause(_)) 753 .WillOnce(RunClosure<0>()); 754 EXPECT_CALL(*audio_renderer_, Flush(_)) 755 .WillOnce(RunClosure<0>()); 756 EXPECT_CALL(*audio_renderer_, Stop(_)) 757 .WillOnce(RunClosure<0>()); 758 759 EXPECT_CALL(*demuxer_, Seek(seek_time, _)) 760 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); 761 EXPECT_CALL(*demuxer_, Stop(_)) 762 .WillOnce(RunClosure<0>()); 763 764 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, 765 base::Unretained(&callbacks_))); 766 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); 767 message_loop_.RunUntilIdle(); 768 } 769 770 // Invoked function OnError. This asserts that the pipeline does not enqueue 771 // non-teardown related tasks while tearing down. 772 static void TestNoCallsAfterError( 773 Pipeline* pipeline, base::MessageLoop* message_loop, 774 PipelineStatus /* status */) { 775 CHECK(pipeline); 776 CHECK(message_loop); 777 778 // When we get to this stage, the message loop should be empty. 779 EXPECT_TRUE(message_loop->IsIdleForTesting()); 780 781 // Make calls on pipeline after error has occurred. 782 pipeline->SetPlaybackRate(0.5f); 783 pipeline->SetVolume(0.5f); 784 785 // No additional tasks should be queued as a result of these calls. 786 EXPECT_TRUE(message_loop->IsIdleForTesting()); 787 } 788 789 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) { 790 CreateAudioStream(); 791 MockDemuxerStreamVector streams; 792 streams.push_back(audio_stream()); 793 794 InitializeDemuxer(&streams); 795 InitializeAudioRenderer(audio_stream(), false); 796 InitializePipeline(PIPELINE_OK); 797 798 // Trigger additional requests on the pipeline during tear down from error. 799 base::Callback<void(PipelineStatus)> cb = base::Bind( 800 &TestNoCallsAfterError, pipeline_.get(), &message_loop_); 801 ON_CALL(callbacks_, OnError(_)) 802 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run)); 803 804 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); 805 806 // Seek() isn't called as the demuxer errors out first. 807 EXPECT_CALL(*audio_renderer_, Pause(_)) 808 .WillOnce(RunClosure<0>()); 809 EXPECT_CALL(*audio_renderer_, Flush(_)) 810 .WillOnce(RunClosure<0>()); 811 EXPECT_CALL(*audio_renderer_, Stop(_)) 812 .WillOnce(RunClosure<0>()); 813 814 EXPECT_CALL(*demuxer_, Seek(seek_time, _)) 815 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); 816 EXPECT_CALL(*demuxer_, Stop(_)) 817 .WillOnce(RunClosure<0>()); 818 819 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, 820 base::Unretained(&callbacks_))); 821 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); 822 message_loop_.RunUntilIdle(); 823 } 824 825 TEST_F(PipelineTest, StartTimeIsZero) { 826 CreateVideoStream(); 827 MockDemuxerStreamVector streams; 828 streams.push_back(video_stream()); 829 830 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); 831 InitializeDemuxer(&streams, kDuration); 832 InitializeVideoRenderer(video_stream()); 833 834 InitializePipeline(PIPELINE_OK); 835 EXPECT_FALSE(pipeline_->HasAudio()); 836 EXPECT_TRUE(pipeline_->HasVideo()); 837 838 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime()); 839 } 840 841 TEST_F(PipelineTest, StartTimeIsNonZero) { 842 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4); 843 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100); 844 845 EXPECT_CALL(*demuxer_, GetStartTime()) 846 .WillRepeatedly(Return(kStartTime)); 847 848 CreateVideoStream(); 849 MockDemuxerStreamVector streams; 850 streams.push_back(video_stream()); 851 852 InitializeDemuxer(&streams, kDuration); 853 InitializeVideoRenderer(video_stream()); 854 855 InitializePipeline(PIPELINE_OK); 856 EXPECT_FALSE(pipeline_->HasAudio()); 857 EXPECT_TRUE(pipeline_->HasVideo()); 858 859 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime()); 860 } 861 862 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb, 863 int time_in_ms, 864 int max_time_in_ms) { 865 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms), 866 base::TimeDelta::FromMilliseconds(max_time_in_ms)); 867 } 868 869 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) { 870 CreateAudioStream(); 871 MockDemuxerStreamVector streams; 872 streams.push_back(audio_stream()); 873 874 InitializeDemuxer(&streams); 875 InitializeAudioRenderer(audio_stream(), false); 876 InitializePipeline(PIPELINE_OK); 877 878 float playback_rate = 1.0f; 879 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate)); 880 pipeline_->SetPlaybackRate(playback_rate); 881 message_loop_.RunUntilIdle(); 882 883 // Provide an initial time update so that the pipeline transitions out of the 884 // "waiting for time update" state. 885 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100), 886 base::TimeDelta::FromMilliseconds(500)); 887 888 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); 889 890 // Arrange to trigger a time update while the demuxer is in the middle of 891 // seeking. This update should be ignored by the pipeline and the clock should 892 // not get updated. 893 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700); 894 EXPECT_CALL(*demuxer_, Seek(seek_time, _)) 895 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run), 896 RunCallback<1>(PIPELINE_OK))); 897 898 EXPECT_CALL(*audio_renderer_, Pause(_)) 899 .WillOnce(RunClosure<0>()); 900 EXPECT_CALL(*audio_renderer_, Flush(_)) 901 .WillOnce(RunClosure<0>()); 902 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _)) 903 .WillOnce(RunCallback<1>(PIPELINE_OK)); 904 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_)); 905 EXPECT_CALL(*audio_renderer_, SetVolume(_)); 906 EXPECT_CALL(*audio_renderer_, Play(_)) 907 .WillOnce(RunClosure<0>()); 908 909 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted)); 910 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); 911 DoSeek(seek_time); 912 913 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time); 914 915 // Now that the seek is complete, verify that time updates advance the current 916 // time. 917 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100); 918 audio_time_cb_.Run(new_time, new_time); 919 920 EXPECT_EQ(pipeline_->GetMediaTime(), new_time); 921 } 922 923 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) { 924 // |pipeline| will go out of scope. 925 } 926 927 TEST_F(PipelineTest, DeleteAfterStop) { 928 CreateAudioStream(); 929 MockDemuxerStreamVector streams; 930 streams.push_back(audio_stream()); 931 InitializeDemuxer(&streams); 932 InitializeAudioRenderer(audio_stream(), false); 933 InitializePipeline(PIPELINE_OK); 934 935 ExpectStop(); 936 937 Pipeline* pipeline = pipeline_.get(); 938 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_))); 939 message_loop_.RunUntilIdle(); 940 } 941 942 class PipelineTeardownTest : public PipelineTest { 943 public: 944 enum TeardownState { 945 kInitDemuxer, 946 kInitAudioRenderer, 947 kInitVideoRenderer, 948 kPausing, 949 kFlushing, 950 kSeeking, 951 kPrerolling, 952 kStarting, 953 kPlaying, 954 }; 955 956 enum StopOrError { 957 kStop, 958 kError, 959 kErrorAndStop, 960 }; 961 962 PipelineTeardownTest() {} 963 virtual ~PipelineTeardownTest() {} 964 965 void RunTest(TeardownState state, StopOrError stop_or_error) { 966 switch (state) { 967 case kInitDemuxer: 968 case kInitAudioRenderer: 969 case kInitVideoRenderer: 970 DoInitialize(state, stop_or_error); 971 break; 972 973 case kPausing: 974 case kFlushing: 975 case kSeeking: 976 case kPrerolling: 977 case kStarting: 978 DoInitialize(state, stop_or_error); 979 DoSeek(state, stop_or_error); 980 break; 981 982 case kPlaying: 983 DoInitialize(state, stop_or_error); 984 DoStopOrError(stop_or_error); 985 break; 986 } 987 } 988 989 private: 990 // TODO(scherkus): We do radically different things whether teardown is 991 // invoked via stop vs error. The teardown path should be the same, 992 // see http://crbug.com/110228 993 void DoInitialize(TeardownState state, StopOrError stop_or_error) { 994 PipelineStatus expected_status = 995 SetInitializeExpectations(state, stop_or_error); 996 997 EXPECT_CALL(callbacks_, OnStart(expected_status)); 998 pipeline_->Start( 999 filter_collection_.Pass(), 1000 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), 1001 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), 1002 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)), 1003 base::Bind(&CallbackHelper::OnBufferingState, 1004 base::Unretained(&callbacks_)), 1005 base::Bind(&CallbackHelper::OnDurationChange, 1006 base::Unretained(&callbacks_))); 1007 message_loop_.RunUntilIdle(); 1008 } 1009 1010 PipelineStatus SetInitializeExpectations(TeardownState state, 1011 StopOrError stop_or_error) { 1012 PipelineStatus status = PIPELINE_OK; 1013 base::Closure stop_cb = base::Bind( 1014 &CallbackHelper::OnStop, base::Unretained(&callbacks_)); 1015 1016 if (state == kInitDemuxer) { 1017 if (stop_or_error == kStop) { 1018 EXPECT_CALL(*demuxer_, Initialize(_, _, _)) 1019 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), 1020 RunCallback<1>(PIPELINE_OK))); 1021 EXPECT_CALL(callbacks_, OnStop()); 1022 } else { 1023 status = DEMUXER_ERROR_COULD_NOT_OPEN; 1024 EXPECT_CALL(*demuxer_, Initialize(_, _, _)) 1025 .WillOnce(RunCallback<1>(status)); 1026 } 1027 1028 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 1029 return status; 1030 } 1031 1032 CreateAudioStream(); 1033 CreateVideoStream(); 1034 MockDemuxerStreamVector streams; 1035 streams.push_back(audio_stream()); 1036 streams.push_back(video_stream()); 1037 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000)); 1038 1039 if (state == kInitAudioRenderer) { 1040 if (stop_or_error == kStop) { 1041 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _)) 1042 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), 1043 RunCallback<1>(PIPELINE_OK))); 1044 EXPECT_CALL(callbacks_, OnStop()); 1045 } else { 1046 status = PIPELINE_ERROR_INITIALIZATION_FAILED; 1047 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _)) 1048 .WillOnce(RunCallback<1>(status)); 1049 } 1050 1051 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 1052 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1053 return status; 1054 } 1055 1056 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _)) 1057 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1058 1059 if (state == kInitVideoRenderer) { 1060 if (stop_or_error == kStop) { 1061 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _)) 1062 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), 1063 RunCallback<1>(PIPELINE_OK))); 1064 EXPECT_CALL(callbacks_, OnStop()); 1065 } else { 1066 status = PIPELINE_ERROR_INITIALIZATION_FAILED; 1067 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _)) 1068 .WillOnce(RunCallback<1>(status)); 1069 } 1070 1071 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 1072 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1073 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1074 return status; 1075 } 1076 1077 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _)) 1078 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1079 1080 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata)); 1081 1082 // If we get here it's a successful initialization. 1083 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _)) 1084 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1085 EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _)) 1086 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1087 1088 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f)); 1089 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f)); 1090 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f)); 1091 1092 EXPECT_CALL(*audio_renderer_, Play(_)) 1093 .WillOnce(RunClosure<0>()); 1094 EXPECT_CALL(*video_renderer_, Play(_)) 1095 .WillOnce(RunClosure<0>()); 1096 1097 if (status == PIPELINE_OK) 1098 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted)); 1099 1100 return status; 1101 } 1102 1103 void DoSeek(TeardownState state, StopOrError stop_or_error) { 1104 InSequence s; 1105 PipelineStatus status = SetSeekExpectations(state, stop_or_error); 1106 1107 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 1108 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1109 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1110 EXPECT_CALL(callbacks_, OnSeek(status)); 1111 1112 if (status == PIPELINE_OK) { 1113 EXPECT_CALL(callbacks_, OnStop()); 1114 } 1115 1116 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind( 1117 &CallbackHelper::OnSeek, base::Unretained(&callbacks_))); 1118 message_loop_.RunUntilIdle(); 1119 } 1120 1121 PipelineStatus SetSeekExpectations(TeardownState state, 1122 StopOrError stop_or_error) { 1123 PipelineStatus status = PIPELINE_OK; 1124 base::Closure stop_cb = base::Bind( 1125 &CallbackHelper::OnStop, base::Unretained(&callbacks_)); 1126 1127 if (state == kPausing) { 1128 if (stop_or_error == kStop) { 1129 EXPECT_CALL(*audio_renderer_, Pause(_)) 1130 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>())); 1131 } else { 1132 status = PIPELINE_ERROR_READ; 1133 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce( 1134 DoAll(SetError(pipeline_.get(), status), RunClosure<0>())); 1135 } 1136 1137 return status; 1138 } 1139 1140 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(RunClosure<0>()); 1141 EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>()); 1142 1143 if (state == kFlushing) { 1144 if (stop_or_error == kStop) { 1145 EXPECT_CALL(*audio_renderer_, Flush(_)) 1146 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>())); 1147 } else { 1148 status = PIPELINE_ERROR_READ; 1149 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce( 1150 DoAll(SetError(pipeline_.get(), status), RunClosure<0>())); 1151 } 1152 1153 return status; 1154 } 1155 1156 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); 1157 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); 1158 1159 if (state == kSeeking) { 1160 if (stop_or_error == kStop) { 1161 EXPECT_CALL(*demuxer_, Seek(_, _)) 1162 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), 1163 RunCallback<1>(PIPELINE_OK))); 1164 } else { 1165 status = PIPELINE_ERROR_READ; 1166 EXPECT_CALL(*demuxer_, Seek(_, _)) 1167 .WillOnce(RunCallback<1>(status)); 1168 } 1169 1170 return status; 1171 } 1172 1173 EXPECT_CALL(*demuxer_, Seek(_, _)) 1174 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1175 1176 if (state == kPrerolling) { 1177 if (stop_or_error == kStop) { 1178 EXPECT_CALL(*audio_renderer_, Preroll(_, _)) 1179 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), 1180 RunCallback<1>(PIPELINE_OK))); 1181 } else { 1182 status = PIPELINE_ERROR_READ; 1183 EXPECT_CALL(*audio_renderer_, Preroll(_, _)) 1184 .WillOnce(RunCallback<1>(status)); 1185 } 1186 1187 return status; 1188 } 1189 1190 EXPECT_CALL(*audio_renderer_, Preroll(_, _)) 1191 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1192 EXPECT_CALL(*video_renderer_, Preroll(_, _)) 1193 .WillOnce(RunCallback<1>(PIPELINE_OK)); 1194 1195 // Playback rate and volume are updated prior to starting. 1196 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f)); 1197 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f)); 1198 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f)); 1199 1200 if (state == kStarting) { 1201 if (stop_or_error == kStop) { 1202 EXPECT_CALL(*audio_renderer_, Play(_)) 1203 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>())); 1204 } else { 1205 status = PIPELINE_ERROR_READ; 1206 EXPECT_CALL(*audio_renderer_, Play(_)).WillOnce( 1207 DoAll(SetError(pipeline_.get(), status), RunClosure<0>())); 1208 } 1209 return status; 1210 } 1211 1212 NOTREACHED() << "State not supported: " << state; 1213 return status; 1214 } 1215 1216 void DoStopOrError(StopOrError stop_or_error) { 1217 InSequence s; 1218 1219 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); 1220 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1221 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); 1222 1223 switch (stop_or_error) { 1224 case kStop: 1225 EXPECT_CALL(callbacks_, OnStop()); 1226 pipeline_->Stop(base::Bind( 1227 &CallbackHelper::OnStop, base::Unretained(&callbacks_))); 1228 break; 1229 1230 case kError: 1231 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); 1232 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ); 1233 break; 1234 1235 case kErrorAndStop: 1236 EXPECT_CALL(callbacks_, OnStop()); 1237 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ); 1238 pipeline_->Stop(base::Bind( 1239 &CallbackHelper::OnStop, base::Unretained(&callbacks_))); 1240 break; 1241 } 1242 1243 message_loop_.RunUntilIdle(); 1244 } 1245 1246 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest); 1247 }; 1248 1249 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \ 1250 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \ 1251 RunTest(k##state, k##stop_or_error); \ 1252 } 1253 1254 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer); 1255 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer); 1256 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer); 1257 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing); 1258 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing); 1259 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking); 1260 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling); 1261 INSTANTIATE_TEARDOWN_TEST(Stop, Starting); 1262 INSTANTIATE_TEARDOWN_TEST(Stop, Playing); 1263 1264 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer); 1265 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer); 1266 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer); 1267 INSTANTIATE_TEARDOWN_TEST(Error, Pausing); 1268 INSTANTIATE_TEARDOWN_TEST(Error, Flushing); 1269 INSTANTIATE_TEARDOWN_TEST(Error, Seeking); 1270 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling); 1271 INSTANTIATE_TEARDOWN_TEST(Error, Starting); 1272 INSTANTIATE_TEARDOWN_TEST(Error, Playing); 1273 1274 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing); 1275 1276 } // namespace media 1277