Commit 2742c957 authored by runge's avatar runge

x11vnc: add kludge to experiment with turbovnc.

parent 453166ec
......@@ -774,7 +774,7 @@ if test "$build_x11vnc" = "yes"; then
#
# configure.ac:690: required file `x11vnc/Makefile.in' not found
#
AC_CONFIG_FILES([x11vnc/Makefile x11vnc/misc/Makefile])
AC_CONFIG_FILES([x11vnc/Makefile x11vnc/misc/Makefile x11vnc/misc/turbovnc/Makefile])
fi
AC_CONFIG_COMMANDS([chmod-libvncserver-config],[chmod a+x libvncserver-config])
......
2009-02-28 Karl Runge <runge@karlrunge.com>
* x11vnc: add kludge to experiment with turbovnc.
2009-02-25 Karl Runge <runge@karlrunge.com>
* x11vnc: fix some -QD cases for use in tkx11vnc.
......
x11vnc README file Date: Wed Feb 25 21:10:01 EST 2009
x11vnc README file Date: Sat Feb 28 10:23:00 EST 2009
The following information is taken from these URLs:
......
SUBDIRS = turbovnc
DIST_SUBDIRS = turbovnc
EXTRA_DIST=README blockdpy.c dtVncPopup rx11vnc rx11vnc.pl shm_clear ranfb.pl slide.pl vcinject.pl x11vnc_loop Xdummy
EXTRA_DIST=README apply_turbovnc convert tight.c turbojpeg.h undo_turbovnc
INTRO:
------
This is a "patch" to make x11vnc/libvncserver work with TurboVNC:
http://www.virtualgl.org/About/TurboVNC
It is very experimental/kludgy. Not all TurboVNC features may be enabled.
We are currently evaluating whether TurboVNC support should be officially
put into x11vnc/libvncserver.
TurboVNC is an optimized VNC for fast refresh rates on fast networks.
It does pretty well on good broadband as well. But it is not as fast
as regular TightVNC on slow links.
TURBOJPEG:
---------
TurboVNC uses the TurboJPEG library based on a fast proprietary JPEG
implementation. You will need to download it from the VirtualGL
sourceforge site:
http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100
Either install it or simply unpack the .deb or .rpm file into a directory.
N.B. you can unpack a .deb via 'ar x package.deb' and the extracting
from the data.tar.gz file. rpm2cpio can be used to unpack .rpm's.
QUICK-START:
------------
For those in a hurry:
cd x11vnc-x.y.z/x11vnc/misc/turbovnc
./apply_turbovnc
cd ../../..
env LDFLAGS='-L/DIR -Xlinker --rpath=/DIR' ./configure
make AM_LDFLAGS='-lturbojpeg'
where you replace /DIR with your directory containing libturbojpeg.so.
PATCHING AND BUILDING:
----------------------
After unpacking your x11vnc-x.y.z.tar.gz tarball cd to the
x11vnc-x.y.z/x11vnc/misc/turbovnc (where this README file is) and from
that directory run:
./apply_turbovnc
that will modify files in the libvncserver and x11vnc directories above
this directory. (To undo these changes run: ./undo_turbovnc) The input
sources, tight.c and turbojpeg.h are from the TurboVNC source package.
After applying, go back to the top level source directory and run:
env LDFLAGS='-L/path/to/turbojpeg -Xlinker --rpath=/path/to/turbojpeg' ./configure
where the turbojpeg library is:
/path/to/turbojpeg/libturbojpeg.so
(change /path/to/turbojpeg to the directory where you installed or
unpacked it.)
If you are not using gnu gcc and gnu linker the options may be a little
different (e.g. -R instead of -Xlinker --rpath).
If you need additional ./configure options or env. var. settings,
add them too.
Next, run this make command:
make AM_LDFLAGS='-lturbojpeg'
This is a hack and may not always work, if it doesn't edit x11vnc/Makefile
and add '-lturbojpeg' to the LIBS variable.
This should create a binary:
./x11vnc/x11vnc
that supports VirtualGL's TurboVNC.
You will need a TurboVNC viewer, you can get one here:
http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=128130
Let us know how it goes.
PERFORMANCE:
------------
Note that x11vnc has to read the display's screen pixels from the
graphics card memory. This can be slow, e.g. 10 MB/sec.
There is not a big need for graphics card manufacturers to optimize the
read rate; the write rate is the one they optimize greatly.
http://www.karlrunge.com/x11vnc/#limitations
If you run x11vnc and see lines like this:
28/02/2009 00:52:07 Autoprobing selected port 5900
28/02/2009 00:52:07 fb read rate: 10 MB/sec
28/02/2009 00:52:07 screen setup finished.
you have a typical slow one.
Whereas if you see this:
28/02/2009 00:54:46 Autoprobing selected port 5900
28/02/2009 00:54:46 fb read rate: 321 MB/sec
28/02/2009 00:54:46 fast read: reset wait ms to: 10
28/02/2009 00:54:46 fast read: reset defer ms to: 10
28/02/2009 00:54:46 screen setup finished.
that is very fast.
We have only seen it this fast on Linux by using the nvidia proprietary
graphics drivers. The Xorg drivers are typically slow 10 MB/sec.
It will also be fast if the X server is virtual: Xvfb or Xdummy
since the screen pixels are stored in RAM:
http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb
And it will be fast if the ShadowFB xorg.conf option is enabled (if the
card supports it.)
The point we are trying to make is that even though TurboVNC uses a
wicked fast JPEG implementation, and cuts out overhead in its attempt to
pump out as many frames per second as it can, if it is slow for x11vnc
to read the screen pixels in the first place then you might not even
notice the TurboVNC speedup.
So TurboVNC+x11vnc will be faster than TightVNC+x11vnc, but if there is
a large overhead/bottleneck from reading the graphics card framebuffer,
then the speedup will be marginal.
#!/bin/sh
ldir="../../../libvncserver"
fail=""
if [ ! -f "./tight.c" ]; then
fail=1
fi
if [ ! -f "./turbojpeg.h" ]; then
fail=1
fi
if [ ! -f "./convert" ]; then
fail=1
fi
if [ ! -f "$ldir/tight.c" ]; then
ls -l "$ldir/tight.c"
fail=1
fi
if [ "X$fail" = "X1" ]; then
echo "Must be run from inside the directory containing 'apply_turbovnc'"
exit 1
fi
if [ -f "$ldir/tight.c.ORIG" ]; then
set -xv
else
set -xv
cp -p "$ldir/tight.c" "$ldir/tight.c.ORIG"
fi
perl ./convert ./tight.c > "$ldir/tight.c"
cp -p ./turbojpeg.h "$ldir"
ls -l $ldir/tight.c* $ldir/turbojpeg.h
#!/usr/bin/perl
while (<>) {
if (/^#include.*"rfb.h"/) {
print <<END;
#include <rfb/rfb.h>
#define Bool rfbBool
#define CARD32 uint32_t
#define CARD16 uint16_t
#define CARD8 uint8_t
#define xalloc malloc
#define xrealloc realloc
#define rfbTightNoZlib 0x0A
END
next;
}
foreach $func (qw(FindBestSolidArea ExtendSolidArea CheckSolidTile CheckSolidTile##bpp CheckSolidTile8 CheckSolidTile16 CheckSolidTile32 Pack24)) {
if (/static.*\b\Q$func\E\b/ && !exists $did_static{$func}) {
$_ =~ s/\b\Q$func\E\b(\s*)\(/$func$1(rfbClientPtr cl, /;
$did_static{$func} = 1;
} elsif (/\b\Q$func\E\b\s*\(/) {
$_ =~ s/\b\Q$func\E\b(\s*)\(/$func$1(cl, /;
}
}
if (/^\s*subsampLevel\s*=\s*cl/) {
$_ = "//$_";
print "subsampLevel = 0;\n";
}
$_ =~ s/cl->tightQualityLevel;/cl->tightQualityLevel * 10;/;
$_ =~ s/rfbScreen.pfbMemory/cl->scaledScreen->frameBuffer/g;
$_ =~ s/rfbScreen.paddedWidthInBytes/cl->scaledScreen->paddedWidthInBytes/g;
$_ =~ s/rfbScreen.bitsPerPixel/cl->scaledScreen->bitsPerPixel/g;
$_ =~ s/rfbServerFormat/cl->screen->serverFormat/g;
if (/^(FindBestSolidArea|ExtendSolidArea|static void Pack24|CheckSolidTile)\(cl/) {
$_ .= "rfbClientPtr cl;\n";
}
if (/^(CheckSolidTile##bpp)\(cl/) {
$_ .= "rfbClientPtr cl; \\\n";
}
$_ =~ s/\bublen\b/cl->ublen/;
$_ =~ s/\bupdateBuf\b/cl->updateBuf/;
if (/cl->(rfbRectanglesSent|rfbBytesSent)/) {
$_ = "//$_";
}
print;
}
print <<END;
void rfbTightCleanup(rfbScreenInfoPtr screen) {
}
END
This diff is collapsed.
/* Copyright (C)2004 Landmark Graphics
* Copyright (C)2005, 2006 Sun Microsystems, Inc.
*
* This library is free software and may be redistributed and/or modified under
* the terms of the wxWindows Library License, Version 3 or (at your option)
* any later version. The full license is in the LICENSE.txt file included
* with this distribution.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* wxWindows Library License for more details.
*/
#if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) && defined(_WIN32) && defined(DLLDEFINE)
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#define DLLCALL
/* Subsampling */
#define NUMSUBOPT 4
enum {TJ_444=0, TJ_422, TJ_411, TJ_GRAYSCALE};
/* Flags */
#define TJ_BGR 1
#define TJ_BOTTOMUP 2
#define TJ_FORCEMMX 8 /* Force IPP to use MMX code even if SSE available */
#define TJ_FORCESSE 16 /* Force IPP to use SSE1 code even if SSE2 available */
#define TJ_FORCESSE2 32 /* Force IPP to use SSE2 code (useful if auto-detect is not working properly) */
#define TJ_ALPHAFIRST 64 /* BGR buffer is ABGR and RGB buffer is ARGB */
#define TJ_FORCESSE3 128 /* Force IPP to use SSE3 code (useful if auto-detect is not working properly) */
typedef void* tjhandle;
#define TJPAD(p) (((p)+3)&(~3))
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* API follows */
/*
tjhandle tjInitCompress(void)
Creates a new JPEG compressor instance, allocates memory for the structures,
and returns a handle to the instance. Most applications will only
need to call this once at the beginning of the program or once for each
concurrent thread. Don't try to create a new instance every time you
compress an image, because this will cause performance to suffer.
RETURNS: NULL on error
*/
DLLEXPORT tjhandle DLLCALL tjInitCompress(void);
/*
int tjCompress(tjhandle j,
unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
unsigned char *dstbuf, unsigned long *size,
int jpegsubsamp, int jpegqual, int flags)
[INPUT] j = instance handle previously returned from a call to
tjInitCompress()
[INPUT] srcbuf = pointer to user-allocated image buffer containing pixels in
RGB(A) or BGR(A) form
[INPUT] width = width (in pixels) of the source image
[INPUT] pitch = bytes per line of the source image (width*pixelsize if the
bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
is padded to the nearest 32-bit boundary, such as is the case for Windows
bitmaps. You can also be clever and use this parameter to skip lines, etc.,
as long as the pitch is greater than 0.)
[INPUT] height = height (in pixels) of the source image
[INPUT] pixelsize = size (in bytes) of each pixel in the source image
RGBA and BGRA: 4, RGB and BGR: 3
[INPUT] dstbuf = pointer to user-allocated image buffer which will receive
the JPEG image. Use the macro TJBUFSIZE(width, height) to determine
the appropriate size for this buffer based on the image width and height.
[OUTPUT] size = pointer to unsigned long which receives the size (in bytes)
of the compressed image
[INPUT] jpegsubsamp = Specifies either 4:1:1, 4:2:2, or 4:4:4 subsampling.
When the image is converted from the RGB to YCbCr colorspace as part of the
JPEG compression process, every other Cb and Cr (chrominance) pixel can be
discarded to produce a smaller image with little perceptible loss of
image clarity (the human eye is more sensitive to small changes in
brightness than small changes in color.)
TJ_411: 4:1:1 subsampling. Discards every other Cb, Cr pixel in both
horizontal and vertical directions.
TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in
the horizontal direction.
TJ_444: no subsampling.
TJ_GRAYSCALE: Generate grayscale JPEG image
[INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive.)
[INPUT] flags = the bitwise OR of one or more of the following
TJ_BGR: The components of each pixel in the source image are stored in
B,G,R order, not R,G,B
TJ_BOTTOMUP: The source image is stored in bottom-up (Windows) order,
not top-down
TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use MMX code (bypass CPU auto-detection)
TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use SSE code (bypass CPU auto-detection)
TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection)
TJ_FORCESSE3: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use SSE3 code (bypass CPU auto-detection)
RETURNS: 0 on success, -1 on error
*/
DLLEXPORT int DLLCALL tjCompress(tjhandle j,
unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
unsigned char *dstbuf, unsigned long *size,
int jpegsubsamp, int jpegqual, int flags);
DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height);
/*
tjhandle tjInitDecompress(void)
Creates a new JPEG decompressor instance, allocates memory for the
structures, and returns a handle to the instance. Most applications will
only need to call this once at the beginning of the program or once for each
concurrent thread. Don't try to create a new instance every time you
decompress an image, because this will cause performance to suffer.
RETURNS: NULL on error
*/
DLLEXPORT tjhandle DLLCALL tjInitDecompress(void);
/*
int tjDecompressHeader(tjhandle j,
unsigned char *srcbuf, unsigned long size,
int *width, int *height)
[INPUT] j = instance handle previously returned from a call to
tjInitDecompress()
[INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
to decompress
[INPUT] size = size of the JPEG image buffer (in bytes)
[OUTPUT] width = width (in pixels) of the JPEG image
[OUTPUT] height = height (in pixels) of the JPEG image
RETURNS: 0 on success, -1 on error
*/
DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
unsigned char *srcbuf, unsigned long size,
int *width, int *height);
/*
int tjDecompress(tjhandle j,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,
int flags)
[INPUT] j = instance handle previously returned from a call to
tjInitDecompress()
[INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
to decompress
[INPUT] size = size of the JPEG image buffer (in bytes)
[INPUT] dstbuf = pointer to user-allocated image buffer which will receive
the bitmap image. This buffer should normally be pitch*height
bytes in size, although this pointer may also be used to decompress into
a specific region of a larger buffer.
[INPUT] width = width (in pixels) of the destination image
[INPUT] pitch = bytes per line of the destination image (width*pixelsize if the
bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
is padded to the nearest 32-bit boundary, such as is the case for Windows
bitmaps. You can also be clever and use this parameter to skip lines, etc.,
as long as the pitch is greater than 0.)
[INPUT] height = height (in pixels) of the destination image
[INPUT] pixelsize = size (in bytes) of each pixel in the destination image
RGBA/RGBx and BGRA/BGRx: 4, RGB and BGR: 3
[INPUT] flags = the bitwise OR of one or more of the following
TJ_BGR: The components of each pixel in the destination image should be
written in B,G,R order, not R,G,B
TJ_BOTTOMUP: The destination image should be stored in bottom-up
(Windows) order, not top-down
TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use MMX code (bypass CPU auto-detection)
TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use SSE code (bypass CPU auto-detection)
TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation
of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection)
RETURNS: 0 on success, -1 on error
*/
DLLEXPORT int DLLCALL tjDecompress(tjhandle j,
unsigned char *srcbuf, unsigned long size,
unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,
int flags);
/*
int tjDestroy(tjhandle h)
Frees structures associated with a compression or decompression instance
[INPUT] h = instance handle (returned from a previous call to
tjInitCompress() or tjInitDecompress()
RETURNS: 0 on success, -1 on error
*/
DLLEXPORT int DLLCALL tjDestroy(tjhandle h);
/*
char *tjGetErrorStr(void)
Returns a descriptive error message explaining why the last command failed
*/
DLLEXPORT char* DLLCALL tjGetErrorStr(void);
#ifdef __cplusplus
}
#endif
#!/bin/sh
ldir="../../../libvncserver"
if [ ! -f "$ldir/tight.c.ORIG" ]; then
ls -l "$ldir/tight.c.ORIG"
exit 1
fi
set -xv
rm -f "$ldir/tight.c" "$ldir/turbojpeg.h"
mv "$ldir/tight.c.ORIG" "$ldir/tight.c"
ls -l $ldir/tight.c*
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment