blob: 280a3c3b71cbe1207934e377868a6dfa2eb3684c [file] [log] [blame]
[email protected]91e4b7f62012-01-25 23:23:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]44f60762011-03-23 12:13:352// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/host/client_session.h"
6
[email protected]4fe827a2011-08-10 03:30:197#include <algorithm>
8
[email protected]ee910fd2011-11-10 18:23:319#include "base/message_loop_proxy.h"
[email protected]497d8a92013-01-28 23:54:0310#include "media/video/capture/screen/screen_capturer.h"
[email protected]a5d181f2013-04-19 14:55:3711#include "remoting/base/capabilities.h"
[email protected]170cba42012-09-12 22:28:3912#include "remoting/codec/audio_encoder.h"
[email protected]a6ccb7722012-10-23 21:10:4313#include "remoting/codec/audio_encoder_opus.h"
[email protected]170cba42012-09-12 22:28:3914#include "remoting/codec/audio_encoder_speex.h"
15#include "remoting/codec/audio_encoder_verbatim.h"
16#include "remoting/codec/video_encoder.h"
[email protected]2149bef2012-10-18 03:26:5317#include "remoting/codec/video_encoder_verbatim.h"
[email protected]170cba42012-09-12 22:28:3918#include "remoting/codec/video_encoder_vp8.h"
[email protected]ce404ca2013-01-16 17:23:5319#include "remoting/host/audio_capturer.h"
[email protected]170cba42012-09-12 22:28:3920#include "remoting/host/audio_scheduler.h"
21#include "remoting/host/desktop_environment.h"
[email protected]b0b72f112013-03-24 03:42:4222#include "remoting/host/input_injector.h"
[email protected]231316a2013-03-25 06:01:1223#include "remoting/host/screen_controls.h"
[email protected]739e2802013-03-18 01:03:4824#include "remoting/host/screen_resolution.h"
[email protected]2ce80252012-10-26 07:23:1225#include "remoting/host/video_scheduler.h"
[email protected]50d71c72012-05-03 01:28:5526#include "remoting/proto/control.pb.h"
[email protected]c78669c92011-06-13 22:42:3827#include "remoting/proto/event.pb.h"
[email protected]ff3761a12012-05-22 22:29:2428#include "remoting/protocol/client_stub.h"
[email protected]7f44ba42012-05-31 20:26:2929#include "remoting/protocol/clipboard_thread_proxy.h"
[email protected]c78669c92011-06-13 22:42:3830
[email protected]48a8ca32013-02-13 04:31:0131// Default DPI to assume for old clients that use notifyClientDimensions.
32const int kDefaultDPI = 96;
[email protected]739e2802013-03-18 01:03:4833
34namespace remoting {
[email protected]48a8ca32013-02-13 04:31:0135
[email protected]44f60762011-03-23 12:13:3536ClientSession::ClientSession(
37 EventHandler* event_handler,
[email protected]032d9dd2012-11-01 17:55:0438 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
[email protected]ce404ca2013-01-16 17:23:5339 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
[email protected]16dbfb0e2012-11-14 04:11:1940 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
41 scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
[email protected]170cba42012-09-12 22:28:3942 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
[email protected]ce404ca2013-01-16 17:23:5343 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
[email protected]3361e1f2012-03-20 20:31:4444 scoped_ptr<protocol::ConnectionToClient> connection,
[email protected]81904792012-10-18 04:16:2845 DesktopEnvironmentFactory* desktop_environment_factory,
[email protected]5dc5b12a2012-06-23 01:05:1446 const base::TimeDelta& max_duration)
[email protected]44f60762011-03-23 12:13:3547 : event_handler_(event_handler),
[email protected]3361e1f2012-03-20 20:31:4448 connection_(connection.Pass()),
49 client_jid_(connection_->session()->jid()),
[email protected]aa46ba52013-04-27 00:00:4450 control_factory_(this),
[email protected]233bb942013-03-15 07:18:1751 desktop_environment_factory_(desktop_environment_factory),
[email protected]eccc2d42013-01-10 19:35:1452 input_tracker_(&host_input_filter_),
[email protected]86cbe6b2012-04-03 00:56:1853 remote_input_filter_(&input_tracker_),
[email protected]58f1ad42013-01-10 23:49:5154 mouse_clamping_filter_(&remote_input_filter_),
[email protected]eccc2d42013-01-10 19:35:1455 disable_input_filter_(mouse_clamping_filter_.input_filter()),
[email protected]750ae6b2012-08-20 22:52:4056 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
57 auth_input_filter_(&disable_input_filter_),
58 auth_clipboard_filter_(&disable_clipboard_filter_),
[email protected]7f44ba42012-05-31 20:26:2959 client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
[email protected]170cba42012-09-12 22:28:3960 max_duration_(max_duration),
[email protected]032d9dd2012-11-01 17:55:0461 audio_task_runner_(audio_task_runner),
[email protected]ce404ca2013-01-16 17:23:5362 input_task_runner_(input_task_runner),
[email protected]16dbfb0e2012-11-14 04:11:1963 video_capture_task_runner_(video_capture_task_runner),
64 video_encode_task_runner_(video_encode_task_runner),
[email protected]170cba42012-09-12 22:28:3965 network_task_runner_(network_task_runner),
[email protected]ce404ca2013-01-16 17:23:5366 ui_task_runner_(ui_task_runner) {
[email protected]ee910fd2011-11-10 18:23:3167 connection_->SetEventHandler(this);
68
69 // TODO(sergeyu): Currently ConnectionToClient expects stubs to be
70 // set before channels are connected. Make it possible to set stubs
71 // later and set them only when connection is authenticated.
[email protected]34df2ab2012-08-19 06:54:2372 connection_->set_clipboard_stub(&auth_clipboard_filter_);
[email protected]ee910fd2011-11-10 18:23:3173 connection_->set_host_stub(this);
[email protected]880c6cd2012-08-21 04:35:0774 connection_->set_input_stub(&auth_input_filter_);
[email protected]750ae6b2012-08-20 22:52:4075
76 // |auth_*_filter_|'s states reflect whether the session is authenticated.
77 auth_input_filter_.set_enabled(false);
78 auth_clipboard_filter_.set_enabled(false);
[email protected]2f4084892013-02-25 20:30:2079
80#if defined(OS_WIN)
81 // LocalInputMonitorWin filters out an echo of the injected input before it
82 // reaches |remote_input_filter_|.
83 remote_input_filter_.SetExpectLocalEcho(false);
84#endif // defined(OS_WIN)
[email protected]44f60762011-03-23 12:13:3585}
86
[email protected]f19f09ca2013-03-13 11:10:2987ClientSession::~ClientSession() {
88 DCHECK(CalledOnValidThread());
89 DCHECK(!audio_scheduler_);
[email protected]231316a2013-03-25 06:01:1290 DCHECK(!desktop_environment_);
[email protected]b0b72f112013-03-24 03:42:4291 DCHECK(!input_injector_);
[email protected]231316a2013-03-25 06:01:1292 DCHECK(!screen_controls_);
[email protected]f19f09ca2013-03-13 11:10:2993 DCHECK(!video_scheduler_);
94
95 connection_.reset();
96}
97
[email protected]48a8ca32013-02-13 04:31:0198void ClientSession::NotifyClientResolution(
99 const protocol::ClientResolution& resolution) {
[email protected]a5d181f2013-04-19 14:55:37100 DCHECK(CalledOnValidThread());
101
[email protected]739e2802013-03-18 01:03:48102 if (!resolution.has_dips_width() || !resolution.has_dips_height())
103 return;
104
105 VLOG(1) << "Received ClientResolution (dips_width="
106 << resolution.dips_width() << ", dips_height="
107 << resolution.dips_height() << ")";
108
[email protected]231316a2013-03-25 06:01:12109 if (!screen_controls_)
[email protected]739e2802013-03-18 01:03:48110 return;
111
112 ScreenResolution client_resolution(
113 SkISize::Make(resolution.dips_width(), resolution.dips_height()),
114 SkIPoint::Make(kDefaultDPI, kDefaultDPI));
115
116 // Try to match the client's resolution.
117 if (client_resolution.IsValid())
[email protected]231316a2013-03-25 06:01:12118 screen_controls_->SetScreenResolution(client_resolution);
[email protected]50d71c72012-05-03 01:28:55119}
120
121void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
[email protected]a5d181f2013-04-19 14:55:37122 DCHECK(CalledOnValidThread());
123
[email protected]50d71c72012-05-03 01:28:55124 if (video_control.has_enable()) {
125 VLOG(1) << "Received VideoControl (enable="
126 << video_control.enable() << ")";
[email protected]324b1962013-05-01 19:30:22127 video_scheduler_->Pause(!video_control.enable());
[email protected]50d71c72012-05-03 01:28:55128 }
[email protected]f2b9cf32012-04-27 00:13:43129}
130
[email protected]f458bed2012-10-18 03:27:59131void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) {
[email protected]a5d181f2013-04-19 14:55:37132 DCHECK(CalledOnValidThread());
133
[email protected]f458bed2012-10-18 03:27:59134 if (audio_control.has_enable()) {
135 VLOG(1) << "Received AudioControl (enable="
136 << audio_control.enable() << ")";
[email protected]ce404ca2013-01-16 17:23:53137 if (audio_scheduler_)
138 audio_scheduler_->Pause(!audio_control.enable());
[email protected]f458bed2012-10-18 03:27:59139 }
140}
141
[email protected]a5d181f2013-04-19 14:55:37142void ClientSession::SetCapabilities(
143 const protocol::Capabilities& capabilities) {
144 DCHECK(CalledOnValidThread());
145
146 // The client should not send protocol::Capabilities if it is not supported by
147 // the config channel.
148 if (!connection_->session()->config().SupportsCapabilities()) {
149 LOG(ERROR) << "Unexpected protocol::Capabilities has been received.";
150 return;
151 }
152
153 // Ignore all the messages but the 1st one.
154 if (client_capabilities_) {
155 LOG(WARNING) << "protocol::Capabilities has been received already.";
156 return;
157 }
158
159 client_capabilities_ = make_scoped_ptr(new std::string());
160 if (capabilities.has_capabilities())
161 *client_capabilities_ = capabilities.capabilities();
162
163 VLOG(1) << "Client capabilities: " << *client_capabilities_;
164
165 // Calculate the set of capabilities enabled by both client and host and
166 // pass it to the desktop environment if it is available.
[email protected]324b1962013-05-01 19:30:22167 desktop_environment_->SetCapabilities(
168 IntersectCapabilities(*client_capabilities_, host_capabilities_));
[email protected]a5d181f2013-04-19 14:55:37169}
170
[email protected]cba6f812012-03-27 01:01:50171void ClientSession::OnConnectionAuthenticated(
[email protected]ee910fd2011-11-10 18:23:31172 protocol::ConnectionToClient* connection) {
[email protected]86cbe6b2012-04-03 00:56:18173 DCHECK(CalledOnValidThread());
174 DCHECK_EQ(connection_.get(), connection);
[email protected]324b1962013-05-01 19:30:22175 DCHECK(!audio_scheduler_);
[email protected]a5d181f2013-04-19 14:55:37176 DCHECK(!desktop_environment_);
[email protected]324b1962013-05-01 19:30:22177 DCHECK(!input_injector_);
178 DCHECK(!screen_controls_);
179 DCHECK(!video_scheduler_);
[email protected]34df2ab2012-08-19 06:54:23180
[email protected]750ae6b2012-08-20 22:52:40181 auth_input_filter_.set_enabled(true);
182 auth_clipboard_filter_.set_enabled(true);
[email protected]34df2ab2012-08-19 06:54:23183
[email protected]ff3761a12012-05-22 22:29:24184 clipboard_echo_filter_.set_client_stub(connection_->client_stub());
[email protected]58f1ad42013-01-10 23:49:51185 mouse_clamping_filter_.set_video_stub(connection_->video_stub());
[email protected]34df2ab2012-08-19 06:54:23186
[email protected]5dc5b12a2012-06-23 01:05:14187 if (max_duration_ > base::TimeDelta()) {
188 // TODO(simonmorris): Let Disconnect() tell the client that the
189 // disconnection was caused by the session exceeding its maximum duration.
190 max_duration_timer_.Start(FROM_HERE, max_duration_,
[email protected]231316a2013-03-25 06:01:12191 this, &ClientSession::DisconnectSession);
[email protected]5dc5b12a2012-06-23 01:05:14192 }
[email protected]34df2ab2012-08-19 06:54:23193
[email protected]324b1962013-05-01 19:30:22194 // Disconnect the session if the connection was rejected by the host.
195 if (!event_handler_->OnSessionAuthenticated(this)) {
196 DisconnectSession();
197 return;
198 }
[email protected]ce404ca2013-01-16 17:23:53199
[email protected]a5d181f2013-04-19 14:55:37200 // Create the desktop environment.
[email protected]231316a2013-03-25 06:01:12201 desktop_environment_ =
202 desktop_environment_factory_->Create(control_factory_.GetWeakPtr());
[email protected]a5d181f2013-04-19 14:55:37203 host_capabilities_ = desktop_environment_->GetCapabilities();
204
[email protected]324b1962013-05-01 19:30:22205 // Ignore protocol::Capabilities messages from the client if it does not
206 // support any capabilities.
207 if (!connection_->session()->config().SupportsCapabilities()) {
[email protected]a5d181f2013-04-19 14:55:37208 VLOG(1) << "The client does not support any capabilities.";
209
210 client_capabilities_ = make_scoped_ptr(new std::string());
211 desktop_environment_->SetCapabilities(*client_capabilities_);
212 }
[email protected]233bb942013-03-15 07:18:17213
[email protected]231316a2013-03-25 06:01:12214 // Create the object that controls the screen resolution.
215 screen_controls_ = desktop_environment_->CreateScreenControls();
[email protected]61cfdc52013-03-09 03:04:56216
[email protected]324b1962013-05-01 19:30:22217 // Create the event executor.
[email protected]231316a2013-03-25 06:01:12218 input_injector_ = desktop_environment_->CreateInputInjector();
[email protected]eccc2d42013-01-10 19:35:14219
220 // Connect the host clipboard and input stubs.
[email protected]b0b72f112013-03-24 03:42:42221 host_input_filter_.set_input_stub(input_injector_.get());
222 clipboard_echo_filter_.set_host_stub(input_injector_.get());
[email protected]eccc2d42013-01-10 19:35:14223
[email protected]2ce80252012-10-26 07:23:12224 // Create a VideoEncoder based on the session's video channel configuration.
225 scoped_ptr<VideoEncoder> video_encoder =
[email protected]170cba42012-09-12 22:28:39226 CreateVideoEncoder(connection_->session()->config());
[email protected]2ce80252012-10-26 07:23:12227
[email protected]cdd1c9e2012-10-26 21:14:04228 // Create a VideoScheduler to pump frames from the capturer to the client.
[email protected]324b1962013-05-01 19:30:22229 video_scheduler_ = new VideoScheduler(
[email protected]c18ad892012-12-08 03:39:24230 video_capture_task_runner_,
231 video_encode_task_runner_,
232 network_task_runner_,
[email protected]231316a2013-03-25 06:01:12233 desktop_environment_->CreateVideoCapturer(),
[email protected]c18ad892012-12-08 03:39:24234 video_encoder.Pass(),
235 connection_->client_stub(),
[email protected]eccc2d42013-01-10 19:35:14236 &mouse_clamping_filter_);
[email protected]170cba42012-09-12 22:28:39237
[email protected]cdd1c9e2012-10-26 21:14:04238 // Create an AudioScheduler if audio is enabled, to pump audio samples.
[email protected]170cba42012-09-12 22:28:39239 if (connection_->session()->config().is_audio_enabled()) {
240 scoped_ptr<AudioEncoder> audio_encoder =
241 CreateAudioEncoder(connection_->session()->config());
[email protected]324b1962013-05-01 19:30:22242 audio_scheduler_ = new AudioScheduler(
[email protected]032d9dd2012-11-01 17:55:04243 audio_task_runner_,
[email protected]170cba42012-09-12 22:28:39244 network_task_runner_,
[email protected]231316a2013-03-25 06:01:12245 desktop_environment_->CreateAudioCapturer(),
[email protected]170cba42012-09-12 22:28:39246 audio_encoder.Pass(),
247 connection_->audio_stub());
[email protected]170cba42012-09-12 22:28:39248 }
[email protected]324b1962013-05-01 19:30:22249}
250
251void ClientSession::OnConnectionChannelsConnected(
252 protocol::ConnectionToClient* connection) {
253 DCHECK(CalledOnValidThread());
254 DCHECK_EQ(connection_.get(), connection);
255
256 // Negotiate capabilities with the client.
257 if (connection_->session()->config().SupportsCapabilities()) {
258 VLOG(1) << "Host capabilities: " << host_capabilities_;
259
260 protocol::Capabilities capabilities;
261 capabilities.set_capabilities(host_capabilities_);
262 connection_->client_stub()->SetCapabilities(capabilities);
263 }
264
265 // Start the event executor.
266 input_injector_->Start(CreateClipboardProxy());
267 SetDisableInputs(false);
268
269 // Start capturing the screen.
270 video_scheduler_->Start();
271
272 // Start recording audio.
273 if (connection_->session()->config().is_audio_enabled())
274 audio_scheduler_->Start();
[email protected]170cba42012-09-12 22:28:39275
[email protected]cdd1c9e2012-10-26 21:14:04276 // Notify the event handler that all our channels are now connected.
[email protected]cba6f812012-03-27 01:01:50277 event_handler_->OnSessionChannelsConnected(this);
[email protected]ee910fd2011-11-10 18:23:31278}
279
[email protected]cba6f812012-03-27 01:01:50280void ClientSession::OnConnectionClosed(
[email protected]1f249e22011-11-29 20:19:59281 protocol::ConnectionToClient* connection,
[email protected]204a9e32012-03-02 05:42:58282 protocol::ErrorCode error) {
[email protected]ec6411872011-11-11 03:28:55283 DCHECK(CalledOnValidThread());
[email protected]ee910fd2011-11-10 18:23:31284 DCHECK_EQ(connection_.get(), connection);
[email protected]750ae6b2012-08-20 22:52:40285
[email protected]231316a2013-03-25 06:01:12286 // Ignore any further callbacks.
287 control_factory_.InvalidateWeakPtrs();
[email protected]a031c972012-12-27 20:10:40288
[email protected]24a2a9d22012-12-07 09:06:47289 // If the client never authenticated then the session failed.
[email protected]750ae6b2012-08-20 22:52:40290 if (!auth_input_filter_.enabled())
[email protected]1f249e22011-11-29 20:19:59291 event_handler_->OnSessionAuthenticationFailed(this);
[email protected]750ae6b2012-08-20 22:52:40292
293 // Block any further input events from the client.
294 // TODO(wez): Fix ChromotingHost::OnSessionClosed not to check our
295 // is_authenticated(), so that we can disable |auth_*_filter_| here.
296 disable_input_filter_.set_enabled(false);
297 disable_clipboard_filter_.set_enabled(false);
[email protected]86cbe6b2012-04-03 00:56:18298
299 // Ensure that any pressed keys or buttons are released.
300 input_tracker_.ReleaseAll();
301
[email protected]24a2a9d22012-12-07 09:06:47302 // Stop components access the client, audio or video stubs, which are no
303 // longer valid once ConnectionToClient calls OnConnectionClosed().
[email protected]ce404ca2013-01-16 17:23:53304 if (audio_scheduler_) {
305 audio_scheduler_->Stop();
[email protected]24a2a9d22012-12-07 09:06:47306 audio_scheduler_ = NULL;
307 }
[email protected]ce404ca2013-01-16 17:23:53308 if (video_scheduler_) {
309 video_scheduler_->Stop();
[email protected]24a2a9d22012-12-07 09:06:47310 video_scheduler_ = NULL;
311 }
[email protected]ce404ca2013-01-16 17:23:53312
[email protected]24a2a9d22012-12-07 09:06:47313 client_clipboard_factory_.InvalidateWeakPtrs();
[email protected]b0b72f112013-03-24 03:42:42314 input_injector_.reset();
[email protected]231316a2013-03-25 06:01:12315 screen_controls_.reset();
316 desktop_environment_.reset();
[email protected]24a2a9d22012-12-07 09:06:47317
318 // Notify the ChromotingHost that this client is disconnected.
[email protected]ee910fd2011-11-10 18:23:31319 // TODO(sergeyu): Log failure reason?
[email protected]ee910fd2011-11-10 18:23:31320 event_handler_->OnSessionClosed(this);
[email protected]ee910fd2011-11-10 18:23:31321}
322
323void ClientSession::OnSequenceNumberUpdated(
324 protocol::ConnectionToClient* connection, int64 sequence_number) {
[email protected]ec6411872011-11-11 03:28:55325 DCHECK(CalledOnValidThread());
[email protected]ee910fd2011-11-10 18:23:31326 DCHECK_EQ(connection_.get(), connection);
[email protected]170cba42012-09-12 22:28:39327
[email protected]ce404ca2013-01-16 17:23:53328 if (video_scheduler_)
[email protected]2ce80252012-10-26 07:23:12329 video_scheduler_->UpdateSequenceNumber(sequence_number);
[email protected]170cba42012-09-12 22:28:39330
[email protected]ee910fd2011-11-10 18:23:31331 event_handler_->OnSessionSequenceNumber(this, sequence_number);
332}
333
[email protected]17af2ab2012-02-02 04:07:52334void ClientSession::OnRouteChange(
335 protocol::ConnectionToClient* connection,
336 const std::string& channel_name,
[email protected]be451c82012-03-20 22:24:47337 const protocol::TransportRoute& route) {
[email protected]91e4b7f62012-01-25 23:23:02338 DCHECK(CalledOnValidThread());
339 DCHECK_EQ(connection_.get(), connection);
[email protected]be451c82012-03-20 22:24:47340 event_handler_->OnSessionRouteChange(this, channel_name, route);
[email protected]91e4b7f62012-01-25 23:23:02341}
342
[email protected]231316a2013-03-25 06:01:12343const std::string& ClientSession::client_jid() const {
344 return client_jid_;
345}
346
347void ClientSession::DisconnectSession() {
[email protected]ec6411872011-11-11 03:28:55348 DCHECK(CalledOnValidThread());
349 DCHECK(connection_.get());
[email protected]a46bcef2011-11-11 01:27:23350
[email protected]5dc5b12a2012-06-23 01:05:14351 max_duration_timer_.Stop();
[email protected]24a2a9d22012-12-07 09:06:47352
[email protected]86cbe6b2012-04-03 00:56:18353 // This triggers OnConnectionClosed(), and the session may be destroyed
[email protected]a46bcef2011-11-11 01:27:23354 // as the result, so this call must be the last in this method.
355 connection_->Disconnect();
[email protected]44f60762011-03-23 12:13:35356}
357
[email protected]231316a2013-03-25 06:01:12358void ClientSession::OnLocalMouseMoved(const SkIPoint& position) {
[email protected]ec6411872011-11-11 03:28:55359 DCHECK(CalledOnValidThread());
[email protected]231316a2013-03-25 06:01:12360 remote_input_filter_.LocalMouseMoved(position);
[email protected]86cbe6b2012-04-03 00:56:18361}
[email protected]ec6411872011-11-11 03:28:55362
[email protected]86cbe6b2012-04-03 00:56:18363void ClientSession::SetDisableInputs(bool disable_inputs) {
364 DCHECK(CalledOnValidThread());
365
[email protected]750ae6b2012-08-20 22:52:40366 if (disable_inputs)
[email protected]86cbe6b2012-04-03 00:56:18367 input_tracker_.ReleaseAll();
[email protected]750ae6b2012-08-20 22:52:40368
369 disable_input_filter_.set_enabled(!disable_inputs);
370 disable_clipboard_filter_.set_enabled(!disable_inputs);
[email protected]c78669c92011-06-13 22:42:38371}
372
[email protected]7f44ba42012-05-31 20:26:29373scoped_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
374 DCHECK(CalledOnValidThread());
375
376 return scoped_ptr<protocol::ClipboardStub>(
377 new protocol::ClipboardThreadProxy(
378 client_clipboard_factory_.GetWeakPtr(),
379 base::MessageLoopProxy::current()));
380}
381
[email protected]170cba42012-09-12 22:28:39382// TODO(sergeyu): Move this to SessionManager?
383// static
[email protected]2ce80252012-10-26 07:23:12384scoped_ptr<VideoEncoder> ClientSession::CreateVideoEncoder(
[email protected]170cba42012-09-12 22:28:39385 const protocol::SessionConfig& config) {
386 const protocol::ChannelConfig& video_config = config.video_config();
387
388 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
[email protected]2ce80252012-10-26 07:23:12389 return scoped_ptr<VideoEncoder>(new remoting::VideoEncoderVerbatim());
[email protected]170cba42012-09-12 22:28:39390 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) {
[email protected]2ce80252012-10-26 07:23:12391 return scoped_ptr<VideoEncoder>(new remoting::VideoEncoderVp8());
[email protected]170cba42012-09-12 22:28:39392 }
393
394 NOTIMPLEMENTED();
[email protected]2ce80252012-10-26 07:23:12395 return scoped_ptr<VideoEncoder>(NULL);
[email protected]170cba42012-09-12 22:28:39396}
397
398// static
399scoped_ptr<AudioEncoder> ClientSession::CreateAudioEncoder(
400 const protocol::SessionConfig& config) {
401 const protocol::ChannelConfig& audio_config = config.audio_config();
402
403 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
404 return scoped_ptr<AudioEncoder>(new AudioEncoderVerbatim());
405 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_SPEEX) {
406 return scoped_ptr<AudioEncoder>(new AudioEncoderSpeex());
[email protected]a6ccb7722012-10-23 21:10:43407 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) {
408 return scoped_ptr<AudioEncoder>(new AudioEncoderOpus());
[email protected]170cba42012-09-12 22:28:39409 }
410
411 NOTIMPLEMENTED();
412 return scoped_ptr<AudioEncoder>(NULL);
413}
414
[email protected]44f60762011-03-23 12:13:35415} // namespace remoting