| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdint.h> | 5 #include <stdint.h> |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 ACTION_P(RunClosure, closure) { | 45 ACTION_P(RunClosure, closure) { |
| 46 closure.Run(); | 46 closure.Run(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 MATCHER_P(HasTimestamp, ms, "") { | 49 MATCHER_P(HasTimestamp, ms, "") { |
| 50 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); | 50 *result_listener << "has timestamp " << arg->timestamp().InMilliseconds(); |
| 51 return arg->timestamp().InMilliseconds() == ms; | 51 return arg->timestamp().InMilliseconds() == ms; |
| 52 } | 52 } |
| 53 | 53 |
| 54 class VideoRendererImplTest | 54 class VideoRendererImplTest : public testing::Test { |
| 55 : public testing::Test { | |
| 56 public: | 55 public: |
| 57 VideoRendererImplTest() | 56 VideoRendererImplTest() |
| 58 : tick_clock_(new base::SimpleTestTickClock()), | 57 : tick_clock_(new base::SimpleTestTickClock()), |
| 59 decoder_(new NiceMock<MockVideoDecoder>()), | 58 decoder_(new NiceMock<MockVideoDecoder>()), |
| 60 demuxer_stream_(DemuxerStream::VIDEO) { | 59 demuxer_stream_(DemuxerStream::VIDEO) { |
| 61 ScopedVector<VideoDecoder> decoders; | 60 ScopedVector<VideoDecoder> decoders; |
| 62 decoders.push_back(decoder_); | 61 decoders.push_back(decoder_); |
| 63 | 62 |
| 64 null_video_sink_.reset(new NullVideoSink( | 63 null_video_sink_.reset(new NullVideoSink( |
| 65 false, base::TimeDelta::FromSecondsD(1.0 / 60), | 64 false, base::TimeDelta::FromSecondsD(1.0 / 60), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 } | 112 } |
| 114 | 113 |
| 115 void CallInitialize(const PipelineStatusCB& status_cb, | 114 void CallInitialize(const PipelineStatusCB& status_cb, |
| 116 bool low_delay, | 115 bool low_delay, |
| 117 bool expect_success) { | 116 bool expect_success) { |
| 118 if (low_delay) | 117 if (low_delay) |
| 119 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE); | 118 demuxer_stream_.set_liveness(DemuxerStream::LIVENESS_LIVE); |
| 120 EXPECT_CALL(*decoder_, Initialize(_, _, _, _, _)) | 119 EXPECT_CALL(*decoder_, Initialize(_, _, _, _, _)) |
| 121 .WillOnce( | 120 .WillOnce( |
| 122 DoAll(SaveArg<4>(&output_cb_), RunCallback<3>(expect_success))); | 121 DoAll(SaveArg<4>(&output_cb_), RunCallback<3>(expect_success))); |
| 123 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | 122 EXPECT_CALL(mock_cb_, OnWaitingForDecryptionKey()).Times(0); |
| 124 renderer_->Initialize( | 123 renderer_->Initialize(&demuxer_stream_, nullptr, &mock_cb_, |
| 125 &demuxer_stream_, status_cb, nullptr, | 124 base::Bind(&WallClockTimeSource::GetWallClockTimes, |
| 126 base::Bind(&VideoRendererImplTest::OnStatisticsUpdate, | 125 base::Unretained(&time_source_)), |
| 127 base::Unretained(this)), | 126 status_cb); |
| 128 base::Bind(&StrictMock<MockCB>::BufferingStateChange, | |
| 129 base::Unretained(&mock_cb_)), | |
| 130 ended_event_.GetClosure(), error_event_.GetPipelineStatusCB(), | |
| 131 base::Bind(&WallClockTimeSource::GetWallClockTimes, | |
| 132 base::Unretained(&time_source_)), | |
| 133 base::Bind(&VideoRendererImplTest::OnWaitingForDecryptionKey, | |
| 134 base::Unretained(this))); | |
| 135 } | 127 } |
| 136 | 128 |
| 137 void StartPlayingFrom(int milliseconds) { | 129 void StartPlayingFrom(int milliseconds) { |
| 138 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds)); | 130 SCOPED_TRACE(base::StringPrintf("StartPlayingFrom(%d)", milliseconds)); |
| 139 const base::TimeDelta media_time = | 131 const base::TimeDelta media_time = |
| 140 base::TimeDelta::FromMilliseconds(milliseconds); | 132 base::TimeDelta::FromMilliseconds(milliseconds); |
| 141 time_source_.SetMediaTime(media_time); | 133 time_source_.SetMediaTime(media_time); |
| 142 renderer_->StartPlayingFrom(media_time); | 134 renderer_->StartPlayingFrom(media_time); |
| 143 message_loop_.RunUntilIdle(); | 135 message_loop_.RunUntilIdle(); |
| 144 } | 136 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 CHECK(false) << "Unrecognized decoder buffer token: " << token; | 190 CHECK(false) << "Unrecognized decoder buffer token: " << token; |
| 199 } | 191 } |
| 200 } | 192 } |
| 201 | 193 |
| 202 bool IsReadPending() { | 194 bool IsReadPending() { |
| 203 return !decode_cb_.is_null(); | 195 return !decode_cb_.is_null(); |
| 204 } | 196 } |
| 205 | 197 |
| 206 void WaitForError(PipelineStatus expected) { | 198 void WaitForError(PipelineStatus expected) { |
| 207 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); | 199 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); |
| 208 error_event_.RunAndWaitForStatus(expected); | 200 |
| 201 WaitableMessageLoopEvent event; |
| 202 PipelineStatusCB error_cb = event.GetPipelineStatusCB(); |
| 203 EXPECT_CALL(mock_cb_, OnError(_)) |
| 204 .WillOnce(Invoke(&error_cb, &PipelineStatusCB::Run)); |
| 205 event.RunAndWaitForStatus(expected); |
| 209 } | 206 } |
| 210 | 207 |
| 211 void WaitForEnded() { | 208 void WaitForEnded() { |
| 212 SCOPED_TRACE("WaitForEnded()"); | 209 SCOPED_TRACE("WaitForEnded()"); |
| 213 ended_event_.RunAndWait(); | 210 |
| 211 WaitableMessageLoopEvent event; |
| 212 EXPECT_CALL(mock_cb_, OnEnded()).WillOnce(RunClosure(event.GetClosure())); |
| 213 event.RunAndWait(); |
| 214 } | 214 } |
| 215 | 215 |
| 216 void WaitForPendingRead() { | 216 void WaitForPendingRead() { |
| 217 SCOPED_TRACE("WaitForPendingRead()"); | 217 SCOPED_TRACE("WaitForPendingRead()"); |
| 218 if (!decode_cb_.is_null()) | 218 if (!decode_cb_.is_null()) |
| 219 return; | 219 return; |
| 220 | 220 |
| 221 DCHECK(wait_for_pending_decode_cb_.is_null()); | 221 DCHECK(wait_for_pending_decode_cb_.is_null()); |
| 222 | 222 |
| 223 WaitableMessageLoopEvent event; | 223 WaitableMessageLoopEvent event; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 | 270 |
| 271 void AdvanceTimeInMs(int time_ms) { | 271 void AdvanceTimeInMs(int time_ms) { |
| 272 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 272 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
| 273 base::AutoLock l(lock_); | 273 base::AutoLock l(lock_); |
| 274 time_ += base::TimeDelta::FromMilliseconds(time_ms); | 274 time_ += base::TimeDelta::FromMilliseconds(time_ms); |
| 275 time_source_.StopTicking(); | 275 time_source_.StopTicking(); |
| 276 time_source_.SetMediaTime(time_); | 276 time_source_.SetMediaTime(time_); |
| 277 time_source_.StartTicking(); | 277 time_source_.StartTicking(); |
| 278 } | 278 } |
| 279 | 279 |
| 280 bool has_ended() const { | |
| 281 return ended_event_.is_signaled(); | |
| 282 } | |
| 283 | |
| 284 enum class UnderflowTestType { | 280 enum class UnderflowTestType { |
| 285 NORMAL, | 281 NORMAL, |
| 286 LOW_DELAY, | 282 LOW_DELAY, |
| 287 CANT_READ_WITHOUT_STALLING | 283 CANT_READ_WITHOUT_STALLING |
| 288 }; | 284 }; |
| 289 void BasicUnderflowTest(UnderflowTestType type) { | 285 void BasicUnderflowTest(UnderflowTestType type) { |
| 290 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); | 286 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
| 291 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) | 287 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
| 292 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 288 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
| 293 | 289 |
| 294 QueueFrames("0 30 60 90"); | 290 QueueFrames("0 30 60 90"); |
| 295 | 291 |
| 296 { | 292 { |
| 297 WaitableMessageLoopEvent event; | 293 WaitableMessageLoopEvent event; |
| 298 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 294 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 299 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 295 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 300 .WillOnce(RunClosure(event.GetClosure())); | 296 .WillOnce(RunClosure(event.GetClosure())); |
| 297 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 301 StartPlayingFrom(0); | 298 StartPlayingFrom(0); |
| 302 event.RunAndWait(); | 299 event.RunAndWait(); |
| 303 Mock::VerifyAndClearExpectations(&mock_cb_); | 300 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 304 } | 301 } |
| 305 | 302 |
| 306 renderer_->OnTimeStateChanged(true); | 303 renderer_->OnTimeStateChanged(true); |
| 307 | 304 |
| 308 // Advance time slightly, but enough to exceed the duration of the last | 305 // Advance time slightly, but enough to exceed the duration of the last |
| 309 // frame. | 306 // frame. |
| 310 // Frames should be dropped and we should NOT signal having nothing. | 307 // Frames should be dropped and we should NOT signal having nothing. |
| 311 { | 308 { |
| 312 SCOPED_TRACE("Waiting for frame drops"); | 309 SCOPED_TRACE("Waiting for frame drops"); |
| 313 WaitableMessageLoopEvent event; | 310 WaitableMessageLoopEvent event; |
| 314 | 311 |
| 315 // Note: Starting the TimeSource will cause the old VideoRendererImpl to | 312 // Note: Starting the TimeSource will cause the old VideoRendererImpl to |
| 316 // start rendering frames on its own thread, so the first frame may be | 313 // start rendering frames on its own thread, so the first frame may be |
| 317 // received. | 314 // received. |
| 318 time_source_.StartTicking(); | 315 time_source_.StartTicking(); |
| 319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); | 316 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); |
| 320 | 317 |
| 321 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); | 318 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); |
| 322 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) | 319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) |
| 323 .WillOnce(RunClosure(event.GetClosure())); | 320 .WillOnce(RunClosure(event.GetClosure())); |
| 321 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 324 AdvanceTimeInMs(91); | 322 AdvanceTimeInMs(91); |
| 325 | 323 |
| 326 event.RunAndWait(); | 324 event.RunAndWait(); |
| 327 Mock::VerifyAndClearExpectations(&mock_cb_); | 325 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 328 } | 326 } |
| 329 | 327 |
| 330 // Advance time more. Now we should signal having nothing. And put | 328 // Advance time more. Now we should signal having nothing. And put |
| 331 // the last frame up for display. | 329 // the last frame up for display. |
| 332 { | 330 { |
| 333 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | 331 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
| 334 WaitableMessageLoopEvent event; | 332 WaitableMessageLoopEvent event; |
| 335 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 333 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 336 .WillOnce(RunClosure(event.GetClosure())); | 334 .WillOnce(RunClosure(event.GetClosure())); |
| 337 AdvanceTimeInMs(30); | 335 AdvanceTimeInMs(30); |
| 338 event.RunAndWait(); | 336 event.RunAndWait(); |
| 339 Mock::VerifyAndClearExpectations(&mock_cb_); | 337 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 340 } | 338 } |
| 341 | 339 |
| 342 // Simulate delayed buffering state callbacks. | 340 // Simulate delayed buffering state callbacks. |
| 343 renderer_->OnTimeStateChanged(false); | 341 renderer_->OnTimeStateChanged(false); |
| 344 renderer_->OnTimeStateChanged(true); | 342 renderer_->OnTimeStateChanged(true); |
| 345 | 343 |
| 346 // Receiving end of stream should signal having enough. | 344 // Receiving end of stream should signal having enough. |
| 347 { | 345 { |
| 348 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 346 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
| 349 WaitableMessageLoopEvent event; | 347 WaitableMessageLoopEvent event; |
| 350 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 348 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 351 .WillOnce(RunClosure(event.GetClosure())); | 349 .WillOnce(RunClosure(event.GetClosure())); |
| 350 EXPECT_CALL(mock_cb_, OnEnded()); |
| 352 SatisfyPendingReadWithEndOfStream(); | 351 SatisfyPendingReadWithEndOfStream(); |
| 353 event.RunAndWait(); | 352 event.RunAndWait(); |
| 354 } | 353 } |
| 355 | 354 |
| 356 WaitForEnded(); | |
| 357 Destroy(); | 355 Destroy(); |
| 358 } | 356 } |
| 359 | 357 |
| 360 void UnderflowRecoveryTest(UnderflowTestType type) { | 358 void UnderflowRecoveryTest(UnderflowTestType type) { |
| 361 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); | 359 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
| 362 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) | 360 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
| 363 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 361 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
| 364 | 362 |
| 365 QueueFrames("0 20 40 60"); | 363 QueueFrames("0 20 40 60"); |
| 366 { | 364 { |
| 367 WaitableMessageLoopEvent event; | 365 WaitableMessageLoopEvent event; |
| 368 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 366 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 369 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 367 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 370 .WillOnce(RunClosure(event.GetClosure())); | 368 .WillOnce(RunClosure(event.GetClosure())); |
| 369 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 371 StartPlayingFrom(0); | 370 StartPlayingFrom(0); |
| 372 event.RunAndWait(); | 371 event.RunAndWait(); |
| 373 Mock::VerifyAndClearExpectations(&mock_cb_); | 372 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 374 } | 373 } |
| 375 | 374 |
| 376 renderer_->OnTimeStateChanged(true); | 375 renderer_->OnTimeStateChanged(true); |
| 377 time_source_.StartTicking(); | 376 time_source_.StartTicking(); |
| 378 | 377 |
| 379 // Advance time, this should cause have nothing to be signaled. | 378 // Advance time, this should cause have nothing to be signaled. |
| 380 { | 379 { |
| 381 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | 380 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
| 382 WaitableMessageLoopEvent event; | 381 WaitableMessageLoopEvent event; |
| 383 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 382 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 384 .WillOnce(RunClosure(event.GetClosure())); | 383 .WillOnce(RunClosure(event.GetClosure())); |
| 385 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); | 384 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); |
| 385 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 386 AdvanceTimeInMs(20); | 386 AdvanceTimeInMs(20); |
| 387 event.RunAndWait(); | 387 event.RunAndWait(); |
| 388 Mock::VerifyAndClearExpectations(&mock_cb_); | 388 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 389 } | 389 } |
| 390 | 390 |
| 391 AdvanceTimeInMs(59); | 391 AdvanceTimeInMs(59); |
| 392 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); | 392 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); |
| 393 time_source_.StopTicking(); | 393 time_source_.StopTicking(); |
| 394 renderer_->OnTimeStateChanged(false); | 394 renderer_->OnTimeStateChanged(false); |
| 395 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); | 395 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); |
| 396 ASSERT_TRUE(IsReadPending()); | 396 ASSERT_TRUE(IsReadPending()); |
| 397 | 397 |
| 398 // Queue some frames, satisfy reads, and make sure expired frames are gone | 398 // Queue some frames, satisfy reads, and make sure expired frames are gone |
| 399 // when the renderer paints the first frame. | 399 // when the renderer paints the first frame. |
| 400 { | 400 { |
| 401 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 401 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
| 402 WaitableMessageLoopEvent event; | 402 WaitableMessageLoopEvent event; |
| 403 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); | 403 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); |
| 404 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 404 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 405 .WillOnce(RunClosure(event.GetClosure())); | 405 .WillOnce(RunClosure(event.GetClosure())); |
| 406 if (type == UnderflowTestType::NORMAL) | 406 if (type == UnderflowTestType::NORMAL) |
| 407 QueueFrames("80 100 120 140 160"); | 407 QueueFrames("80 100 120 140 160"); |
| 408 else | 408 else |
| 409 QueueFrames("40 60 80"); | 409 QueueFrames("40 60 80"); |
| 410 SatisfyPendingRead(); | 410 SatisfyPendingRead(); |
| 411 event.RunAndWait(); | 411 event.RunAndWait(); |
| 412 } | 412 } |
| 413 | 413 |
| 414 Destroy(); | 414 Destroy(); |
| 415 } | 415 } |
| 416 | 416 |
| 417 protected: | 417 protected: |
| 418 // Fixture members. | 418 // Fixture members. |
| 419 std::unique_ptr<VideoRendererImpl> renderer_; | 419 std::unique_ptr<VideoRendererImpl> renderer_; |
| 420 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. | 420 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. |
| 421 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. | 421 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. |
| 422 NiceMock<MockDemuxerStream> demuxer_stream_; | 422 NiceMock<MockDemuxerStream> demuxer_stream_; |
| 423 | 423 |
| 424 // Use StrictMock<T> to catch missing/extra callbacks. | 424 // Use StrictMock<T> to catch missing/extra callbacks. |
| 425 class MockCB { | 425 class MockCB : public MockRendererClient { |
| 426 public: | 426 public: |
| 427 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&)); | 427 MOCK_METHOD1(FrameReceived, void(const scoped_refptr<VideoFrame>&)); |
| 428 MOCK_METHOD1(BufferingStateChange, void(BufferingState)); | |
| 429 }; | 428 }; |
| 430 StrictMock<MockCB> mock_cb_; | 429 StrictMock<MockCB> mock_cb_; |
| 431 | 430 |
| 432 // Must be destroyed before |renderer_| since they share |tick_clock_|. | 431 // Must be destroyed before |renderer_| since they share |tick_clock_|. |
| 433 std::unique_ptr<NullVideoSink> null_video_sink_; | 432 std::unique_ptr<NullVideoSink> null_video_sink_; |
| 434 | 433 |
| 435 PipelineStatistics last_pipeline_statistics_; | |
| 436 | |
| 437 WallClockTimeSource time_source_; | 434 WallClockTimeSource time_source_; |
| 438 | 435 |
| 439 base::MessageLoop message_loop_; | 436 base::MessageLoop message_loop_; |
| 440 | 437 |
| 441 private: | 438 private: |
| 442 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer, | 439 void DecodeRequested(const scoped_refptr<DecoderBuffer>& buffer, |
| 443 const VideoDecoder::DecodeCB& decode_cb) { | 440 const VideoDecoder::DecodeCB& decode_cb) { |
| 444 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 441 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
| 445 CHECK(decode_cb_.is_null()); | 442 CHECK(decode_cb_.is_null()); |
| 446 decode_cb_ = decode_cb; | 443 decode_cb_ = decode_cb; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 459 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); | 456 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); |
| 460 decode_results_.clear(); | 457 decode_results_.clear(); |
| 461 if (!decode_cb_.is_null()) { | 458 if (!decode_cb_.is_null()) { |
| 462 QueueFrames("abort"); | 459 QueueFrames("abort"); |
| 463 SatisfyPendingRead(); | 460 SatisfyPendingRead(); |
| 464 } | 461 } |
| 465 | 462 |
| 466 message_loop_.PostTask(FROM_HERE, callback); | 463 message_loop_.PostTask(FROM_HERE, callback); |
| 467 } | 464 } |
| 468 | 465 |
| 469 void OnStatisticsUpdate(const PipelineStatistics& stats) { | |
| 470 last_pipeline_statistics_ = stats; | |
| 471 } | |
| 472 | |
| 473 MOCK_METHOD0(OnWaitingForDecryptionKey, void(void)); | |
| 474 | |
| 475 // Used to protect |time_|. | 466 // Used to protect |time_|. |
| 476 base::Lock lock_; | 467 base::Lock lock_; |
| 477 base::TimeDelta time_; | 468 base::TimeDelta time_; |
| 478 | 469 |
| 479 // Used for satisfying reads. | 470 // Used for satisfying reads. |
| 480 VideoDecoder::OutputCB output_cb_; | 471 VideoDecoder::OutputCB output_cb_; |
| 481 VideoDecoder::DecodeCB decode_cb_; | 472 VideoDecoder::DecodeCB decode_cb_; |
| 482 base::TimeDelta next_frame_timestamp_; | 473 base::TimeDelta next_frame_timestamp_; |
| 483 | 474 |
| 484 WaitableMessageLoopEvent error_event_; | |
| 485 WaitableMessageLoopEvent ended_event_; | |
| 486 | |
| 487 // Run during DecodeRequested() to unblock WaitForPendingRead(). | 475 // Run during DecodeRequested() to unblock WaitForPendingRead(). |
| 488 base::Closure wait_for_pending_decode_cb_; | 476 base::Closure wait_for_pending_decode_cb_; |
| 489 | 477 |
| 490 std::deque<std::pair<DecodeStatus, scoped_refptr<VideoFrame>>> | 478 std::deque<std::pair<DecodeStatus, scoped_refptr<VideoFrame>>> |
| 491 decode_results_; | 479 decode_results_; |
| 492 | 480 |
| 493 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); | 481 DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest); |
| 494 }; | 482 }; |
| 495 | 483 |
| 496 TEST_F(VideoRendererImplTest, DoNothing) { | 484 TEST_F(VideoRendererImplTest, DoNothing) { |
| 497 // Test that creation and deletion doesn't depend on calls to Initialize() | 485 // Test that creation and deletion doesn't depend on calls to Initialize() |
| 498 // and/or Destroy(). | 486 // and/or Destroy(). |
| 499 } | 487 } |
| 500 | 488 |
| 501 TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) { | 489 TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) { |
| 502 Destroy(); | 490 Destroy(); |
| 503 } | 491 } |
| 504 | 492 |
| 505 TEST_F(VideoRendererImplTest, Initialize) { | 493 TEST_F(VideoRendererImplTest, Initialize) { |
| 506 Initialize(); | 494 Initialize(); |
| 507 Destroy(); | 495 Destroy(); |
| 508 } | 496 } |
| 509 | 497 |
| 510 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) { | 498 TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) { |
| 511 Initialize(); | 499 Initialize(); |
| 512 QueueFrames("0 10 20 30"); | 500 QueueFrames("0 10 20 30"); |
| 513 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 501 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 514 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 502 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 503 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 515 StartPlayingFrom(0); | 504 StartPlayingFrom(0); |
| 516 Destroy(); | 505 Destroy(); |
| 517 } | 506 } |
| 518 | 507 |
| 519 TEST_F(VideoRendererImplTest, InitializeAndEndOfStream) { | 508 TEST_F(VideoRendererImplTest, InitializeAndEndOfStream) { |
| 520 Initialize(); | 509 Initialize(); |
| 521 StartPlayingFrom(0); | 510 StartPlayingFrom(0); |
| 522 WaitForPendingRead(); | 511 WaitForPendingRead(); |
| 523 { | 512 { |
| 524 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | 513 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
| 525 WaitableMessageLoopEvent event; | 514 WaitableMessageLoopEvent event; |
| 526 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 515 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 527 .WillOnce(RunClosure(event.GetClosure())); | 516 .WillOnce(RunClosure(event.GetClosure())); |
| 517 EXPECT_CALL(mock_cb_, OnEnded()); |
| 528 SatisfyPendingReadWithEndOfStream(); | 518 SatisfyPendingReadWithEndOfStream(); |
| 529 event.RunAndWait(); | 519 event.RunAndWait(); |
| 530 } | 520 } |
| 531 // Firing a time state changed to true should be ignored... | 521 // Firing a time state changed to true should be ignored... |
| 532 renderer_->OnTimeStateChanged(true); | 522 renderer_->OnTimeStateChanged(true); |
| 533 EXPECT_FALSE(null_video_sink_->is_started()); | 523 EXPECT_FALSE(null_video_sink_->is_started()); |
| 534 Destroy(); | 524 Destroy(); |
| 535 } | 525 } |
| 536 | 526 |
| 537 TEST_F(VideoRendererImplTest, DestroyWhileInitializing) { | 527 TEST_F(VideoRendererImplTest, DestroyWhileInitializing) { |
| 538 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK); | 528 CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK); |
| 539 Destroy(); | 529 Destroy(); |
| 540 } | 530 } |
| 541 | 531 |
| 542 TEST_F(VideoRendererImplTest, DestroyWhileFlushing) { | 532 TEST_F(VideoRendererImplTest, DestroyWhileFlushing) { |
| 543 Initialize(); | 533 Initialize(); |
| 544 QueueFrames("0 10 20 30"); | 534 QueueFrames("0 10 20 30"); |
| 545 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 535 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 546 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 536 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 537 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 547 StartPlayingFrom(0); | 538 StartPlayingFrom(0); |
| 548 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)); | |
| 549 renderer_->Flush(NewExpectedClosure()); | 539 renderer_->Flush(NewExpectedClosure()); |
| 550 Destroy(); | 540 Destroy(); |
| 551 } | 541 } |
| 552 | 542 |
| 553 TEST_F(VideoRendererImplTest, Play) { | 543 TEST_F(VideoRendererImplTest, Play) { |
| 554 Initialize(); | 544 Initialize(); |
| 555 QueueFrames("0 10 20 30"); | 545 QueueFrames("0 10 20 30"); |
| 556 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 546 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 557 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 547 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 548 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 558 StartPlayingFrom(0); | 549 StartPlayingFrom(0); |
| 559 Destroy(); | 550 Destroy(); |
| 560 } | 551 } |
| 561 | 552 |
| 562 TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) { | 553 TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) { |
| 563 Initialize(); | 554 Initialize(); |
| 564 StartPlayingFrom(0); | 555 StartPlayingFrom(0); |
| 565 | 556 |
| 566 // We shouldn't expect a buffering state change since we never reached | 557 // We shouldn't expect a buffering state change since we never reached |
| 567 // BUFFERING_HAVE_ENOUGH. | 558 // BUFFERING_HAVE_ENOUGH. |
| 568 Flush(); | 559 Flush(); |
| 569 Destroy(); | 560 Destroy(); |
| 570 } | 561 } |
| 571 | 562 |
| 572 TEST_F(VideoRendererImplTest, DecodeError_Playing) { | 563 TEST_F(VideoRendererImplTest, DecodeError_Playing) { |
| 573 Initialize(); | 564 Initialize(); |
| 574 QueueFrames("0 10 20 30"); | 565 QueueFrames("0 10 20 30"); |
| 575 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1)); | 566 EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1)); |
| 576 | 567 |
| 577 // Consider the case that rendering is faster than we setup the test event. | 568 // Consider the case that rendering is faster than we setup the test event. |
| 578 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will | 569 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will |
| 579 // be called. | 570 // be called. |
| 580 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 571 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 581 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 572 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 582 .Times(testing::AtMost(1)); | 573 .Times(testing::AtMost(1)); |
| 574 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 583 | 575 |
| 584 StartPlayingFrom(0); | 576 StartPlayingFrom(0); |
| 585 renderer_->OnTimeStateChanged(true); | 577 renderer_->OnTimeStateChanged(true); |
| 586 time_source_.StartTicking(); | 578 time_source_.StartTicking(); |
| 587 AdvanceTimeInMs(10); | 579 AdvanceTimeInMs(10); |
| 588 | 580 |
| 589 QueueFrames("error"); | 581 QueueFrames("error"); |
| 590 SatisfyPendingRead(); | 582 SatisfyPendingRead(); |
| 591 WaitForError(PIPELINE_ERROR_DECODE); | 583 WaitForError(PIPELINE_ERROR_DECODE); |
| 592 Destroy(); | 584 Destroy(); |
| 593 } | 585 } |
| 594 | 586 |
| 595 TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) { | 587 TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) { |
| 596 Initialize(); | 588 Initialize(); |
| 597 QueueFrames("error"); | 589 QueueFrames("error"); |
| 590 EXPECT_CALL(mock_cb_, OnError(PIPELINE_ERROR_DECODE)); |
| 598 StartPlayingFrom(0); | 591 StartPlayingFrom(0); |
| 599 Destroy(); | 592 Destroy(); |
| 600 } | 593 } |
| 601 | 594 |
| 602 TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) { | 595 TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) { |
| 603 Initialize(); | 596 Initialize(); |
| 604 QueueFrames("50 60 70 80 90"); | 597 QueueFrames("50 60 70 80 90"); |
| 605 | 598 |
| 606 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); | 599 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); |
| 607 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 600 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 601 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 608 StartPlayingFrom(60); | 602 StartPlayingFrom(60); |
| 609 Destroy(); | 603 Destroy(); |
| 610 } | 604 } |
| 611 | 605 |
| 612 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) { | 606 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) { |
| 613 Initialize(); | 607 Initialize(); |
| 614 QueueFrames("50 60 70 80 90"); | 608 QueueFrames("50 60 70 80 90"); |
| 615 | 609 |
| 616 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50))); | 610 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(50))); |
| 617 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 611 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 612 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 618 StartPlayingFrom(59); | 613 StartPlayingFrom(59); |
| 619 Destroy(); | 614 Destroy(); |
| 620 } | 615 } |
| 621 | 616 |
| 622 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) { | 617 TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) { |
| 623 Initialize(); | 618 Initialize(); |
| 624 QueueFrames("50 60 70 80 90"); | 619 QueueFrames("50 60 70 80 90"); |
| 625 | 620 |
| 626 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); | 621 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))); |
| 627 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 622 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 623 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 628 StartPlayingFrom(61); | 624 StartPlayingFrom(61); |
| 629 Destroy(); | 625 Destroy(); |
| 630 } | 626 } |
| 631 | 627 |
| 632 TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) { | 628 TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) { |
| 633 // In low-delay mode only one frame is required to finish preroll. But frames | 629 // In low-delay mode only one frame is required to finish preroll. But frames |
| 634 // prior to the start time will not be used. | 630 // prior to the start time will not be used. |
| 635 InitializeWithLowDelay(true); | 631 InitializeWithLowDelay(true); |
| 636 QueueFrames("0 10"); | 632 QueueFrames("0 10"); |
| 637 | 633 |
| 638 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))); | 634 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))); |
| 639 // Expect some amount of have enough/nothing due to only requiring one frame. | 635 // Expect some amount of have enough/nothing due to only requiring one frame. |
| 640 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 636 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 641 .Times(AnyNumber()); | 637 .Times(AnyNumber()); |
| 642 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 638 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 643 .Times(AnyNumber()); | 639 .Times(AnyNumber()); |
| 640 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 644 StartPlayingFrom(10); | 641 StartPlayingFrom(10); |
| 645 | 642 |
| 646 QueueFrames("20"); | 643 QueueFrames("20"); |
| 647 SatisfyPendingRead(); | 644 SatisfyPendingRead(); |
| 648 | 645 |
| 649 renderer_->OnTimeStateChanged(true); | 646 renderer_->OnTimeStateChanged(true); |
| 650 time_source_.StartTicking(); | 647 time_source_.StartTicking(); |
| 651 | 648 |
| 652 WaitableMessageLoopEvent event; | 649 WaitableMessageLoopEvent event; |
| 653 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))) | 650 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))) |
| 654 .WillOnce(RunClosure(event.GetClosure())); | 651 .WillOnce(RunClosure(event.GetClosure())); |
| 655 AdvanceTimeInMs(20); | 652 AdvanceTimeInMs(20); |
| 656 event.RunAndWait(); | 653 event.RunAndWait(); |
| 657 | 654 |
| 658 Destroy(); | 655 Destroy(); |
| 659 } | 656 } |
| 660 | 657 |
| 661 // Verify that a late decoder response doesn't break invariants in the renderer. | 658 // Verify that a late decoder response doesn't break invariants in the renderer. |
| 662 TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) { | 659 TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) { |
| 663 Initialize(); | 660 Initialize(); |
| 664 QueueFrames("0 10 20 30"); | 661 QueueFrames("0 10 20 30"); |
| 665 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 662 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 666 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 663 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 664 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 667 StartPlayingFrom(0); | 665 StartPlayingFrom(0); |
| 668 | 666 |
| 669 // Check that there is an outstanding Read() request. | 667 // Check that there is an outstanding Read() request. |
| 670 EXPECT_TRUE(IsReadPending()); | 668 EXPECT_TRUE(IsReadPending()); |
| 671 | 669 |
| 672 Destroy(); | 670 Destroy(); |
| 673 } | 671 } |
| 674 | 672 |
| 675 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { | 673 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { |
| 676 InitializeRenderer(false, false); | 674 InitializeRenderer(false, false); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 701 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); | 699 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); |
| 702 } | 700 } |
| 703 | 701 |
| 704 // Verifies that the sink is stopped after rendering the first frame if | 702 // Verifies that the sink is stopped after rendering the first frame if |
| 705 // playback hasn't started. | 703 // playback hasn't started. |
| 706 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { | 704 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { |
| 707 InitializeWithLowDelay(true); | 705 InitializeWithLowDelay(true); |
| 708 QueueFrames("0"); | 706 QueueFrames("0"); |
| 709 | 707 |
| 710 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 708 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 711 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 709 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 710 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 711 EXPECT_CALL(mock_cb_, OnEnded()).Times(0); |
| 712 | 712 |
| 713 { | 713 { |
| 714 SCOPED_TRACE("Waiting for sink to stop."); | 714 SCOPED_TRACE("Waiting for sink to stop."); |
| 715 WaitableMessageLoopEvent event; | 715 WaitableMessageLoopEvent event; |
| 716 | 716 |
| 717 null_video_sink_->set_background_render(true); | 717 null_video_sink_->set_background_render(true); |
| 718 null_video_sink_->set_stop_cb(event.GetClosure()); | 718 null_video_sink_->set_stop_cb(event.GetClosure()); |
| 719 StartPlayingFrom(0); | 719 StartPlayingFrom(0); |
| 720 | 720 |
| 721 EXPECT_TRUE(IsReadPending()); | 721 EXPECT_TRUE(IsReadPending()); |
| 722 SatisfyPendingReadWithEndOfStream(); | 722 SatisfyPendingReadWithEndOfStream(); |
| 723 | 723 |
| 724 event.RunAndWait(); | 724 event.RunAndWait(); |
| 725 } | 725 } |
| 726 | 726 |
| 727 EXPECT_FALSE(has_ended()); | |
| 728 Destroy(); | 727 Destroy(); |
| 729 } | 728 } |
| 730 | 729 |
| 731 // Verifies that the sink is stopped after rendering the first frame if | 730 // Verifies that the sink is stopped after rendering the first frame if |
| 732 // playback ha started. | 731 // playback ha started. |
| 733 TEST_F(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) { | 732 TEST_F(VideoRendererImplTest, RenderingStopsAfterOneFrameWithEOS) { |
| 734 InitializeWithLowDelay(true); | 733 InitializeWithLowDelay(true); |
| 735 QueueFrames("0"); | 734 QueueFrames("0"); |
| 736 | 735 |
| 737 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 736 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 738 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 737 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 738 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 739 | 739 |
| 740 { | 740 { |
| 741 SCOPED_TRACE("Waiting for sink to stop."); | 741 SCOPED_TRACE("Waiting for sink to stop."); |
| 742 WaitableMessageLoopEvent event; | 742 WaitableMessageLoopEvent event; |
| 743 | 743 |
| 744 null_video_sink_->set_stop_cb(event.GetClosure()); | 744 null_video_sink_->set_stop_cb(event.GetClosure()); |
| 745 StartPlayingFrom(0); | 745 StartPlayingFrom(0); |
| 746 renderer_->OnTimeStateChanged(true); | 746 renderer_->OnTimeStateChanged(true); |
| 747 | 747 |
| 748 EXPECT_TRUE(IsReadPending()); | 748 EXPECT_TRUE(IsReadPending()); |
| 749 SatisfyPendingReadWithEndOfStream(); | 749 SatisfyPendingReadWithEndOfStream(); |
| 750 WaitForEnded(); | 750 WaitForEnded(); |
| 751 | 751 |
| 752 renderer_->OnTimeStateChanged(false); | 752 renderer_->OnTimeStateChanged(false); |
| 753 event.RunAndWait(); | 753 event.RunAndWait(); |
| 754 } | 754 } |
| 755 | 755 |
| 756 Destroy(); | 756 Destroy(); |
| 757 } | 757 } |
| 758 | 758 |
| 759 // Tests the case where the video started and received a single Render() call, | 759 // Tests the case where the video started and received a single Render() call, |
| 760 // then the video was put into the background. | 760 // then the video was put into the background. |
| 761 TEST_F(VideoRendererImplTest, RenderingStartedThenStopped) { | 761 TEST_F(VideoRendererImplTest, RenderingStartedThenStopped) { |
| 762 Initialize(); | 762 Initialize(); |
| 763 QueueFrames("0 30 60 90"); | 763 QueueFrames("0 30 60 90"); |
| 764 | 764 |
| 765 // Start the sink and wait for the first callback. Set statistics to a non | 765 // Start the sink and wait for the first callback. Set statistics to a non |
| 766 // zero value, once we have some decoded frames they should be overwritten. | 766 // zero value, once we have some decoded frames they should be overwritten. |
| 767 last_pipeline_statistics_.video_frames_dropped = 1; | 767 PipelineStatistics last_pipeline_statistics; |
| 768 last_pipeline_statistics.video_frames_dropped = 1; |
| 768 { | 769 { |
| 769 WaitableMessageLoopEvent event; | 770 WaitableMessageLoopEvent event; |
| 770 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 771 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 771 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))) | 772 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))) |
| 772 .WillOnce(RunClosure(event.GetClosure())); | 773 .WillOnce(RunClosure(event.GetClosure())); |
| 774 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)) |
| 775 .WillRepeatedly(SaveArg<0>(&last_pipeline_statistics)); |
| 773 StartPlayingFrom(0); | 776 StartPlayingFrom(0); |
| 774 event.RunAndWait(); | 777 event.RunAndWait(); |
| 775 Mock::VerifyAndClearExpectations(&mock_cb_); | 778 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 776 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped); | 779 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped); |
| 777 EXPECT_EQ(460800, last_pipeline_statistics_.video_memory_usage); | 780 EXPECT_EQ(460800, last_pipeline_statistics.video_memory_usage); |
| 778 } | 781 } |
| 779 | 782 |
| 780 // Consider the case that rendering is faster than we setup the test event. | 783 // Consider the case that rendering is faster than we setup the test event. |
| 781 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will | 784 // In that case, when we run out of the frames, BUFFERING_HAVE_NOTHING will |
| 782 // be called. And then during SatisfyPendingReadWithEndOfStream, | 785 // be called. And then during SatisfyPendingReadWithEndOfStream, |
| 783 // BUFFER_HAVE_ENOUGH will be called again. | 786 // BUFFER_HAVE_ENOUGH will be called again. |
| 784 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 787 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 785 .Times(testing::AtMost(1)); | 788 .Times(testing::AtMost(1)); |
| 786 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | 789 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 787 .Times(testing::AtMost(1)); | 790 .Times(testing::AtMost(1)); |
| 788 renderer_->OnTimeStateChanged(true); | 791 renderer_->OnTimeStateChanged(true); |
| 789 time_source_.StartTicking(); | 792 time_source_.StartTicking(); |
| 790 | 793 |
| 791 // Suspend all future callbacks and synthetically advance the media time, | 794 // Suspend all future callbacks and synthetically advance the media time, |
| 792 // because this is a background render, we won't underflow by waiting until | 795 // because this is a background render, we won't underflow by waiting until |
| 793 // a pending read is ready. | 796 // a pending read is ready. |
| 794 null_video_sink_->set_background_render(true); | 797 null_video_sink_->set_background_render(true); |
| 795 AdvanceTimeInMs(91); | 798 AdvanceTimeInMs(91); |
| 796 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))); | 799 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))); |
| 797 WaitForPendingRead(); | 800 WaitForPendingRead(); |
| 798 SatisfyPendingReadWithEndOfStream(); | 801 SatisfyPendingReadWithEndOfStream(); |
| 799 | 802 |
| 800 // If this wasn't background rendering mode, this would result in two frames | 803 // If this wasn't background rendering mode, this would result in two frames |
| 801 // being dropped, but since we set background render to true, none should be | 804 // being dropped, but since we set background render to true, none should be |
| 802 // reported | 805 // reported |
| 803 EXPECT_EQ(0u, last_pipeline_statistics_.video_frames_dropped); | 806 EXPECT_EQ(0u, last_pipeline_statistics.video_frames_dropped); |
| 804 EXPECT_EQ(4u, last_pipeline_statistics_.video_frames_decoded); | 807 EXPECT_EQ(4u, last_pipeline_statistics.video_frames_decoded); |
| 805 EXPECT_EQ(460800, last_pipeline_statistics_.video_memory_usage); | 808 EXPECT_EQ(460800, last_pipeline_statistics.video_memory_usage); |
| 806 | 809 |
| 807 AdvanceTimeInMs(30); | 810 AdvanceTimeInMs(30); |
| 808 WaitForEnded(); | 811 WaitForEnded(); |
| 809 Destroy(); | 812 Destroy(); |
| 810 } | 813 } |
| 811 | 814 |
| 812 TEST_F(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) { | 815 TEST_F(VideoRendererImplTest, StartPlayingFromThenFlushThenEOS) { |
| 813 Initialize(); | 816 Initialize(); |
| 814 QueueFrames("0 30 60 90"); | 817 QueueFrames("0 30 60 90"); |
| 815 | 818 |
| 816 WaitableMessageLoopEvent event; | 819 WaitableMessageLoopEvent event; |
| 817 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 820 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 818 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 821 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 819 .WillOnce(RunClosure(event.GetClosure())); | 822 .WillOnce(RunClosure(event.GetClosure())); |
| 823 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 820 StartPlayingFrom(0); | 824 StartPlayingFrom(0); |
| 821 event.RunAndWait(); | 825 event.RunAndWait(); |
| 822 | 826 |
| 823 // Cycle ticking so that we get a non-null reference time. | 827 // Cycle ticking so that we get a non-null reference time. |
| 824 time_source_.StartTicking(); | 828 time_source_.StartTicking(); |
| 825 time_source_.StopTicking(); | 829 time_source_.StopTicking(); |
| 826 | 830 |
| 827 // Flush and simulate a seek past EOS, where some error prevents the decoder | 831 // Flush and simulate a seek past EOS, where some error prevents the decoder |
| 828 // from returning any frames. | 832 // from returning any frames. |
| 829 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)); | 833 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); |
| 830 Flush(); | 834 Flush(); |
| 831 | 835 |
| 832 StartPlayingFrom(200); | 836 StartPlayingFrom(200); |
| 833 WaitForPendingRead(); | 837 WaitForPendingRead(); |
| 834 SatisfyPendingReadWithEndOfStream(); | 838 SatisfyPendingReadWithEndOfStream(); |
| 835 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 839 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 836 WaitForEnded(); | 840 WaitForEnded(); |
| 837 Destroy(); | 841 Destroy(); |
| 838 } | 842 } |
| 839 | 843 |
| 840 TEST_F(VideoRendererImplTest, FramesAreNotExpiredDuringPreroll) { | 844 TEST_F(VideoRendererImplTest, FramesAreNotExpiredDuringPreroll) { |
| 841 Initialize(); | 845 Initialize(); |
| 842 // !CanReadWithoutStalling() puts the renderer in state BUFFERING_HAVE_ENOUGH | 846 // !CanReadWithoutStalling() puts the renderer in state BUFFERING_HAVE_ENOUGH |
| 843 // after the first frame. | 847 // after the first frame. |
| 844 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | 848 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
| 845 // Set background rendering to simulate the first couple of Render() calls | 849 // Set background rendering to simulate the first couple of Render() calls |
| 846 // by VFC. | 850 // by VFC. |
| 847 null_video_sink_->set_background_render(true); | 851 null_video_sink_->set_background_render(true); |
| 848 QueueFrames("0 10 20"); | 852 QueueFrames("0 10 20"); |
| 849 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 853 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 850 .Times(testing::AtMost(1)); | 854 .Times(testing::AtMost(1)); |
| 851 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 855 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 856 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 852 StartPlayingFrom(0); | 857 StartPlayingFrom(0); |
| 853 | 858 |
| 854 renderer_->OnTimeStateChanged(true); | 859 renderer_->OnTimeStateChanged(true); |
| 855 time_source_.StartTicking(); | 860 time_source_.StartTicking(); |
| 856 | 861 |
| 857 WaitableMessageLoopEvent event; | 862 WaitableMessageLoopEvent event; |
| 858 // Frame "10" should not have been expired. | 863 // Frame "10" should not have been expired. |
| 859 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))) | 864 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10))) |
| 860 .WillOnce(RunClosure(event.GetClosure())); | 865 .WillOnce(RunClosure(event.GetClosure())); |
| 861 AdvanceTimeInMs(10); | 866 AdvanceTimeInMs(10); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 874 } | 879 } |
| 875 | 880 |
| 876 protected: | 881 protected: |
| 877 std::vector<base::Closure> frame_ready_cbs_; | 882 std::vector<base::Closure> frame_ready_cbs_; |
| 878 }; | 883 }; |
| 879 | 884 |
| 880 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) { | 885 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, InitializeAndStartPlayingFrom) { |
| 881 Initialize(); | 886 Initialize(); |
| 882 QueueFrames("0 10 20 30"); | 887 QueueFrames("0 10 20 30"); |
| 883 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 888 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 884 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 889 EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| 890 EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); |
| 885 StartPlayingFrom(0); | 891 StartPlayingFrom(0); |
| 886 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 892 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
| 887 | 893 |
| 888 uint32_t frame_ready_index = 0; | 894 uint32_t frame_ready_index = 0; |
| 889 while (frame_ready_index < frame_ready_cbs_.size()) { | 895 while (frame_ready_index < frame_ready_cbs_.size()) { |
| 890 frame_ready_cbs_[frame_ready_index++].Run(); | 896 frame_ready_cbs_[frame_ready_index++].Run(); |
| 891 message_loop_.RunUntilIdle(); | 897 message_loop_.RunUntilIdle(); |
| 892 } | 898 } |
| 893 Destroy(); | 899 Destroy(); |
| 894 } | 900 } |
| 895 | 901 |
| 896 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, SequenceTokenDiscardOneFrame) { | 902 TEST_F(VideoRendererImplAsyncAddFrameReadyTest, SequenceTokenDiscardOneFrame) { |
| 897 Initialize(); | 903 Initialize(); |
| 898 QueueFrames("0 10 20 30"); | 904 QueueFrames("0 10 20 30"); |
| 899 StartPlayingFrom(0); | 905 StartPlayingFrom(0); |
| 900 Flush(); | 906 Flush(); |
| 901 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 907 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
| 902 // This frame will be discarded. | 908 // This frame will be discarded. |
| 903 frame_ready_cbs_.front().Run(); | 909 frame_ready_cbs_.front().Run(); |
| 904 Destroy(); | 910 Destroy(); |
| 905 } | 911 } |
| 906 | 912 |
| 907 } // namespace media | 913 } // namespace media |
| OLD | NEW |