1 // Copyright 2014 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 "base/message_loop/message_loop.h" 6 #include "base/test/simple_test_tick_clock.h" 7 #include "media/base/test_helpers.h" 8 #include "media/base/video_frame.h" 9 #include "media/filters/video_frame_scheduler_impl.h" 10 #include "testing/gmock/include/gmock/gmock.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 namespace media { 14 15 using testing::_; 16 17 // NOTE: millisecond-level resolution is used for times as real delayed tasks 18 // are posted. Don't use large values if you want to keep tests running fast. 19 class VideoFrameSchedulerImplTest : public testing::Test { 20 public: 21 VideoFrameSchedulerImplTest() 22 : scheduler_(message_loop_.message_loop_proxy(), 23 base::Bind(&VideoFrameSchedulerImplTest::OnDisplay, 24 base::Unretained(this))), 25 tick_clock_(new base::SimpleTestTickClock()) { 26 scheduler_.SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_)); 27 } 28 29 virtual ~VideoFrameSchedulerImplTest() {} 30 31 MOCK_METHOD1(OnDisplay, void(const scoped_refptr<VideoFrame>&)); 32 MOCK_METHOD2(OnFrameDone, 33 void(const scoped_refptr<VideoFrame>&, 34 VideoFrameScheduler::Reason)); 35 36 void Schedule(const scoped_refptr<VideoFrame>& frame, int64 target_ms) { 37 scheduler_.ScheduleVideoFrame( 38 frame, 39 base::TimeTicks() + base::TimeDelta::FromMilliseconds(target_ms), 40 base::Bind(&VideoFrameSchedulerImplTest::OnFrameDone, 41 base::Unretained(this))); 42 } 43 44 void RunUntilTimeHasElapsed(int64 ms) { 45 WaitableMessageLoopEvent waiter; 46 message_loop_.PostDelayedTask( 47 FROM_HERE, waiter.GetClosure(), base::TimeDelta::FromMilliseconds(ms)); 48 waiter.RunAndWait(); 49 } 50 51 void AdvanceTime(int64 ms) { 52 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(ms)); 53 } 54 55 void Reset() { 56 scheduler_.Reset(); 57 } 58 59 private: 60 base::MessageLoop message_loop_; 61 VideoFrameSchedulerImpl scheduler_; 62 base::SimpleTestTickClock* tick_clock_; // Owned by |scheduler_|. 63 64 DISALLOW_COPY_AND_ASSIGN(VideoFrameSchedulerImplTest); 65 }; 66 67 TEST_F(VideoFrameSchedulerImplTest, ImmediateDisplay) { 68 scoped_refptr<VideoFrame> frame = 69 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 70 Schedule(frame, 0); 71 72 EXPECT_CALL(*this, OnDisplay(frame)); 73 EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED)); 74 RunUntilTimeHasElapsed(0); 75 } 76 77 TEST_F(VideoFrameSchedulerImplTest, EventualDisplay) { 78 scoped_refptr<VideoFrame> frame = 79 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 80 Schedule(frame, 10); 81 82 // Nothing should happen. 83 RunUntilTimeHasElapsed(10); 84 85 // Now we should get the frame. 86 EXPECT_CALL(*this, OnDisplay(frame)); 87 EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED)); 88 AdvanceTime(10); 89 RunUntilTimeHasElapsed(10); 90 } 91 92 TEST_F(VideoFrameSchedulerImplTest, DroppedFrame) { 93 scoped_refptr<VideoFrame> dropped = 94 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 95 scoped_refptr<VideoFrame> displayed = 96 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 97 Schedule(dropped, 10); 98 Schedule(displayed, 20); 99 100 // The frame past its deadline will get dropped. 101 EXPECT_CALL(*this, OnDisplay(displayed)); 102 EXPECT_CALL(*this, OnFrameDone(dropped, VideoFrameScheduler::DROPPED)); 103 EXPECT_CALL(*this, OnFrameDone(displayed, VideoFrameScheduler::DISPLAYED)); 104 AdvanceTime(20); 105 RunUntilTimeHasElapsed(20); 106 } 107 108 TEST_F(VideoFrameSchedulerImplTest, SingleFrameLate) { 109 scoped_refptr<VideoFrame> frame = 110 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 111 Schedule(frame, 10); 112 113 // Despite frame being late it should still get displayed as it's the only 114 // one. 115 EXPECT_CALL(*this, OnDisplay(frame)); 116 EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED)); 117 AdvanceTime(20); 118 RunUntilTimeHasElapsed(20); 119 } 120 121 TEST_F(VideoFrameSchedulerImplTest, ManyFramesLate) { 122 scoped_refptr<VideoFrame> dropped = 123 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 124 scoped_refptr<VideoFrame> displayed = 125 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 126 Schedule(dropped, 10); 127 Schedule(displayed, 20); 128 129 // Despite both being late, the scheduler should always displays the latest 130 // expired frame. 131 EXPECT_CALL(*this, OnDisplay(displayed)); 132 EXPECT_CALL(*this, OnFrameDone(dropped, VideoFrameScheduler::DROPPED)); 133 EXPECT_CALL(*this, OnFrameDone(displayed, VideoFrameScheduler::DISPLAYED)); 134 AdvanceTime(30); 135 RunUntilTimeHasElapsed(30); 136 } 137 138 TEST_F(VideoFrameSchedulerImplTest, Reset) { 139 scoped_refptr<VideoFrame> frame = 140 VideoFrame::CreateBlackFrame(gfx::Size(8, 8)); 141 Schedule(frame, 10); 142 143 // Despite being on time, frame callback isn't run. 144 EXPECT_CALL(*this, OnFrameDone(_, _)).Times(0); 145 AdvanceTime(10); 146 Reset(); 147 RunUntilTimeHasElapsed(10); 148 } 149 150 } // namespace media 151