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