| Index: remoting/host/client_session.cc
|
| diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
|
| index 445900010f99031bf8d3f0b2d0ace98cd10ae68b..51a33a5937cbafad54a2e4489f799b3fb711b269 100644
|
| --- a/remoting/host/client_session.cc
|
| +++ b/remoting/host/client_session.cc
|
| @@ -7,6 +7,16 @@
|
| #include <algorithm>
|
|
|
| #include "base/message_loop_proxy.h"
|
| +#include "remoting/codec/audio_encoder.h"
|
| +#include "remoting/codec/audio_encoder_speex.h"
|
| +#include "remoting/codec/audio_encoder_verbatim.h"
|
| +#include "remoting/codec/video_encoder.h"
|
| +#include "remoting/codec/video_encoder_row_based.h"
|
| +#include "remoting/codec/video_encoder_vp8.h"
|
| +#include "remoting/host/audio_scheduler.h"
|
| +#include "remoting/host/desktop_environment.h"
|
| +#include "remoting/host/event_executor.h"
|
| +#include "remoting/host/screen_recorder.h"
|
| #include "remoting/host/video_frame_capturer.h"
|
| #include "remoting/proto/control.pb.h"
|
| #include "remoting/proto/event.pb.h"
|
| @@ -17,26 +27,32 @@ namespace remoting {
|
|
|
| ClientSession::ClientSession(
|
| EventHandler* event_handler,
|
| + scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
|
| + scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
|
| + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
|
| scoped_ptr<protocol::ConnectionToClient> connection,
|
| - protocol::ClipboardStub* host_clipboard_stub,
|
| - protocol::InputStub* host_input_stub,
|
| - VideoFrameCapturer* capturer,
|
| + scoped_ptr<DesktopEnvironment> desktop_environment,
|
| const base::TimeDelta& max_duration)
|
| : event_handler_(event_handler),
|
| connection_(connection.Pass()),
|
| + desktop_environment_(desktop_environment.Pass()),
|
| client_jid_(connection_->session()->jid()),
|
| - host_clipboard_stub_(host_clipboard_stub),
|
| - host_input_stub_(host_input_stub),
|
| + host_clipboard_stub_(desktop_environment_->event_executor()),
|
| + host_input_stub_(desktop_environment_->event_executor()),
|
| input_tracker_(host_input_stub_),
|
| remote_input_filter_(&input_tracker_),
|
| - mouse_clamping_filter_(capturer, &remote_input_filter_),
|
| + mouse_clamping_filter_(desktop_environment_->video_capturer(),
|
| + &remote_input_filter_),
|
| disable_input_filter_(&mouse_clamping_filter_),
|
| disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
|
| auth_input_filter_(&disable_input_filter_),
|
| auth_clipboard_filter_(&disable_clipboard_filter_),
|
| client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
|
| - capturer_(capturer),
|
| - max_duration_(max_duration) {
|
| + max_duration_(max_duration),
|
| + capture_task_runner_(capture_task_runner),
|
| + encode_task_runner_(encode_task_runner),
|
| + network_task_runner_(network_task_runner),
|
| + active_recorders_(0) {
|
| connection_->SetEventHandler(this);
|
|
|
| // TODO(sergeyu): Currently ConnectionToClient expects stubs to be
|
| @@ -52,9 +68,6 @@ ClientSession::ClientSession(
|
| auth_clipboard_filter_.set_enabled(false);
|
| }
|
|
|
| -ClientSession::~ClientSession() {
|
| -}
|
| -
|
| void ClientSession::NotifyClientDimensions(
|
| const protocol::ClientDimensions& dimensions) {
|
| // TODO(wez): Use the dimensions, e.g. to resize the host desktop to match.
|
| @@ -98,6 +111,34 @@ void ClientSession::OnConnectionChannelsConnected(
|
| DCHECK(CalledOnValidThread());
|
| DCHECK_EQ(connection_.get(), connection);
|
| SetDisableInputs(false);
|
| +
|
| + // Create a ScreenRecorder, passing the message loops that it should run on.
|
| + VideoEncoder* video_encoder =
|
| + CreateVideoEncoder(connection_->session()->config());
|
| + video_recorder_ = new ScreenRecorder(capture_task_runner_,
|
| + encode_task_runner_,
|
| + network_task_runner_,
|
| + desktop_environment_->video_capturer(),
|
| + video_encoder);
|
| + ++active_recorders_;
|
| +
|
| + if (connection_->session()->config().is_audio_enabled()) {
|
| + scoped_ptr<AudioEncoder> audio_encoder =
|
| + CreateAudioEncoder(connection_->session()->config());
|
| + audio_scheduler_ = new AudioScheduler(
|
| + capture_task_runner_,
|
| + network_task_runner_,
|
| + desktop_environment_->audio_capturer(),
|
| + audio_encoder.Pass(),
|
| + connection_->audio_stub());
|
| + ++active_recorders_;
|
| + }
|
| +
|
| + // Start the session.
|
| + video_recorder_->AddConnection(connection_.get());
|
| + video_recorder_->Start();
|
| + desktop_environment_->Start(CreateClipboardProxy());
|
| +
|
| event_handler_->OnSessionChannelsConnected(this);
|
| }
|
|
|
| @@ -127,6 +168,10 @@ void ClientSession::OnSequenceNumberUpdated(
|
| protocol::ConnectionToClient* connection, int64 sequence_number) {
|
| DCHECK(CalledOnValidThread());
|
| DCHECK_EQ(connection_.get(), connection);
|
| +
|
| + if (video_recorder_.get())
|
| + video_recorder_->UpdateSequenceNumber(sequence_number);
|
| +
|
| event_handler_->OnSessionSequenceNumber(this, sequence_number);
|
| }
|
|
|
| @@ -149,6 +194,27 @@ void ClientSession::Disconnect() {
|
| connection_->Disconnect();
|
| }
|
|
|
| +void ClientSession::Stop(const base::Closure& done_task) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(done_task_.is_null());
|
| +
|
| + done_task_ = done_task;
|
| + if (audio_scheduler_.get()) {
|
| + audio_scheduler_->OnClientDisconnected();
|
| + audio_scheduler_->Stop(base::Bind(&ClientSession::OnRecorderStopped, this));
|
| + audio_scheduler_ = NULL;
|
| + }
|
| +
|
| + if (video_recorder_.get()) {
|
| + video_recorder_->RemoveConnection(connection_.get());
|
| + video_recorder_->Stop(base::Bind(&ClientSession::OnRecorderStopped, this));
|
| + video_recorder_ = NULL;
|
| + }
|
| +
|
| + if (!active_recorders_)
|
| + done_task_.Run();
|
| +}
|
| +
|
| void ClientSession::LocalMouseMoved(const SkIPoint& mouse_pos) {
|
| DCHECK(CalledOnValidThread());
|
| remote_input_filter_.LocalMouseMoved(mouse_pos);
|
| @@ -164,6 +230,12 @@ void ClientSession::SetDisableInputs(bool disable_inputs) {
|
| disable_clipboard_filter_.set_enabled(!disable_inputs);
|
| }
|
|
|
| +ClientSession::~ClientSession() {
|
| + DCHECK(!active_recorders_);
|
| + DCHECK(audio_scheduler_.get() == NULL);
|
| + DCHECK(video_recorder_.get() == NULL);
|
| +}
|
| +
|
| scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
|
| DCHECK(CalledOnValidThread());
|
|
|
| @@ -173,4 +245,58 @@ scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
|
| base::MessageLoopProxy::current()));
|
| }
|
|
|
| +void ClientSession::OnRecorderStopped() {
|
| + if (!network_task_runner_->BelongsToCurrentThread()) {
|
| + network_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&ClientSession::OnRecorderStopped, this));
|
| + return;
|
| + }
|
| +
|
| + DCHECK(!done_task_.is_null());
|
| +
|
| + --active_recorders_;
|
| + DCHECK_GE(active_recorders_, 0);
|
| +
|
| + if (!active_recorders_)
|
| + done_task_.Run();
|
| +}
|
| +
|
| +// TODO(sergeyu): Move this to SessionManager?
|
| +// static
|
| +VideoEncoder* ClientSession::CreateVideoEncoder(
|
| + const protocol::SessionConfig& config) {
|
| + const protocol::ChannelConfig& video_config = config.video_config();
|
| +
|
| + if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
|
| + return VideoEncoderRowBased::CreateVerbatimEncoder();
|
| + } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
|
| + return VideoEncoderRowBased::CreateZlibEncoder();
|
| + } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
|
| + return new remoting::VideoEncoderVp8();
|
| + }
|
| +
|
| + NOTIMPLEMENTED();
|
| + return NULL;
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder(
|
| + const protocol::SessionConfig& config) {
|
| + const protocol::ChannelConfig& audio_config = config.audio_config();
|
| +
|
| + if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
|
| + return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim());
|
| + } else if (audio_config.codec == protocol::ChannelConfig::CODEC_SPEEX) {
|
| + return scoped_ptr<AudioEncoder>(new AudioEncoderSpeex());
|
| + }
|
| +
|
| + NOTIMPLEMENTED();
|
| + return scoped_ptr<AudioEncoder>(NULL);
|
| +}
|
| +
|
| +// static
|
| +void ClientSessionTraits::Destruct(const ClientSession* client) {
|
| + client->network_task_runner_->DeleteSoon(FROM_HERE, client);
|
| +}
|
| +
|
| } // namespace remoting
|
|
|