Home | History | Annotate | Download | only in host
      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
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/host/video_scheduler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/run_loop.h"
     10 #include "remoting/base/auto_thread_task_runner.h"
     11 #include "remoting/codec/video_encoder.h"
     12 #include "remoting/proto/video.pb.h"
     13 #include "remoting/protocol/protocol_mock_objects.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
     17 #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
     18 
     19 using ::remoting::protocol::MockClientStub;
     20 using ::remoting::protocol::MockVideoStub;
     21 
     22 using ::testing::_;
     23 using ::testing::AtLeast;
     24 using ::testing::AnyNumber;
     25 using ::testing::DeleteArg;
     26 using ::testing::DoAll;
     27 using ::testing::Expectation;
     28 using ::testing::InSequence;
     29 using ::testing::InvokeWithoutArgs;
     30 using ::testing::Return;
     31 using ::testing::ReturnRef;
     32 using ::testing::SaveArg;
     33 
     34 namespace remoting {
     35 
     36 namespace {
     37 
     38 ACTION(FinishEncode) {
     39   scoped_ptr<VideoPacket> packet(new VideoPacket());
     40   return packet.release();
     41 }
     42 
     43 ACTION(FinishSend) {
     44   arg1.Run();
     45 }
     46 
     47 }  // namespace
     48 
     49 static const int kWidth = 640;
     50 static const int kHeight = 480;
     51 
     52 class MockVideoEncoder : public VideoEncoder {
     53  public:
     54   MockVideoEncoder();
     55   virtual ~MockVideoEncoder();
     56 
     57   scoped_ptr<VideoPacket> Encode(
     58       const webrtc::DesktopFrame& frame) {
     59     return scoped_ptr<VideoPacket>(EncodePtr(frame));
     60   }
     61   MOCK_METHOD1(EncodePtr, VideoPacket*(const webrtc::DesktopFrame& frame));
     62 
     63  private:
     64   DISALLOW_COPY_AND_ASSIGN(MockVideoEncoder);
     65 };
     66 
     67 MockVideoEncoder::MockVideoEncoder() {}
     68 
     69 MockVideoEncoder::~MockVideoEncoder() {}
     70 
     71 class VideoSchedulerTest : public testing::Test {
     72  public:
     73   VideoSchedulerTest();
     74 
     75   virtual void SetUp() OVERRIDE;
     76 
     77   void StartVideoScheduler(scoped_ptr<webrtc::ScreenCapturer> capturer);
     78   void StopVideoScheduler();
     79 
     80   // webrtc::ScreenCapturer mocks.
     81   void OnCapturerStart(webrtc::ScreenCapturer::Callback* callback);
     82   void OnCaptureFrame(const webrtc::DesktopRegion& region);
     83 
     84  protected:
     85   base::MessageLoop message_loop_;
     86   base::RunLoop run_loop_;
     87   scoped_refptr<AutoThreadTaskRunner> task_runner_;
     88   scoped_refptr<VideoScheduler> scheduler_;
     89 
     90   MockClientStub client_stub_;
     91   MockVideoStub video_stub_;
     92 
     93   // The following mock objects are owned by VideoScheduler.
     94   MockVideoEncoder* encoder_;
     95 
     96   scoped_ptr<webrtc::DesktopFrame> frame_;
     97 
     98   // Points to the callback passed to webrtc::ScreenCapturer::Start().
     99   webrtc::ScreenCapturer::Callback* capturer_callback_;
    100 
    101  private:
    102   DISALLOW_COPY_AND_ASSIGN(VideoSchedulerTest);
    103 };
    104 
    105 VideoSchedulerTest::VideoSchedulerTest()
    106     : encoder_(NULL),
    107       capturer_callback_(NULL) {
    108 }
    109 
    110 void VideoSchedulerTest::SetUp() {
    111   task_runner_ = new AutoThreadTaskRunner(
    112       message_loop_.message_loop_proxy(), run_loop_.QuitClosure());
    113 
    114   encoder_ = new MockVideoEncoder();
    115 }
    116 
    117 void VideoSchedulerTest::StartVideoScheduler(
    118     scoped_ptr<webrtc::ScreenCapturer> capturer) {
    119   scheduler_ = new VideoScheduler(
    120       task_runner_, // Capture
    121       task_runner_, // Encode
    122       task_runner_, // Network
    123       capturer.Pass(),
    124       scoped_ptr<VideoEncoder>(encoder_),
    125       &client_stub_,
    126       &video_stub_);
    127   scheduler_->Start();
    128 }
    129 
    130 void VideoSchedulerTest::StopVideoScheduler() {
    131   scheduler_->Stop();
    132   scheduler_ = NULL;
    133 }
    134 
    135 void VideoSchedulerTest::OnCapturerStart(
    136     webrtc::ScreenCapturer::Callback* callback) {
    137   EXPECT_FALSE(capturer_callback_);
    138   EXPECT_TRUE(callback);
    139 
    140   capturer_callback_ = callback;
    141 }
    142 
    143 void VideoSchedulerTest::OnCaptureFrame(const webrtc::DesktopRegion& region) {
    144   frame_->mutable_updated_region()->SetRect(
    145       webrtc::DesktopRect::MakeXYWH(0, 0, 10, 10));
    146   capturer_callback_->OnCaptureCompleted(frame_.release());
    147 }
    148 
    149 // This test mocks capturer, encoder and network layer to simulate one capture
    150 // cycle. When the first encoded packet is submitted to the network
    151 // VideoScheduler is instructed to come to a complete stop. We expect the stop
    152 // sequence to be executed successfully.
    153 TEST_F(VideoSchedulerTest, StartAndStop) {
    154   scoped_ptr<webrtc::MockScreenCapturer> capturer(
    155       new webrtc::MockScreenCapturer());
    156   Expectation capturer_start =
    157       EXPECT_CALL(*capturer, Start(_))
    158           .WillOnce(Invoke(this, &VideoSchedulerTest::OnCapturerStart));
    159 
    160   frame_.reset(new webrtc::BasicDesktopFrame(
    161       webrtc::DesktopSize(kWidth, kHeight)));
    162 
    163   // First the capturer is called.
    164   Expectation capturer_capture = EXPECT_CALL(*capturer, Capture(_))
    165       .After(capturer_start)
    166       .WillRepeatedly(Invoke(this, &VideoSchedulerTest::OnCaptureFrame));
    167 
    168   // Expect the encoder be called.
    169   EXPECT_CALL(*encoder_, EncodePtr(_))
    170       .WillRepeatedly(FinishEncode());
    171 
    172   // By default delete the arguments when ProcessVideoPacket is received.
    173   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
    174       .WillRepeatedly(FinishSend());
    175 
    176   // For the first time when ProcessVideoPacket is received we stop the
    177   // VideoScheduler.
    178   EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
    179       .WillOnce(DoAll(
    180           FinishSend(),
    181           InvokeWithoutArgs(this, &VideoSchedulerTest::StopVideoScheduler)))
    182       .RetiresOnSaturation();
    183 
    184   // Start video frame capture.
    185   StartVideoScheduler(capturer.PassAs<webrtc::ScreenCapturer>());
    186 
    187   task_runner_ = NULL;
    188   run_loop_.Run();
    189 }
    190 
    191 }  // namespace remoting
    192