Commit 1afb35a1 authored by sergeyu's avatar sergeyu Committed by Commit bot

Cleanup VideoFramePump.

1. Threading logic for the capture thread has been moved to
   ScreenCapturerProxy.
2. Mouse shape handling has been moved to MouseShapePump.

BUG=455818

Review URL: https://codereview.chromium.org/883673004

Cr-Commit-Position: refs/heads/master@{#316247}
parent 0f2586fc
......@@ -17,9 +17,11 @@
#include "remoting/codec/video_encoder_vpx.h"
#include "remoting/host/audio_capturer.h"
#include "remoting/host/audio_scheduler.h"
#include "remoting/host/desktop_capturer_proxy.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/host_extension_session.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/mouse_shape_pump.h"
#include "remoting/host/screen_controls.h"
#include "remoting/host/screen_resolution.h"
#include "remoting/host/video_frame_pump.h"
......@@ -29,6 +31,7 @@
#include "remoting/protocol/clipboard_thread_proxy.h"
#include "remoting/protocol/pairing_registry.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
// Default DPI to assume for old clients that use notifyClientDimensions.
const int kDefaultDPI = 96;
......@@ -142,21 +145,21 @@ void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
VLOG(1) << "Received VideoControl (enable="
<< video_control.enable() << ")";
pause_video_ = !video_control.enable();
if (video_frame_pump_.get())
if (video_frame_pump_)
video_frame_pump_->Pause(pause_video_);
}
if (video_control.has_lossless_encode()) {
VLOG(1) << "Received VideoControl (lossless_encode="
<< video_control.lossless_encode() << ")";
lossless_video_encode_ = video_control.lossless_encode();
if (video_frame_pump_.get())
if (video_frame_pump_)
video_frame_pump_->SetLosslessEncode(lossless_video_encode_);
}
if (video_control.has_lossless_color()) {
VLOG(1) << "Received VideoControl (lossless_color="
<< video_control.lossless_color() << ")";
lossless_video_color_ = video_control.lossless_color();
if (video_frame_pump_.get())
if (video_frame_pump_)
video_frame_pump_->SetLosslessColor(lossless_video_color_);
}
}
......@@ -368,10 +371,9 @@ void ClientSession::OnConnectionClosed(
audio_scheduler_->Stop();
audio_scheduler_ = nullptr;
}
if (video_frame_pump_.get()) {
video_frame_pump_->Stop();
video_frame_pump_ = nullptr;
}
video_frame_pump_.reset();
mouse_shape_pump_.reset();
client_clipboard_factory_.InvalidateWeakPtrs();
input_injector_.reset();
......@@ -434,10 +436,8 @@ void ClientSession::SetDisableInputs(bool disable_inputs) {
void ClientSession::ResetVideoPipeline() {
DCHECK(CalledOnValidThread());
if (video_frame_pump_.get()) {
video_frame_pump_->Stop();
video_frame_pump_ = nullptr;
}
mouse_shape_pump_.reset();
video_frame_pump_.reset();
// Create VideoEncoder and DesktopCapturer to match the session's video
// channel configuration.
......@@ -452,24 +452,26 @@ void ClientSession::ResetVideoPipeline() {
if (!video_capturer || !video_encoder)
return;
// Create a VideoFramePump to pump frames from the capturer to the client.
video_frame_pump_ = new VideoFramePump(
video_capture_task_runner_,
video_encode_task_runner_,
network_task_runner_,
video_capturer.Pass(),
desktop_environment_->CreateMouseCursorMonitor(),
video_encoder.Pass(),
connection_->client_stub(),
&mouse_clamping_filter_);
// Create MouseShapePump to send mouse cursor shape.
mouse_shape_pump_.reset(
new MouseShapePump(video_capture_task_runner_,
desktop_environment_->CreateMouseCursorMonitor(),
connection_->client_stub()));
// Create a VideoFramePump to pump frames from the capturer to the client.'
//
// TODO(sergeyu): Move DesktopCapturerProxy creation to DesktopEnvironment.
// When using IpcDesktopCapturer the capture thread is not useful.
scoped_ptr<DesktopCapturerProxy> capturer_proxy(new DesktopCapturerProxy(
video_capture_task_runner_, video_capturer.Pass()));
video_frame_pump_.reset(
new VideoFramePump(video_encode_task_runner_, capturer_proxy.Pass(),
video_encoder.Pass(), &mouse_clamping_filter_));
// Apply video-control parameters to the new scheduler.
video_frame_pump_->SetLosslessEncode(lossless_video_encode_);
video_frame_pump_->SetLosslessColor(lossless_video_color_);
// Start capturing the screen.
video_frame_pump_->Start();
// Pause capturing if necessary.
video_frame_pump_->Pause(pause_video_);
}
......
......@@ -40,6 +40,7 @@ class AudioScheduler;
class DesktopEnvironment;
class DesktopEnvironmentFactory;
class InputInjector;
class MouseShapePump;
class ScreenControls;
class VideoEncoder;
class VideoFramePump;
......@@ -222,7 +223,8 @@ class ClientSession
// |video_frame_pump_| may be nullptr if the video channel is not required -
// see ResetVideoPipeline().
scoped_refptr<AudioScheduler> audio_scheduler_;
scoped_refptr<VideoFramePump> video_frame_pump_;
scoped_ptr<VideoFramePump> video_frame_pump_;
scoped_ptr<MouseShapePump> mouse_shape_pump_;
// The set of all capabilities supported by the client.
scoped_ptr<std::string> client_capabilities_;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/desktop_capturer_proxy.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "remoting/proto/control.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
namespace remoting {
class DesktopCapturerProxy::Core : public webrtc::DesktopCapturer::Callback {
public:
Core(base::WeakPtr<DesktopCapturerProxy> proxy,
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer);
~Core() override;
void Start();
void Capture(const webrtc::DesktopRegion& rect);
private:
// webrtc::DesktopCapturer::Callback implementation.
webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
base::ThreadChecker thread_checker_;
base::WeakPtr<DesktopCapturerProxy> proxy_;
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
scoped_ptr<webrtc::DesktopCapturer> capturer_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
DesktopCapturerProxy::Core::Core(
base::WeakPtr<DesktopCapturerProxy> proxy,
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer)
: proxy_(proxy),
caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
capturer_(capturer.Pass()) {
thread_checker_.DetachFromThread();
}
DesktopCapturerProxy::Core::~Core() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void DesktopCapturerProxy::Core::Start() {
DCHECK(thread_checker_.CalledOnValidThread());
capturer_->Start(this);
}
void DesktopCapturerProxy::Core::Capture(const webrtc::DesktopRegion& rect) {
DCHECK(thread_checker_.CalledOnValidThread());
capturer_->Capture(rect);
}
webrtc::SharedMemory* DesktopCapturerProxy::Core::CreateSharedMemory(
size_t size) {
DCHECK(thread_checker_.CalledOnValidThread());
// CreateSharedMemory() call is synchronous and cannot be proxied to another
// thread.
return nullptr;
}
void DesktopCapturerProxy::Core::OnCaptureCompleted(
webrtc::DesktopFrame* frame) {
DCHECK(thread_checker_.CalledOnValidThread());
caller_task_runner_->PostTask(
FROM_HERE, base::Bind(&DesktopCapturerProxy::OnFrameCaptured, proxy_,
base::Passed(make_scoped_ptr(frame))));
}
DesktopCapturerProxy::DesktopCapturerProxy(
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer)
: capture_task_runner_(capture_task_runner),
weak_factory_(this) {
core_.reset(new Core(weak_factory_.GetWeakPtr(), capture_task_runner,
capturer.Pass()));
}
void DesktopCapturerProxy::Start(Callback* callback) {
DCHECK(thread_checker_.CalledOnValidThread());
callback_ = callback;
capture_task_runner_->PostTask(
FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get())));
}
DesktopCapturerProxy::~DesktopCapturerProxy() {
DCHECK(thread_checker_.CalledOnValidThread());
capture_task_runner_->DeleteSoon(FROM_HERE, core_.release());
}
void DesktopCapturerProxy::Capture(const webrtc::DesktopRegion& rect) {
DCHECK(thread_checker_.CalledOnValidThread());
// Start() must be called before Capture().
DCHECK(callback_);
capture_task_runner_->PostTask(
FROM_HERE,
base::Bind(&Core::Capture, base::Unretained(core_.get()), rect));
}
void DesktopCapturerProxy::OnFrameCaptured(
scoped_ptr<webrtc::DesktopFrame> frame) {
DCHECK(thread_checker_.CalledOnValidThread());
callback_->OnCaptureCompleted(frame.release());
}
} // namespace remoting
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_DESKTOP_CAPTURER_PROXY_H_
#define REMOTING_HOST_DESKTOP_CAPTURER_PROXY_H_
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace remoting {
namespace protocol {
class CursorShapeInfo;
} // namespace protocol
// DesktopCapturerProxy is responsible for calling webrtc::DesktopCapturer on
// the capturer thread and then returning results to the caller's thread.
class DesktopCapturerProxy : public webrtc::DesktopCapturer {
public:
DesktopCapturerProxy(
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer);
~DesktopCapturerProxy() override;
// webrtc::DesktopCapturer interface.
void Start(Callback* callback) override;
void Capture(const webrtc::DesktopRegion& rect) override;
private:
class Core;
void OnFrameCaptured(scoped_ptr<webrtc::DesktopFrame> frame);
base::ThreadChecker thread_checker_;
scoped_ptr<Core> core_;
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
webrtc::DesktopCapturer::Callback* callback_;
base::WeakPtrFactory<DesktopCapturerProxy> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DesktopCapturerProxy);
};
} // namespace remoting
#endif // REMOTING_HOST_DESKTOP_CAPTURER_PROXY_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/mouse_shape_pump.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "remoting/proto/control.pb.h"
#include "remoting/protocol/cursor_shape_stub.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
namespace remoting {
// Poll mouse shape 10 times a second.
static const int kCursorCaptureIntervalMs = 100;
class MouseShapePump::Core : public webrtc::MouseCursorMonitor::Callback {
public:
Core(base::WeakPtr<MouseShapePump> proxy,
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor);
~Core() override;
void Start();
void Capture();
private:
// webrtc::MouseCursorMonitor::Callback implementation.
void OnMouseCursor(webrtc::MouseCursor* mouse_cursor) override;
void OnMouseCursorPosition(webrtc::MouseCursorMonitor::CursorState state,
const webrtc::DesktopVector& position) override;
base::ThreadChecker thread_checker_;
base::WeakPtr<MouseShapePump> proxy_;
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor_;
base::Timer capture_timer_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
MouseShapePump::Core::Core(
base::WeakPtr<MouseShapePump> proxy,
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor)
: proxy_(proxy),
caller_task_runner_(caller_task_runner),
mouse_cursor_monitor_(mouse_cursor_monitor.Pass()),
capture_timer_(true, true) {
thread_checker_.DetachFromThread();
}
MouseShapePump::Core::~Core() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void MouseShapePump::Core::Start() {
DCHECK(thread_checker_.CalledOnValidThread());
mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY);
capture_timer_.Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(kCursorCaptureIntervalMs),
base::Bind(&MouseShapePump::Core::Capture, base::Unretained(this)));
}
void MouseShapePump::Core::Capture() {
DCHECK(thread_checker_.CalledOnValidThread());
mouse_cursor_monitor_->Capture();
}
void MouseShapePump::Core::OnMouseCursor(webrtc::MouseCursor* cursor) {
DCHECK(thread_checker_.CalledOnValidThread());
scoped_ptr<webrtc::MouseCursor> owned_cursor(cursor);
scoped_ptr<protocol::CursorShapeInfo> cursor_proto(
new protocol::CursorShapeInfo());
cursor_proto->set_width(cursor->image()->size().width());
cursor_proto->set_height(cursor->image()->size().height());
cursor_proto->set_hotspot_x(cursor->hotspot().x());
cursor_proto->set_hotspot_y(cursor->hotspot().y());
cursor_proto->set_data(std::string());
uint8_t* current_row = cursor->image()->data();
for (int y = 0; y < cursor->image()->size().height(); ++y) {
cursor_proto->mutable_data()->append(
current_row,
current_row + cursor->image()->size().width() *
webrtc::DesktopFrame::kBytesPerPixel);
current_row += cursor->image()->stride();
}
caller_task_runner_->PostTask(
FROM_HERE, base::Bind(&MouseShapePump::OnCursorShape, proxy_,
base::Passed(&cursor_proto)));
}
void MouseShapePump::Core::OnMouseCursorPosition(
webrtc::MouseCursorMonitor::CursorState state,
const webrtc::DesktopVector& position) {
// We're not subscribing to mouse position changes.
NOTREACHED();
}
MouseShapePump::MouseShapePump(
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
protocol::CursorShapeStub* cursor_shape_stub)
: capture_task_runner_(capture_task_runner),
cursor_shape_stub_(cursor_shape_stub),
weak_factory_(this) {
core_.reset(new Core(weak_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get(),
mouse_cursor_monitor.Pass()));
capture_task_runner_->PostTask(
FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get())));
}
MouseShapePump::~MouseShapePump() {
capture_task_runner_->DeleteSoon(FROM_HERE, core_.release());
}
void MouseShapePump::OnCursorShape(
scoped_ptr<protocol::CursorShapeInfo> cursor) {
DCHECK(thread_checker_.CalledOnValidThread());
cursor_shape_stub_->SetCursorShape(*cursor);
}
} // namespace remoting
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_MOUSE_SHAPE_PUMP_H_
#define REMOTING_HOST_MOUSE_SHAPE_PUMP_H_
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace webrtc {
class MouseCursorMonitor;
} // namespace webrtc
namespace remoting {
namespace protocol {
class CursorShapeStub;
class CursorShapeInfo;
} // namespace protocol
// MouseShapePump is responsible for capturing mouse shape using
// MouseCursorMonitor and sending it to a CursorShapeStub.
class MouseShapePump {
public:
MouseShapePump(
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
protocol::CursorShapeStub* cursor_shape_stub);
~MouseShapePump();
private:
class Core;
void OnCursorShape(scoped_ptr<protocol::CursorShapeInfo> cursor);
base::ThreadChecker thread_checker_;
scoped_ptr<Core> core_;
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
protocol::CursorShapeStub* cursor_shape_stub_;
base::WeakPtrFactory<MouseShapePump> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MouseShapePump);
};
} // namespace remoting
#endif // REMOTING_HOST_MOUSE_SHAPE_PUMP_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/mouse_shape_pump.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/host/host_mock_objects.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
using ::remoting::protocol::MockClientStub;
using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::InvokeWithoutArgs;
namespace remoting {
static const int kCursorWidth = 64;
static const int kCursorHeight = 32;
static const int kHotspotX = 11;
static const int kHotspotY = 12;
class ThreadCheckMouseCursorMonitor : public webrtc::MouseCursorMonitor {
public:
ThreadCheckMouseCursorMonitor(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(task_runner), callback_(nullptr) {
}
~ThreadCheckMouseCursorMonitor() override {
EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
}
void Init(Callback* callback, Mode mode) override {
EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
EXPECT_FALSE(callback_);
EXPECT_TRUE(callback);
callback_ = callback;
}
void Capture() override {
EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
ASSERT_TRUE(callback_);
scoped_ptr<webrtc::MouseCursor> mouse_cursor(new webrtc::MouseCursor(
new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kCursorWidth, kCursorHeight)),
webrtc::DesktopVector(kHotspotX, kHotspotY)));
callback_->OnMouseCursor(mouse_cursor.release());
}
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
Callback* callback_;
DISALLOW_COPY_AND_ASSIGN(ThreadCheckMouseCursorMonitor);
};
class MouseShapePumpTest : public testing::Test {
public:
void SetUp() override;
void TearDown() override;
void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape);
protected:
base::MessageLoop message_loop_;
base::RunLoop run_loop_;
scoped_refptr<AutoThreadTaskRunner> capture_task_runner_;
scoped_refptr<AutoThreadTaskRunner> main_task_runner_;
scoped_ptr<MouseShapePump> pump_;
MockClientStub client_stub_;
};
void MouseShapePumpTest::SetUp() {
main_task_runner_ = new AutoThreadTaskRunner(
message_loop_.message_loop_proxy(), run_loop_.QuitClosure());
capture_task_runner_ = AutoThread::Create("capture", main_task_runner_);
}
void MouseShapePumpTest::TearDown() {
pump_.reset();
// Release the task runners, so that the test can quit.
capture_task_runner_ = nullptr;
main_task_runner_ = nullptr;
// Run the MessageLoop until everything has torn down.
run_loop_.Run();
}
void MouseShapePumpTest::SetCursorShape(
const protocol::CursorShapeInfo& cursor_shape) {
EXPECT_TRUE(cursor_shape.has_width());
EXPECT_EQ(kCursorWidth, cursor_shape.width());
EXPECT_TRUE(cursor_shape.has_height());
EXPECT_EQ(kCursorHeight, cursor_shape.height());
EXPECT_TRUE(cursor_shape.has_hotspot_x());
EXPECT_EQ(kHotspotX, cursor_shape.hotspot_x());
EXPECT_TRUE(cursor_shape.has_hotspot_y());
EXPECT_EQ(kHotspotY, cursor_shape.hotspot_y());
EXPECT_TRUE(cursor_shape.has_data());
EXPECT_EQ(kCursorWidth * kCursorHeight * webrtc::DesktopFrame::kBytesPerPixel,
static_cast<int>(cursor_shape.data().size()));
}
// This test mocks MouseCursorMonitor and ClientStub to verify that the
// MouseShapePump sends the cursor successfully.
TEST_F(MouseShapePumpTest, FirstCursor) {
scoped_ptr<ThreadCheckMouseCursorMonitor> cursor_monitor(
new ThreadCheckMouseCursorMonitor(capture_task_runner_));
base::RunLoop run_loop;
// Stop the |run_loop| once it has captured the cursor.
EXPECT_CALL(client_stub_, SetCursorShape(_))
.WillOnce(DoAll(
Invoke(this, &MouseShapePumpTest::SetCursorShape),
InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)))
.RetiresOnSaturation();
// Start the pump.
pump_.reset(new MouseShapePump(capture_task_runner_, cursor_monitor.Pass(),
&client_stub_));
run_loop.Run();
}
} // namespace remoting
This diff is collapsed.
......@@ -5,38 +5,29 @@
#ifndef REMOTING_HOST_VIDEO_FRAME_PUMP_H_
#define REMOTING_HOST_VIDEO_FRAME_PUMP_H_
#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "remoting/codec/video_encoder.h"
#include "remoting/host/capture_scheduler.h"
#include "remoting/proto/video.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace media {
class DesktopCapturer;
} // namespace media
namespace remoting {
class CaptureScheduler;
namespace protocol {
class CursorShapeInfo;
class CursorShapeStub;
class VideoStub;
} // namespace protocol
// Class responsible for scheduling frame captures from a
// webrtc::DesktopCapturer, delivering them to a VideoEncoder to encode, and
// Class responsible for scheduling frame captures from a screen capturer.,
// delivering them to a VideoEncoder to encode, and
// finally passing the encoded video packets to the specified VideoStub to send
// on the network.
//
......@@ -71,35 +62,20 @@ class VideoStub;
// of the capture, encode and network processes. However, it also needs to
// rate-limit captures to avoid overloading the host system, either by consuming
// too much CPU, or hogging the host's graphics subsystem.
//
// TODO(sergeyu): Rename this class to VideoFramePump.
class VideoFramePump : public base::RefCountedThreadSafe<VideoFramePump>,
public webrtc::DesktopCapturer::Callback,
public webrtc::MouseCursorMonitor::Callback {
class VideoFramePump : public webrtc::DesktopCapturer::Callback {
public:
// Enables timestamps for generated frames. Used for testing.
static void EnableTimestampsForTests();
// Creates a VideoFramePump running capture, encode and network tasks on the
// supplied TaskRunners. Video and cursor shape updates will be pumped to
// |video_stub| and |client_stub|, which must remain valid until Stop() is
// called. |capturer| is used to capture frames.
// supplied TaskRunners. Video will be pumped to |video_stub|, which must
// outlive the pump..
VideoFramePump(
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer,
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
scoped_ptr<VideoEncoder> encoder,
protocol::CursorShapeStub* cursor_stub,
protocol::VideoStub* video_stub);
// Starts scheduling frame captures.
void Start();
// Stop scheduling frame captures. This object cannot be re-used once
// it has been stopped.
void Stop();
~VideoFramePump() override;
// Pauses or resumes scheduling of frame captures. Pausing/resuming captures
// only affects capture scheduling and does not stop/start the capturer.
......@@ -115,40 +91,13 @@ class VideoFramePump : public base::RefCountedThreadSafe<VideoFramePump>,
void SetLosslessColor(bool want_lossless);
private:
friend class base::RefCountedThreadSafe<VideoFramePump>;
~VideoFramePump() override;
// Capturer thread ----------------------------------------------------------
// TODO(sergeyu): Move all methods that run on the capture thread to a
// separate class and make VideoFramePump not ref-counted.
// webrtc::DesktopCapturer::Callback implementation.
// webrtc::DesktopCapturer::Callback interface.
webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
// webrtc::MouseCursorMonitor::Callback implementation.
void OnMouseCursor(webrtc::MouseCursor* mouse_cursor) override;
void OnMouseCursorPosition(webrtc::MouseCursorMonitor::CursorState state,
const webrtc::DesktopVector& position) override;
// Starts the capturer on the capture thread.
void StartOnCaptureThread();
// Stops scheduling frame captures on the capture thread.
void StopOnCaptureThread();
// Captures next frame on the capture thread.
void CaptureNextFrameOnCaptureThread();
// Network thread -----------------------------------------------------------
// Captures a new frame. Called by CaptureScheduler.
// Callback for CaptureScheduler.
void CaptureNextFrame();
// Encodes and sends |frame|.
void EncodeAndSendFrame(scoped_ptr<webrtc::DesktopFrame> frame);
// Sends encoded frame
void SendEncodedFrame(int64 latest_event_timestamp,
base::TimeTicks timestamp,
......@@ -164,36 +113,32 @@ class VideoFramePump : public base::RefCountedThreadSafe<VideoFramePump>,
// Callback for |video_stub_| called after a keep-alive packet is sent.
void OnKeepAlivePacketSent();
// Send updated cursor shape to client.
void SendCursorShape(scoped_ptr<protocol::CursorShapeInfo> cursor_shape);
base::ThreadChecker thread_checker_;
// Task runners used by this class.
scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
// Task runner used to run |encoder_|.
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
// Used to capture frames. Always accessed on the capture thread.
// Capturer used to capture the screen.
scoped_ptr<webrtc::DesktopCapturer> capturer_;
// Used to capture mouse cursor shapes. Always accessed on the capture thread.
scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor_;
// Used to encode captured frames. Always accessed on the encode thread.
scoped_ptr<VideoEncoder> encoder_;
// Interfaces through which video frames and cursor shapes are passed to the
// client. These members are always accessed on the network thread.
protocol::CursorShapeStub* cursor_stub_;
// Interface through which video frames are passed to the client.
protocol::VideoStub* video_stub_;
// Timer used to ensure that we send empty keep-alive frames to the client
// even when the video stream is paused or encoder is busy.
scoped_ptr<base::DelayTimer<VideoFramePump> > keep_alive_timer_;
base::Timer keep_alive_timer_;
// CaptureScheduler calls CaptureNextFrame() whenever a new frame needs to be
// captured.
CaptureScheduler capture_scheduler_;
// Number updated by the caller to trace performance.
int64 latest_event_timestamp_;
scoped_ptr<CaptureScheduler> capture_scheduler_;
base::WeakPtrFactory<VideoFramePump> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoFramePump);
};
......
This diff is collapsed.
......@@ -65,26 +65,28 @@
'host/daemon_process.cc',
'host/daemon_process.h',
'host/daemon_process_win.cc',
'host/desktop_capturer_proxy.cc',
'host/desktop_capturer_proxy.h',
'host/desktop_environment.h',
'host/desktop_process.cc',
'host/desktop_process.h',
'host/desktop_resizer.h',
'host/desktop_resizer_linux.cc',
'host/desktop_resizer_mac.cc',
'host/desktop_resizer_win.cc',
'host/desktop_session.cc',
'host/desktop_session.h',
'host/desktop_session_agent.cc',
'host/desktop_session_agent.h',
'host/desktop_session_win.cc',
'host/desktop_session_win.h',
'host/desktop_resizer_mac.cc',
'host/desktop_resizer_win.cc',
'host/desktop_session_connector.h',
'host/desktop_session_proxy.cc',
'host/desktop_session_proxy.h',
'host/desktop_session_win.cc',
'host/desktop_session_win.h',
'host/desktop_shape_tracker.h',
'host/desktop_shape_tracker_linux.cc',
'host/desktop_shape_tracker_mac.cc',
'host/desktop_shape_tracker_win.cc',
'host/desktop_shape_tracker_linux.cc',
'host/disconnect_window_chromeos.cc',
'host/disconnect_window_linux.cc',
'host/disconnect_window_mac.h',
......@@ -103,8 +105,8 @@
'host/host_change_notification_listener.cc',
'host/host_change_notification_listener.h',
'host/host_config.cc',
'host/host_config_constants.cc',
'host/host_config.h',
'host/host_config_constants.cc',
'host/host_event_logger.h',
'host/host_event_logger_posix.cc',
'host/host_event_logger_win.cc',
......@@ -174,6 +176,8 @@
'host/me2me_desktop_environment.h',
'host/mouse_clamping_filter.cc',
'host/mouse_clamping_filter.h',
'host/mouse_shape_pump.cc',
'host/mouse_shape_pump.h',
'host/oauth_token_getter.cc',
'host/oauth_token_getter.h',
'host/pairing_registry_delegate.cc',
......
......@@ -162,6 +162,7 @@
'host/linux/unicode_to_keysym_unittest.cc',
'host/linux/x_server_clipboard_unittest.cc',
'host/local_input_monitor_unittest.cc',
'host/mouse_shape_pump_unittest.cc',
'host/native_messaging/native_messaging_reader_unittest.cc',
'host/native_messaging/native_messaging_writer_unittest.cc',
'host/pairing_registry_delegate_linux_unittest.cc',
......@@ -180,8 +181,8 @@
'host/setup/pin_validator_unittest.cc',
'host/shaped_desktop_capturer_unittest.cc',
'host/token_validator_factory_impl_unittest.cc',
'host/video_frame_recorder_unittest.cc',
'host/video_frame_pump_unittest.cc',
'host/video_frame_recorder_unittest.cc',
'host/win/rdp_client_unittest.cc',
'host/win/worker_process_launcher.cc',
'host/win/worker_process_launcher.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment