Home | History | Annotate | Download | only in filters
      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