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 "base/base64.h" | 5 #include "base/base64.h" |
6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
| 8 #include "base/rand_util.h" |
8 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
9 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
10 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
11 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
12 #include "jingle/glue/thread_wrapper.h" | 13 #include "jingle/glue/thread_wrapper.h" |
13 #include "net/base/test_data_directory.h" | 14 #include "net/base/test_data_directory.h" |
14 #include "net/url_request/url_request_context_getter.h" | 15 #include "net/url_request/url_request_context_getter.h" |
15 #include "remoting/base/rsa_key_pair.h" | 16 #include "remoting/base/rsa_key_pair.h" |
16 #include "remoting/client/audio_player.h" | 17 #include "remoting/client/audio_player.h" |
17 #include "remoting/client/chromoting_client.h" | 18 #include "remoting/client/chromoting_client.h" |
18 #include "remoting/client/client_context.h" | 19 #include "remoting/client/client_context.h" |
19 #include "remoting/client/client_user_interface.h" | 20 #include "remoting/client/client_user_interface.h" |
20 #include "remoting/client/video_renderer.h" | 21 #include "remoting/client/video_renderer.h" |
21 #include "remoting/host/chromoting_host.h" | 22 #include "remoting/host/chromoting_host.h" |
22 #include "remoting/host/chromoting_host_context.h" | 23 #include "remoting/host/chromoting_host_context.h" |
23 #include "remoting/host/fake_desktop_environment.h" | 24 #include "remoting/host/fake_desktop_environment.h" |
24 #include "remoting/host/video_scheduler.h" | 25 #include "remoting/host/video_scheduler.h" |
25 #include "remoting/protocol/chromium_port_allocator.h" | |
26 #include "remoting/protocol/jingle_session_manager.h" | 26 #include "remoting/protocol/jingle_session_manager.h" |
27 #include "remoting/protocol/libjingle_transport_factory.h" | 27 #include "remoting/protocol/libjingle_transport_factory.h" |
28 #include "remoting/protocol/me2me_host_authenticator_factory.h" | 28 #include "remoting/protocol/me2me_host_authenticator_factory.h" |
29 #include "remoting/protocol/negotiating_client_authenticator.h" | 29 #include "remoting/protocol/negotiating_client_authenticator.h" |
30 #include "remoting/protocol/session_config.h" | 30 #include "remoting/protocol/session_config.h" |
31 #include "remoting/signaling/fake_signal_strategy.h" | 31 #include "remoting/signaling/fake_signal_strategy.h" |
| 32 #include "remoting/test/fake_network_dispatcher.h" |
| 33 #include "remoting/test/fake_port_allocator.h" |
| 34 #include "remoting/test/fake_socket_factory.h" |
32 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
33 | 36 |
34 namespace remoting { | 37 namespace remoting { |
35 | 38 |
36 using protocol::ChannelConfig; | 39 using protocol::ChannelConfig; |
37 | 40 |
38 const char kHostJid[] = "host_jid@example.com/host"; | 41 const char kHostJid[] = "host_jid@example.com/host"; |
39 const char kHostOwner[] = "jane.doe@example.com"; | 42 const char kHostOwner[] = "jane.doe@example.com"; |
40 const char kClientJid[] = "jane.doe@example.com/client"; | 43 const char kClientJid[] = "jane.doe@example.com/client"; |
41 | 44 |
42 class ProtocolPerfTest : public testing::Test, | 45 struct NetworkPerformanceParams { |
43 public ClientUserInterface, | 46 NetworkPerformanceParams(int bandwidth, |
44 public VideoRenderer, | 47 int max_buffers, |
45 public HostStatusObserver { | 48 double latency_average_ms, |
| 49 double latency_variance_ms, |
| 50 double out_of_order_rate) |
| 51 : bandwidth(bandwidth), |
| 52 max_buffers(max_buffers), |
| 53 latency_average(base::TimeDelta::FromMillisecondsD(latency_average_ms)), |
| 54 latency_variance( |
| 55 base::TimeDelta::FromMillisecondsD(latency_variance_ms)), |
| 56 out_of_order_rate(out_of_order_rate) {} |
| 57 |
| 58 int bandwidth; |
| 59 int max_buffers; |
| 60 base::TimeDelta latency_average; |
| 61 base::TimeDelta latency_variance; |
| 62 double out_of_order_rate; |
| 63 }; |
| 64 |
| 65 class ProtocolPerfTest |
| 66 : public testing::Test, |
| 67 public testing::WithParamInterface<NetworkPerformanceParams>, |
| 68 public ClientUserInterface, |
| 69 public VideoRenderer, |
| 70 public HostStatusObserver { |
46 public: | 71 public: |
47 ProtocolPerfTest() | 72 ProtocolPerfTest() |
48 : host_thread_("host"), | 73 : host_thread_("host"), |
49 capture_thread_("capture"), | 74 capture_thread_("capture"), |
50 encode_thread_("encode") { | 75 encode_thread_("encode") { |
51 VideoScheduler::EnableTimestampsForTests(); | 76 VideoScheduler::EnableTimestampsForTests(); |
52 host_thread_.StartWithOptions( | 77 host_thread_.StartWithOptions( |
53 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 78 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
54 capture_thread_.Start(); | 79 capture_thread_.Start(); |
55 encode_thread_.Start(); | 80 encode_thread_.Start(); |
56 } | 81 } |
| 82 |
57 virtual ~ProtocolPerfTest() { | 83 virtual ~ProtocolPerfTest() { |
58 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, host_.release()); | 84 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, host_.release()); |
59 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, | 85 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, |
60 host_signaling_.release()); | 86 host_signaling_.release()); |
61 message_loop_.RunUntilIdle(); | 87 message_loop_.RunUntilIdle(); |
62 } | 88 } |
63 | 89 |
64 // ClientUserInterface interface. | 90 // ClientUserInterface interface. |
65 virtual void OnConnectionState(protocol::ConnectionToHost::State state, | 91 virtual void OnConnectionState(protocol::ConnectionToHost::State state, |
66 protocol::ErrorCode error) OVERRIDE { | 92 protocol::ErrorCode error) OVERRIDE { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 *max_latency = latency; | 181 *max_latency = latency; |
156 } | 182 } |
157 } | 183 } |
158 } | 184 } |
159 | 185 |
160 // Creates test host and client and starts connection between them. Caller | 186 // Creates test host and client and starts connection between them. Caller |
161 // should call WaitConnected() to wait until connection is established. The | 187 // should call WaitConnected() to wait until connection is established. The |
162 // host is started on |host_thread_| while the client works on the main | 188 // host is started on |host_thread_| while the client works on the main |
163 // thread. | 189 // thread. |
164 void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) { | 190 void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) { |
| 191 fake_network_dispatcher_ = new FakeNetworkDispatcher(); |
| 192 |
165 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); | 193 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); |
166 | 194 |
167 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | 195 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
168 | 196 |
169 protocol_config_ = protocol::CandidateSessionConfig::CreateDefault(); | 197 protocol_config_ = protocol::CandidateSessionConfig::CreateDefault(); |
170 protocol_config_->DisableAudioChannel(); | 198 protocol_config_->DisableAudioChannel(); |
171 protocol_config_->mutable_video_configs()->clear(); | 199 protocol_config_->mutable_video_configs()->clear(); |
172 protocol_config_->mutable_video_configs()->push_back( | 200 protocol_config_->mutable_video_configs()->push_back( |
173 protocol::ChannelConfig( | 201 protocol::ChannelConfig( |
174 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); | 202 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); |
175 | 203 |
176 host_thread_.message_loop_proxy()->PostTask( | 204 host_thread_.message_loop_proxy()->PostTask( |
177 FROM_HERE, | 205 FROM_HERE, |
178 base::Bind(&ProtocolPerfTest::StartHost, base::Unretained(this))); | 206 base::Bind(&ProtocolPerfTest::StartHost, base::Unretained(this))); |
179 } | 207 } |
180 | 208 |
181 void StartHost() { | 209 void StartHost() { |
182 DCHECK(host_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 210 DCHECK(host_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
183 | 211 |
184 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | 212 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
185 | 213 |
186 host_signaling_.reset(new FakeSignalStrategy(kHostJid)); | 214 host_signaling_.reset(new FakeSignalStrategy(kHostJid)); |
187 host_signaling_->ConnectTo(client_signaling_.get()); | 215 host_signaling_->ConnectTo(client_signaling_.get()); |
188 | 216 |
189 protocol::NetworkSettings network_settings( | 217 protocol::NetworkSettings network_settings( |
190 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); | 218 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); |
191 | 219 |
192 // TODO(sergeyu): Replace with a fake port allocator. | 220 scoped_ptr<FakePortAllocator> port_allocator( |
193 scoped_ptr<cricket::HttpPortAllocatorBase> host_port_allocator = | 221 FakePortAllocator::Create(fake_network_dispatcher_)); |
194 protocol::ChromiumPortAllocator::Create(NULL, network_settings) | 222 port_allocator->socket_factory()->SetBandwidth(GetParam().bandwidth, |
195 .PassAs<cricket::HttpPortAllocatorBase>(); | 223 GetParam().max_buffers); |
196 | 224 port_allocator->socket_factory()->SetLatency(GetParam().latency_average, |
| 225 GetParam().latency_variance); |
| 226 port_allocator->socket_factory()->set_out_of_order_rate( |
| 227 GetParam().out_of_order_rate); |
197 scoped_ptr<protocol::TransportFactory> host_transport_factory( | 228 scoped_ptr<protocol::TransportFactory> host_transport_factory( |
198 new protocol::LibjingleTransportFactory( | 229 new protocol::LibjingleTransportFactory( |
199 host_signaling_.get(), | 230 host_signaling_.get(), |
200 host_port_allocator.Pass(), | 231 port_allocator.PassAs<cricket::HttpPortAllocatorBase>(), |
201 network_settings)); | 232 network_settings)); |
202 | 233 |
203 scoped_ptr<protocol::SessionManager> session_manager( | 234 scoped_ptr<protocol::SessionManager> session_manager( |
204 new protocol::JingleSessionManager(host_transport_factory.Pass())); | 235 new protocol::JingleSessionManager(host_transport_factory.Pass())); |
205 | 236 |
206 // Encoder runs on a separate thread, main thread is used for everything | 237 // Encoder runs on a separate thread, main thread is used for everything |
207 // else. | 238 // else. |
208 host_.reset(new ChromotingHost(host_signaling_.get(), | 239 host_.reset(new ChromotingHost(host_signaling_.get(), |
209 &desktop_environment_factory_, | 240 &desktop_environment_factory_, |
210 session_manager.Pass(), | 241 session_manager.Pass(), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 void StartClientAfterHost() { | 281 void StartClientAfterHost() { |
251 client_signaling_->ConnectTo(host_signaling_.get()); | 282 client_signaling_->ConnectTo(host_signaling_.get()); |
252 | 283 |
253 protocol::NetworkSettings network_settings( | 284 protocol::NetworkSettings network_settings( |
254 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); | 285 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); |
255 | 286 |
256 // Initialize client. | 287 // Initialize client. |
257 client_context_.reset( | 288 client_context_.reset( |
258 new ClientContext(base::ThreadTaskRunnerHandle::Get())); | 289 new ClientContext(base::ThreadTaskRunnerHandle::Get())); |
259 | 290 |
260 // TODO(sergeyu): Replace with a fake port allocator | 291 scoped_ptr<FakePortAllocator> port_allocator( |
261 scoped_ptr<cricket::HttpPortAllocatorBase> client_port_allocator = | 292 FakePortAllocator::Create(fake_network_dispatcher_)); |
262 protocol::ChromiumPortAllocator::Create(NULL, network_settings) | 293 port_allocator->socket_factory()->SetBandwidth(GetParam().bandwidth, |
263 .PassAs<cricket::HttpPortAllocatorBase>(); | 294 GetParam().max_buffers); |
264 | 295 port_allocator->socket_factory()->SetLatency(GetParam().latency_average, |
| 296 GetParam().latency_variance); |
| 297 port_allocator->socket_factory()->set_out_of_order_rate( |
| 298 GetParam().out_of_order_rate); |
265 scoped_ptr<protocol::TransportFactory> client_transport_factory( | 299 scoped_ptr<protocol::TransportFactory> client_transport_factory( |
266 new protocol::LibjingleTransportFactory(client_signaling_.get(), | 300 new protocol::LibjingleTransportFactory( |
267 client_port_allocator.Pass(), | 301 client_signaling_.get(), |
268 network_settings)); | 302 port_allocator.PassAs<cricket::HttpPortAllocatorBase>(), |
| 303 network_settings)); |
269 | 304 |
270 std::vector<protocol::AuthenticationMethod> auth_methods; | 305 std::vector<protocol::AuthenticationMethod> auth_methods; |
271 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( | 306 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( |
272 protocol::AuthenticationMethod::NONE)); | 307 protocol::AuthenticationMethod::NONE)); |
273 scoped_ptr<protocol::Authenticator> client_authenticator( | 308 scoped_ptr<protocol::Authenticator> client_authenticator( |
274 new protocol::NegotiatingClientAuthenticator( | 309 new protocol::NegotiatingClientAuthenticator( |
275 std::string(), // client_pairing_id | 310 std::string(), // client_pairing_id |
276 std::string(), // client_pairing_secret | 311 std::string(), // client_pairing_secret |
277 std::string(), // authentication_tag | 312 std::string(), // authentication_tag |
278 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), | 313 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), |
279 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(), | 314 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(), |
280 auth_methods)); | 315 auth_methods)); |
281 client_.reset(new ChromotingClient( | 316 client_.reset(new ChromotingClient( |
282 client_context_.get(), this, this, scoped_ptr<AudioPlayer>())); | 317 client_context_.get(), this, this, scoped_ptr<AudioPlayer>())); |
283 client_->SetProtocolConfigForTests(protocol_config_->Clone()); | 318 client_->SetProtocolConfigForTests(protocol_config_->Clone()); |
284 client_->Start( | 319 client_->Start( |
285 client_signaling_.get(), client_authenticator.Pass(), | 320 client_signaling_.get(), client_authenticator.Pass(), |
286 client_transport_factory.Pass(), kHostJid, std::string()); | 321 client_transport_factory.Pass(), kHostJid, std::string()); |
287 } | 322 } |
288 | 323 |
289 void FetchPin( | 324 void FetchPin( |
290 bool pairing_supported, | 325 bool pairing_supported, |
291 const protocol::SecretFetchedCallback& secret_fetched_callback) { | 326 const protocol::SecretFetchedCallback& secret_fetched_callback) { |
292 secret_fetched_callback.Run("123456"); | 327 secret_fetched_callback.Run("123456"); |
293 } | 328 } |
294 | 329 |
295 base::MessageLoopForIO message_loop_; | 330 base::MessageLoopForIO message_loop_; |
296 | 331 |
| 332 scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; |
| 333 |
297 base::Thread host_thread_; | 334 base::Thread host_thread_; |
298 base::Thread capture_thread_; | 335 base::Thread capture_thread_; |
299 base::Thread encode_thread_; | 336 base::Thread encode_thread_; |
300 FakeDesktopEnvironmentFactory desktop_environment_factory_; | 337 FakeDesktopEnvironmentFactory desktop_environment_factory_; |
301 | 338 |
302 scoped_ptr<protocol::CandidateSessionConfig> protocol_config_; | 339 scoped_ptr<protocol::CandidateSessionConfig> protocol_config_; |
303 | 340 |
304 scoped_ptr<FakeSignalStrategy> host_signaling_; | 341 scoped_ptr<FakeSignalStrategy> host_signaling_; |
305 scoped_ptr<FakeSignalStrategy> client_signaling_; | 342 scoped_ptr<FakeSignalStrategy> client_signaling_; |
306 | 343 |
307 scoped_ptr<ChromotingHost> host_; | 344 scoped_ptr<ChromotingHost> host_; |
308 scoped_ptr<ClientContext> client_context_; | 345 scoped_ptr<ClientContext> client_context_; |
309 scoped_ptr<ChromotingClient> client_; | 346 scoped_ptr<ChromotingClient> client_; |
310 | 347 |
311 scoped_ptr<base::RunLoop> connecting_loop_; | 348 scoped_ptr<base::RunLoop> connecting_loop_; |
312 scoped_ptr<base::RunLoop> waiting_frames_loop_; | 349 scoped_ptr<base::RunLoop> waiting_frames_loop_; |
313 | 350 |
314 bool client_connected_; | 351 bool client_connected_; |
315 bool host_connected_; | 352 bool host_connected_; |
316 | 353 |
317 base::Closure on_frame_task_; | 354 base::Closure on_frame_task_; |
318 | 355 |
319 scoped_ptr<VideoPacket> last_video_packet_; | 356 scoped_ptr<VideoPacket> last_video_packet_; |
320 | 357 |
321 DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); | 358 DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); |
322 }; | 359 }; |
323 | 360 |
324 TEST_F(ProtocolPerfTest, StreamFrameRate) { | 361 INSTANTIATE_TEST_CASE_P( |
| 362 NoDelay, |
| 363 ProtocolPerfTest, |
| 364 ::testing::Values(NetworkPerformanceParams(0, 0, 0, 0, 0.0))); |
| 365 |
| 366 INSTANTIATE_TEST_CASE_P( |
| 367 HighLatency, |
| 368 ProtocolPerfTest, |
| 369 ::testing::Values(NetworkPerformanceParams(0, 0, 300, 30, 0.0), |
| 370 NetworkPerformanceParams(0, 0, 30, 10, 0.0))); |
| 371 |
| 372 INSTANTIATE_TEST_CASE_P( |
| 373 OutOfOrder, |
| 374 ProtocolPerfTest, |
| 375 ::testing::Values(NetworkPerformanceParams(0, 0, 2, 0, 0.01), |
| 376 NetworkPerformanceParams(0, 0, 30, 1, 0.01), |
| 377 NetworkPerformanceParams(0, 0, 30, 1, 0.1), |
| 378 NetworkPerformanceParams(0, 0, 300, 20, 0.01), |
| 379 NetworkPerformanceParams(0, 0, 300, 20, 0.1))); |
| 380 |
| 381 INSTANTIATE_TEST_CASE_P( |
| 382 LimitedBandwidth, |
| 383 ProtocolPerfTest, |
| 384 ::testing::Values( |
| 385 // 100 MBps |
| 386 NetworkPerformanceParams(800000000, 800000000, 2, 1, 0.0), |
| 387 // 8 MBps |
| 388 NetworkPerformanceParams(1000000, 300000, 30, 5, 0.01), |
| 389 NetworkPerformanceParams(1000000, 2000000, 30, 5, 0.01), |
| 390 // 800 kBps |
| 391 NetworkPerformanceParams(100000, 30000, 130, 5, 0.01), |
| 392 NetworkPerformanceParams(100000, 200000, 130, 5, 0.01))); |
| 393 |
| 394 TEST_P(ProtocolPerfTest, StreamFrameRate) { |
325 StartHostAndClient(protocol::ChannelConfig::CODEC_VP8); | 395 StartHostAndClient(protocol::ChannelConfig::CODEC_VP8); |
326 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 396 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
327 | 397 |
328 base::TimeDelta latency; | 398 base::TimeDelta latency; |
329 | 399 |
330 ReceiveFrame(&latency); | 400 ReceiveFrame(&latency); |
331 LOG(INFO) << "First frame latency: " << latency.InMillisecondsF() << "ms"; | 401 LOG(INFO) << "First frame latency: " << latency.InMillisecondsF() << "ms"; |
332 ReceiveFrames(20, NULL); | 402 ReceiveFrames(20, NULL); |
333 | 403 |
334 base::TimeTicks started = base::TimeTicks::Now(); | 404 base::TimeTicks started = base::TimeTicks::Now(); |
335 ReceiveFrames(40, &latency); | 405 ReceiveFrames(40, &latency); |
336 base::TimeDelta elapsed = base::TimeTicks::Now() - started; | 406 base::TimeDelta elapsed = base::TimeTicks::Now() - started; |
337 LOG(INFO) << "Frame rate: " << (40.0 / elapsed.InSecondsF()); | 407 LOG(INFO) << "Frame rate: " << (40.0 / elapsed.InSecondsF()); |
338 LOG(INFO) << "Maximum latency: " << latency.InMillisecondsF() << "ms"; | 408 LOG(INFO) << "Maximum latency: " << latency.InMillisecondsF() << "ms"; |
339 } | 409 } |
340 | 410 |
| 411 const int kIntermittentFrameSize = 100 * 1000; |
| 412 |
341 // Frame generator that rewrites the whole screen every 60th frame. Should only | 413 // Frame generator that rewrites the whole screen every 60th frame. Should only |
342 // be used with the VERBATIM codec as the allocated frame may contain arbitrary | 414 // be used with the VERBATIM codec as the allocated frame may contain arbitrary |
343 // data. | 415 // data. |
344 class IntermittentChangeFrameGenerator | 416 class IntermittentChangeFrameGenerator |
345 : public base::RefCountedThreadSafe<IntermittentChangeFrameGenerator> { | 417 : public base::RefCountedThreadSafe<IntermittentChangeFrameGenerator> { |
346 public: | 418 public: |
347 IntermittentChangeFrameGenerator() | 419 IntermittentChangeFrameGenerator() |
348 : frame_index_(0) {} | 420 : frame_index_(0) {} |
349 | 421 |
350 scoped_ptr<webrtc::DesktopFrame> GenerateFrame( | 422 scoped_ptr<webrtc::DesktopFrame> GenerateFrame( |
351 webrtc::ScreenCapturer::Callback* callback) { | 423 webrtc::ScreenCapturer::Callback* callback) { |
352 const int kWidth = 800; | 424 const int kWidth = 1000; |
353 const int kHeight = 600; | 425 const int kHeight = kIntermittentFrameSize / kWidth / 4; |
354 | 426 |
355 bool fresh_frame = false; | 427 bool fresh_frame = false; |
356 if (frame_index_ % 60 == 0 || !current_frame_) { | 428 if (frame_index_ % 60 == 0 || !current_frame_) { |
357 current_frame_.reset(webrtc::SharedDesktopFrame::Wrap( | 429 current_frame_.reset(webrtc::SharedDesktopFrame::Wrap( |
358 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)))); | 430 new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight)))); |
359 fresh_frame = true; | 431 fresh_frame = true; |
360 } | 432 } |
361 ++frame_index_; | 433 ++frame_index_; |
362 | 434 |
363 scoped_ptr<webrtc::DesktopFrame> result(current_frame_->Share()); | 435 scoped_ptr<webrtc::DesktopFrame> result(current_frame_->Share()); |
364 result->mutable_updated_region()->Clear(); | 436 result->mutable_updated_region()->Clear(); |
365 if (fresh_frame) { | 437 if (fresh_frame) { |
366 result->mutable_updated_region()->AddRect( | 438 result->mutable_updated_region()->AddRect( |
367 webrtc::DesktopRect::MakeXYWH(0, 0, kWidth, kHeight)); | 439 webrtc::DesktopRect::MakeXYWH(0, 0, kWidth, kHeight)); |
368 } | 440 } |
369 return result.Pass(); | 441 return result.Pass(); |
370 } | 442 } |
371 | 443 |
372 private: | 444 private: |
373 ~IntermittentChangeFrameGenerator() {} | 445 ~IntermittentChangeFrameGenerator() {} |
374 friend class base::RefCountedThreadSafe<IntermittentChangeFrameGenerator>; | 446 friend class base::RefCountedThreadSafe<IntermittentChangeFrameGenerator>; |
375 | 447 |
376 int frame_index_; | 448 int frame_index_; |
377 scoped_ptr<webrtc::SharedDesktopFrame> current_frame_; | 449 scoped_ptr<webrtc::SharedDesktopFrame> current_frame_; |
378 | 450 |
379 DISALLOW_COPY_AND_ASSIGN(IntermittentChangeFrameGenerator); | 451 DISALLOW_COPY_AND_ASSIGN(IntermittentChangeFrameGenerator); |
380 }; | 452 }; |
381 | 453 |
382 TEST_F(ProtocolPerfTest, IntermittentChanges) { | 454 TEST_P(ProtocolPerfTest, IntermittentChanges) { |
383 desktop_environment_factory_.set_frame_generator( | 455 desktop_environment_factory_.set_frame_generator( |
384 base::Bind(&IntermittentChangeFrameGenerator::GenerateFrame, | 456 base::Bind(&IntermittentChangeFrameGenerator::GenerateFrame, |
385 new IntermittentChangeFrameGenerator())); | 457 new IntermittentChangeFrameGenerator())); |
386 | 458 |
387 StartHostAndClient(protocol::ChannelConfig::CODEC_VERBATIM); | 459 StartHostAndClient(protocol::ChannelConfig::CODEC_VERBATIM); |
388 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 460 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
389 | 461 |
390 ReceiveFrame(NULL); | 462 ReceiveFrame(NULL); |
391 | 463 |
392 for (int i = 0; i < 5; ++i) { | 464 base::TimeDelta expected = GetParam().latency_average; |
| 465 if (GetParam().bandwidth > 0) { |
| 466 expected += base::TimeDelta::FromSecondsD(kIntermittentFrameSize / |
| 467 GetParam().bandwidth); |
| 468 } |
| 469 LOG(INFO) << "Expected: " << expected.InMillisecondsF() << "ms"; |
| 470 |
| 471 base::TimeDelta sum; |
| 472 |
| 473 const int kFrames = 5; |
| 474 for (int i = 0; i < kFrames; ++i) { |
393 base::TimeDelta latency; | 475 base::TimeDelta latency; |
394 ReceiveFrame(&latency); | 476 ReceiveFrame(&latency); |
395 LOG(INFO) << "Latency: " << latency.InMillisecondsF() | 477 LOG(INFO) << "Latency: " << latency.InMillisecondsF() |
396 << "ms Encode: " << last_video_packet_->encode_time_ms() | 478 << "ms Encode: " << last_video_packet_->encode_time_ms() |
397 << "ms Capture: " << last_video_packet_->capture_time_ms() | 479 << "ms Capture: " << last_video_packet_->capture_time_ms() |
398 << "ms"; | 480 << "ms"; |
| 481 sum += latency; |
399 } | 482 } |
| 483 |
| 484 LOG(INFO) << "Average: " << (sum / kFrames).InMillisecondsF(); |
400 } | 485 } |
401 | 486 |
402 } // namespace remoting | 487 } // namespace remoting |
OLD | NEW |