diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-27 05:18:25 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-27 05:18:25 +0000 |
commit | ff72dd1d95125512b475bcaee0a4252aa057d3f2 (patch) | |
tree | 30387d00ef14a12a8ffd5160f1a70a9fafaa5776 /remoting | |
parent | 961419632602c1ef815439dbbb8c8693448e9be9 (diff) | |
download | chromium_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.cc | 4 | ||||
-rw-r--r-- | remoting/base/shared_buffer.h | 10 | ||||
-rw-r--r-- | remoting/base/shared_buffer_unittest.cc | 4 | ||||
-rw-r--r-- | remoting/host/chromoting_messages.h | 86 | ||||
-rw-r--r-- | remoting/host/desktop_process.cc | 17 | ||||
-rw-r--r-- | remoting/host/desktop_process.h | 2 | ||||
-rw-r--r-- | remoting/host/desktop_session_agent.cc | 208 | ||||
-rw-r--r-- | remoting/host/desktop_session_agent.h | 97 | ||||
-rw-r--r-- | remoting/host/desktop_session_agent_posix.cc | 25 | ||||
-rw-r--r-- | remoting/host/desktop_session_agent_win.cc | 26 | ||||
-rw-r--r-- | remoting/host/video_scheduler.h | 2 |
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_ |