| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <utility> | 5 #include <utility> |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
| 15 #include "base/task_runner_util.h" |
| 15 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
| 16 #include "jingle/glue/thread_wrapper.h" | 17 #include "jingle/glue/thread_wrapper.h" |
| 17 #include "net/base/test_data_directory.h" | 18 #include "net/base/test_data_directory.h" |
| 18 #include "net/url_request/url_request_context_getter.h" | 19 #include "net/url_request/url_request_context_getter.h" |
| 19 #include "remoting/base/rsa_key_pair.h" | 20 #include "remoting/base/rsa_key_pair.h" |
| 20 #include "remoting/client/audio_player.h" | 21 #include "remoting/client/audio_player.h" |
| 21 #include "remoting/client/chromoting_client.h" | 22 #include "remoting/client/chromoting_client.h" |
| 22 #include "remoting/client/client_context.h" | 23 #include "remoting/client/client_context.h" |
| 23 #include "remoting/client/client_user_interface.h" | 24 #include "remoting/client/client_user_interface.h" |
| 25 #include "remoting/codec/video_decoder_verbatim.h" |
| 26 #include "remoting/codec/video_decoder_vpx.h" |
| 24 #include "remoting/host/chromoting_host.h" | 27 #include "remoting/host/chromoting_host.h" |
| 25 #include "remoting/host/chromoting_host_context.h" | 28 #include "remoting/host/chromoting_host_context.h" |
| 26 #include "remoting/host/fake_desktop_environment.h" | 29 #include "remoting/host/fake_desktop_environment.h" |
| 30 #include "remoting/protocol/frame_consumer.h" |
| 27 #include "remoting/protocol/jingle_session_manager.h" | 31 #include "remoting/protocol/jingle_session_manager.h" |
| 28 #include "remoting/protocol/me2me_host_authenticator_factory.h" | 32 #include "remoting/protocol/me2me_host_authenticator_factory.h" |
| 29 #include "remoting/protocol/negotiating_client_authenticator.h" | 33 #include "remoting/protocol/negotiating_client_authenticator.h" |
| 30 #include "remoting/protocol/session_config.h" | 34 #include "remoting/protocol/session_config.h" |
| 31 #include "remoting/protocol/transport_context.h" | 35 #include "remoting/protocol/transport_context.h" |
| 32 #include "remoting/protocol/video_frame_pump.h" | 36 #include "remoting/protocol/video_frame_pump.h" |
| 33 #include "remoting/protocol/video_renderer.h" | 37 #include "remoting/protocol/video_renderer.h" |
| 34 #include "remoting/signaling/fake_signal_strategy.h" | 38 #include "remoting/signaling/fake_signal_strategy.h" |
| 39 #include "remoting/test/cyclic_frame_generator.h" |
| 35 #include "remoting/test/fake_network_dispatcher.h" | 40 #include "remoting/test/fake_network_dispatcher.h" |
| 36 #include "remoting/test/fake_port_allocator.h" | 41 #include "remoting/test/fake_port_allocator.h" |
| 37 #include "remoting/test/fake_socket_factory.h" | 42 #include "remoting/test/fake_socket_factory.h" |
| 38 #include "testing/gtest/include/gtest/gtest.h" | 43 #include "testing/gtest/include/gtest/gtest.h" |
| 39 | 44 |
| 40 namespace remoting { | 45 namespace remoting { |
| 41 | 46 |
| 42 using protocol::ChannelConfig; | 47 using protocol::ChannelConfig; |
| 43 | 48 |
| 49 namespace { |
| 50 |
| 44 const char kHostJid[] = "host_jid@example.com/host"; | 51 const char kHostJid[] = "host_jid@example.com/host"; |
| 45 const char kHostOwner[] = "jane.doe@example.com"; | 52 const char kHostOwner[] = "jane.doe@example.com"; |
| 46 const char kClientJid[] = "jane.doe@example.com/client"; | 53 const char kClientJid[] = "jane.doe@example.com/client"; |
| 47 | 54 |
| 48 struct NetworkPerformanceParams { | 55 struct NetworkPerformanceParams { |
| 49 NetworkPerformanceParams(int bandwidth, | 56 NetworkPerformanceParams(int bandwidth, |
| 50 int max_buffers, | 57 int max_buffers, |
| 51 double latency_average_ms, | 58 double latency_average_ms, |
| 52 double latency_stddev_ms, | 59 double latency_stddev_ms, |
| 53 double out_of_order_rate) | 60 double out_of_order_rate) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 66 | 73 |
| 67 class FakeCursorShapeStub : public protocol::CursorShapeStub { | 74 class FakeCursorShapeStub : public protocol::CursorShapeStub { |
| 68 public: | 75 public: |
| 69 FakeCursorShapeStub() {} | 76 FakeCursorShapeStub() {} |
| 70 ~FakeCursorShapeStub() override {} | 77 ~FakeCursorShapeStub() override {} |
| 71 | 78 |
| 72 // protocol::CursorShapeStub interface. | 79 // protocol::CursorShapeStub interface. |
| 73 void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override{}; | 80 void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override{}; |
| 74 }; | 81 }; |
| 75 | 82 |
| 83 scoped_ptr<webrtc::DesktopFrame> DoDecodeFrame( |
| 84 VideoDecoder* decoder, |
| 85 VideoPacket* packet, |
| 86 scoped_ptr<webrtc::DesktopFrame> frame) { |
| 87 if (!decoder->DecodePacket(*packet, frame.get())) |
| 88 frame.reset(); |
| 89 return frame; |
| 90 } |
| 91 |
| 92 } // namespace |
| 93 |
| 76 class ProtocolPerfTest | 94 class ProtocolPerfTest |
| 77 : public testing::Test, | 95 : public testing::Test, |
| 78 public testing::WithParamInterface<NetworkPerformanceParams>, | 96 public testing::WithParamInterface<NetworkPerformanceParams>, |
| 79 public ClientUserInterface, | 97 public ClientUserInterface, |
| 80 public protocol::VideoRenderer, | 98 public protocol::VideoRenderer, |
| 81 public protocol::VideoStub, | 99 public protocol::VideoStub, |
| 100 public protocol::FrameConsumer, |
| 82 public HostStatusObserver { | 101 public HostStatusObserver { |
| 83 public: | 102 public: |
| 84 ProtocolPerfTest() | 103 ProtocolPerfTest() |
| 85 : host_thread_("host"), | 104 : host_thread_("host"), |
| 86 capture_thread_("capture"), | 105 capture_thread_("capture"), |
| 87 encode_thread_("encode") { | 106 encode_thread_("encode"), |
| 107 decode_thread_("decode") { |
| 88 protocol::VideoFramePump::EnableTimestampsForTests(); | 108 protocol::VideoFramePump::EnableTimestampsForTests(); |
| 89 host_thread_.StartWithOptions( | 109 host_thread_.StartWithOptions( |
| 90 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 110 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
| 91 capture_thread_.Start(); | 111 capture_thread_.Start(); |
| 92 encode_thread_.Start(); | 112 encode_thread_.Start(); |
| 113 decode_thread_.Start(); |
| 93 } | 114 } |
| 94 | 115 |
| 95 virtual ~ProtocolPerfTest() { | 116 virtual ~ProtocolPerfTest() { |
| 96 host_thread_.task_runner()->DeleteSoon(FROM_HERE, host_.release()); | 117 host_thread_.task_runner()->DeleteSoon(FROM_HERE, host_.release()); |
| 97 host_thread_.task_runner()->DeleteSoon(FROM_HERE, | 118 host_thread_.task_runner()->DeleteSoon(FROM_HERE, |
| 98 host_signaling_.release()); | 119 host_signaling_.release()); |
| 99 message_loop_.RunUntilIdle(); | 120 message_loop_.RunUntilIdle(); |
| 100 } | 121 } |
| 101 | 122 |
| 102 // ClientUserInterface interface. | 123 // ClientUserInterface interface. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 116 const protocol::PairingResponse& pairing_response) override {} | 137 const protocol::PairingResponse& pairing_response) override {} |
| 117 void DeliverHostMessage(const protocol::ExtensionMessage& message) override {} | 138 void DeliverHostMessage(const protocol::ExtensionMessage& message) override {} |
| 118 protocol::ClipboardStub* GetClipboardStub() override { return nullptr; } | 139 protocol::ClipboardStub* GetClipboardStub() override { return nullptr; } |
| 119 protocol::CursorShapeStub* GetCursorShapeStub() override { | 140 protocol::CursorShapeStub* GetCursorShapeStub() override { |
| 120 return &cursor_shape_stub_; | 141 return &cursor_shape_stub_; |
| 121 } | 142 } |
| 122 | 143 |
| 123 // VideoRenderer interface. | 144 // VideoRenderer interface. |
| 124 void OnSessionConfig(const protocol::SessionConfig& config) override {} | 145 void OnSessionConfig(const protocol::SessionConfig& config) override {} |
| 125 protocol::VideoStub* GetVideoStub() override { return this; } | 146 protocol::VideoStub* GetVideoStub() override { return this; } |
| 126 protocol::FrameConsumer* GetFrameConsumer() override { | 147 protocol::FrameConsumer* GetFrameConsumer() override { return this; } |
| 127 NOTREACHED(); | |
| 128 return nullptr; | |
| 129 } | |
| 130 | 148 |
| 131 // protocol::VideoStub interface. | 149 // protocol::VideoStub interface. |
| 132 void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet, | 150 void ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
| 133 const base::Closure& done) override { | 151 const base::Closure& done) override { |
| 134 if (video_packet->data().empty()) { | 152 if (packet->data().empty()) { |
| 135 // Ignore keep-alive packets | 153 // Ignore keep-alive packets |
| 136 done.Run(); | 154 done.Run(); |
| 137 return; | 155 return; |
| 138 } | 156 } |
| 139 | 157 |
| 140 last_video_packet_ = std::move(video_packet); | 158 if (packet->format().has_screen_width() && |
| 159 packet->format().has_screen_height()) { |
| 160 frame_size_.set(packet->format().screen_width(), |
| 161 packet->format().screen_height()); |
| 162 } |
| 141 | 163 |
| 164 scoped_ptr<webrtc::DesktopFrame> frame( |
| 165 new webrtc::BasicDesktopFrame(frame_size_)); |
| 166 base::PostTaskAndReplyWithResult( |
| 167 decode_thread_.task_runner().get(), FROM_HERE, |
| 168 base::Bind(&DoDecodeFrame, video_decoder_.get(), packet.get(), |
| 169 base::Passed(&frame)), |
| 170 base::Bind(&ProtocolPerfTest::OnFrameDecoded, base::Unretained(this), |
| 171 base::Passed(&packet), done)); |
| 172 } |
| 173 |
| 174 void OnFrameDecoded(scoped_ptr<VideoPacket> packet, |
| 175 const base::Closure& done, |
| 176 scoped_ptr<webrtc::DesktopFrame> frame) { |
| 177 last_video_packet_ = std::move(packet); |
| 178 DrawFrame(std::move(frame), done); |
| 179 } |
| 180 |
| 181 // protocol::FrameConsumer interface. |
| 182 scoped_ptr<webrtc::DesktopFrame> AllocateFrame( |
| 183 const webrtc::DesktopSize& size) override { |
| 184 return make_scoped_ptr(new webrtc::BasicDesktopFrame(size)); |
| 185 } |
| 186 |
| 187 void DrawFrame(scoped_ptr<webrtc::DesktopFrame> frame, |
| 188 const base::Closure& done) override { |
| 189 last_video_frame_ = std::move(frame); |
| 142 if (!on_frame_task_.is_null()) | 190 if (!on_frame_task_.is_null()) |
| 143 on_frame_task_.Run(); | 191 on_frame_task_.Run(); |
| 192 if (!done.is_null()) |
| 193 done.Run(); |
| 194 } |
| 144 | 195 |
| 145 done.Run(); | 196 protocol::FrameConsumer::PixelFormat GetPixelFormat() override { |
| 197 return FORMAT_BGRA; |
| 146 } | 198 } |
| 147 | 199 |
| 148 // HostStatusObserver interface. | 200 // HostStatusObserver interface. |
| 149 void OnClientConnected(const std::string& jid) override { | 201 void OnClientConnected(const std::string& jid) override { |
| 150 message_loop_.PostTask( | 202 message_loop_.PostTask( |
| 151 FROM_HERE, | 203 FROM_HERE, |
| 152 base::Bind(&ProtocolPerfTest::OnHostConnectedMainThread, | 204 base::Bind(&ProtocolPerfTest::OnHostConnectedMainThread, |
| 153 base::Unretained(this))); | 205 base::Unretained(this))); |
| 154 } | 206 } |
| 155 | 207 |
| 156 protected: | 208 protected: |
| 157 void WaitConnected() { | 209 void WaitConnected() { |
| 158 client_connected_ = false; | 210 client_connected_ = false; |
| 159 host_connected_ = false; | 211 host_connected_ = false; |
| 160 | 212 |
| 161 connecting_loop_.reset(new base::RunLoop()); | 213 connecting_loop_.reset(new base::RunLoop()); |
| 162 connecting_loop_->Run(); | 214 connecting_loop_->Run(); |
| 163 | 215 |
| 164 ASSERT_TRUE(client_connected_ && host_connected_); | 216 ASSERT_TRUE(client_connected_ && host_connected_); |
| 165 } | 217 } |
| 166 | 218 |
| 167 void OnHostConnectedMainThread() { | 219 void OnHostConnectedMainThread() { |
| 168 host_connected_ = true; | 220 host_connected_ = true; |
| 169 if (client_connected_) | 221 if (client_connected_) |
| 170 connecting_loop_->Quit(); | 222 connecting_loop_->Quit(); |
| 171 } | 223 } |
| 172 | 224 |
| 173 void ReceiveFrame(base::TimeDelta* latency) { | 225 scoped_ptr<webrtc::DesktopFrame> ReceiveFrame() { |
| 226 last_video_frame_.reset(); |
| 227 |
| 174 waiting_frames_loop_.reset(new base::RunLoop()); | 228 waiting_frames_loop_.reset(new base::RunLoop()); |
| 175 on_frame_task_ = waiting_frames_loop_->QuitClosure(); | 229 on_frame_task_ = waiting_frames_loop_->QuitClosure(); |
| 176 waiting_frames_loop_->Run(); | 230 waiting_frames_loop_->Run(); |
| 177 | 231 |
| 232 EXPECT_TRUE(last_video_frame_); |
| 233 return std::move(last_video_frame_); |
| 234 } |
| 235 |
| 236 void ReceiveFrameAndGetLatency(base::TimeDelta* latency) { |
| 237 last_video_packet_.reset(); |
| 238 |
| 239 ReceiveFrame(); |
| 240 |
| 178 if (latency) { | 241 if (latency) { |
| 179 base::TimeTicks timestamp = | 242 base::TimeTicks timestamp = |
| 180 base::TimeTicks::FromInternalValue(last_video_packet_->timestamp()); | 243 base::TimeTicks::FromInternalValue(last_video_packet_->timestamp()); |
| 181 *latency = base::TimeTicks::Now() - timestamp; | 244 *latency = base::TimeTicks::Now() - timestamp; |
| 182 } | 245 } |
| 183 } | 246 } |
| 184 | 247 |
| 185 void ReceiveFrames(int frames, base::TimeDelta* max_latency) { | 248 void ReceiveMultipleFramesAndGetMaxLatency(int frames, |
| 249 base::TimeDelta* max_latency) { |
| 186 if (max_latency) | 250 if (max_latency) |
| 187 *max_latency = base::TimeDelta(); | 251 *max_latency = base::TimeDelta(); |
| 188 | 252 |
| 189 for (int i = 0; i < frames; ++i) { | 253 for (int i = 0; i < frames; ++i) { |
| 190 base::TimeDelta latency; | 254 base::TimeDelta latency; |
| 191 | 255 |
| 192 ReceiveFrame(&latency); | 256 ReceiveFrameAndGetLatency(&latency); |
| 193 | 257 |
| 194 if (max_latency && latency > *max_latency) { | 258 if (max_latency && latency > *max_latency) { |
| 195 *max_latency = latency; | 259 *max_latency = latency; |
| 196 } | 260 } |
| 197 } | 261 } |
| 198 } | 262 } |
| 199 | 263 |
| 200 // Creates test host and client and starts connection between them. Caller | 264 // Creates test host and client and starts connection between them. Caller |
| 201 // should call WaitConnected() to wait until connection is established. The | 265 // should call WaitConnected() to wait until connection is established. The |
| 202 // host is started on |host_thread_| while the client works on the main | 266 // host is started on |host_thread_| while the client works on the main |
| 203 // thread. | 267 // thread. |
| 204 void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) { | 268 void StartHostAndClient(bool use_webrtc, |
| 269 protocol::ChannelConfig::Codec video_codec) { |
| 205 fake_network_dispatcher_ = new FakeNetworkDispatcher(); | 270 fake_network_dispatcher_ = new FakeNetworkDispatcher(); |
| 206 | 271 |
| 207 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); | 272 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); |
| 208 | 273 |
| 209 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | 274 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
| 210 | 275 |
| 211 protocol_config_ = protocol::CandidateSessionConfig::CreateDefault(); | 276 protocol_config_ = protocol::CandidateSessionConfig::CreateDefault(); |
| 212 protocol_config_->DisableAudioChannel(); | 277 protocol_config_->DisableAudioChannel(); |
| 213 protocol_config_->mutable_video_configs()->clear(); | 278 protocol_config_->mutable_video_configs()->clear(); |
| 214 protocol_config_->mutable_video_configs()->push_back( | 279 protocol_config_->mutable_video_configs()->push_back( |
| 215 protocol::ChannelConfig( | 280 protocol::ChannelConfig( |
| 216 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); | 281 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); |
| 282 protocol_config_->set_webrtc_supported(use_webrtc); |
| 283 protocol_config_->set_ice_supported(!use_webrtc); |
| 284 |
| 285 switch (video_codec) { |
| 286 case ChannelConfig::CODEC_VERBATIM: |
| 287 video_decoder_.reset(new VideoDecoderVerbatim()); |
| 288 break; |
| 289 case ChannelConfig::CODEC_VP8: |
| 290 video_decoder_ = VideoDecoderVpx::CreateForVP8(); |
| 291 break; |
| 292 default: |
| 293 NOTREACHED(); |
| 294 } |
| 217 | 295 |
| 218 host_thread_.task_runner()->PostTask( | 296 host_thread_.task_runner()->PostTask( |
| 219 FROM_HERE, | 297 FROM_HERE, |
| 220 base::Bind(&ProtocolPerfTest::StartHost, base::Unretained(this))); | 298 base::Bind(&ProtocolPerfTest::StartHost, base::Unretained(this))); |
| 221 } | 299 } |
| 222 | 300 |
| 223 void StartHost() { | 301 void StartHost() { |
| 224 DCHECK(host_thread_.task_runner()->BelongsToCurrentThread()); | 302 DCHECK(host_thread_.task_runner()->BelongsToCurrentThread()); |
| 225 | 303 |
| 226 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | 304 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 new FakePortAllocatorFactory(fake_network_dispatcher_)); | 378 new FakePortAllocatorFactory(fake_network_dispatcher_)); |
| 301 port_allocator_factory->socket_factory()->SetBandwidth( | 379 port_allocator_factory->socket_factory()->SetBandwidth( |
| 302 GetParam().bandwidth, GetParam().max_buffers); | 380 GetParam().bandwidth, GetParam().max_buffers); |
| 303 port_allocator_factory->socket_factory()->SetLatency( | 381 port_allocator_factory->socket_factory()->SetLatency( |
| 304 GetParam().latency_average, GetParam().latency_stddev); | 382 GetParam().latency_average, GetParam().latency_stddev); |
| 305 port_allocator_factory->socket_factory()->set_out_of_order_rate( | 383 port_allocator_factory->socket_factory()->set_out_of_order_rate( |
| 306 GetParam().out_of_order_rate); | 384 GetParam().out_of_order_rate); |
| 307 scoped_refptr<protocol::TransportContext> transport_context( | 385 scoped_refptr<protocol::TransportContext> transport_context( |
| 308 new protocol::TransportContext( | 386 new protocol::TransportContext( |
| 309 host_signaling_.get(), std::move(port_allocator_factory), | 387 host_signaling_.get(), std::move(port_allocator_factory), |
| 310 network_settings, protocol::TransportRole::SERVER)); | 388 network_settings, protocol::TransportRole::CLIENT)); |
| 311 | 389 |
| 312 std::vector<protocol::AuthenticationMethod> auth_methods; | 390 std::vector<protocol::AuthenticationMethod> auth_methods; |
| 313 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( | 391 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( |
| 314 protocol::AuthenticationMethod::NONE)); | 392 protocol::AuthenticationMethod::NONE)); |
| 315 scoped_ptr<protocol::Authenticator> client_authenticator( | 393 scoped_ptr<protocol::Authenticator> client_authenticator( |
| 316 new protocol::NegotiatingClientAuthenticator( | 394 new protocol::NegotiatingClientAuthenticator( |
| 317 std::string(), // client_pairing_id | 395 std::string(), // client_pairing_id |
| 318 std::string(), // client_pairing_secret | 396 std::string(), // client_pairing_secret |
| 319 std::string(), // authentication_tag | 397 std::string(), // authentication_tag |
| 320 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), | 398 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), |
| 321 nullptr, auth_methods)); | 399 nullptr, auth_methods)); |
| 322 client_.reset( | 400 client_.reset( |
| 323 new ChromotingClient(client_context_.get(), this, this, nullptr)); | 401 new ChromotingClient(client_context_.get(), this, this, nullptr)); |
| 324 client_->set_protocol_config(protocol_config_->Clone()); | 402 client_->set_protocol_config(protocol_config_->Clone()); |
| 325 client_->Start(client_signaling_.get(), std::move(client_authenticator), | 403 client_->Start(client_signaling_.get(), std::move(client_authenticator), |
| 326 transport_context, kHostJid, std::string()); | 404 transport_context, kHostJid, std::string()); |
| 327 } | 405 } |
| 328 | 406 |
| 329 void FetchPin( | 407 void FetchPin( |
| 330 bool pairing_supported, | 408 bool pairing_supported, |
| 331 const protocol::SecretFetchedCallback& secret_fetched_callback) { | 409 const protocol::SecretFetchedCallback& secret_fetched_callback) { |
| 332 secret_fetched_callback.Run("123456"); | 410 secret_fetched_callback.Run("123456"); |
| 333 } | 411 } |
| 334 | 412 |
| 413 void MeasureTotalLatency(bool webrtc) { |
| 414 scoped_refptr<test::CyclicFrameGenerator> frame_generator = |
| 415 test::CyclicFrameGenerator::Create(); |
| 416 frame_generator->set_draw_barcode(true); |
| 417 |
| 418 desktop_environment_factory_.set_frame_generator(base::Bind( |
| 419 &test::CyclicFrameGenerator::GenerateFrame, frame_generator)); |
| 420 |
| 421 StartHostAndClient(webrtc, protocol::ChannelConfig::CODEC_VP8); |
| 422 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
| 423 |
| 424 base::TimeDelta total_latency_big_frames; |
| 425 int big_frame_count = 0; |
| 426 base::TimeDelta total_latency_small_frames; |
| 427 int small_frame_count = 0; |
| 428 |
| 429 int last_frame_id = -1; |
| 430 for (int i = 0; i < 30; ++i) { |
| 431 scoped_ptr<webrtc::DesktopFrame> frame = ReceiveFrame(); |
| 432 test::CyclicFrameGenerator::FrameInfo frame_info = |
| 433 frame_generator->IdentifyFrame(frame.get()); |
| 434 base::TimeDelta latency = base::TimeTicks::Now() - frame_info.timestamp; |
| 435 |
| 436 if (frame_info.frame_id > last_frame_id) { |
| 437 last_frame_id = frame_info.frame_id; |
| 438 |
| 439 switch (frame_info.type) { |
| 440 case test::CyclicFrameGenerator::FrameType::EMPTY: |
| 441 NOTREACHED(); |
| 442 break; |
| 443 case test::CyclicFrameGenerator::FrameType::FULL: |
| 444 total_latency_big_frames += latency; |
| 445 ++big_frame_count; |
| 446 break; |
| 447 case test::CyclicFrameGenerator::FrameType::CURSOR: |
| 448 total_latency_small_frames += latency; |
| 449 ++small_frame_count; |
| 450 break; |
| 451 } |
| 452 } else { |
| 453 LOG(ERROR) << "Unexpected duplicate frame " << frame_info.frame_id; |
| 454 } |
| 455 } |
| 456 |
| 457 CHECK(big_frame_count); |
| 458 VLOG(0) << "Average latency for big frames: " |
| 459 << (total_latency_big_frames / big_frame_count).InMillisecondsF(); |
| 460 |
| 461 if (small_frame_count) { |
| 462 VLOG(0) |
| 463 << "Average latency for small frames: " |
| 464 << (total_latency_small_frames / small_frame_count).InMillisecondsF(); |
| 465 } |
| 466 } |
| 467 |
| 335 base::MessageLoopForIO message_loop_; | 468 base::MessageLoopForIO message_loop_; |
| 336 | 469 |
| 337 scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; | 470 scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; |
| 338 | 471 |
| 339 base::Thread host_thread_; | 472 base::Thread host_thread_; |
| 340 base::Thread capture_thread_; | 473 base::Thread capture_thread_; |
| 341 base::Thread encode_thread_; | 474 base::Thread encode_thread_; |
| 475 base::Thread decode_thread_; |
| 342 FakeDesktopEnvironmentFactory desktop_environment_factory_; | 476 FakeDesktopEnvironmentFactory desktop_environment_factory_; |
| 343 | 477 |
| 344 FakeCursorShapeStub cursor_shape_stub_; | 478 FakeCursorShapeStub cursor_shape_stub_; |
| 345 | 479 |
| 346 scoped_ptr<protocol::CandidateSessionConfig> protocol_config_; | 480 scoped_ptr<protocol::CandidateSessionConfig> protocol_config_; |
| 347 | 481 |
| 348 scoped_ptr<FakeSignalStrategy> host_signaling_; | 482 scoped_ptr<FakeSignalStrategy> host_signaling_; |
| 349 scoped_ptr<FakeSignalStrategy> client_signaling_; | 483 scoped_ptr<FakeSignalStrategy> client_signaling_; |
| 350 | 484 |
| 351 scoped_ptr<ChromotingHost> host_; | 485 scoped_ptr<ChromotingHost> host_; |
| 352 scoped_ptr<ClientContext> client_context_; | 486 scoped_ptr<ClientContext> client_context_; |
| 353 scoped_ptr<ChromotingClient> client_; | 487 scoped_ptr<ChromotingClient> client_; |
| 488 webrtc::DesktopSize frame_size_; |
| 489 scoped_ptr<VideoDecoder> video_decoder_; |
| 354 | 490 |
| 355 scoped_ptr<base::RunLoop> connecting_loop_; | 491 scoped_ptr<base::RunLoop> connecting_loop_; |
| 356 scoped_ptr<base::RunLoop> waiting_frames_loop_; | 492 scoped_ptr<base::RunLoop> waiting_frames_loop_; |
| 357 | 493 |
| 358 bool client_connected_; | 494 bool client_connected_; |
| 359 bool host_connected_; | 495 bool host_connected_; |
| 360 | 496 |
| 361 base::Closure on_frame_task_; | 497 base::Closure on_frame_task_; |
| 362 | 498 |
| 363 scoped_ptr<VideoPacket> last_video_packet_; | 499 scoped_ptr<VideoPacket> last_video_packet_; |
| 500 scoped_ptr<webrtc::DesktopFrame> last_video_frame_; |
| 364 | 501 |
| 365 private: | 502 private: |
| 366 DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); | 503 DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); |
| 367 }; | 504 }; |
| 368 | 505 |
| 369 INSTANTIATE_TEST_CASE_P( | 506 INSTANTIATE_TEST_CASE_P( |
| 370 NoDelay, | 507 NoDelay, |
| 371 ProtocolPerfTest, | 508 ProtocolPerfTest, |
| 372 ::testing::Values(NetworkPerformanceParams(0, 0, 0, 0, 0.0))); | 509 ::testing::Values(NetworkPerformanceParams(0, 0, 0, 0, 0.0))); |
| 373 | 510 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 393 // 100 MBps | 530 // 100 MBps |
| 394 NetworkPerformanceParams(800000000, 800000000, 2, 1, 0.0), | 531 NetworkPerformanceParams(800000000, 800000000, 2, 1, 0.0), |
| 395 // 8 MBps | 532 // 8 MBps |
| 396 NetworkPerformanceParams(1000000, 300000, 30, 5, 0.01), | 533 NetworkPerformanceParams(1000000, 300000, 30, 5, 0.01), |
| 397 NetworkPerformanceParams(1000000, 2000000, 30, 5, 0.01), | 534 NetworkPerformanceParams(1000000, 2000000, 30, 5, 0.01), |
| 398 // 800 kBps | 535 // 800 kBps |
| 399 NetworkPerformanceParams(100000, 30000, 130, 5, 0.01), | 536 NetworkPerformanceParams(100000, 30000, 130, 5, 0.01), |
| 400 NetworkPerformanceParams(100000, 200000, 130, 5, 0.01))); | 537 NetworkPerformanceParams(100000, 200000, 130, 5, 0.01))); |
| 401 | 538 |
| 402 TEST_P(ProtocolPerfTest, StreamFrameRate) { | 539 TEST_P(ProtocolPerfTest, StreamFrameRate) { |
| 403 StartHostAndClient(protocol::ChannelConfig::CODEC_VP8); | 540 StartHostAndClient(false, protocol::ChannelConfig::CODEC_VP8); |
| 404 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 541 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
| 405 | 542 |
| 406 base::TimeDelta latency; | 543 base::TimeDelta latency; |
| 407 | 544 |
| 408 ReceiveFrame(&latency); | 545 ReceiveFrameAndGetLatency(&latency); |
| 409 LOG(INFO) << "First frame latency: " << latency.InMillisecondsF() << "ms"; | 546 LOG(INFO) << "First frame latency: " << latency.InMillisecondsF() << "ms"; |
| 410 ReceiveFrames(20, nullptr); | 547 ReceiveMultipleFramesAndGetMaxLatency(20, nullptr); |
| 411 | 548 |
| 412 base::TimeTicks started = base::TimeTicks::Now(); | 549 base::TimeTicks started = base::TimeTicks::Now(); |
| 413 ReceiveFrames(40, &latency); | 550 ReceiveMultipleFramesAndGetMaxLatency(40, &latency); |
| 414 base::TimeDelta elapsed = base::TimeTicks::Now() - started; | 551 base::TimeDelta elapsed = base::TimeTicks::Now() - started; |
| 415 LOG(INFO) << "Frame rate: " << (40.0 / elapsed.InSecondsF()); | 552 LOG(INFO) << "Frame rate: " << (40.0 / elapsed.InSecondsF()); |
| 416 LOG(INFO) << "Maximum latency: " << latency.InMillisecondsF() << "ms"; | 553 LOG(INFO) << "Maximum latency: " << latency.InMillisecondsF() << "ms"; |
| 417 } | 554 } |
| 418 | 555 |
| 419 const int kIntermittentFrameSize = 100 * 1000; | 556 const int kIntermittentFrameSize = 100 * 1000; |
| 420 | 557 |
| 421 // Frame generator that rewrites the whole screen every 60th frame. Should only | 558 // Frame generator that rewrites the whole screen every 60th frame. Should only |
| 422 // be used with the VERBATIM codec as the allocated frame may contain arbitrary | 559 // be used with the VERBATIM codec as the allocated frame may contain arbitrary |
| 423 // data. | 560 // data. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 scoped_ptr<webrtc::SharedDesktopFrame> current_frame_; | 594 scoped_ptr<webrtc::SharedDesktopFrame> current_frame_; |
| 458 | 595 |
| 459 DISALLOW_COPY_AND_ASSIGN(IntermittentChangeFrameGenerator); | 596 DISALLOW_COPY_AND_ASSIGN(IntermittentChangeFrameGenerator); |
| 460 }; | 597 }; |
| 461 | 598 |
| 462 TEST_P(ProtocolPerfTest, IntermittentChanges) { | 599 TEST_P(ProtocolPerfTest, IntermittentChanges) { |
| 463 desktop_environment_factory_.set_frame_generator( | 600 desktop_environment_factory_.set_frame_generator( |
| 464 base::Bind(&IntermittentChangeFrameGenerator::GenerateFrame, | 601 base::Bind(&IntermittentChangeFrameGenerator::GenerateFrame, |
| 465 new IntermittentChangeFrameGenerator())); | 602 new IntermittentChangeFrameGenerator())); |
| 466 | 603 |
| 467 StartHostAndClient(protocol::ChannelConfig::CODEC_VERBATIM); | 604 StartHostAndClient(false, protocol::ChannelConfig::CODEC_VERBATIM); |
| 468 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 605 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
| 469 | 606 |
| 470 ReceiveFrame(nullptr); | 607 ReceiveFrameAndGetLatency(nullptr); |
| 471 | 608 |
| 472 base::TimeDelta expected = GetParam().latency_average; | 609 base::TimeDelta expected = GetParam().latency_average; |
| 473 if (GetParam().bandwidth > 0) { | 610 if (GetParam().bandwidth > 0) { |
| 474 expected += base::TimeDelta::FromSecondsD(kIntermittentFrameSize / | 611 expected += base::TimeDelta::FromSecondsD(kIntermittentFrameSize / |
| 475 GetParam().bandwidth); | 612 GetParam().bandwidth); |
| 476 } | 613 } |
| 477 LOG(INFO) << "Expected: " << expected.InMillisecondsF() << "ms"; | 614 LOG(INFO) << "Expected: " << expected.InMillisecondsF() << "ms"; |
| 478 | 615 |
| 479 base::TimeDelta sum; | 616 base::TimeDelta sum; |
| 480 | 617 |
| 481 const int kFrames = 5; | 618 const int kFrames = 5; |
| 482 for (int i = 0; i < kFrames; ++i) { | 619 for (int i = 0; i < kFrames; ++i) { |
| 483 base::TimeDelta latency; | 620 base::TimeDelta latency; |
| 484 ReceiveFrame(&latency); | 621 ReceiveFrameAndGetLatency(&latency); |
| 485 LOG(INFO) << "Latency: " << latency.InMillisecondsF() | 622 LOG(INFO) << "Latency: " << latency.InMillisecondsF() |
| 486 << "ms Encode: " << last_video_packet_->encode_time_ms() | 623 << "ms Encode: " << last_video_packet_->encode_time_ms() |
| 487 << "ms Capture: " << last_video_packet_->capture_time_ms() | 624 << "ms Capture: " << last_video_packet_->capture_time_ms() |
| 488 << "ms"; | 625 << "ms"; |
| 489 sum += latency; | 626 sum += latency; |
| 490 } | 627 } |
| 491 | 628 |
| 492 LOG(INFO) << "Average: " << (sum / kFrames).InMillisecondsF(); | 629 LOG(INFO) << "Average: " << (sum / kFrames).InMillisecondsF(); |
| 493 } | 630 } |
| 494 | 631 |
| 632 TEST_P(ProtocolPerfTest, TotalLatencyIce) { |
| 633 MeasureTotalLatency(false); |
| 634 } |
| 635 |
| 636 TEST_P(ProtocolPerfTest, TotalLatencyWebrtc) { |
| 637 MeasureTotalLatency(true); |
| 638 } |
| 639 |
| 495 } // namespace remoting | 640 } // namespace remoting |
| OLD | NEW |