⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncencodezlib.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//  Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
//  Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
//  This file is part of TeamViewer.
//
//  TeamViewer 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 TeamViewer is not available from the place 
//  whence you received this file, check http://www.teamviewer.com
//  for information on obtaining it.


// vncEncodeZlib

// This file implements the vncEncoder-derived vncEncodeZlib class.
// This class overrides some vncEncoder functions to produce a bitmap
// to Zlib encoder.  Zlib is much more efficient than RAW format on
// most screen data and usually twice as efficient as hextile.  Of
// course, zlib compression uses more CPU time on the server.
// However, over slower (64kbps or less) connections, the reduction
// in data transmitted usually outweighs the extra latency added
// while the server CPU performs the compression algorithms.

#include "stdhdrs.h"
#include "vncEncodeZlib.h"
#include "..\..\vncviewer\vncviewer.h"

vncEncodeZlib::vncEncodeZlib()
{
	m_buffer = NULL;
	m_buffer2 = NULL;
	m_Queuebuffer = NULL;
	m_QueueCompressedbuffer = NULL;
	m_bufflen = 0;
	m_Queuelen = 0;
	m_Maskbuffer =NULL;
	m_MaskbufferSize =0;
	compStreamInited = false;
	MaxQueuebufflen=128*1024;
	m_Queuebuffer = new BYTE [MaxQueuebufflen+1];
		if (m_Queuebuffer == NULL)
		{
			vnclog.Print(LL_INTINFO, VNCLOG("Memory error"));
		}
	m_QueueCompressedbuffer = new BYTE [MaxQueuebufflen+(MaxQueuebufflen/100)+8];
		if (m_Queuebuffer == NULL)
		{
			vnclog.Print(LL_INTINFO, VNCLOG("Memory error"));
		}
}

vncEncodeZlib::~vncEncodeZlib()
{
	if (m_buffer != NULL)
	{
		delete [] m_buffer;
		m_buffer = NULL;
	}

	if (m_buffer2 != NULL)
	{
		delete [] m_buffer2;
		m_buffer2 = NULL;
	}

	if (m_Queuebuffer != NULL)
	{
		delete [] m_Queuebuffer;
		m_Queuebuffer = NULL;
	}

	if (m_QueueCompressedbuffer != NULL)
	{
		delete [] m_QueueCompressedbuffer;
		m_QueueCompressedbuffer = NULL;
	}

	if (m_Maskbuffer !=NULL)
	{
		delete [] m_Maskbuffer;
		m_Maskbuffer = NULL;

	}

	if ( compStreamInited == true )
	{
		deflateEnd( &compStream );
	}
	compStreamInited = false;

	vnclog.Print(LL_INTINFO, VNCLOG("Zlib Xor encoder stats: rawdata=%d  protocol=%d compressed=%d transmitted=%d"),dataSize, rectangleOverhead, encodedSize,transmittedSize);

	if (dataSize != 0) {
		vnclog.Print(LL_INTINFO, VNCLOG("Zlib Xor encoder efficiency: %.3f%%"),(double)((double)((dataSize - transmittedSize) * 100) / dataSize));
	}
}

void
vncEncodeZlib::Init()
{
	totalraw=0;
	encodedSize=0;
	rectangleOverhead=0;
	transmittedSize=0;
	dataSize=0;
	vncEncoder::Init();
	m_nNbRects=0;
}

UINT
vncEncodeZlib::RequiredBuffSize(UINT width, UINT height)
{
	int result;

	// The zlib library specifies a maximum compressed size of
	// the raw size plus one percent plus 8 bytes.  We also need
	// to cover the zlib header space.
	result = vncEncoder::RequiredBuffSize(width, height);
	Firstrun=result*2;//Needed to exclude xor when cachebuffer is empty
	result += ((result / 100) + 8) + sz_rfbZlibHeader;
	return result;
}

UINT
vncEncodeZlib::NumCodedRects(const rfb::Rect &rect)
{
	const int rectW = rect.br.x - rect.tl.x;
	const int rectH = rect.br.y - rect.tl.y;
	int aantal=(( rectH - 1 ) / ( ZLIB_MAX_SIZE( rectW ) / rectW ) + 1 );
	m_queueEnable=false;
	if (m_use_lastrect && aantal>1) {
		m_queueEnable=true;
		return 0;
	}
/******************************************************************
	return 1;
******************************************************************/

	// Return the number of rectangles needed to encode the given
	// update.  ( ZLIB_MAX_SIZE(rectW) / rectW ) is the number of lines in 
	// each maximum size rectangle.
	// When solid is enabled, most of the pixels are removed
	return (( rectH - 1 ) / ( ZLIB_MAX_SIZE( rectW ) / rectW ) + 1 );
}

/*****************************************************************************
 *
 * Routines to implement zlib Encoding (LZ+Huffman compression) by calling
 * the included zlib library.
 */

// Encode the rectangle using zlib compression
inline UINT
vncEncodeZlib::EncodeRect(BYTE *source,BYTE *source2, VSocket *outConn, BYTE *dest, const rfb::Rect &rect)
{
	int  totalSize = 0;
	int  partialSize = 0;
	int  maxLines;
	int  linesRemaining;
	RECT partialRect;

	const int rectW = rect.br.x - rect.tl.x;
	const int rectH = rect.br.y - rect.tl.y;

	partialRect.right = rect.br.x;
	partialRect.left = rect.tl.x;
	partialRect.top = rect.tl.y;
	partialRect.bottom = rect.br.y;

	/* WBB: For testing purposes only! */
	// vnclog.Print(LL_INTINFO, VNCLOG("rect.right=%d rect.left=%d rect.top=%d rect.bottom=%d"), rect.right, rect.left, rect.top, rect.bottom);

	maxLines = ( ZLIB_MAX_SIZE(rectW) / rectW );
	linesRemaining = rectH;

	while ( linesRemaining > 0 ) {

		int linesToComp;

		if ( maxLines < linesRemaining )
			linesToComp = maxLines;
		else
			linesToComp = linesRemaining;

		partialRect.bottom = partialRect.top + linesToComp;

		/* WBB: For testing purposes only! */
		// vnclog.Print(LL_INTINFO, VNCLOG("partialRect.right=%d partialRect.left=%d partialRect.top=%d partialRect.bottom=%d"), partialRect.right, partialRect.left, partialRect.top, partialRect.bottom);

		partialSize = EncodeOneRect( source,source2, dest, partialRect,outConn );
		totalSize += partialSize;

		linesRemaining -= linesToComp;
		partialRect.top += linesToComp;

		if (( linesRemaining > 0 ) &&
			( partialSize > 0 ))
		{
			// Send the encoded data
			outConn->SendExactQueue( (char *)dest, partialSize );
			transmittedSize += partialSize;
		}


	}
	transmittedSize += partialSize;

	return partialSize;

}

// Encode the rectangle using zlib compression
inline UINT
vncEncodeZlib::EncodeOneRect(BYTE *source,BYTE *source2, BYTE *dest, const RECT &rect,VSocket *outConn)
{
	int totalCompDataLen = 0;
	int previousTotalOut;
	int deflateResult;

	const int rectW = rect.right - rect.left;
	const int rectH = rect.bottom - rect.top;
	const int rawDataSize = (rectW*rectH*m_remoteformat.bitsPerPixel / 8);
	const int maxCompSize = (rawDataSize + (rawDataSize/100) + 8);

	// Create the rectangle header
	rfbFramebufferUpdateRectHeader *surh=(rfbFramebufferUpdateRectHeader *)dest;
	// Modif rdv@2002 - v1.1.x - Application Resize
	surh->r.x = (CARD16) rect.left-m_SWOffsetx;
	surh->r.y = (CARD16) rect.top-m_SWOffsety;
	surh->r.w = (CARD16) (rectW);
	surh->r.h = (CARD16) (rectH);
	surh->r.x = Swap16IfLE(surh->r.x);
	surh->r.y = Swap16IfLE(surh->r.y);
	surh->r.w = Swap16IfLE(surh->r.w);
	surh->r.h = Swap16IfLE(surh->r.h);
	surh->encoding = Swap32IfLE(rfbEncodingZlib);

	dataSize += ( rectW * rectH * m_remoteformat.bitsPerPixel) / 8;
	rectangleOverhead += sz_rfbFramebufferUpdateRectHeader;
	
	// create a space big enough for the Zlib encoded pixels
	if (m_bufflen < rawDataSize)
	{
		if (m_buffer != NULL)
		{
			delete [] m_buffer;
			m_buffer = NULL;
		}
		m_buffer = new BYTE [rawDataSize+1];
		if (m_buffer == NULL)
			return vncEncoder::EncodeRect(source, dest, rect);
		m_bufflen = rawDataSize;
		if (m_buffer2 != NULL)
		{
			delete [] m_buffer2;
			m_buffer2 = NULL;
		}
		m_buffer2 = new BYTE [rawDataSize+1];
	}
	bool full_solid=false;
	// Translate the data into our new buffer
	compStream.avail_in = rawDataSize;
	Translate(source, m_buffer, rect);
	// Perhaps we can queue the small updates and compress them combined
	if (rawDataSize < VNC_ENCODE_ZLIB_MIN_COMP_SIZE)
	{
		if (m_queueEnable && source2 && dataSize>Firstrun)
			{
				surh->encoding = Swap32IfLE(rfbEncodingRaw);
				memcpy(dest+sz_rfbFramebufferUpdateRectHeader,m_buffer,rawDataSize);
				AddToQueu(dest,sz_rfbFramebufferUpdateRectHeader +rawDataSize,outConn,0);
				return 0;
			}
		else return vncEncoder::EncodeRect(source, dest, rect);
	}


	UINT newsize;
	SoMoMu=PURE_ZLIB;
	if (m_buffer2 && source2 && dataSize>Firstrun)
		{
			Translate(source2,m_buffer2, rect);
			newsize=PrepareXOR(m_buffer,m_buffer2,rect);
		}
	switch (SoMoMu)
	{
		case SOLID_COLOR:
			{
				surh->encoding = Swap32IfLE(rfbEncodingSolidColor);
				memcpy(dest+sz_rfbFramebufferUpdateRectHeader,m_buffer,compStream.avail_in);
				//vnclog.Print(LL_INTINFO, VNCLOG("Solid "));
				if (m_queueEnable)
				{
				AddToQueu(dest,sz_rfbFramebufferUpdateRectHeader +newsize,outConn,0);
				return 0;
				}
				return sz_rfbFramebufferUpdateRectHeader +newsize;
			}
		case MONO_COLOR:
			{
				compStream.avail_in = newsize;
				surh->encoding = Swap32IfLE(rfbEncodingXORMonoColor_Zlib);
				//vnclog.Print(LL_INTINFO, VNCLOG("Mono "));
				if (m_queueEnable)
				{
				memcpy(dest+sz_rfbFramebufferUpdateRectHeader,m_buffer,newsize);
				AddToQueu(dest,sz_rfbFramebufferUpdateRectHeader +newsize,outConn,1);
				return 0;
				}
				break;

			}
		case MULTI_COLOR:
			{
				compStream.avail_in = newsize;
				surh->encoding = Swap32IfLE(rfbEncodingXORMultiColor_Zlib);
				///vnclog.Print(LL_INTINFO, VNCLOG("MultiColor "));
				break;
			}

		case XOR_SEQUENCE:
			{
				compStream.avail_in = newsize;
				surh->encoding = Swap32IfLE(rfbEncodingXOR_Zlib);
				memcpy(dest+sz_rfbFramebufferUpdateRectHeader,m_buffer,newsize);
				if (newsize<1000 && m_queueEnable)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -