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 |