📄 vncencodecorre.cpp
字号:
// Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of the VNC system.
//
// The VNC system 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 program 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 program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
//
// If the source code for the VNC system is not available from the place
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
// the authors on vnc@uk.research.att.com for information on obtaining it.
// vncEncodeCoRRE
// This file implements the vncEncoder-derived vncEncodeCoRRE class.
// This class overrides some vncEncoder functions to produce a
// Compact RRE encoder. Compact RRE (CoRRE) uses fewer bytes to
// encode each subrect, which makes it faster in general. It also
// splits large rectangles up into ones of at most 256 pixels width
// & height. This results in better granularity to use for deciding
// whether to send RAW or CoRRE/RRE.
#include "vncEncodeCoRRE.h"
#include "rfb.h"
#include "MinMax.h"
#include <stdlib.h>
#include <time.h>
vncEncodeCoRRE::vncEncodeCoRRE()
{
m_buffer = NULL;
m_bufflen = 0;
// Set some sensible defaults
m_maxwidth = 24;
m_maxheight = 24;
m_maxadjust = 1;
// Set the threshold up/down probability
m_threshold = 50;
// Seed the random number generator
srand((unsigned)time(NULL));
m_statsready = FALSE;
m_encodedbytes = 0;
m_rectbytes = 0;
}
vncEncodeCoRRE::~vncEncodeCoRRE()
{
if (m_buffer != NULL)
{
delete [] m_buffer;
m_buffer = NULL;
}
}
void vncEncodeCoRRE::Init()
{
vncEncoder::Init();
}
UINT vncEncodeCoRRE::RequiredBuffSize(UINT width, UINT height)
{
RECT fullscreen;
UINT codedrects;
// Work out how many rectangles the entire screen would
// be re-encoded to...
fullscreen.left = 0;
fullscreen.top = 0;
fullscreen.right = width;
fullscreen.bottom = height;
codedrects = NumCodedRects(fullscreen);
// The buffer size required is the size of raw data for the whole
// screen plus enough space for the required number of rectangle
// headers.
// This is inherently always greater than the RAW encoded size of
// the whole screen!
return (codedrects * sz_rfbFramebufferUpdateRectHeader) +
(width * height * m_remoteformat.bitsPerPixel)/8;
}
UINT
vncEncodeCoRRE::NumCodedRects(RECT &rect)
{
// If we have any statistical data handy then adjust the CoRRE sizes
if (m_statsready)
{
m_statsready = FALSE;
UINT newscore = m_encodedbytes * m_lastrectbytes;
UINT oldscore = m_lastencodedbytes * m_rectbytes;
if (newscore <= oldscore)
{
// The change was a good one, so adjust the threshold accordingly!
m_threshold = Max(5, Min(95, m_threshold + m_maxadjust));
m_maxwidth = Max(8, Min(255, m_maxwidth + m_maxadjust));
m_maxheight = Max(8, Min(255, m_maxheight + m_maxadjust));
}
else
{
// The change was a bad one, so adjust the threshold accordingly!
// m_threshold = Max(5, Min(95, m_threshold - m_maxadjust));
}
// Now calculate a new adjustment and apply it
m_maxadjust = ((rand() % 99)<m_threshold) ? 1 : -1;
// Prepare the stats data for next time...
m_lastencodedbytes = m_encodedbytes;
m_lastrectbytes = m_rectbytes;
m_encodedbytes = 0;
m_rectbytes = 0;
}
// Now return the number of rects that this one would encode to
if ((rect.bottom-rect.top) > m_maxheight)
{
RECT subrect1, subrect2;
// Find how many rects the two subrects would take
subrect1.left = rect.left;
subrect1.right = rect.right;
subrect1.top = rect.top;
subrect1.bottom = rect.top + m_maxheight;
subrect2.left = rect.left;
subrect2.right = rect.right;
subrect2.top = rect.top + m_maxheight;
subrect2.bottom = rect.bottom;
return NumCodedRects(subrect1) + NumCodedRects(subrect2);
}
if ((rect.right-rect.left) > m_maxwidth)
{
RECT subrect1, subrect2;
// Find how many rects the two subrects would take
subrect1.left = rect.left;
subrect1.right = rect.left + m_maxwidth;
subrect1.top = rect.top;
subrect1.bottom = rect.bottom;
subrect2.left = rect.left + m_maxwidth;
subrect2.right = rect.right;
subrect2.top = rect.top;
subrect2.bottom = rect.bottom;
return NumCodedRects(subrect1) + NumCodedRects(subrect2);
}
// This rectangle is small enough not to require splitting
return 1;
}
/*
* corre.c
*
* Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
* code is based on krw's original javatel rfbserver.
*/
/*
* This version modified for WinVNC by jnw.
*/
static int rreAfterBufLen;
static int subrectEncode8 (CARD8 *source, CARD8 *dest, int w, int h, int max);
static int subrectEncode16 (CARD16 *source, CARD8 *dest, int w, int h, int max);
static int subrectEncode32 (CARD32 *source, CARD8 *dest, int w, int h, int max);
static CARD32 getBgColour (char *data, int size, int bpp);
/*
* vncEncodeCoRRE::EncodeRect - send an arbitrary size rectangle using CoRRE
* encoding.
*/
UINT
vncEncodeCoRRE::EncodeRect(BYTE *source, BYTE *dest, const RECT &rect, int offx, int offy)
{
// Do the encoding
UINT size = InternalEncodeRect(source, dest, rect);
const int rectW = rect.right - rect.left;
const int rectH = rect.bottom - rect.top;
offsetx = offx;
offsety = offy;
// Will this rectangle have been split for encoding?
if ((rectW>m_maxwidth) || (rectH>m_maxheight))
{
// Yes : Once we return, the stats will be valid!
m_statsready = TRUE;
// Update the stats
m_encodedbytes += size;
m_rectbytes += sz_rfbFramebufferUpdateRectHeader +
(rectW*rectH*m_remoteformat.bitsPerPixel/8);
}
return size;
}
UINT
vncEncodeCoRRE::InternalEncodeRect(BYTE *source, BYTE *dest, const RECT &rect)
{
int size = 0;
if ((rect.bottom-rect.top) > m_maxheight)
{
RECT subrect;
// Rectangle is too high - split it into two subrects to send
subrect.left = rect.left;
subrect.right = rect.right;
subrect.top = rect.top;
subrect.bottom = rect.top + m_maxheight;
size += InternalEncodeRect(source, dest + size, subrect);
subrect.left = rect.left;
subrect.right = rect.right;
subrect.top = rect.top + m_maxheight;
subrect.bottom = rect.bottom;
size += InternalEncodeRect(source, dest + size, subrect);
return size;
}
if ((rect.right-rect.left) > m_maxwidth)
{
RECT subrect;
// Rectangle is too high - split it into two subrects to send
subrect.left = rect.left;
subrect.right = rect.left + m_maxwidth;
subrect.top = rect.top;
subrect.bottom = rect.bottom;
size += InternalEncodeRect(source, dest + size, subrect);
subrect.left = rect.left + m_maxwidth;
subrect.right = rect.right;
subrect.top = rect.top;
subrect.bottom = rect.bottom;
size += InternalEncodeRect(source, dest + size, subrect);
return size;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -