| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 EXPECT_CALL(*demuxer_stream_, video_decoder_config()) | 56 EXPECT_CALL(*demuxer_stream_, video_decoder_config()) |
| 57 .WillRepeatedly(ReturnRef(video_config_)); | 57 .WillRepeatedly(ReturnRef(video_config_)); |
| 58 | 58 |
| 59 // We expect these to be called but we don't care how/when. | 59 // We expect these to be called but we don't care how/when. |
| 60 EXPECT_CALL(*decoder_, Stop(_)) | 60 EXPECT_CALL(*decoder_, Stop(_)) |
| 61 .WillRepeatedly(RunClosure<0>()); | 61 .WillRepeatedly(RunClosure<0>()); |
| 62 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) | 62 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) |
| 63 .Times(AnyNumber()); | 63 .Times(AnyNumber()); |
| 64 EXPECT_CALL(*this, OnTimeUpdate(_)) | 64 EXPECT_CALL(*this, OnTimeUpdate(_)) |
| 65 .Times(AnyNumber()); | 65 .Times(AnyNumber()); |
| 66 EXPECT_CALL(*this, OnPaint()) | |
| 67 .Times(AnyNumber()); | |
| 68 EXPECT_CALL(*this, OnSetOpaque(_)) | 66 EXPECT_CALL(*this, OnSetOpaque(_)) |
| 69 .Times(AnyNumber()); | 67 .Times(AnyNumber()); |
| 70 } | 68 } |
| 71 | 69 |
| 72 virtual ~VideoRendererBaseTest() {} | 70 virtual ~VideoRendererBaseTest() {} |
| 73 | 71 |
| 74 // Callbacks passed into VideoRendererBase(). | 72 // Callbacks passed into VideoRendererBase(). |
| 75 MOCK_CONST_METHOD0(OnPaint, void()); | |
| 76 MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); | 73 MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); |
| 77 | 74 |
| 78 // Callbacks passed into Initialize(). | 75 // Callbacks passed into Initialize(). |
| 79 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); | 76 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); |
| 80 MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); | 77 MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); |
| 81 | 78 |
| 82 void Initialize() { | 79 void Initialize() { |
| 83 InitializeWithDuration(kVideoDurationInMs); | 80 InitializeWithDuration(kVideoDurationInMs); |
| 84 } | 81 } |
| 85 | 82 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 while (next_frame_timestamp_ < timestamp) { | 218 while (next_frame_timestamp_ < timestamp) { |
| 222 QueueNextFrame(); | 219 QueueNextFrame(); |
| 223 } | 220 } |
| 224 | 221 |
| 225 // Queue the frame at |timestamp| plus additional ones for prerolling. | 222 // Queue the frame at |timestamp| plus additional ones for prerolling. |
| 226 for (int i = 0; i < limits::kMaxVideoFrames; ++i) { | 223 for (int i = 0; i < limits::kMaxVideoFrames; ++i) { |
| 227 QueueNextFrame(); | 224 QueueNextFrame(); |
| 228 } | 225 } |
| 229 } | 226 } |
| 230 | 227 |
| 228 void ResetCurrentFrame() { |
| 229 base::AutoLock l(lock_); |
| 230 current_frame_ = NULL; |
| 231 } |
| 232 |
| 231 scoped_refptr<VideoFrame> GetCurrentFrame() { | 233 scoped_refptr<VideoFrame> GetCurrentFrame() { |
| 232 scoped_refptr<VideoFrame> frame; | 234 base::AutoLock l(lock_); |
| 233 renderer_->GetCurrentFrame(&frame); | 235 return current_frame_; |
| 234 renderer_->PutCurrentFrame(frame); | |
| 235 return frame; | |
| 236 } | 236 } |
| 237 | 237 |
| 238 int GetCurrentTimestampInMs() { | 238 int GetCurrentTimestampInMs() { |
| 239 scoped_refptr<VideoFrame> frame = GetCurrentFrame(); | 239 scoped_refptr<VideoFrame> frame = GetCurrentFrame(); |
| 240 if (!frame) | 240 if (!frame) |
| 241 return -1; | 241 return -1; |
| 242 return frame->GetTimestamp().InMilliseconds(); | 242 return frame->GetTimestamp().InMilliseconds(); |
| 243 } | 243 } |
| 244 | 244 |
| 245 void WaitForError(PipelineStatus expected) { | 245 void WaitForError(PipelineStatus expected) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 private: | 298 private: |
| 299 base::TimeDelta GetTime() { | 299 base::TimeDelta GetTime() { |
| 300 base::AutoLock l(lock_); | 300 base::AutoLock l(lock_); |
| 301 return time_; | 301 return time_; |
| 302 } | 302 } |
| 303 | 303 |
| 304 base::TimeDelta GetDuration() { | 304 base::TimeDelta GetDuration() { |
| 305 return duration_; | 305 return duration_; |
| 306 } | 306 } |
| 307 | 307 |
| 308 void OnPaint(const scoped_refptr<VideoFrame>& frame) { |
| 309 base::AutoLock l(lock_); |
| 310 current_frame_ = frame; |
| 311 } |
| 312 |
| 308 void FrameRequested(const VideoDecoder::ReadCB& read_cb) { | 313 void FrameRequested(const VideoDecoder::ReadCB& read_cb) { |
| 309 DCHECK_EQ(&message_loop_, MessageLoop::current()); | 314 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
| 310 CHECK(read_cb_.is_null()); | 315 CHECK(read_cb_.is_null()); |
| 311 read_cb_ = read_cb; | 316 read_cb_ = read_cb; |
| 312 | 317 |
| 313 // Wake up WaitForPendingRead() if needed. | 318 // Wake up WaitForPendingRead() if needed. |
| 314 if (!wait_for_pending_read_cb_.is_null()) | 319 if (!wait_for_pending_read_cb_.is_null()) |
| 315 base::ResetAndReturn(&wait_for_pending_read_cb_).Run(); | 320 base::ResetAndReturn(&wait_for_pending_read_cb_).Run(); |
| 316 | 321 |
| 317 if (decode_results_.empty()) | 322 if (decode_results_.empty()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 328 SatisfyPendingRead(); | 333 SatisfyPendingRead(); |
| 329 } | 334 } |
| 330 | 335 |
| 331 message_loop_.PostTask(FROM_HERE, callback); | 336 message_loop_.PostTask(FROM_HERE, callback); |
| 332 } | 337 } |
| 333 | 338 |
| 334 MessageLoop message_loop_; | 339 MessageLoop message_loop_; |
| 335 | 340 |
| 336 VideoDecoderConfig video_config_; | 341 VideoDecoderConfig video_config_; |
| 337 | 342 |
| 338 // Used to protect |time_|. | 343 // Used to protect |time_| and |current_frame_|. |
| 339 base::Lock lock_; | 344 base::Lock lock_; |
| 340 base::TimeDelta time_; | 345 base::TimeDelta time_; |
| 346 scoped_refptr<VideoFrame> current_frame_; |
| 341 | 347 |
| 342 // Used for satisfying reads. | 348 // Used for satisfying reads. |
| 343 VideoDecoder::ReadCB read_cb_; | 349 VideoDecoder::ReadCB read_cb_; |
| 344 base::TimeDelta next_frame_timestamp_; | 350 base::TimeDelta next_frame_timestamp_; |
| 345 base::TimeDelta duration_; | 351 base::TimeDelta duration_; |
| 346 | 352 |
| 347 WaitableMessageLoopEvent error_event_; | 353 WaitableMessageLoopEvent error_event_; |
| 348 WaitableMessageLoopEvent ended_event_; | 354 WaitableMessageLoopEvent ended_event_; |
| 349 | 355 |
| 350 // Run during FrameRequested() to unblock WaitForPendingRead(). | 356 // Run during FrameRequested() to unblock WaitForPendingRead(). |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 Play(); | 487 Play(); |
| 482 Pause(); | 488 Pause(); |
| 483 EXPECT_TRUE(GetCurrentFrame()); | 489 EXPECT_TRUE(GetCurrentFrame()); |
| 484 Shutdown(); | 490 Shutdown(); |
| 485 } | 491 } |
| 486 | 492 |
| 487 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { | 493 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { |
| 488 Initialize(); | 494 Initialize(); |
| 489 Play(); | 495 Play(); |
| 490 Pause(); | 496 Pause(); |
| 497 |
| 498 // Frame shouldn't be updated. |
| 499 ResetCurrentFrame(); |
| 491 Flush(); | 500 Flush(); |
| 492 EXPECT_FALSE(GetCurrentFrame()); | 501 EXPECT_FALSE(GetCurrentFrame()); |
| 502 |
| 493 Shutdown(); | 503 Shutdown(); |
| 494 } | 504 } |
| 495 | 505 |
| 496 TEST_F(VideoRendererBaseTest, GetCurrentFrame_EndOfStream) { | 506 TEST_F(VideoRendererBaseTest, GetCurrentFrame_EndOfStream) { |
| 497 Initialize(); | 507 Initialize(); |
| 498 Play(); | 508 Play(); |
| 499 Pause(); | 509 Pause(); |
| 500 Flush(); | 510 Flush(); |
| 501 | 511 |
| 502 // Preroll only end of stream frames. | 512 // Preroll only end of stream frames. |
| 503 QueueEndOfStream(); | 513 QueueEndOfStream(); |
| 514 |
| 515 // Frame shouldn't be updated. |
| 516 ResetCurrentFrame(); |
| 504 Preroll(0, PIPELINE_OK); | 517 Preroll(0, PIPELINE_OK); |
| 505 EXPECT_FALSE(GetCurrentFrame()); | 518 EXPECT_FALSE(GetCurrentFrame()); |
| 506 | 519 |
| 507 // Start playing, we should immediately get notified of end of stream. | 520 // Start playing, we should immediately get notified of end of stream. |
| 508 Play(); | 521 Play(); |
| 509 WaitForEnded(); | 522 WaitForEnded(); |
| 510 | 523 |
| 511 Shutdown(); | 524 Shutdown(); |
| 512 } | 525 } |
| 513 | 526 |
| 514 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { | 527 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { |
| 515 Initialize(); | 528 Initialize(); |
| 529 |
| 530 // Frame shouldn't be updated. |
| 531 ResetCurrentFrame(); |
| 516 Shutdown(); | 532 Shutdown(); |
| 517 EXPECT_FALSE(GetCurrentFrame()); | 533 EXPECT_FALSE(GetCurrentFrame()); |
| 518 } | 534 } |
| 519 | 535 |
| 520 // Stop() is called immediately during an error. | 536 // Stop() is called immediately during an error. |
| 521 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { | 537 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { |
| 522 Initialize(); | 538 Initialize(); |
| 539 |
| 540 // Frame shouldn't be updated. |
| 541 ResetCurrentFrame(); |
| 523 Stop(); | 542 Stop(); |
| 524 EXPECT_FALSE(GetCurrentFrame()); | 543 EXPECT_FALSE(GetCurrentFrame()); |
| 525 } | 544 } |
| 526 | 545 |
| 527 // Verify that shutdown can only proceed after we return the current frame. | |
| 528 TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) { | |
| 529 Initialize(); | |
| 530 Play(); | |
| 531 | |
| 532 // Grab the frame. | |
| 533 scoped_refptr<VideoFrame> frame; | |
| 534 renderer_->GetCurrentFrame(&frame); | |
| 535 EXPECT_TRUE(frame); | |
| 536 | |
| 537 Pause(); | |
| 538 | |
| 539 // Start flushing -- it won't complete until we return the frame. | |
| 540 WaitableMessageLoopEvent event; | |
| 541 renderer_->Flush(event.GetClosure()); | |
| 542 | |
| 543 // Return the frame and wait. | |
| 544 renderer_->PutCurrentFrame(frame); | |
| 545 event.RunAndWait(); | |
| 546 | |
| 547 Stop(); | |
| 548 } | |
| 549 | |
| 550 // Verify that a late decoder response doesn't break invariants in the renderer. | 546 // Verify that a late decoder response doesn't break invariants in the renderer. |
| 551 TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { | 547 TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { |
| 552 Initialize(); | 548 Initialize(); |
| 553 Play(); | 549 Play(); |
| 554 | 550 |
| 555 // Advance time a bit to trigger a Read(). | 551 // Advance time a bit to trigger a Read(). |
| 556 AdvanceTimeInMs(kFrameDurationInMs); | 552 AdvanceTimeInMs(kFrameDurationInMs); |
| 557 WaitForPendingRead(); | 553 WaitForPendingRead(); |
| 558 | 554 |
| 559 WaitableMessageLoopEvent event; | 555 WaitableMessageLoopEvent event; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 InSequence s; | 607 InSequence s; |
| 612 | 608 |
| 613 EXPECT_CALL(*decoder_, Initialize(_, _, _)) | 609 EXPECT_CALL(*decoder_, Initialize(_, _, _)) |
| 614 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); | 610 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); |
| 615 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED); | 611 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED); |
| 616 | 612 |
| 617 Stop(); | 613 Stop(); |
| 618 } | 614 } |
| 619 | 615 |
| 620 } // namespace media | 616 } // namespace media |
| OLD | NEW |