summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-27 05:18:25 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-27 05:18:25 +0000
commitff72dd1d95125512b475bcaee0a4252aa057d3f2 (patch)
tree30387d00ef14a12a8ffd5160f1a70a9fafaa5776 /remoting
parent961419632602c1ef815439dbbb8c8693448e9be9 (diff)
downloadchromium_src-ff72dd1d95125512b475bcaee0a4252aa057d3f2.zip
chromium_src-ff72dd1d95125512b475bcaee0a4252aa057d3f2.tar.gz
chromium_src-ff72dd1d95125512b475bcaee0a4252aa057d3f2.tar.bz2
DesktopSessionAgent now hosts the video capturer and provides necessary plumbing to drive it via an IPC channel.
BUG=134694 Review URL: https://chromiumcodereview.appspot.com/11413022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169587 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/base/shared_buffer.cc4
-rw-r--r--remoting/base/shared_buffer.h10
-rw-r--r--remoting/base/shared_buffer_unittest.cc4
-rw-r--r--remoting/host/chromoting_messages.h86
-rw-r--r--remoting/host/desktop_process.cc17
-rw-r--r--remoting/host/desktop_process.h2
-rw-r--r--remoting/host/desktop_session_agent.cc208
-rw-r--r--remoting/host/desktop_session_agent.h97
-rw-r--r--remoting/host/desktop_session_agent_posix.cc25
-rw-r--r--remoting/host/desktop_session_agent_win.cc26
-rw-r--r--remoting/host/video_scheduler.h2
11 files changed, 415 insertions, 66 deletions
diff --git a/remoting/base/shared_buffer.cc b/remoting/base/shared_buffer.cc
index 646f343..ff0bc93 100644
--- a/remoting/base/shared_buffer.cc
+++ b/remoting/base/shared_buffer.cc
@@ -15,7 +15,7 @@ SharedBuffer::SharedBuffer(uint32 size)
}
SharedBuffer::SharedBuffer(
- intptr_t id, base::SharedMemoryHandle handle, uint32 size)
+ int id, base::SharedMemoryHandle handle, uint32 size)
: id_(id),
shared_memory_(handle, kReadOnly),
size_(size) {
@@ -23,7 +23,7 @@ SharedBuffer::SharedBuffer(
}
SharedBuffer::SharedBuffer(
- intptr_t id, base::SharedMemoryHandle handle, base::ProcessHandle process,
+ int id, base::SharedMemoryHandle handle, base::ProcessHandle process,
uint32 size)
: id_(id),
shared_memory_(handle, kReadOnly, process),
diff --git a/remoting/base/shared_buffer.h b/remoting/base/shared_buffer.h
index a25c862..7b144d16 100644
--- a/remoting/base/shared_buffer.h
+++ b/remoting/base/shared_buffer.h
@@ -27,12 +27,12 @@ class SharedBuffer
// Opens an existing shared memory buffer and maps it to the memory of
// the calling process (in read only mode). If the operation fails for any
// reason, ptr() method will return NULL.
- SharedBuffer(intptr_t id, base::SharedMemoryHandle handle, uint32 size);
+ SharedBuffer(int id, base::SharedMemoryHandle handle, uint32 size);
// Opens an existing shared memory buffer created by a different process and
// maps it to the memory of the calling process (in read only mode). If
// the operation fails for any reason, ptr() method will return NULL.
- SharedBuffer(intptr_t id, base::SharedMemoryHandle handle,
+ SharedBuffer(int id, base::SharedMemoryHandle handle,
base::ProcessHandle process, uint32 size);
// Returns pointer to the beginning of the allocated data buffer. Returns NULL
@@ -43,17 +43,17 @@ class SharedBuffer
// data buffer.
base::SharedMemoryHandle handle() const { return shared_memory_.handle(); }
- intptr_t id() const { return id_; }
+ int id() const { return id_; }
uint32 size() const { return size_; }
- void set_id(intptr_t id) { id_ = id; }
+ void set_id(int id) { id_ = id; }
private:
friend class base::RefCountedThreadSafe<SharedBuffer>;
virtual ~SharedBuffer();
// Unique identifier of the buffer or 0 if ID hasn't been set.
- intptr_t id_;
+ int id_;
// Shared memory section backing up the buffer.
base::SharedMemory shared_memory_;
diff --git a/remoting/base/shared_buffer_unittest.cc b/remoting/base/shared_buffer_unittest.cc
index d09de2c..bb7e57b 100644
--- a/remoting/base/shared_buffer_unittest.cc
+++ b/remoting/base/shared_buffer_unittest.cc
@@ -8,8 +8,8 @@
const uint32 kBufferSize = 4096;
const int kPattern = 0x12345678;
-const intptr_t kIdZero = 0;
-const intptr_t kIdOne = 1;
+const int kIdZero = 0;
+const int kIdOne = 1;
namespace remoting {
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index 5cfa146..c9a37f7 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -2,11 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Defines IPC messages used by Chromoting components.
+#ifndef REMOTING_HOST_CHROMOTING_MESSAGES_H_
+#define REMOTING_HOST_CHROMOTING_MESSAGES_H_
+
+#include "ipc/ipc_platform_file.h"
+#include "third_party/skia/include/core/SkPoint.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkSize.h"
+
+#endif // REMOTING_HOST_CHROMOTING_MESSAGES_H_
// Multiply-included message file, no traditional include guard.
#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_platform_file.h"
#define IPC_MESSAGE_START ChromotingMsgStart
@@ -83,3 +90,78 @@ IPC_MESSAGE_CONTROL3(ChromotingDaemonDesktopMsg_Crash,
// the receiver of the message.
IPC_MESSAGE_CONTROL1(ChromotingDesktopDaemonMsg_DesktopAttached,
IPC::PlatformFileForTransit /* desktop_pipe */)
+
+//-----------------------------------------------------------------------------
+// Chromoting messages sent from the desktop to the network process.
+
+// Notifies the network process that a shared buffer has been created. Receiving
+// of this message must be confirmed by replying with
+// ChromotingNetworkDesktopMsg_SharedBufferCreated message.
+IPC_MESSAGE_CONTROL3(ChromotingDesktopNetworkMsg_CreateSharedBuffer,
+ int /* id */,
+ IPC::PlatformFileForTransit /* handle */,
+ uint32 /* size */)
+
+// Request the network process to stop using a shared buffer.
+IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_ReleaseSharedBuffer,
+ int /* id */)
+
+IPC_STRUCT_TRAITS_BEGIN(SkIPoint)
+ IPC_STRUCT_TRAITS_MEMBER(fX)
+ IPC_STRUCT_TRAITS_MEMBER(fY)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(SkIRect)
+ IPC_STRUCT_TRAITS_MEMBER(fLeft)
+ IPC_STRUCT_TRAITS_MEMBER(fTop)
+ IPC_STRUCT_TRAITS_MEMBER(fRight)
+ IPC_STRUCT_TRAITS_MEMBER(fBottom)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(SkISize)
+ IPC_STRUCT_TRAITS_MEMBER(fWidth)
+ IPC_STRUCT_TRAITS_MEMBER(fHeight)
+IPC_STRUCT_TRAITS_END()
+
+// Serialized CaptureData structure.
+IPC_STRUCT_BEGIN(SerializedCapturedData)
+ // ID of the shared memory buffer containing the pixels.
+ IPC_STRUCT_MEMBER(int, shared_buffer_id)
+
+ // Captured region.
+ IPC_STRUCT_MEMBER(std::vector<SkIRect>, dirty_region)
+
+ // Dimentions of the buffer in pixels.
+ IPC_STRUCT_MEMBER(SkISize, dimensions)
+
+ // Pixel format.
+ IPC_STRUCT_MEMBER(int32, pixel_format)
+
+ // Time spent in capture. Unit is in milliseconds.
+ IPC_STRUCT_MEMBER(int, capture_time_ms)
+
+ // Sequence number supplied by client for performance tracking.
+ IPC_STRUCT_MEMBER(int64, client_sequence_number)
+
+ // DPI for this frame.
+ IPC_STRUCT_MEMBER(SkIPoint, dpi)
+IPC_STRUCT_END()
+
+// Notifies the network process that a shared buffer has been created.
+IPC_MESSAGE_CONTROL1(ChromotingDesktopNetworkMsg_CaptureCompleted,
+ SerializedCapturedData /* capture_data */ )
+
+
+//-----------------------------------------------------------------------------
+// Chromoting messages sent from the network to the desktop process.
+
+// Notifies the desktop process that the shared memory buffer has been mapped to
+// the memory of the network process and so it can be safely dropped by
+// the network process at any time.
+IPC_MESSAGE_CONTROL1(ChromotingNetworkDesktopMsg_SharedBufferCreated,
+ int /* id */)
+
+IPC_MESSAGE_CONTROL1(ChromotingNetworkDesktopMsg_InvalidateRegion,
+ std::vector<SkIRect> /* invalid_region */ )
+
+IPC_MESSAGE_CONTROL0(ChromotingNetworkDesktopMsg_CaptureFrame)
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc
index 7f3d730..6fcb4ff 100644
--- a/remoting/host/desktop_process.cc
+++ b/remoting/host/desktop_process.cc
@@ -18,8 +18,6 @@
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/desktop_session_agent.h"
-const char kIoThreadName[] = "I/O thread";
-
namespace remoting {
DesktopProcess::DesktopProcess(
@@ -60,7 +58,8 @@ void DesktopProcess::OnChannelError() {
// Shutdown the desktop process.
daemon_channel_.reset();
- desktop_agent_.reset();
+ desktop_agent_->Stop();
+ desktop_agent_ = NULL;
caller_task_runner_ = NULL;
}
@@ -69,12 +68,17 @@ bool DesktopProcess::Start() {
// Launch the I/O thread.
scoped_refptr<AutoThreadTaskRunner> io_task_runner =
- AutoThread::CreateWithType(kIoThreadName, caller_task_runner_,
+ AutoThread::CreateWithType("I/O thread", caller_task_runner_,
MessageLoop::TYPE_IO);
+ // Launch the video capture thread.
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner =
+ AutoThread::Create("Video capture thread", caller_task_runner_);
+
// Create a desktop agent.
desktop_agent_ = DesktopSessionAgent::Create(caller_task_runner_,
- io_task_runner);
+ io_task_runner,
+ video_capture_task_runner);
// Start the agent and create an IPC channel to talk to it. It is safe to
// use base::Unretained(this) here because the message loop below will run
@@ -83,7 +87,8 @@ bool DesktopProcess::Start() {
if (!desktop_agent_->Start(base::Bind(&DesktopProcess::OnChannelError,
base::Unretained(this)),
&desktop_pipe)) {
- desktop_agent_.reset();
+ desktop_agent_ = NULL;
+ caller_task_runner_ = NULL;
return false;
}
diff --git a/remoting/host/desktop_process.h b/remoting/host/desktop_process.h
index 75786b5..e95971e 100644
--- a/remoting/host/desktop_process.h
+++ b/remoting/host/desktop_process.h
@@ -57,7 +57,7 @@ class DesktopProcess : public IPC::Listener {
// Provides screen/audio capturing and input injection services for
// the network process.
- scoped_ptr<DesktopSessionAgent> desktop_agent_;
+ scoped_refptr<DesktopSessionAgent> desktop_agent_;
DISALLOW_COPY_AND_ASSIGN(DesktopProcess);
};
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index 3664369..56d7127 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -9,27 +9,36 @@
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/base/capture_data.h"
#include "remoting/host/chromoting_messages.h"
+#include "remoting/proto/control.pb.h"
+#include "third_party/skia/include/core/SkRegion.h"
namespace remoting {
DesktopSessionAgent::~DesktopSessionAgent() {
- DCHECK(caller_task_runner()->BelongsToCurrentThread());
+ DCHECK(!video_capturer_);
}
bool DesktopSessionAgent::OnMessageReceived(const IPC::Message& message) {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
- NOTIMPLEMENTED();
- return false;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DesktopSessionAgent, message)
+ IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_CaptureFrame,
+ OnCaptureFrame)
+ IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InvalidateRegion,
+ OnInvalidateRegion)
+ IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_SharedBufferCreated,
+ OnSharedBufferCreated)
+ IPC_END_MESSAGE_MAP()
+ return handled;
}
void DesktopSessionAgent::OnChannelConnected(int32 peer_pid) {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
VLOG(1) << "IPC: desktop <- network (" << peer_pid << ")";
-
- NOTIMPLEMENTED();
}
void DesktopSessionAgent::OnChannelError() {
@@ -38,23 +47,198 @@ void DesktopSessionAgent::OnChannelError() {
// Make sure the channel is closed.
network_channel_.reset();
- // Notify the caller that |this| can be destroyed now.
- done_task_.Run();
+ // Notify the caller that the channel has been disconnected.
+ disconnected_task_.Run();
+}
+
+scoped_refptr<SharedBuffer> DesktopSessionAgent::CreateSharedBuffer(
+ uint32 size) {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+
+ scoped_refptr<SharedBuffer> buffer = new SharedBuffer(size);
+ if (buffer->ptr() != NULL) {
+ buffer->set_id(next_shared_buffer_id_);
+ shared_buffers_.push_back(buffer);
+
+ // |next_shared_buffer_id_| starts from 1 and incrementing it by 2 makes
+ // sure it is always odd and therefore zero is never used as a valid buffer
+ // ID.
+ //
+ // It is very unlikely (though theoretically possible) to allocate the same
+ // ID for two different buffers due to integer overflow. It should take
+ // about a year of allocating 100 new buffers every second. Practically
+ // speaking it never happens.
+ next_shared_buffer_id_ += 2;
+
+ SendToNetwork(new ChromotingDesktopNetworkMsg_CreateSharedBuffer(
+ buffer->id(), buffer->handle(), buffer->size()));
+ }
+
+ return buffer;
+}
+
+void DesktopSessionAgent::ReleaseSharedBuffer(
+ scoped_refptr<SharedBuffer> buffer) {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+ DCHECK(buffer->id() != 0);
+
+ SendToNetwork(
+ new ChromotingDesktopNetworkMsg_ReleaseSharedBuffer(buffer->id()));
}
-bool DesktopSessionAgent::Start(const base::Closure& done_task,
+void DesktopSessionAgent::OnCaptureCompleted(
+ scoped_refptr<CaptureData> capture_data) {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+
+ // Serialize CaptureData
+ SerializedCapturedData serialized_data;
+ serialized_data.shared_buffer_id = capture_data->shared_buffer()->id();
+ serialized_data.dimensions = capture_data->size();
+ serialized_data.pixel_format = capture_data->pixel_format();
+ serialized_data.capture_time_ms = capture_data->capture_time_ms();
+ serialized_data.client_sequence_number =
+ capture_data->client_sequence_number();
+ serialized_data.dpi = capture_data->dpi();
+ for (SkRegion::Iterator i(capture_data->dirty_region()); !i.done(); i.next())
+ serialized_data.dirty_region.push_back(i.rect());
+
+ SendToNetwork(
+ new ChromotingDesktopNetworkMsg_CaptureCompleted(serialized_data));
+}
+
+void DesktopSessionAgent::OnCursorShapeChanged(
+ scoped_ptr<protocol::CursorShapeInfo> cursor_shape) {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+
+ NOTIMPLEMENTED();
+}
+
+bool DesktopSessionAgent::Start(const base::Closure& disconnected_task,
IPC::PlatformFileForTransit* desktop_pipe_out) {
DCHECK(caller_task_runner()->BelongsToCurrentThread());
- done_task_ = done_task;
- return DoCreateNetworkChannel(desktop_pipe_out, &network_channel_);
+ disconnected_task_ = disconnected_task;
+ if (!CreateChannelForNetworkProcess(desktop_pipe_out, &network_channel_))
+ return false;
+
+ // Start the video capturer.
+ video_capture_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DesktopSessionAgent::StartVideoCapturer, this));
+ return true;
+}
+
+void DesktopSessionAgent::Stop() {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ // Stop the video capturer.
+ video_capture_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DesktopSessionAgent::StopVideoCapturer, this));
+}
+
+void DesktopSessionAgent::OnCaptureFrame() {
+ if (!video_capture_task_runner()->BelongsToCurrentThread()) {
+ video_capture_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DesktopSessionAgent::OnCaptureFrame, this));
+ return;
+ }
+
+ // VideoFrameCapturer supports a very few (currently 2) outstanding capture
+ // requests. The requests are serialized on |video_capture_task_runner()| task
+ // runner. If the client issues more requests, pixel data in captured frames
+ // will likely be corrupted but stability of VideoFrameCapturer will not be
+ // affected.
+ video_capturer_->CaptureInvalidRegion();
+}
+
+void DesktopSessionAgent::OnInvalidateRegion(
+ const std::vector<SkIRect>& invalid_rects) {
+ if (!video_capture_task_runner()->BelongsToCurrentThread()) {
+ video_capture_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DesktopSessionAgent::OnInvalidateRegion, this,
+ invalid_rects));
+ return;
+ }
+
+ SkIRect bounds = SkIRect::MakeSize(video_capturer_->size_most_recent());
+
+ // Convert |invalid_rects| into a region.
+ SkRegion invalid_region;
+ for (std::vector<SkIRect>::const_iterator i = invalid_rects.begin();
+ i != invalid_rects.end(); ++i) {
+ // Validate each rectange and clip it to the frame bounds. If the rectangle
+ // is not valid it is ignored.
+ SkIRect rect;
+ if (rect.intersect(*i, bounds)) {
+ invalid_region.op(rect, SkRegion::kUnion_Op);
+ }
+ }
+
+ video_capturer_->InvalidateRegion(invalid_region);
+}
+
+void DesktopSessionAgent::OnSharedBufferCreated(int id) {
+ if (!video_capture_task_runner()->BelongsToCurrentThread()) {
+ video_capture_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DesktopSessionAgent::OnSharedBufferCreated, this, id));
+ return;
+ }
+
+ // Drop the cached reference to the buffer.
+ SharedBuffers::iterator i = shared_buffers_.begin();
+ for (; i != shared_buffers_.end(); ++i) {
+ if ((*i)->id() == id) {
+ shared_buffers_.erase(i);
+ break;
+ }
+ }
+}
+
+void DesktopSessionAgent::SendToNetwork(IPC::Message* message) {
+ if (!caller_task_runner()->BelongsToCurrentThread()) {
+ caller_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DesktopSessionAgent::SendToNetwork, this, message));
+ return;
+ }
+
+ if (network_channel_) {
+ network_channel_->Send(message);
+ } else {
+ delete message;
+ }
+}
+
+void DesktopSessionAgent::StartVideoCapturer() {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+
+ video_capturer_ = VideoFrameCapturer::CreateWithFactory(this);
+ if (video_capturer_)
+ video_capturer_->Start(this);
+}
+
+void DesktopSessionAgent::StopVideoCapturer() {
+ DCHECK(video_capture_task_runner()->BelongsToCurrentThread());
+
+ if (video_capturer_) {
+ video_capturer_->Stop();
+ video_capturer_.reset();
+ }
+
+ // Free any shared buffers left.
+ shared_buffers_.clear();
}
DesktopSessionAgent::DesktopSessionAgent(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner)
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner)
: caller_task_runner_(caller_task_runner),
- io_task_runner_(io_task_runner) {
+ io_task_runner_(io_task_runner),
+ video_capture_task_runner_(video_capture_task_runner),
+ next_shared_buffer_id_(1) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
}
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index 569dfd5..85ea314 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -5,6 +5,8 @@
#ifndef REMOTING_HOST_DESKTOP_SESSION_AGENT_H_
#define REMOTING_HOST_DESKTOP_SESSION_AGENT_H_
+#include <list>
+
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -12,6 +14,10 @@
#include "base/memory/scoped_ptr.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_platform_file.h"
+#include "remoting/base/shared_buffer.h"
+#include "remoting/base/shared_buffer_factory.h"
+#include "remoting/host/video_frame_capturer.h"
+#include "third_party/skia/include/core/SkRect.h"
namespace IPC {
class ChannelProxy;
@@ -24,36 +30,81 @@ class AutoThreadTaskRunner;
// Provides screen/audio capturing and input injection services for
// the network process.
-class DesktopSessionAgent : public IPC::Listener {
+class DesktopSessionAgent
+ : public base::RefCountedThreadSafe<DesktopSessionAgent>,
+ public IPC::Listener,
+ public SharedBufferFactory,
+ public VideoFrameCapturer::Delegate {
public:
- static scoped_ptr<DesktopSessionAgent> Create(
+ static scoped_refptr<DesktopSessionAgent> Create(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner);
-
- virtual ~DesktopSessionAgent();
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner);
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
virtual void OnChannelError() OVERRIDE;
- // Creates the screen/audio recorders, input stubs and the IPC channel to be
- // used to access them. Returns a handle of the client end of the IPC channel
- // pipe to be forwarder to the corresponding desktop environment.
- bool Start(const base::Closure& done_task,
+ // SharedBufferFactory implementation.
+ virtual scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size) OVERRIDE;
+ virtual void ReleaseSharedBuffer(scoped_refptr<SharedBuffer> buffer) OVERRIDE;
+
+ // VideoFrameCapturer::Delegate implementation.
+ virtual void OnCaptureCompleted(
+ scoped_refptr<CaptureData> capture_data) OVERRIDE;
+ virtual void OnCursorShapeChanged(
+ scoped_ptr<protocol::CursorShapeInfo> cursor_shape) OVERRIDE;
+
+ // Creates desktop integration components and a connected IPC channel to be
+ // used to access them. The client end of the channel is returned in
+ // the variable pointed by |desktop_pipe_out|.
+ //
+ // |disconnected_task| is invoked on |caller_task_runner_| to notify
+ // the caller that the network-to-desktop channel has been disconnected.
+ bool Start(const base::Closure& disconnected_task,
IPC::PlatformFileForTransit* desktop_pipe_out);
+ // Stops the agent asynchronously.
+ void Stop();
+
protected:
DesktopSessionAgent(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner);
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner);
- // Creates a pre-connected IPC channel to be used to access the screen/audio
+ friend class base::RefCountedThreadSafe<DesktopSessionAgent>;
+ virtual ~DesktopSessionAgent();
+
+ // Creates a connected IPC channel to be used to access the screen/audio
// recorders and input stubs.
- virtual bool DoCreateNetworkChannel(
+ virtual bool CreateChannelForNetworkProcess(
IPC::PlatformFileForTransit* client_out,
scoped_ptr<IPC::ChannelProxy>* server_out) = 0;
+ // Handles CaptureFrame requests from the client.
+ void OnCaptureFrame();
+
+ // Handles InvalidateRegion requests from the client.
+ void OnInvalidateRegion(const std::vector<SkIRect>& invalid_rects);
+
+ // Handles SharedBufferCreated notification from the client.
+ void OnSharedBufferCreated(int id);
+
+ // Sends a message to the network process.
+ void SendToNetwork(IPC::Message* message);
+
+ // Posted to |video_capture_task_runner_| task runner to start the video
+ // capturer.
+ void StartVideoCapturer();
+
+ // Posted to |video_capture_task_runner_| task runner to stop the video
+ // capturer.
+ void StopVideoCapturer();
+
+ // Getters providing access to the task runners for platform-specific derived
+ // classes.
scoped_refptr<AutoThreadTaskRunner> caller_task_runner() const {
return caller_task_runner_;
}
@@ -62,6 +113,10 @@ class DesktopSessionAgent : public IPC::Listener {
return io_task_runner_;
}
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner() const {
+ return video_capture_task_runner_;
+ }
+
private:
// Task runner on which public methods of this class should be called.
scoped_refptr<AutoThreadTaskRunner> caller_task_runner_;
@@ -69,13 +124,25 @@ class DesktopSessionAgent : public IPC::Listener {
// Message loop used by the IPC channel.
scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
- // Run on |caller_task_runner_| to notify the caller that |this| has been
- // stopped.
- base::Closure done_task_;
+ // Task runner dedicated to running themethods of the video capturer.
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner_;
+
+ // Runs on |caller_task_runner_| to notify the caller that the network-to-
+ // desktop channel has been disconnected.
+ base::Closure disconnected_task_;
// IPC channel connecting the desktop process with the network process.
scoped_ptr<IPC::ChannelProxy> network_channel_;
+ // Next shared buffer ID to be used.
+ int next_shared_buffer_id_;
+
+ // List of the shared buffers registered via |SharedBufferFactory| interface.
+ typedef std::list<scoped_refptr<SharedBuffer> > SharedBuffers;
+ SharedBuffers shared_buffers_;
+
+ scoped_ptr<VideoFrameCapturer> video_capturer_;
+
DISALLOW_COPY_AND_ASSIGN(DesktopSessionAgent);
};
diff --git a/remoting/host/desktop_session_agent_posix.cc b/remoting/host/desktop_session_agent_posix.cc
index 445bc16..cc198bd 100644
--- a/remoting/host/desktop_session_agent_posix.cc
+++ b/remoting/host/desktop_session_agent_posix.cc
@@ -23,11 +23,13 @@ class DesktopSessionAgentPosix : public DesktopSessionAgent {
public:
DesktopSessionAgentPosix(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner);
- virtual ~DesktopSessionAgentPosix();
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner);
protected:
- virtual bool DoCreateNetworkChannel(
+ virtual ~DesktopSessionAgentPosix();
+
+ virtual bool CreateChannelForNetworkProcess(
IPC::PlatformFileForTransit* client_out,
scoped_ptr<IPC::ChannelProxy>* server_out) OVERRIDE;
@@ -37,14 +39,16 @@ class DesktopSessionAgentPosix : public DesktopSessionAgent {
DesktopSessionAgentPosix::DesktopSessionAgentPosix(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner)
- : DesktopSessionAgent(caller_task_runner, io_task_runner) {
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner)
+ : DesktopSessionAgent(caller_task_runner, io_task_runner,
+ video_capture_task_runner) {
}
DesktopSessionAgentPosix::~DesktopSessionAgentPosix() {
}
-bool DesktopSessionAgentPosix::DoCreateNetworkChannel(
+bool DesktopSessionAgentPosix::CreateChannelForNetworkProcess(
IPC::PlatformFileForTransit* client_out,
scoped_ptr<IPC::ChannelProxy>* server_out) {
// Create a socket pair.
@@ -83,11 +87,12 @@ bool DesktopSessionAgentPosix::DoCreateNetworkChannel(
}
// static
-scoped_ptr<DesktopSessionAgent> DesktopSessionAgent::Create(
+scoped_refptr<DesktopSessionAgent> DesktopSessionAgent::Create(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner) {
- return scoped_ptr<DesktopSessionAgent>(new DesktopSessionAgentPosix(
- caller_task_runner, io_task_runner));
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner) {
+ return scoped_refptr<DesktopSessionAgent>(new DesktopSessionAgentPosix(
+ caller_task_runner, io_task_runner, video_capture_task_runner));
}
} // namespace remoting
diff --git a/remoting/host/desktop_session_agent_win.cc b/remoting/host/desktop_session_agent_win.cc
index ff771e5..6ef4f01 100644
--- a/remoting/host/desktop_session_agent_win.cc
+++ b/remoting/host/desktop_session_agent_win.cc
@@ -25,11 +25,13 @@ class DesktopSessionAgentWin : public DesktopSessionAgent {
public:
DesktopSessionAgentWin(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner);
- virtual ~DesktopSessionAgentWin();
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner);
protected:
- virtual bool DoCreateNetworkChannel(
+ virtual ~DesktopSessionAgentWin();
+
+ virtual bool CreateChannelForNetworkProcess(
IPC::PlatformFileForTransit* client_out,
scoped_ptr<IPC::ChannelProxy>* server_out) OVERRIDE;
@@ -39,14 +41,17 @@ class DesktopSessionAgentWin : public DesktopSessionAgent {
DesktopSessionAgentWin::DesktopSessionAgentWin(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner)
- : DesktopSessionAgent(caller_task_runner, io_task_runner) {
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner)
+ : DesktopSessionAgent(caller_task_runner,
+ io_task_runner,
+ video_capture_task_runner) {
}
DesktopSessionAgentWin::~DesktopSessionAgentWin() {
}
-bool DesktopSessionAgentWin::DoCreateNetworkChannel(
+bool DesktopSessionAgentWin::CreateChannelForNetworkProcess(
IPC::PlatformFileForTransit* client_out,
scoped_ptr<IPC::ChannelProxy>* server_out) {
// Generate a unique name for the channel.
@@ -80,11 +85,12 @@ bool DesktopSessionAgentWin::DoCreateNetworkChannel(
}
// static
-scoped_ptr<DesktopSessionAgent> DesktopSessionAgent::Create(
+scoped_refptr<DesktopSessionAgent> DesktopSessionAgent::Create(
scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
- scoped_refptr<AutoThreadTaskRunner> io_task_runner) {
- return scoped_ptr<DesktopSessionAgent>(new DesktopSessionAgentWin(
- caller_task_runner, io_task_runner));
+ scoped_refptr<AutoThreadTaskRunner> io_task_runner,
+ scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner) {
+ return scoped_refptr<DesktopSessionAgent>(new DesktopSessionAgentWin(
+ caller_task_runner, io_task_runner, video_capture_task_runner));
}
} // namespace remoting
diff --git a/remoting/host/video_scheduler.h b/remoting/host/video_scheduler.h
index 597a0f7..c57ad10 100644
--- a/remoting/host/video_scheduler.h
+++ b/remoting/host/video_scheduler.h
@@ -191,4 +191,4 @@ class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
} // namespace remoting
-#endif // REMOTING_HOST_SCREEN_RECORDER_H_
+#endif // REMOTING_HOST_VIDEO_SCHEDULER_H_