10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// found in the LICENSE file.
40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/message_loop/message_loop.h"
60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/test/simple_test_tick_clock.h"
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "media/base/test_helpers.h"
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "media/base/video_frame.h"
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "media/filters/video_frame_scheduler_impl.h"
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "testing/gmock/include/gmock/gmock.h"
110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace media {
140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing testing::_;
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// NOTE: millisecond-level resolution is used for times as real delayed tasks
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// are posted. Don't use large values if you want to keep tests running fast.
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass VideoFrameSchedulerImplTest : public testing::Test {
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public:
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  VideoFrameSchedulerImplTest()
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      : scheduler_(message_loop_.message_loop_proxy(),
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   base::Bind(&VideoFrameSchedulerImplTest::OnDisplay,
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                              base::Unretained(this))),
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        tick_clock_(new base::SimpleTestTickClock()) {
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scheduler_.SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~VideoFrameSchedulerImplTest() {}
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MOCK_METHOD1(OnDisplay, void(const scoped_refptr<VideoFrame>&));
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MOCK_METHOD2(OnFrameDone,
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch               void(const scoped_refptr<VideoFrame>&,
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    VideoFrameScheduler::Reason));
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void Schedule(const scoped_refptr<VideoFrame>& frame, int64 target_ms) {
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scheduler_.ScheduleVideoFrame(
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        frame,
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        base::TimeTicks() + base::TimeDelta::FromMilliseconds(target_ms),
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        base::Bind(&VideoFrameSchedulerImplTest::OnFrameDone,
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   base::Unretained(this)));
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void RunUntilTimeHasElapsed(int64 ms) {
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    WaitableMessageLoopEvent waiter;
460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    message_loop_.PostDelayedTask(
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        FROM_HERE, waiter.GetClosure(), base::TimeDelta::FromMilliseconds(ms));
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    waiter.RunAndWait();
490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void AdvanceTime(int64 ms) {
520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    tick_clock_->Advance(base::TimeDelta::FromMilliseconds(ms));
530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void Reset() {
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scheduler_.Reset();
570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch private:
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::MessageLoop message_loop_;
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  VideoFrameSchedulerImpl scheduler_;
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::SimpleTestTickClock* tick_clock_;  // Owned by |scheduler_|.
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(VideoFrameSchedulerImplTest);
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
670529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, ImmediateDisplay) {
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> frame =
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(frame, 0);
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnDisplay(frame));
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED));
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(0);
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
770529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, EventualDisplay) {
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> frame =
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(frame, 10);
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Nothing should happen.
830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(10);
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Now we should get the frame.
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnDisplay(frame));
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED));
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AdvanceTime(10);
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(10);
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
920529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, DroppedFrame) {
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> dropped =
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> displayed =
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(dropped, 10);
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(displayed, 20);
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // The frame past its deadline will get dropped.
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnDisplay(displayed));
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(dropped, VideoFrameScheduler::DROPPED));
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(displayed, VideoFrameScheduler::DISPLAYED));
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AdvanceTime(20);
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(20);
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1080529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, SingleFrameLate) {
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> frame =
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(frame, 10);
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Despite frame being late it should still get displayed as it's the only
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // one.
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnDisplay(frame));
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(frame, VideoFrameScheduler::DISPLAYED));
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AdvanceTime(20);
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(20);
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1210529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, ManyFramesLate) {
1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> dropped =
1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> displayed =
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(dropped, 10);
1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(displayed, 20);
1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Despite both being late, the scheduler should always displays the latest
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // expired frame.
1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnDisplay(displayed));
1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(dropped, VideoFrameScheduler::DROPPED));
1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*this, OnFrameDone(displayed, VideoFrameScheduler::DISPLAYED));
1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AdvanceTime(30);
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(30);
1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1380529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(VideoFrameSchedulerImplTest, Reset) {
1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<VideoFrame> frame =
1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Schedule(frame, 10);
1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Despite being on time, frame callback isn't run.
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_CALL(*this, OnFrameDone(_, _)).Times(0);
1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AdvanceTime(10);
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Reset();
1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunUntilTimeHasElapsed(10);
1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace media
151