• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ACTION(FinishEncode)38 ACTION(FinishEncode) {
39   scoped_ptr<VideoPacket> packet(new VideoPacket());
40   return packet.release();
41 }
42 
ACTION(FinishSend)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 
Encode(const webrtc::DesktopFrame & frame)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 
MockVideoEncoder()67 MockVideoEncoder::MockVideoEncoder() {}
68 
~MockVideoEncoder()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 
VideoSchedulerTest()105 VideoSchedulerTest::VideoSchedulerTest()
106     : encoder_(NULL),
107       capturer_callback_(NULL) {
108 }
109 
SetUp()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 
StartVideoScheduler(scoped_ptr<webrtc::ScreenCapturer> capturer)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 
StopVideoScheduler()130 void VideoSchedulerTest::StopVideoScheduler() {
131   scheduler_->Stop();
132   scheduler_ = NULL;
133 }
134 
OnCapturerStart(webrtc::ScreenCapturer::Callback * callback)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 
OnCaptureFrame(const webrtc::DesktopRegion & region)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.
TEST_F(VideoSchedulerTest,StartAndStop)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