blob: dfd8a907ae6a27389d8ebc91797b7fa255549110 [file] [log] [blame]
Pierre Ossmane1f25452015-02-04 14:12:04 +01001/* Copyright 2015 Pierre Ossman <ossman@cendio.se> for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19/*
20 * This program reads files produced by TightVNC's/TurboVNC's
21 * compare-encodings. It is basically a dump of the RFB protocol
22 * from the server side from the ServerInit message and forward.
23 * It is assumed that the client is using a bgr888 (LE) pixel
24 * format.
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <math.h>
30
31#include <rdr/Exception.h>
32#include <rdr/FileInStream.h>
33
34#include <rfb/CConnection.h>
35#include <rfb/CMsgReader.h>
Pierre Ossmane1f25452015-02-04 14:12:04 +010036#include <rfb/PixelBuffer.h>
37#include <rfb/PixelFormat.h>
38
39#include "util.h"
40
41// FIXME: Files are always in this format
42static const rfb::PixelFormat filePF(32, 24, false, true, 255, 255, 255, 0, 8, 16);
43
44class CConn : public rfb::CConnection {
45public:
46 CConn(const char *filename);
47 ~CConn();
48
49 virtual void setDesktopSize(int w, int h);
50 virtual void setPixelFormat(const rfb::PixelFormat& pf);
51 virtual void setCursor(int, int, const rfb::Point&, void*, void*);
Pierre Ossman9f273e92015-11-09 16:34:54 +010052 virtual void framebufferUpdateStart();
53 virtual void framebufferUpdateEnd();
Pierre Ossmane1f25452015-02-04 14:12:04 +010054 virtual void setColourMapEntries(int, int, rdr::U16*);
55 virtual void bell();
56 virtual void serverCutText(const char*, rdr::U32);
57
58public:
59 double cpuTime;
60
61protected:
62 rdr::FileInStream *in;
Pierre Ossmane1f25452015-02-04 14:12:04 +010063};
64
65CConn::CConn(const char *filename)
66{
Pierre Ossmane1f25452015-02-04 14:12:04 +010067 cpuTime = 0.0;
68
69 in = new rdr::FileInStream(filename);
70 setStreams(in, NULL);
71
Pierre Ossmane1f25452015-02-04 14:12:04 +010072 // Need to skip the initial handshake
73 setState(RFBSTATE_INITIALISATION);
74 // That also means that the reader and writer weren't setup
75 setReader(new rfb::CMsgReader(this, in));
76}
77
78CConn::~CConn()
79{
Pierre Ossmane1f25452015-02-04 14:12:04 +010080 delete in;
Pierre Ossmane1f25452015-02-04 14:12:04 +010081}
82
83void CConn::setDesktopSize(int w, int h)
84{
85 CConnection::setDesktopSize(w, h);
86
Pierre Ossman9f273e92015-11-09 16:34:54 +010087 setFramebuffer(new rfb::ManagedPixelBuffer(filePF, cp.width, cp.height));
Pierre Ossmane1f25452015-02-04 14:12:04 +010088}
89
90void CConn::setPixelFormat(const rfb::PixelFormat& pf)
91{
92 // Override format
93 CConnection::setPixelFormat(filePF);
Pierre Ossmane1f25452015-02-04 14:12:04 +010094}
95
96void CConn::setCursor(int, int, const rfb::Point&, void*, void*)
97{
98}
99
Pierre Ossman9f273e92015-11-09 16:34:54 +0100100void CConn::framebufferUpdateStart()
Pierre Ossmane1f25452015-02-04 14:12:04 +0100101{
Pierre Ossmane1f25452015-02-04 14:12:04 +0100102 startCpuCounter();
Pierre Ossman9f273e92015-11-09 16:34:54 +0100103}
104
105void CConn::framebufferUpdateEnd()
106{
Pierre Ossmane1f25452015-02-04 14:12:04 +0100107 endCpuCounter();
108
109 cpuTime += getCpuCounter();
110}
111
112void CConn::setColourMapEntries(int, int, rdr::U16*)
113{
114}
115
116void CConn::bell()
117{
118}
119
120void CConn::serverCutText(const char*, rdr::U32)
121{
122}
123
124static double runTest(const char *fn)
125{
126 CConn *cc;
127 double time;
128
Pierre Ossmane1f25452015-02-04 14:12:04 +0100129 try {
DRC13cfb512015-02-26 12:24:03 -0600130 cc = new CConn(fn);
Pierre Ossman86475a62015-03-03 16:42:15 +0100131 } catch (rdr::Exception e) {
132 fprintf(stderr, "Failed to open rfb file: %s\n", e.str());
133 exit(1);
134 }
DRC13cfb512015-02-26 12:24:03 -0600135
Pierre Ossman86475a62015-03-03 16:42:15 +0100136 try {
Pierre Ossmane1f25452015-02-04 14:12:04 +0100137 while (true)
138 cc->processMsg();
139 } catch (rdr::EndOfStream e) {
140 } catch (rdr::Exception e) {
141 fprintf(stderr, "Failed to run rfb file: %s\n", e.str());
142 exit(1);
143 }
144
145 time = cc->cpuTime;
146
147 delete cc;
148
149 return time;
150}
151
152static void sort(double *array, int count)
153{
154 bool sorted;
155 int i;
156 do {
157 sorted = true;
158 for (i = 1;i < count;i++) {
159 if (array[i-1] > array[i]) {
160 double d;
161 d = array[i];
162 array[i] = array[i-1];
163 array[i-1] = d;
164 sorted = false;
165 }
166 }
167 } while (!sorted);
168}
169
170static const int runCount = 9;
171
172int main(int argc, char **argv)
173{
174 int i;
175 double times[runCount], dev[runCount];
176 double median, meddev;
177
178 if (argc != 2) {
179 printf("Syntax: %s <rfb file>\n", argv[0]);
180 return 1;
181 }
182
183 // Warmup
184 runTest(argv[1]);
185
186 // Multiple runs to get a good average
187 for (i = 0;i < runCount;i++)
188 times[i] = runTest(argv[1]);
189
190 // Calculate median and median deviation
191 sort(times, runCount);
192 median = times[runCount/2];
193
194 for (i = 0;i < runCount;i++)
195 dev[i] = fabs((times[i] - median) / median) * 100;
196
197 sort(dev, runCount);
198 meddev = dev[runCount/2];
199
Pierre Ossmanfb450fb2015-03-03 16:34:56 +0100200 printf("CPU time: %g s (+/- %g %%)\n", median, meddev);
Pierre Ossmane1f25452015-02-04 14:12:04 +0100201
202 return 0;
203}