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 |