Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: remoting/test/dummy_host.cc

Issue 1923573006: Implement a dummy host to do capturing and analysis only. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« remoting/test/BUILD.gn ('K') | « remoting/test/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
joedow 2016/04/28 22:53:54 no copyright in the header for new files.
Hzj_jie 2016/05/03 19:07:05 Done.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <cassert>
6 #include <iostream>
7 #include <memory>
8 #include <string>
9 #include <vector>
10
11 #include "base/at_exit.h"
12 #include "base/atomicops.h"
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/run_loop.h"
21 #include "base/threading/platform_thread.h"
22 #include "base/time/time.h"
23 #include "remoting/base/auto_thread_task_runner.h"
24 #include "remoting/codec/video_encoder_verbatim.h"
25 #include "remoting/codec/video_encoder_vpx.h"
26 #include "remoting/host/chromoting_host.h"
27 #include "remoting/host/chromoting_host_context.h"
28 #include "remoting/host/client_session.h"
29 #include "remoting/host/host_extension.h"
30 #include "remoting/host/host_mock_objects.h"
31 #include "remoting/host/it2me_desktop_environment.h"
32 #include "remoting/host/resources.h"
33 #include "remoting/proto/audio.pb.h"
34 #include "remoting/protocol/audio_stub.h"
35 #include "remoting/protocol/fake_connection_to_client.h"
36 #include "remoting/protocol/pairing_registry.h"
37 #include "remoting/protocol/protocol_mock_objects.h"
38 #include "remoting/protocol/session_config.h"
39 #include "remoting/protocol/video_frame_pump.h"
40 #include "remoting/protocol/video_stub.h"
41
42 #if defined(OS_LINUX)
43 #include <gtk/gtk.h>
44 #include <X11/Xlib.h>
45
46 #include "base/linux_util.h"
47 #endif // defined(OS_LINUX)
48
49 using base::AtExitManager;
50 using base::Bind;
51 using base::Closure;
52 using base::CommandLine;
53 using base::MessageLoopForUI;
54 using base::RunLoop;
55 using base::TimeDelta;
56 using base::WrapUnique;
57 using google::protobuf::MessageLite;
58 using remoting::AudioPacket;
59 using remoting::ChromotingHostContext;
60 using remoting::ClientSession;
61 using remoting::HostExtension;
62 using remoting::MockClientSessionEventHandler;
63 using remoting::It2MeDesktopEnvironmentFactory;
64 using remoting::VideoAck;
65 using remoting::VideoEncoder;
66 using remoting::VideoEncoderVpx;
67 using remoting::VideoEncoderVerbatim;
68 using remoting::VideoPacket;
69 using remoting::protocol::AudioControl;
70 using remoting::protocol::AudioStub;
71 using remoting::protocol::Capabilities;
72 using remoting::protocol::ChannelConfig;
73 using remoting::protocol::ClientResolution;
74 using remoting::protocol::ClientStub;
75 using remoting::protocol::ClipboardEvent;
76 using remoting::protocol::ConnectionToClient;
77 using remoting::protocol::CursorShapeInfo;
78 using remoting::protocol::ExtensionMessage;
79 using remoting::protocol::FakeConnectionToClient;
80 using remoting::protocol::HostStub;
81 using remoting::protocol::MockClientStub;
82 using remoting::protocol::MockHostStub;
83 using remoting::protocol::MockSession;
84 using remoting::protocol::PairingRegistry;
85 using remoting::protocol::PairingRequest;
86 using remoting::protocol::PairingResponse;
87 using remoting::protocol::SessionConfig;
88 using remoting::protocol::VideoControl;
89 using remoting::protocol::VideoFeedbackStub;
90 using remoting::protocol::VideoFramePump;
91 using remoting::protocol::VideoLayout;
92 using remoting::protocol::VideoStream;
93 using remoting::protocol::VideoStub;
94 using std::cout;
95 using std::endl;
96 using std::move;
97 using std::string;
98 using std::vector;
99 using std::unique_ptr;
100 using testing::ReturnRef;
101 using webrtc::DesktopCapturer;
joedow 2016/04/28 22:53:55 In general we don't use using statements like this
Hzj_jie 2016/05/03 19:07:05 Yes, I should remove most of them before sending o
102
103 namespace {
104
105 const bool g_output_to_stdout = false;
106
107 template <typename T>
108 class NoBarrierAtomic {
109 public:
110 T operator++() {
111 return base::subtle::NoBarrier_AtomicIncrement(&i, 1) - 1;
112 }
113
114 T operator++(int) {
115 return base::subtle::NoBarrier_AtomicIncrement(&i, 1);
116 }
117
118 T operator--() {
119 return base::subtle::NoBarrier_AtomicIncrement(&i, -1) - 1;
120 }
121
122 T operator--(int) {
123 return base::subtle::NoBarrier_AtomicIncrement(&i, -1);
124 }
125
126 T operator+=(T other) {
127 return base::subtle::NoBarrier_AtomicIncrement(&i, other);
128 }
129
130 T operator-=(T other) {
131 return base::subtle::NoBarrier_AtomicIncrement(&i, -other);
132 }
133
134 T operator*() const {
135 return base::subtle::NoBarrier_Load(&i);
136 }
137
138 private:
139 volatile T i;
140 };
141
142 class NoBarrierAtomicInt32 : public NoBarrierAtomic<base::subtle::Atomic32> {};
143 #if ARCH_CPU_64_BITS
144 class NoBarrierAtomicInt64 : public NoBarrierAtomic<base::subtle::Atomic64> {};
145 #else
146
147 #include "base/synchronization/lock.h"
148 using base::AutoLock;
149 using base::Lock;
150
151 // A barriered, lock based implementation
152 class NoBarrierAtomicInt64 {
153 public:
154 int64_t operator++() {
155 AutoLock l(lock);
156 return i++;
157 }
158
159 int64_t operator++(int) {
160 AutoLock l(lock);
161 return ++i;
162 }
163
164 int64_t operator--() {
165 AutoLock l(lock);
166 return i--;
167 }
168
169 int64_t operator--(int) {
170 AutoLock l(lock);
171 return --i;
172 }
173
174 int64_t operator+=(int64_t other) {
175 AutoLock l(lock);
176 return (i += other);
177 }
178
179 int64_t operator-=(int64_t other) {
180 AutoLock l(lock);
181 return (i -= other);
182 }
183
184 int64_t operator*() const {
185 base::subtle::MemoryBarrier();
186 return i;
187 }
188
189 private:
190 volatile int64_t i;
191 Lock lock;
192 };
193 #endif
194
195 class MessageLogger {
joedow 2016/04/28 22:53:55 Why aren't you using the standard logging infra we
Hzj_jie 2016/05/03 19:07:05 Renamed to MessageCounter, sorry for the confusion
196 public:
197 MessageLogger()
198 : count_(),
199 size_(),
200 last_size_(),
201 started_(base::Time::Now()) {}
202
203 int message_count() const {
204 return *count_;
205 }
206
207 int64_t message_size() const {
208 return *size_;
209 }
210
211 int last_message_size() const {
212 return last_size_;
213 }
214
215 double DurationSeconds() const {
216 return (base::Time::Now() - started_).InSecondsF();
217 }
218
219 protected:
220 void LogMessage(const MessageLite& message) {
221 count_++;
222 last_size_ = message.ByteSize();
223 size_ += last_size_;
224 }
225
226 private:
227 NoBarrierAtomicInt32 count_;
228 NoBarrierAtomicInt64 size_;
229 int last_size_;
230 base::Time started_;
231 };
232
233 class LogClientStub : public ClientStub, public MessageLogger {
234 public:
235 void SetCapabilities(const Capabilities& capabilities) override {}
236 void SetPairingResponse(const PairingResponse& response) override {}
237 void InjectClipboardEvent(const ClipboardEvent& event) override {}
238 void SetCursorShape(const CursorShapeInfo& cursor_shape) override {}
239
240 void DeliverHostMessage(const ExtensionMessage& message) override {
241 if (g_output_to_stdout) {
242 cout << "DeliverHostMessage(" << message.ByteSize() << ")" << endl;
joedow 2016/04/28 22:53:54 I don't think cout is right, we should use the sam
Hzj_jie 2016/05/03 19:07:05 These cout(s) have been removed, they were for a q
243 }
244 LogMessage(message);
245 }
246
247 void SetVideoLayout(const VideoLayout& video_layout) override {}
248 };
249
250 class LogHostStub : public HostStub, public MessageLogger {
251 public:
252 void NotifyClientResolution(const ClientResolution& resolution) override {}
253 void ControlVideo(const VideoControl& video_control) override {}
254 void ControlAudio(const AudioControl& audio_control) override {}
255 void SetCapabilities(const Capabilities& capabilities) override {}
256 void RequestPairing(const PairingRequest& pairing_request) override {}
257
258 void DeliverClientMessage(const ExtensionMessage& message) override {
259 if (g_output_to_stdout) {
260 cout << "DeliverClientMessage(" << message.ByteSize() << ")" << endl;
261 }
262 LogMessage(message);
263 }
264 };
265
266 class LogAudioStub : public AudioStub, public MessageLogger {
267 public:
268 void ProcessAudioPacket(unique_ptr<AudioPacket> audio_packet,
269 const Closure& done) override {
270 if (audio_packet) {
271 if (g_output_to_stdout) {
272 cout << "ProcessAudioPacket(" << audio_packet->data_size();
273 for (int i = 0; i < audio_packet->data_size(); i++) {
274 cout << " - " << audio_packet->data(i).size();
275 }
276 cout << ")" << endl;
277 }
278 LogMessage(*audio_packet);
279 }
280 done.Run();
281 }
282 };
283
284 class LogVideoStub : public VideoStub, public MessageLogger {
285 public:
286 LogVideoStub(FakeConnectionToClient* connection) : connection_(connection) {}
287
288 void ProcessVideoPacket(unique_ptr<VideoPacket> video_packet,
289 const Closure& done) override {
290 if (video_packet) {
291 if (g_output_to_stdout) {
292 cout << "ProcessVideoPacket("
293 << video_packet->data().size()
294 << ")"
295 << endl;
296 }
297 if (connection_ && connection_->video_feedback_stub()) {
298 VideoAck* ack = new VideoAck();
299 ack->set_frame_id(video_packet->frame_id());
300 connection_->video_feedback_stub()->ProcessVideoAck(WrapUnique(ack));
301 }
302 LogMessage(*video_packet);
303 }
304 done.Run();
305 }
306
307 private:
308 FakeConnectionToClient* connection_ = nullptr;
309 };
310
311 // Stores all objects a host needs
312 struct Container {
joedow 2016/04/28 22:53:55 I wonder if this should be a class and go into it'
Hzj_jie 2016/05/03 19:07:05 Done.
313 MessageLoopForUI message_loop;
314 RunLoop run_loop;
315 unique_ptr<ChromotingHostContext> context;
316 It2MeDesktopEnvironmentFactory factory;
317 FakeConnectionToClient connection;
318 string session_jid;
319 unique_ptr<SessionConfig> config;
320 LogAudioStub audio_stub;
321 LogVideoStub video_stub;
322 LogClientStub client_stub;
323 LogHostStub host_stub;
324 MockClientSessionEventHandler handler;
325 unique_ptr<ClientSession> session;
326
327 Container()
328 : message_loop(),
329 run_loop(),
330 context(ChromotingHostContext::Create(
331 new remoting::AutoThreadTaskRunner(
332 message_loop.task_runner(), run_loop.QuitClosure()))),
333 factory(context->network_task_runner(),
334 context->video_capture_task_runner(),
335 context->input_task_runner(),
336 context->ui_task_runner()),
337 connection(WrapUnique(new MockSession())),
338 session_jid("user@domain/rest-of-jid"),
339 #if defined(OS_LINUX)
340 config(SessionConfig::ForTest()), // Need a pipe name for linux
joedow 2016/04/28 22:53:55 This comment is confusing to me, is a pipe name sp
Hzj_jie 2016/05/03 19:07:05 Updated. We cannot support audio capture in Linux
341 #else
342 config(SessionConfig::ForTestWithAudio()),
343 #endif
344 audio_stub(),
345 video_stub(&connection),
346 client_stub(),
347 host_stub(),
348 handler(),
349 session() {
350 EXPECT_CALL(*static_cast<MockSession*>(connection.session()), jid())
joedow 2016/04/28 22:53:55 Did you pull in the GMOCK header? I didn't see it
Hzj_jie 2016/05/03 19:07:05 Great, thank you for the hint.
351 .WillRepeatedly(ReturnRef(session_jid));
352 EXPECT_CALL(*static_cast<MockSession*>(connection.session()), config())
353 .WillRepeatedly(ReturnRef(*config));
354 connection.set_audio_stub(&audio_stub);
355 connection.set_video_stub(&video_stub);
356 connection.set_client_stub(&client_stub);
357 connection.set_host_stub(&host_stub);
358 connection.set_video_encode_task_runner(
359 context->video_encode_task_runner());
360 }
361
362 void CreateClientSession() {
363 // Must run in network_task_runner
joedow 2016/04/28 22:53:55 You should DCHECK this to prevent it.
Hzj_jie 2016/05/03 19:07:05 No, ClientSession::OnConnectionAuthenticated and o
364 session.reset(new ClientSession(
365 &handler,
366 context->audio_task_runner(),
367 unique_ptr<ConnectionToClient>(&connection),
368 &factory,
369 TimeDelta(),
370 scoped_refptr<PairingRegistry>(),
371 vector<HostExtension*>()));
372 }
373 };
374
375 void Execute(Container* container) {
376 container->CreateClientSession();
377 container->session->OnConnectionAuthenticated(&container->connection);
378 container->session->OnConnectionChannelsConnected(&container->connection);
379 container->session->CreateVideoStreams(&container->connection);
380 }
381
382 void BindAnalysisResultOutputter(Container* container);
383
384 void OutputLogger(const char* name, const MessageLogger& logger) {
385 cout << name
386 << ": "
387 << logger.message_size()
388 << " bytes in "
389 << logger.message_count()
390 << " packages, last package "
391 << logger.last_message_size()
392 << " bytes, "
393 << static_cast<double>(logger.message_size()) / logger.message_count()
394 << " bytes/package, "
395 << static_cast<double>(logger.message_count()) / logger.DurationSeconds()
396 << " packages/sec, "
397 << static_cast<double>(logger.message_size()) / logger.DurationSeconds()
398 << " bytes/sec"
399 << endl;
400 }
401
402 void OutputAnalysisResult(Container* container) {
403 OutputLogger("audio", container->audio_stub);
404 OutputLogger("video", container->video_stub);
405 OutputLogger("client", container->client_stub);
406 OutputLogger("host", container->host_stub);
407 BindAnalysisResultOutputter(container);
408 }
409
410 void BindAnalysisResultOutputter(Container* container) {
411 container->context->ui_task_runner()->PostDelayedTask(
412 FROM_HERE,
413 Bind(&OutputAnalysisResult, container),
414 TimeDelta::FromSeconds(1));
415 }
416
417 } // namespace
418
419 int main(int argc, const char** argv) {
420 AtExitManager at_exit_manager;
421 CommandLine::Init(argc, argv);
422 CommandLine::ForCurrentProcess()->AppendSwitch("disable-it2me-ui");
joedow 2016/04/28 22:53:55 This feels odd unless there is a use case where we
Hzj_jie 2016/05/03 19:07:05 Yes, removed.
423 Container container;
424
425 #if defined(OS_LINUX)
426 // Required in order for us to run multiple X11 threads.
427 XInitThreads();
428
429 // Required for any calls into GTK functions, such as the Disconnect and
430 // Continue windows. Calling with nullptr arguments because we don't have
431 // any command line arguments for gtk to consume.
432 gtk_init(nullptr, nullptr);
433
434 // Need to prime the host OS version value for linux to prevent IO on the
435 // network thread. base::GetLinuxDistro() caches the result.
436 base::GetLinuxDistro();
437 #endif // OS_LINUX
438
439 assert(remoting::LoadResources("en-US"));
joedow 2016/04/28 22:53:55 Why aren't we using chromium asserts here?
Hzj_jie 2016/05/03 19:07:05 Done.
440 container.context->network_task_runner()->PostTask(
441 FROM_HERE,
442 Bind(&Execute, &container));
443 BindAnalysisResultOutputter(&container);
444 container.run_loop.Run();
445 }
OLDNEW
« remoting/test/BUILD.gn ('K') | « remoting/test/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698