15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/video_scheduler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/single_thread_task_runner.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/base/auto_thread.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/base/auto_thread_task_runner.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/codec/video_encoder.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/codec/video_encoder_verbatim.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/host/fake_desktop_capturer.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/host/fake_mouse_cursor_monitor.h"
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/host/host_mock_objects.h"
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/proto/control.pb.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/video.pb.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/protocol_mock_objects.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::remoting::protocol::MockClientStub;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::remoting::protocol::MockVideoStub;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DeleteArg;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Expectation;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InvokeWithoutArgs;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::ReturnRef;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::SaveArg;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(FinishEncode) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<VideoPacket> packet(new VideoPacket());
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return packet.release();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION(FinishSend) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arg1.Run();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kWidth = 640;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kHeight = 480;
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kCursorWidth = 64;
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kCursorHeight = 32;
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kHotspotX = 11;
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kHotspotY = 12;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockVideoEncoder : public VideoEncoder {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MockVideoEncoder() {}
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual ~MockVideoEncoder() {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<VideoPacket> Encode(
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const webrtc::DesktopFrame& frame) {
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return scoped_ptr<VideoPacket>(EncodePtr(frame));
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  MOCK_METHOD1(EncodePtr, VideoPacket*(const webrtc::DesktopFrame& frame));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockVideoEncoder);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass ThreadCheckVideoEncoder : public VideoEncoderVerbatim {
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ThreadCheckVideoEncoder(
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : task_runner_(task_runner) {
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual ~ThreadCheckVideoEncoder() {
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ThreadCheckVideoEncoder);
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ThreadCheckDesktopCapturer : public FakeDesktopCapturer {
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ThreadCheckDesktopCapturer(
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : task_runner_(task_runner) {
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~ThreadCheckDesktopCapturer() {
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ThreadCheckDesktopCapturer);
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ThreadCheckMouseCursorMonitor : public FakeMouseCursorMonitor {
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ThreadCheckMouseCursorMonitor(
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : task_runner_(task_runner) {
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~ThreadCheckMouseCursorMonitor() {
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ThreadCheckMouseCursorMonitor);
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoSchedulerTest : public testing::Test {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VideoSchedulerTest();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE;
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void TearDown() OVERRIDE;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void StartVideoScheduler(
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      scoped_ptr<webrtc::DesktopCapturer> capturer,
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      scoped_ptr<VideoEncoder> encoder,
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      scoped_ptr<webrtc::MouseCursorMonitor> mouse_monitor);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StopVideoScheduler();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // webrtc::DesktopCapturer mocks.
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void OnCapturerStart(webrtc::DesktopCapturer::Callback* callback);
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OnCaptureFrame(const webrtc::DesktopRegion& region);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // webrtc::MouseCursorMonitor mocks.
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void OnMouseCursorMonitorInit(
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      webrtc::MouseCursorMonitor::Callback* callback,
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      webrtc::MouseCursorMonitor::Mode mode);
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void OnCaptureMouse();
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape);
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop message_loop_;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop_;
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<AutoThreadTaskRunner> capture_task_runner_;
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<AutoThreadTaskRunner> encode_task_runner_;
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<AutoThreadTaskRunner> main_task_runner_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoScheduler> scheduler_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientStub client_stub_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockVideoStub video_stub_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Points to the callback passed to webrtc::DesktopCapturer::Start().
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  webrtc::DesktopCapturer::Callback* capturer_callback_;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Points to the callback passed to webrtc::MouseCursor::Init().
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  webrtc::MouseCursorMonitor::Callback* mouse_monitor_callback_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VideoSchedulerTest);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VideoSchedulerTest::VideoSchedulerTest()
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : capturer_callback_(NULL),
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      mouse_monitor_callback_(NULL) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoSchedulerTest::SetUp() {
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  main_task_runner_ = new AutoThreadTaskRunner(
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      message_loop_.message_loop_proxy(), run_loop_.QuitClosure());
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  capture_task_runner_ = main_task_runner_;
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  encode_task_runner_ = main_task_runner_;
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid VideoSchedulerTest::TearDown() {
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Release the task runners, so that the test can quit.
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  capture_task_runner_ = NULL;
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  encode_task_runner_ = NULL;
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  main_task_runner_ = NULL;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Run the MessageLoop until everything has torn down.
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  run_loop_.Run();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoSchedulerTest::StartVideoScheduler(
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<webrtc::DesktopCapturer> capturer,
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<VideoEncoder> encoder,
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<webrtc::MouseCursorMonitor> mouse_monitor) {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scheduler_ = new VideoScheduler(
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      capture_task_runner_,
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      encode_task_runner_,
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      main_task_runner_,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      capturer.Pass(),
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      mouse_monitor.Pass(),
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      encoder.Pass(),
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &client_stub_,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &video_stub_);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scheduler_->Start();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoSchedulerTest::StopVideoScheduler() {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scheduler_->Stop();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scheduler_ = NULL;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoSchedulerTest::OnCapturerStart(
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    webrtc::DesktopCapturer::Callback* callback) {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(capturer_callback_);
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(callback);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  capturer_callback_ = callback;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void VideoSchedulerTest::OnCaptureFrame(const webrtc::DesktopRegion& region) {
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::DesktopFrame> frame(
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)));
2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  frame->mutable_updated_region()->SetRect(
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      webrtc::DesktopRect::MakeXYWH(0, 0, 10, 10));
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  capturer_callback_->OnCaptureCompleted(frame.release());
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void VideoSchedulerTest::OnCaptureMouse() {
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(mouse_monitor_callback_);
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::MouseCursor> mouse_cursor(
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new webrtc::MouseCursor(
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          new webrtc::BasicDesktopFrame(
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              webrtc::DesktopSize(kCursorWidth, kCursorHeight)),
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          webrtc::DesktopVector(kHotspotX, kHotspotY)));
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  mouse_monitor_callback_->OnMouseCursor(mouse_cursor.release());
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void VideoSchedulerTest::OnMouseCursorMonitorInit(
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    webrtc::MouseCursorMonitor::Callback* callback,
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    webrtc::MouseCursorMonitor::Mode mode) {
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_FALSE(mouse_monitor_callback_);
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(callback);
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  mouse_monitor_callback_ = callback;
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void VideoSchedulerTest::SetCursorShape(
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const protocol::CursorShapeInfo& cursor_shape) {
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(cursor_shape.has_width());
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(kCursorWidth, cursor_shape.width());
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(cursor_shape.has_height());
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(kCursorHeight, cursor_shape.height());
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(cursor_shape.has_hotspot_x());
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(kHotspotX, cursor_shape.hotspot_x());
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(cursor_shape.has_hotspot_y());
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(kHotspotY, cursor_shape.hotspot_y());
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(cursor_shape.has_data());
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(kCursorWidth * kCursorHeight * webrtc::DesktopFrame::kBytesPerPixel,
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            static_cast<int>(cursor_shape.data().size()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test mocks capturer, encoder and network layer to simulate one capture
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cycle. When the first encoded packet is submitted to the network
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VideoScheduler is instructed to come to a complete stop. We expect the stop
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sequence to be executed successfully.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoSchedulerTest, StartAndStop) {
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<webrtc::MockScreenCapturer> capturer(
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new webrtc::MockScreenCapturer());
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<MockMouseCursorMonitor> cursor_monitor(
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new MockMouseCursorMonitor());
2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  {
2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    InSequence s;
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    EXPECT_CALL(*cursor_monitor, Init(_, _))
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        .WillOnce(
2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            Invoke(this, &VideoSchedulerTest::OnMouseCursorMonitorInit));
2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    EXPECT_CALL(*cursor_monitor, Capture())
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        .WillRepeatedly(Invoke(this, &VideoSchedulerTest::OnCaptureMouse));
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Expectation capturer_start =
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_CALL(*capturer, Start(_))
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .WillOnce(Invoke(this, &VideoSchedulerTest::OnCapturerStart));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First the capturer is called.
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Expectation capturer_capture = EXPECT_CALL(*capturer, Capture(_))
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .After(capturer_start)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillRepeatedly(Invoke(this, &VideoSchedulerTest::OnCaptureFrame));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<MockVideoEncoder> encoder(new MockVideoEncoder());
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expect the encoder be called.
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_CALL(*encoder, EncodePtr(_))
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(FinishEncode());
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default delete the arguments when ProcessVideoPacket is received.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(FinishSend());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // When the first ProcessVideoPacket is received we stop the VideoScheduler.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(DoAll(
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FinishSend(),
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          InvokeWithoutArgs(this, &VideoSchedulerTest::StopVideoScheduler)))
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .RetiresOnSaturation();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_CALL(client_stub_, SetCursorShape(_))
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      .WillOnce(Invoke(this, &VideoSchedulerTest::SetCursorShape));
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start video frame capture.
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor(
3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new FakeMouseCursorMonitor());
3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  StartVideoScheduler(capturer.PassAs<webrtc::DesktopCapturer>(),
3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      encoder.PassAs<VideoEncoder>(),
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      cursor_monitor.PassAs<webrtc::MouseCursorMonitor>());
3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Run until there are no more pending tasks from the VideoScheduler.
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Otherwise, a lingering frame capture might attempt to trigger a capturer
3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // expectation action and crash.
3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Verify that the capturer, encoder and mouse monitor are torn down on the
3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// correct threads.
332116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(VideoSchedulerTest, DeleteOnThreads) {
3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  capture_task_runner_ = AutoThread::Create("capture", main_task_runner_);
3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  encode_task_runner_ = AutoThread::Create("encode", main_task_runner_);
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::DesktopCapturer> capturer(
3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new ThreadCheckDesktopCapturer(capture_task_runner_));
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<VideoEncoder> encoder(
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new ThreadCheckVideoEncoder(encode_task_runner_));
3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor(
3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new ThreadCheckMouseCursorMonitor(capture_task_runner_));
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Start and stop the scheduler, so it will tear down the screen capturer,
3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // video encoder and mouse monitor.
3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  StartVideoScheduler(capturer.Pass(), encoder.Pass(),
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      mouse_cursor_monitor.Pass());
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  StopVideoScheduler();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
351