| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/client_session.h" | 5 #include "remoting/host/client_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "remoting/base/capabilities.h" | 15 #include "remoting/base/capabilities.h" |
| 16 #include "remoting/base/constants.h" | 16 #include "remoting/base/constants.h" |
| 17 #include "remoting/base/logging.h" | 17 #include "remoting/base/logging.h" |
| 18 #include "remoting/codec/audio_encoder.h" | |
| 19 #include "remoting/codec/audio_encoder_opus.h" | |
| 20 #include "remoting/codec/audio_encoder_verbatim.h" | |
| 21 #include "remoting/host/audio_capturer.h" | 18 #include "remoting/host/audio_capturer.h" |
| 22 #include "remoting/host/audio_pump.h" | |
| 23 #include "remoting/host/desktop_environment.h" | 19 #include "remoting/host/desktop_environment.h" |
| 24 #include "remoting/host/host_extension_session.h" | 20 #include "remoting/host/host_extension_session.h" |
| 25 #include "remoting/host/input_injector.h" | 21 #include "remoting/host/input_injector.h" |
| 26 #include "remoting/host/mouse_shape_pump.h" | 22 #include "remoting/host/mouse_shape_pump.h" |
| 27 #include "remoting/host/screen_controls.h" | 23 #include "remoting/host/screen_controls.h" |
| 28 #include "remoting/host/screen_resolution.h" | 24 #include "remoting/host/screen_resolution.h" |
| 29 #include "remoting/proto/control.pb.h" | 25 #include "remoting/proto/control.pb.h" |
| 30 #include "remoting/proto/event.pb.h" | 26 #include "remoting/proto/event.pb.h" |
| 27 #include "remoting/protocol/audio_send_stream.h" |
| 31 #include "remoting/protocol/client_stub.h" | 28 #include "remoting/protocol/client_stub.h" |
| 32 #include "remoting/protocol/clipboard_thread_proxy.h" | 29 #include "remoting/protocol/clipboard_thread_proxy.h" |
| 33 #include "remoting/protocol/pairing_registry.h" | 30 #include "remoting/protocol/pairing_registry.h" |
| 34 #include "remoting/protocol/session.h" | 31 #include "remoting/protocol/session.h" |
| 35 #include "remoting/protocol/session_config.h" | 32 #include "remoting/protocol/session_config.h" |
| 36 #include "remoting/protocol/video_frame_pump.h" | 33 #include "remoting/protocol/video_frame_pump.h" |
| 37 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" | 34 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" |
| 38 | 35 |
| 39 namespace remoting { | 36 namespace remoting { |
| 40 | 37 |
| 41 namespace { | 38 namespace { |
| 42 | 39 |
| 43 // Name of command-line flag to disable use of I444 by default. | 40 // Name of command-line flag to disable use of I444 by default. |
| 44 const char kDisableI444SwitchName[] = "disable-i444"; | 41 const char kDisableI444SwitchName[] = "disable-i444"; |
| 45 | 42 |
| 46 std::unique_ptr<AudioEncoder> CreateAudioEncoder( | |
| 47 const protocol::SessionConfig& config) { | |
| 48 const protocol::ChannelConfig& audio_config = config.audio_config(); | |
| 49 | |
| 50 if (audio_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { | |
| 51 return base::WrapUnique(new AudioEncoderVerbatim()); | |
| 52 } else if (audio_config.codec == protocol::ChannelConfig::CODEC_OPUS) { | |
| 53 return base::WrapUnique(new AudioEncoderOpus()); | |
| 54 } | |
| 55 | |
| 56 NOTREACHED(); | |
| 57 return nullptr; | |
| 58 } | |
| 59 | |
| 60 } // namespace | 43 } // namespace |
| 61 | 44 |
| 62 ClientSession::ClientSession( | 45 ClientSession::ClientSession( |
| 63 EventHandler* event_handler, | 46 EventHandler* event_handler, |
| 64 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, | |
| 65 std::unique_ptr<protocol::ConnectionToClient> connection, | 47 std::unique_ptr<protocol::ConnectionToClient> connection, |
| 66 DesktopEnvironmentFactory* desktop_environment_factory, | 48 DesktopEnvironmentFactory* desktop_environment_factory, |
| 67 const base::TimeDelta& max_duration, | 49 const base::TimeDelta& max_duration, |
| 68 scoped_refptr<protocol::PairingRegistry> pairing_registry, | 50 scoped_refptr<protocol::PairingRegistry> pairing_registry, |
| 69 const std::vector<HostExtension*>& extensions) | 51 const std::vector<HostExtension*>& extensions) |
| 70 : event_handler_(event_handler), | 52 : event_handler_(event_handler), |
| 71 connection_(std::move(connection)), | 53 connection_(std::move(connection)), |
| 72 client_jid_(connection_->session()->jid()), | 54 client_jid_(connection_->session()->jid()), |
| 73 desktop_environment_factory_(desktop_environment_factory), | 55 desktop_environment_factory_(desktop_environment_factory), |
| 74 input_tracker_(&host_input_filter_), | 56 input_tracker_(&host_input_filter_), |
| 75 remote_input_filter_(&input_tracker_), | 57 remote_input_filter_(&input_tracker_), |
| 76 mouse_clamping_filter_(&remote_input_filter_), | 58 mouse_clamping_filter_(&remote_input_filter_), |
| 77 disable_input_filter_(&mouse_clamping_filter_), | 59 disable_input_filter_(&mouse_clamping_filter_), |
| 78 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), | 60 disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), |
| 79 client_clipboard_factory_(clipboard_echo_filter_.client_filter()), | 61 client_clipboard_factory_(clipboard_echo_filter_.client_filter()), |
| 80 max_duration_(max_duration), | 62 max_duration_(max_duration), |
| 81 audio_task_runner_(audio_task_runner), | |
| 82 pairing_registry_(pairing_registry), | 63 pairing_registry_(pairing_registry), |
| 83 // Note that |lossless_video_color_| defaults to true, but actually only | 64 // Note that |lossless_video_color_| defaults to true, but actually only |
| 84 // controls VP9 video stream color quality. | 65 // controls VP9 video stream color quality. |
| 85 lossless_video_color_(!base::CommandLine::ForCurrentProcess()->HasSwitch( | 66 lossless_video_color_(!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 86 kDisableI444SwitchName)), | 67 kDisableI444SwitchName)), |
| 87 weak_factory_(this) { | 68 weak_factory_(this) { |
| 88 connection_->SetEventHandler(this); | 69 connection_->SetEventHandler(this); |
| 89 | 70 |
| 90 // Create a manager for the configured extensions, if any. | 71 // Create a manager for the configured extensions, if any. |
| 91 extension_manager_.reset(new HostExtensionSessionManager(extensions, this)); | 72 extension_manager_.reset(new HostExtensionSessionManager(extensions, this)); |
| 92 | 73 |
| 93 #if defined(OS_WIN) | 74 #if defined(OS_WIN) |
| 94 // LocalInputMonitorWin filters out an echo of the injected input before it | 75 // LocalInputMonitorWin filters out an echo of the injected input before it |
| 95 // reaches |remote_input_filter_|. | 76 // reaches |remote_input_filter_|. |
| 96 remote_input_filter_.SetExpectLocalEcho(false); | 77 remote_input_filter_.SetExpectLocalEcho(false); |
| 97 #endif // defined(OS_WIN) | 78 #endif // defined(OS_WIN) |
| 98 } | 79 } |
| 99 | 80 |
| 100 ClientSession::~ClientSession() { | 81 ClientSession::~ClientSession() { |
| 101 DCHECK(CalledOnValidThread()); | 82 DCHECK(CalledOnValidThread()); |
| 102 DCHECK(!audio_pump_); | 83 DCHECK(!audio_stream_); |
| 103 DCHECK(!desktop_environment_); | 84 DCHECK(!desktop_environment_); |
| 104 DCHECK(!input_injector_); | 85 DCHECK(!input_injector_); |
| 105 DCHECK(!screen_controls_); | 86 DCHECK(!screen_controls_); |
| 106 DCHECK(!video_stream_); | 87 DCHECK(!video_stream_); |
| 107 | 88 |
| 108 connection_.reset(); | 89 connection_.reset(); |
| 109 } | 90 } |
| 110 | 91 |
| 111 void ClientSession::NotifyClientResolution( | 92 void ClientSession::NotifyClientResolution( |
| 112 const protocol::ClientResolution& resolution) { | 93 const protocol::ClientResolution& resolution) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 video_stream_->SetLosslessColor(lossless_video_color_); | 136 video_stream_->SetLosslessColor(lossless_video_color_); |
| 156 } | 137 } |
| 157 } | 138 } |
| 158 | 139 |
| 159 void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) { | 140 void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) { |
| 160 DCHECK(CalledOnValidThread()); | 141 DCHECK(CalledOnValidThread()); |
| 161 | 142 |
| 162 if (audio_control.has_enable()) { | 143 if (audio_control.has_enable()) { |
| 163 VLOG(1) << "Received AudioControl (enable=" | 144 VLOG(1) << "Received AudioControl (enable=" |
| 164 << audio_control.enable() << ")"; | 145 << audio_control.enable() << ")"; |
| 165 if (audio_pump_) | 146 if (audio_stream_) |
| 166 audio_pump_->Pause(!audio_control.enable()); | 147 audio_stream_->Pause(!audio_control.enable()); |
| 167 } | 148 } |
| 168 } | 149 } |
| 169 | 150 |
| 170 void ClientSession::SetCapabilities( | 151 void ClientSession::SetCapabilities( |
| 171 const protocol::Capabilities& capabilities) { | 152 const protocol::Capabilities& capabilities) { |
| 172 DCHECK(CalledOnValidThread()); | 153 DCHECK(CalledOnValidThread()); |
| 173 | 154 |
| 174 // Ignore all the messages but the 1st one. | 155 // Ignore all the messages but the 1st one. |
| 175 if (client_capabilities_) { | 156 if (client_capabilities_) { |
| 176 LOG(WARNING) << "protocol::Capabilities has been received already."; | 157 LOG(WARNING) << "protocol::Capabilities has been received already."; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 | 206 |
| 226 void ClientSession::OnConnectionAuthenticating( | 207 void ClientSession::OnConnectionAuthenticating( |
| 227 protocol::ConnectionToClient* connection) { | 208 protocol::ConnectionToClient* connection) { |
| 228 event_handler_->OnSessionAuthenticating(this); | 209 event_handler_->OnSessionAuthenticating(this); |
| 229 } | 210 } |
| 230 | 211 |
| 231 void ClientSession::OnConnectionAuthenticated( | 212 void ClientSession::OnConnectionAuthenticated( |
| 232 protocol::ConnectionToClient* connection) { | 213 protocol::ConnectionToClient* connection) { |
| 233 DCHECK(CalledOnValidThread()); | 214 DCHECK(CalledOnValidThread()); |
| 234 DCHECK_EQ(connection_.get(), connection); | 215 DCHECK_EQ(connection_.get(), connection); |
| 235 DCHECK(!audio_pump_); | 216 DCHECK(!audio_stream_); |
| 236 DCHECK(!desktop_environment_); | 217 DCHECK(!desktop_environment_); |
| 237 DCHECK(!input_injector_); | 218 DCHECK(!input_injector_); |
| 238 DCHECK(!screen_controls_); | 219 DCHECK(!screen_controls_); |
| 239 DCHECK(!video_stream_); | 220 DCHECK(!video_stream_); |
| 240 | 221 |
| 241 is_authenticated_ = true; | 222 is_authenticated_ = true; |
| 242 | 223 |
| 243 if (max_duration_ > base::TimeDelta()) { | 224 if (max_duration_ > base::TimeDelta()) { |
| 244 max_duration_timer_.Start( | 225 max_duration_timer_.Start( |
| 245 FROM_HERE, max_duration_, | 226 FROM_HERE, max_duration_, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 // Connect the host input stubs. | 258 // Connect the host input stubs. |
| 278 connection_->set_input_stub(&disable_input_filter_); | 259 connection_->set_input_stub(&disable_input_filter_); |
| 279 host_input_filter_.set_input_stub(input_injector_.get()); | 260 host_input_filter_.set_input_stub(input_injector_.get()); |
| 280 | 261 |
| 281 // Connect the clipboard stubs. | 262 // Connect the clipboard stubs. |
| 282 connection_->set_clipboard_stub(&disable_clipboard_filter_); | 263 connection_->set_clipboard_stub(&disable_clipboard_filter_); |
| 283 clipboard_echo_filter_.set_host_stub(input_injector_.get()); | 264 clipboard_echo_filter_.set_host_stub(input_injector_.get()); |
| 284 clipboard_echo_filter_.set_client_stub(connection_->client_stub()); | 265 clipboard_echo_filter_.set_client_stub(connection_->client_stub()); |
| 285 } | 266 } |
| 286 | 267 |
| 287 void ClientSession::CreateVideoStreams( | 268 void ClientSession::CreateMediaStreams( |
| 288 protocol::ConnectionToClient* connection) { | 269 protocol::ConnectionToClient* connection) { |
| 289 DCHECK(CalledOnValidThread()); | 270 DCHECK(CalledOnValidThread()); |
| 290 DCHECK_EQ(connection_.get(), connection); | 271 DCHECK_EQ(connection_.get(), connection); |
| 291 | 272 |
| 292 // Create a VideoStream to pump frames from the capturer to the client. | 273 // Create a VideoStream to pump frames from the capturer to the client. |
| 293 video_stream_ = connection_->StartVideoStream( | 274 video_stream_ = connection_->StartVideoStream( |
| 294 desktop_environment_->CreateVideoCapturer()); | 275 desktop_environment_->CreateVideoCapturer()); |
| 295 | 276 |
| 277 // Create a AudioStream to pump audio from the capturer to the client. |
| 278 audio_stream_ = connection_->StartAudioStream( |
| 279 desktop_environment_->CreateAudioCapturer()); |
| 280 |
| 296 video_stream_->SetObserver(this); | 281 video_stream_->SetObserver(this); |
| 297 | 282 |
| 298 // Apply video-control parameters to the new stream. | 283 // Apply video-control parameters to the new stream. |
| 299 video_stream_->SetLosslessEncode(lossless_video_encode_); | 284 video_stream_->SetLosslessEncode(lossless_video_encode_); |
| 300 video_stream_->SetLosslessColor(lossless_video_color_); | 285 video_stream_->SetLosslessColor(lossless_video_color_); |
| 301 | 286 |
| 302 // Pause capturing if necessary. | 287 // Pause capturing if necessary. |
| 303 video_stream_->Pause(pause_video_); | 288 video_stream_->Pause(pause_video_); |
| 304 } | 289 } |
| 305 | 290 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 319 | 304 |
| 320 // Start the event executor. | 305 // Start the event executor. |
| 321 input_injector_->Start(CreateClipboardProxy()); | 306 input_injector_->Start(CreateClipboardProxy()); |
| 322 SetDisableInputs(false); | 307 SetDisableInputs(false); |
| 323 | 308 |
| 324 // Create MouseShapePump to send mouse cursor shape. | 309 // Create MouseShapePump to send mouse cursor shape. |
| 325 mouse_shape_pump_.reset( | 310 mouse_shape_pump_.reset( |
| 326 new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(), | 311 new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(), |
| 327 connection_->client_stub())); | 312 connection_->client_stub())); |
| 328 | 313 |
| 329 // Create an AudioPump if audio is enabled, to pump audio samples. | |
| 330 if (connection_->session()->config().is_audio_enabled()) { | |
| 331 std::unique_ptr<AudioEncoder> audio_encoder = | |
| 332 CreateAudioEncoder(connection_->session()->config()); | |
| 333 audio_pump_.reset(new AudioPump( | |
| 334 audio_task_runner_, desktop_environment_->CreateAudioCapturer(), | |
| 335 std::move(audio_encoder), connection_->audio_stub())); | |
| 336 } | |
| 337 | |
| 338 if (pending_video_layout_message_) { | 314 if (pending_video_layout_message_) { |
| 339 connection_->client_stub()->SetVideoLayout(*pending_video_layout_message_); | 315 connection_->client_stub()->SetVideoLayout(*pending_video_layout_message_); |
| 340 pending_video_layout_message_.reset(); | 316 pending_video_layout_message_.reset(); |
| 341 } | 317 } |
| 342 | 318 |
| 343 // Notify the event handler that all our channels are now connected. | 319 // Notify the event handler that all our channels are now connected. |
| 344 event_handler_->OnSessionChannelsConnected(this); | 320 event_handler_->OnSessionChannelsConnected(this); |
| 345 } | 321 } |
| 346 | 322 |
| 347 void ClientSession::OnConnectionClosed( | 323 void ClientSession::OnConnectionClosed( |
| 348 protocol::ConnectionToClient* connection, | 324 protocol::ConnectionToClient* connection, |
| 349 protocol::ErrorCode error) { | 325 protocol::ErrorCode error) { |
| 350 DCHECK(CalledOnValidThread()); | 326 DCHECK(CalledOnValidThread()); |
| 351 DCHECK_EQ(connection_.get(), connection); | 327 DCHECK_EQ(connection_.get(), connection); |
| 352 | 328 |
| 353 HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error; | 329 HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error; |
| 354 | 330 |
| 355 // Ignore any further callbacks. | 331 // Ignore any further callbacks. |
| 356 weak_factory_.InvalidateWeakPtrs(); | 332 weak_factory_.InvalidateWeakPtrs(); |
| 357 | 333 |
| 358 // If the client never authenticated then the session failed. | 334 // If the client never authenticated then the session failed. |
| 359 if (!is_authenticated_) | 335 if (!is_authenticated_) |
| 360 event_handler_->OnSessionAuthenticationFailed(this); | 336 event_handler_->OnSessionAuthenticationFailed(this); |
| 361 | 337 |
| 362 // Ensure that any pressed keys or buttons are released. | 338 // Ensure that any pressed keys or buttons are released. |
| 363 input_tracker_.ReleaseAll(); | 339 input_tracker_.ReleaseAll(); |
| 364 | 340 |
| 365 // Stop components access the client, audio or video stubs, which are no | 341 // Stop components access the client, audio or video stubs, which are no |
| 366 // longer valid once ConnectionToClient calls OnConnectionClosed(). | 342 // longer valid once ConnectionToClient calls OnConnectionClosed(). |
| 367 audio_pump_.reset(); | 343 audio_stream_.reset(); |
| 368 video_stream_.reset(); | 344 video_stream_.reset(); |
| 369 mouse_shape_pump_.reset(); | 345 mouse_shape_pump_.reset(); |
| 370 client_clipboard_factory_.InvalidateWeakPtrs(); | 346 client_clipboard_factory_.InvalidateWeakPtrs(); |
| 371 input_injector_.reset(); | 347 input_injector_.reset(); |
| 372 screen_controls_.reset(); | 348 screen_controls_.reset(); |
| 373 desktop_environment_.reset(); | 349 desktop_environment_.reset(); |
| 374 | 350 |
| 375 // Notify the ChromotingHost that this client is disconnected. | 351 // Notify the ChromotingHost that this client is disconnected. |
| 376 event_handler_->OnSessionClosed(this); | 352 event_handler_->OnSessionClosed(this); |
| 377 } | 353 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 463 } |
| 488 } | 464 } |
| 489 | 465 |
| 490 void ClientSession::OnVideoFrameSent(protocol::VideoStream* stream, | 466 void ClientSession::OnVideoFrameSent(protocol::VideoStream* stream, |
| 491 uint32_t frame_id, | 467 uint32_t frame_id, |
| 492 int64_t input_event_timestamp) { | 468 int64_t input_event_timestamp) { |
| 493 // TODO(sergeyu): Send a message to the client to notify about the new frame. | 469 // TODO(sergeyu): Send a message to the client to notify about the new frame. |
| 494 } | 470 } |
| 495 | 471 |
| 496 } // namespace remoting | 472 } // namespace remoting |
| OLD | NEW |