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