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