Commit afa9fae0 authored by steven_carr's avatar steven_carr

Ultra Encoding added. Tested against UltraVNC V1.01

parent e57c4dcd
2006-05-02 Steven Carr <scarr@jsa-usa.com>
* Ultra Encoding added. Tested against UltraVNC V1.01
* libvncclient/rfbproto.c CopyRectangle() BPP!=8 bug fixed.
* Incompatible pointer usage warnings eliminated (gcc 4.0.1)
2006-04-27 Johannes E. Schindelin <Johannes.Schindelin@gmx.de> 2006-04-27 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
* examples/{rotate.c, rotatetemplate.c}: add modified pnmshow * examples/{rotate.c, rotatetemplate.c}: add modified pnmshow
which demonstrates fast rotating and flipping. which demonstrates fast rotating and flipping.
......
AM_CFLAGS=-g -I $(top_srcdir) -I. -Wall AM_CFLAGS=-g -I $(top_srcdir) -I. -Wall
libvncclient_a_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c libvncclient_a_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c minilzo.c
rfbproto.o: rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c rfbproto.o: rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c
EXTRA_DIST=corre.c hextile.c rre.c tight.c zlib.c zrle.c EXTRA_DIST=corre.c hextile.c rre.c tight.c zlib.c zrle.c
......
This diff is collapsed.
This diff is collapsed.
/* minilzo.h -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __MINILZO_H
#define __MINILZO_H
#define MINILZO_VERSION 0x1080
#ifdef __LZOCONF_H
# error "you cannot use both LZO and miniLZO"
#endif
#undef LZO_HAVE_CONFIG_H
#include "lzoconf.h"
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
# error "version mismatch in header files"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
//
************************************************************************/
/* Memory required for the wrkmem parameter.
* When the required size is 0, you can also pass a NULL pointer.
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
/* compression */
LZO_EXTERN(int)
lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
/* decompression */
LZO_EXTERN(int)
lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
/* safe decompression with overrun testing */
LZO_EXTERN(int)
lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <time.h> #include <time.h>
#include "minilzo.h"
/* /*
* rfbClientLog prints a time-stamped message to the log file (stderr). * rfbClientLog prints a time-stamped message to the log file (stderr).
*/ */
...@@ -189,6 +191,12 @@ static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh); ...@@ -189,6 +191,12 @@ static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh);
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh);
static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh); static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh);
...@@ -498,6 +506,10 @@ SetFormatAndEncodings(rfbClient* client) ...@@ -498,6 +506,10 @@ SetFormatAndEncodings(rfbClient* client)
} else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
#endif #endif
} else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) {
/* There are 2 encodings used in 'ultra' */
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
} else if (strncasecmp(encStr,"corre",encStrLen) == 0) { } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
} else if (strncasecmp(encStr,"rre",encStrLen) == 0) { } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
...@@ -565,6 +577,8 @@ SetFormatAndEncodings(rfbClient* client) ...@@ -565,6 +577,8 @@ SetFormatAndEncodings(rfbClient* client)
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
#endif #endif
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
...@@ -783,8 +797,10 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -783,8 +797,10 @@ HandleRFBServerMessage(rfbClient* client)
rect.r.w = rfbClientSwap16IfLE(rect.r.w); rect.r.w = rfbClientSwap16IfLE(rect.r.w);
rect.r.h = rfbClientSwap16IfLE(rect.r.h); rect.r.h = rfbClientSwap16IfLE(rect.r.h);
if (rect.encoding == rfbEncodingXCursor || if (rect.encoding == rfbEncodingXCursor ||
rect.encoding == rfbEncodingRichCursor) { rect.encoding == rfbEncodingRichCursor) {
if (!HandleCursorShape(client, if (!HandleCursorShape(client,
rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.r.w, rect.r.h,
rect.encoding)) { rect.encoding)) {
...@@ -805,7 +821,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -805,7 +821,7 @@ HandleRFBServerMessage(rfbClient* client)
client->KeyboardLedStateEnabled = 1; client->KeyboardLedStateEnabled = 1;
if (client->HandleKeyboardLedState!=NULL) if (client->HandleKeyboardLedState!=NULL)
client->HandleKeyboardLedState(client, rect.r.x, 0); client->HandleKeyboardLedState(client, rect.r.x, 0);
// stash it for the future /* stash it for the future */
client->CurrentKeyboardLedState = rect.r.x; client->CurrentKeyboardLedState = rect.r.x;
continue; continue;
} }
...@@ -819,6 +835,9 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -819,6 +835,9 @@ HandleRFBServerMessage(rfbClient* client)
continue; continue;
} }
/* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */
if (rect.encoding != rfbEncodingUltraZip)
{
if ((rect.r.x + rect.r.w > client->width) || if ((rect.r.x + rect.r.w > client->width) ||
(rect.r.y + rect.r.h > client->height)) (rect.r.y + rect.r.h > client->height))
{ {
...@@ -835,6 +854,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -835,6 +854,7 @@ HandleRFBServerMessage(rfbClient* client)
/* If RichCursor encoding is used, we should prevent collisions /* If RichCursor encoding is used, we should prevent collisions
between framebuffer updates and cursor drawing operations. */ between framebuffer updates and cursor drawing operations. */
client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
}
switch (rect.encoding) { switch (rect.encoding) {
...@@ -851,7 +871,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -851,7 +871,7 @@ HandleRFBServerMessage(rfbClient* client)
if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead)) if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
return FALSE; return FALSE;
CopyRectangle(client, client->buffer, CopyRectangle(client, (uint8_t *)client->buffer,
rect.r.x, y, rect.r.w,linesToRead); rect.r.x, y, rect.r.w,linesToRead);
h -= linesToRead; h -= linesToRead;
...@@ -940,6 +960,43 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -940,6 +960,43 @@ HandleRFBServerMessage(rfbClient* client)
break; break;
} }
case rfbEncodingUltra:
{
switch (client->format.bitsPerPixel) {
case 8:
if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
case 16:
if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
case 32:
if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
}
break;
}
case rfbEncodingUltraZip:
{
switch (client->format.bitsPerPixel) {
case 8:
if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
case 16:
if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
case 32:
if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return FALSE;
break;
}
break;
}
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZlib: case rfbEncodingZlib:
{ {
...@@ -1119,6 +1176,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -1119,6 +1176,7 @@ HandleRFBServerMessage(rfbClient* client)
#include "rre.c" #include "rre.c"
#include "corre.c" #include "corre.c"
#include "hextile.c" #include "hextile.c"
#include "ultra.c"
#include "zlib.c" #include "zlib.c"
#include "tight.c" #include "tight.c"
#include "zrle.c" #include "zrle.c"
...@@ -1127,6 +1185,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -1127,6 +1185,7 @@ HandleRFBServerMessage(rfbClient* client)
#include "rre.c" #include "rre.c"
#include "corre.c" #include "corre.c"
#include "hextile.c" #include "hextile.c"
#include "ultra.c"
#include "zlib.c" #include "zlib.c"
#include "tight.c" #include "tight.c"
#include "zrle.c" #include "zrle.c"
...@@ -1135,6 +1194,7 @@ HandleRFBServerMessage(rfbClient* client) ...@@ -1135,6 +1194,7 @@ HandleRFBServerMessage(rfbClient* client)
#include "rre.c" #include "rre.c"
#include "corre.c" #include "corre.c"
#include "hextile.c" #include "hextile.c"
#include "ultra.c"
#include "zlib.c" #include "zlib.c"
#include "tight.c" #include "tight.c"
#include "zrle.c" #include "zrle.c"
......
/*
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef LIBVNCSERVER_HAVE_LIBZ
/*
* ultrazip.c - handle ultrazip encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles an zlib
* encoded rectangle with BPP bits per pixel.
*/
#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP)
#define HandleUltraBPP CONCAT2E(HandleUltra,BPP)
#define CARDBPP CONCAT3E(uint,BPP,_t)
static rfbBool
HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh)
{
rfbZlibHeader hdr;
int toRead=0;
int inflateResult=0;
int uncompressedBytes = (( rw * rh ) * ( BPP / 8 ));
if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
return FALSE;
toRead = rfbClientSwap32IfLE(hdr.nBytes);
if (toRead==0) return TRUE;
if (uncompressedBytes==0)
{
rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP);
return FALSE;
}
/* First make sure we have a large enough raw buffer to hold the
* decompressed data. In practice, with a fixed BPP, fixed frame
* buffer size and the first update containing the entire frame
* buffer, this buffer allocation should only happen once, on the
* first update.
*/
if ( client->raw_buffer_size < uncompressedBytes) {
if ( client->raw_buffer != NULL ) {
free( client->raw_buffer );
}
client->raw_buffer_size = uncompressedBytes;
/* buffer needs to be aligned on 4-byte boundaries */
if ((client->raw_buffer_size % 4)!=0)
client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
client->raw_buffer = (char*) malloc( client->raw_buffer_size );
}
/* allocate enough space to store the incoming compressed packet */
if ( client->ultra_buffer_size < toRead ) {
if ( client->ultra_buffer != NULL ) {
free( client->ultra_buffer );
}
client->ultra_buffer_size = toRead;
/* buffer needs to be aligned on 4-byte boundaries */
if ((client->ultra_buffer_size % 4)!=0)
client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4));
client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
}
/* Fill the buffer, obtaining data from the server. */
if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
return FALSE;
/* uncompress the data */
uncompressedBytes = client->raw_buffer_size;
inflateResult = lzo1x_decompress(
(lzo_byte *)client->ultra_buffer, toRead,
(lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes,
NULL);
if ((rw * rh * (BPP / 8)) != uncompressedBytes)
rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes);
/* Put the uncompressed contents of the update on the screen. */
if ( inflateResult == LZO_E_OK )
{
CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh);
}
else
{
rfbClientLog("ultra decompress returned error: %d\n",
inflateResult);
return FALSE;
}
return TRUE;
}
/* UltraZip is like rre in that it is composed of subrects */
static rfbBool
HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh)
{
rfbZlibHeader hdr;
int i=0;
int toRead=0;
int inflateResult=0;
unsigned char *ptr=NULL;
int uncompressedBytes = ry + (rw * 65535);
unsigned int numCacheRects = rx;
if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
return FALSE;
toRead = rfbClientSwap32IfLE(hdr.nBytes);
if (toRead==0) return TRUE;
if (uncompressedBytes==0)
{
rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx);
return FALSE;
}
/* First make sure we have a large enough raw buffer to hold the
* decompressed data. In practice, with a fixed BPP, fixed frame
* buffer size and the first update containing the entire frame
* buffer, this buffer allocation should only happen once, on the
* first update.
*/
if ( client->raw_buffer_size < (uncompressedBytes + 500)) {
if ( client->raw_buffer != NULL ) {
free( client->raw_buffer );
}
client->raw_buffer_size = uncompressedBytes + 500;
/* buffer needs to be aligned on 4-byte boundaries */
if ((client->raw_buffer_size % 4)!=0)
client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
client->raw_buffer = (char*) malloc( client->raw_buffer_size );
}
/* allocate enough space to store the incoming compressed packet */
if ( client->ultra_buffer_size < toRead ) {
if ( client->ultra_buffer != NULL ) {
free( client->ultra_buffer );
}
client->ultra_buffer_size = toRead;
client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
}
/* Fill the buffer, obtaining data from the server. */
if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
return FALSE;
/* uncompress the data */
uncompressedBytes = client->raw_buffer_size;
inflateResult = lzo1x_decompress(
(lzo_byte *)client->ultra_buffer, toRead,
(lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, NULL);
if ( inflateResult != LZO_E_OK )
{
rfbClientLog("ultra decompress returned error: %d\n",
inflateResult);
return FALSE;
}
/* Put the uncompressed contents of the update on the screen. */
ptr = (unsigned char *)client->raw_buffer;
for (i=0; i<numCacheRects; i++)
{
unsigned short sx, sy, sw, sh;
unsigned int se;
memcpy((char *)&sx, ptr, 2); ptr += 2;
memcpy((char *)&sy, ptr, 2); ptr += 2;
memcpy((char *)&sw, ptr, 2); ptr += 2;
memcpy((char *)&sh, ptr, 2); ptr += 2;
memcpy((char *)&se, ptr, 4); ptr += 4;
sx = rfbClientSwap16IfLE(sx);
sy = rfbClientSwap16IfLE(sy);
sw = rfbClientSwap16IfLE(sw);
sh = rfbClientSwap16IfLE(sh);
se = rfbClientSwap32IfLE(se);
if (se == rfbEncodingRaw)
{
CopyRectangle(client, (unsigned char *)ptr, sx, sy, sw, sh);
ptr += ((sw * sh) * (BPP / 8));
}
}
return TRUE;
}
#undef CARDBPP
#endif
...@@ -87,7 +87,7 @@ static rfbBool MallocFrameBuffer(rfbClient* client) { ...@@ -87,7 +87,7 @@ static rfbBool MallocFrameBuffer(rfbClient* client) {
static void initAppData(AppData* data) { static void initAppData(AppData* data) {
data->shareDesktop=TRUE; data->shareDesktop=TRUE;
data->viewOnly=FALSE; data->viewOnly=FALSE;
data->encodingsString="tight zrle hextile zlib corre rre raw"; data->encodingsString="tight zrle ultra hextile zlib corre rre raw";
data->useBGR233=FALSE; data->useBGR233=FALSE;
data->nColours=0; data->nColours=0;
data->forceOwnCmap=FALSE; data->forceOwnCmap=FALSE;
......
...@@ -19,7 +19,7 @@ include_HEADERS=../rfb/rfb.h ../rfb/rfbconfig.h ../rfb/rfbint.h \ ...@@ -19,7 +19,7 @@ include_HEADERS=../rfb/rfb.h ../rfb/rfbconfig.h ../rfb/rfbint.h \
../rfb/rfbproto.h ../rfb/keysym.h ../rfb/rfbregion.h ../rfb/rfbclient.h ../rfb/rfbproto.h ../rfb/keysym.h ../rfb/rfbregion.h ../rfb/rfbclient.h
noinst_HEADERS=d3des.h ../rfb/default8x16.h zrleoutstream.h \ noinst_HEADERS=d3des.h ../rfb/default8x16.h zrleoutstream.h \
zrlepalettehelper.h zrletypes.h private.h \ zrlepalettehelper.h zrletypes.h private.h minilzo.h lzoconf.h \
$(TIGHTVNCFILETRANSFERHDRS) $(TIGHTVNCFILETRANSFERHDRS)
EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \ EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \
...@@ -36,7 +36,7 @@ endif ...@@ -36,7 +36,7 @@ endif
LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c \ LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c \
stats.c corre.c hextile.c rre.c translate.c cutpaste.c \ stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
httpd.c cursor.c font.c \ httpd.c cursor.c font.c \
draw.c selbox.c d3des.c vncauth.c cargs.c \ draw.c selbox.c d3des.c vncauth.c cargs.c minilzo.c ultra.c \
$(ZLIBSRCS) $(JPEGSRCS) $(TIGHTVNCFILETRANSFERSRCS) $(ZLIBSRCS) $(JPEGSRCS) $(TIGHTVNCFILETRANSFERSRCS)
libvncserver_a_SOURCES=$(LIB_SRCS) libvncserver_a_SOURCES=$(LIB_SRCS)
......
This diff is collapsed.
This diff is collapsed.
/* minilzo.h -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __MINILZO_H
#define __MINILZO_H
#define MINILZO_VERSION 0x1080
#ifdef __LZOCONF_H
# error "you cannot use both LZO and miniLZO"
#endif
#undef LZO_HAVE_CONFIG_H
#include "lzoconf.h"
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
# error "version mismatch in header files"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
//
************************************************************************/
/* Memory required for the wrkmem parameter.
* When the required size is 0, you can also pass a NULL pointer.
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
/* compression */
LZO_EXTERN(int)
lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
/* decompression */
LZO_EXTERN(int)
lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
/* safe decompression with overrun testing */
LZO_EXTERN(int)
lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
lzo_byte *dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
...@@ -884,6 +884,13 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) ...@@ -884,6 +884,13 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl->host); cl->host);
} }
break; break;
case rfbEncodingUltra:
if (cl->preferredEncoding == -1) {
cl->preferredEncoding = enc;
rfbLog("Using Ultra encoding for client %s\n",
cl->host);
}
break;
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZlib: case rfbEncodingZlib:
if (cl->preferredEncoding == -1) { if (cl->preferredEncoding == -1) {
...@@ -1399,6 +1406,17 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -1399,6 +1406,17 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
nUpdateRegionRects += rectsPerRow*rows; nUpdateRegionRects += rectsPerRow*rows;
} }
sraRgnReleaseIterator(i); sraRgnReleaseIterator(i);
} else if (cl->preferredEncoding == rfbEncodingUltra) {
nUpdateRegionRects = 0;
for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
int x = rect.x1;
int y = rect.y1;
int w = rect.x2 - x;
int h = rect.y2 - y;
nUpdateRegionRects += (((h-1) / (ULTRA_MAX_SIZE( w ) / w)) + 1);
}
sraRgnReleaseIterator(i);
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
} else if (cl->preferredEncoding == rfbEncodingZlib) { } else if (cl->preferredEncoding == rfbEncodingZlib) {
nUpdateRegionRects = 0; nUpdateRegionRects = 0;
...@@ -1437,14 +1455,16 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -1437,14 +1455,16 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
fu->type = rfbFramebufferUpdate; fu->type = rfbFramebufferUpdate;
if (nUpdateRegionRects != 0xFFFF) { if (nUpdateRegionRects != 0xFFFF) {
if(cl->screen->maxRectsPerUpdate>0 if(cl->screen->maxRectsPerUpdate>0
/* CoRRE splits the screen into smaller squares */
&& cl->preferredEncoding != rfbEncodingCoRRE
/* Ultra encoding splits rectangles up into smaller chunks */
&& cl->preferredEncoding != rfbEncodingUltra
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
/* Zlib encoding splits rectangles up into smaller chunks */
&& cl->preferredEncoding != rfbEncodingZlib
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #ifdef LIBVNCSERVER_HAVE_LIBJPEG
/* Tight encoding counts the rectangles differently */ /* Tight encoding counts the rectangles differently */
&& cl->preferredEncoding != rfbEncodingTight && cl->preferredEncoding != rfbEncodingTight
/* XXX Should rfbEncodingCoRRE be in here? */
&& cl->preferredEncoding != rfbEncodingCoRRE
/* Zlib encoding splits rectangles up into smaller chunks */
&& cl->preferredEncoding != rfbEncodingZlib
#endif #endif
#endif #endif
&& nUpdateRegionRects>cl->screen->maxRectsPerUpdate) { && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
...@@ -1510,6 +1530,10 @@ rfbSendFramebufferUpdate(rfbClientPtr cl, ...@@ -1510,6 +1530,10 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) if (!rfbSendRectEncodingHextile(cl, x, y, w, h))
goto updateFailed; goto updateFailed;
break; break;
case rfbEncodingUltra:
if (!rfbSendRectEncodingUltra(cl, x, y, w, h))
goto updateFailed;
break;
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZlib: case rfbEncodingZlib:
if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) if (!rfbSendRectEncodingZlib(cl, x, y, w, h))
......
/*
* ultra.c
*
* Routines to implement ultra based encoding (minilzo).
* ultrazip supports packed rectangles if the rects are tiny...
* This improves performance as lzo has more data to work with at once
* This is 'UltraZip' and is currently not implemented.
*/
#include <rfb/rfb.h>
#include "minilzo.h"
/*
* lzoBeforeBuf contains pixel data in the client's format.
* lzoAfterBuf contains the lzo (deflated) encoding version.
* If the lzo compressed/encoded version is
* larger than the raw data or if it exceeds lzoAfterBufSize then
* raw encoding is used instead.
*/
static int lzoBeforeBufSize = 0;
static char *lzoBeforeBuf = NULL;
static int lzoAfterBufSize = 0;
static char *lzoAfterBuf = NULL;
static int lzoAfterBufLen;
/*
* rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
* rectangle encoding.
*/
#define MAX_WRKMEM ((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)
static rfbBool
rfbSendOneRectEncodingUltra(rfbClientPtr cl,
int x,
int y,
int w,
int h)
{
rfbFramebufferUpdateRectHeader rect;
rfbZlibHeader hdr;
int deflateResult;
int i;
char *fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y)
+ (x * (cl->screen->bitsPerPixel / 8)));
int maxRawSize;
int maxCompSize;
maxRawSize = (w * h * (cl->format.bitsPerPixel / 8));
if (lzoBeforeBufSize < maxRawSize) {
lzoBeforeBufSize = maxRawSize;
if (lzoBeforeBuf == NULL)
lzoBeforeBuf = (char *)malloc(lzoBeforeBufSize);
else
lzoBeforeBuf = (char *)realloc(lzoBeforeBuf, lzoBeforeBufSize);
}
/*
* lzo requires output buffer to be slightly larger than the input
* buffer, in the worst case.
*/
maxCompSize = (maxRawSize + maxRawSize / 16 + 64 + 3);
if (lzoAfterBufSize < maxCompSize) {
lzoAfterBufSize = maxCompSize;
if (lzoAfterBuf == NULL)
lzoAfterBuf = (char *)malloc(lzoAfterBufSize);
else
lzoAfterBuf = (char *)realloc(lzoAfterBuf, lzoAfterBufSize);
}
/*
* Convert pixel data to client format.
*/
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,
&cl->format, fbptr, lzoBeforeBuf,
cl->screen->paddedWidthInBytes, w, h);
if ( cl->compStreamInitedLZO == FALSE ) {
cl->compStreamInitedLZO = TRUE;
/* Work-memory needed for compression. Allocate memory in units
* of `lzo_align_t' (instead of `char') to make sure it is properly aligned.
*/
cl->lzoWrkMem = malloc(sizeof(lzo_align_t) * (((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)));
}
/* Perform the compression here. */
deflateResult = lzo1x_1_compress((unsigned char *)lzoBeforeBuf, (lzo_uint)(w * h * (cl->format.bitsPerPixel / 8)), (unsigned char *)lzoAfterBuf, (lzo_uint *)&maxCompSize, cl->lzoWrkMem);
/* maxCompSize now contains the compressed size */
/* Find the total size of the resulting compressed data. */
lzoAfterBufLen = maxCompSize;
if ( deflateResult != LZO_E_OK ) {
rfbErr("lzo deflation error: %d\n", deflateResult);
return FALSE;
}
/* Update statics */
cl->rectanglesSent[rfbEncodingUltra]++;
cl->bytesSent[rfbEncodingUltra] += (sz_rfbFramebufferUpdateRectHeader
+ sz_rfbZlibHeader + lzoAfterBufLen);
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
> UPDATE_BUF_SIZE)
{
if (!rfbSendUpdateBuf(cl))
return FALSE;
}
rect.r.x = Swap16IfLE(x);
rect.r.y = Swap16IfLE(y);
rect.r.w = Swap16IfLE(w);
rect.r.h = Swap16IfLE(h);
rect.encoding = Swap32IfLE(rfbEncodingUltra);
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
hdr.nBytes = Swap32IfLE(lzoAfterBufLen);
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
cl->ublen += sz_rfbZlibHeader;
for (i = 0; i < lzoAfterBufLen;) {
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
if (i + bytesToCopy > lzoAfterBufLen) {
bytesToCopy = lzoAfterBufLen - i;
}
memcpy(&cl->updateBuf[cl->ublen], &lzoAfterBuf[i], bytesToCopy);
cl->ublen += bytesToCopy;
i += bytesToCopy;
if (cl->ublen == UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl))
return FALSE;
}
}
return TRUE;
}
/*
* rfbSendRectEncodingUltra - send a given rectangle using one or more
* LZO encoding rectangles.
*/
rfbBool
rfbSendRectEncodingUltra(rfbClientPtr cl,
int x,
int y,
int w,
int h)
{
int maxLines;
int linesRemaining;
rfbRectangle partialRect;
partialRect.x = x;
partialRect.y = y;
partialRect.w = w;
partialRect.h = h;
/* Determine maximum pixel/scan lines allowed per rectangle. */
maxLines = ( ULTRA_MAX_SIZE(w) / w );
/* Initialize number of scan lines left to do. */
linesRemaining = h;
/* Loop until all work is done. */
while ( linesRemaining > 0 ) {
int linesToComp;
if ( maxLines < linesRemaining )
linesToComp = maxLines;
else
linesToComp = linesRemaining;
partialRect.h = linesToComp;
/* Encode (compress) and send the next rectangle. */
if ( ! rfbSendOneRectEncodingUltra( cl,
partialRect.x,
partialRect.y,
partialRect.w,
partialRect.h )) {
return FALSE;
}
/* Technically, flushing the buffer here is not extrememly
* efficient. However, this improves the overall throughput
* of the system over very slow networks. By flushing
* the buffer with every maximum size lzo rectangle, we
* improve the pipelining usage of the server CPU, network,
* and viewer CPU components. Insuring that these components
* are working in parallel actually improves the performance
* seen by the user.
* Since, lzo is most useful for slow networks, this flush
* is appropriate for the desired behavior of the lzo encoding.
*/
if (( cl->ublen > 0 ) &&
( linesToComp == maxLines )) {
if (!rfbSendUpdateBuf(cl)) {
return FALSE;
}
}
/* Update remaining and incremental rectangle location. */
linesRemaining -= linesToComp;
partialRect.y += linesToComp;
}
return TRUE;
}
...@@ -484,6 +484,12 @@ typedef struct _rfbClientRec { ...@@ -484,6 +484,12 @@ typedef struct _rfbClientRec {
int tightQualityLevel; int tightQualityLevel;
#endif #endif
#endif #endif
/* Ultra Encoding support */
rfbBool compStreamInitedLZO;
char *lzoWrkMem;
int lastKeyboardLedState; /* keep track of last value so we can send *change* events */ int lastKeyboardLedState; /* keep track of last value so we can send *change* events */
rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */ rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */
rfbBool enableLastRectEncoding; /* client supports LastRect encoding */ rfbBool enableLastRectEncoding; /* client supports LastRect encoding */
...@@ -658,6 +664,17 @@ extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h ...@@ -658,6 +664,17 @@ extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h
extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
int h); int h);
/* ultra.c */
/* Set maximum ultra rectangle size in pixels. Always allow at least
* two scan lines.
*/
#define ULTRA_MAX_RECT_SIZE (128*256)
#define ULTRA_MAX_SIZE(min) ((( min * 2 ) > ULTRA_MAX_RECT_SIZE ) ? \
( min * 2 ) : ULTRA_MAX_RECT_SIZE )
extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h);
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
/* zlib.c */ /* zlib.c */
......
...@@ -148,13 +148,17 @@ typedef struct _rfbClient { ...@@ -148,13 +148,17 @@ typedef struct _rfbClient {
based on the bitsPerPixel, height and width of the rectangle. We based on the bitsPerPixel, height and width of the rectangle. We
allocate this buffer one time to be the full size of the buffer. */ allocate this buffer one time to be the full size of the buffer. */
#ifdef LIBVNCSERVER_HAVE_LIBZ /* Ultra Encoding uses this buffer too */
int ultra_buffer_size;
char *ultra_buffer;
int raw_buffer_size; int raw_buffer_size;
char *raw_buffer; char *raw_buffer;
#ifdef LIBVNCSERVER_HAVE_LIBZ
z_stream decompStream; z_stream decompStream;
rfbBool decompStreamInited; rfbBool decompStreamInited;
#endif #endif
......
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