Click here to Skip to main content
15,891,136 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more: (untagged)
Hi,

While adding ZLIB encoding for my VNC server and I came across a problem. The issue is, only the very first framebuffer is accepted by the client (viewer) and subsequent framebuffers are plotted as blank screens. Somewhere I saw that we have to make use of a single ZLIB stream for a VNC session but I don't know how to implement it. Below is my code snippet sending a rectangle of pixel data in my VNC server.

C++
//==============================================================================
//Note: Rectangle header containing x, y, height, width and encoding is sent
//prior to this code.
//
//reduce the BMP header size from total length
uLongf sourceLen = DATA_SIZE-0x436;
//add sufficient length for encoding algorithm
uLongf destLen = (sourceLen*1.001)+12;
unsigned char* compressedBuffer = (unsigned char*)malloc(destLen);
zlibstream.next_in = (Bytef*)pixelDataBuffer;
zlibstream.avail_in = (uInt)sourceLen;
zlibstream.next_out = compressedBuffer;
zlibstream.avail_out = (uInt)destLen;
if ((uLong)zlibstream.avail_out != destLen) return 1;//Z_BUF_ERROR;

zlibstream.zalloc = (alloc_func)0;
zlibstream.zfree = (free_func)0;
zlibstream.opaque = (voidpf)0;

if(!bFirstUpdateSent)
{
	//Initialize the ZLIB ONLY for the first time
	printf("before deflateInit \r\n");
	zliberr = deflateInit(&zlibstream, Z_DEFAULT_COMPRESSION);
	if (zliberr != Z_OK) 
	{
		printf("deflateInit failed \r\n");
	}
}
bFirstUpdateSent = TRUE;

printf("before deflate \r\n");
//Apply ZLIB encoding to the pixel buffer
zliberr = deflate(&zlibstream, Z_FINISH);
if (zliberr != Z_STREAM_END) {
	return zliberr == Z_OK ? 0 : 1;
}
destLen = zlibstream.total_out;
	
printf("zlib data length = %d \r\n", zlibPixelBufferLength-4);
unsigned char zlibHeader[4]; 
UINT32 zlibLength = destLen;
zlibHeader[0] = zlibLength>>24; 
zlibHeader[1] = zlibLength>>16; 
zlibHeader[2] = zlibLength>>8; 
zlibHeader[3] = zlibLength;

//Send length of the zlib buffer
iSendResult = send( ClientSocket, (const char*)zlibHeader, 4, 0 );
if(iSendResult==SOCKET_ERROR){return 1;}

//send zlib encoded pixel data
iSendResult = send( ClientSocket, (const char*)compressedBuffer, destLen, 0 );
//==============================================================================


Please help.

Regards,

-KK-
Posted
Updated 6-Sep-13 1:37am
v3

I could resolve the issue by myself. I suppose to initialize zalloc, zfree and opaque before calling the init function and reset the stream after each deflate cycle. Following is the updated code.

C++
//==============================================================================
//Note: Rectangle header containing x, y, height, width and encoding is sent
//prior to this code.
//
//reduce the BMP header size from total length
uLongf sourceLen = DATA_SIZE-0x436;
//add sufficient length for encoding algorithm
uLongf destLen = (sourceLen*1.001)+12;
unsigned char* compressedBuffer = (unsigned char*)malloc(destLen);
zlibstream.next_in = (Bytef*)pixelDataBuffer;
zlibstream.avail_in = (uInt)sourceLen;
zlibstream.next_out = compressedBuffer;
zlibstream.avail_out = (uInt)destLen;

if ((uLong)zlibstream.avail_out != destLen) return 1;//Z_BUF_ERROR;
if(!bFirstUpdateSent)
{
	//must initialize zalloc, zfree and opaque before calling the init function
	zlibstream.zalloc = (alloc_func)0;
	zlibstream.zfree = (free_func)0;
	zlibstream.opaque = (voidpf)0;

	//Initialize the ZLIB for the first time
	printf("before deflateInit \r\n");
	zliberr = deflateInit(&zlibstream, Z_DEFAULT_COMPRESSION);
	if (zliberr != Z_OK) 
	{
		printf("deflateInit failed \r\n");
	}
}
bFirstUpdateSent = TRUE;
printf("before deflate \r\n");
//Apply ZLIB encoding to the pixel buffer
zliberr = deflate(&zlibstream, Z_FINISH);
if (zliberr != Z_STREAM_END) {
	return zliberr == Z_OK ? 0 : 1;
}
destLen = zlibstream.total_out;
unsigned char zlibHeader[4]; 
UINT32 zlibLength = destLen;
zlibHeader[0] = zlibLength>>24; zlibHeader[1] = zlibLength>>16; zlibHeader[2] = zlibLength>>8; zlibHeader[3] = zlibLength;
//Send length of the zlib buffer
iSendResult = send( ClientSocket, (const char*)zlibHeader, 4, 0 );
if(iSendResult==SOCKET_ERROR){return 1;}
//send zlib encoded pixel data
iSendResult = send( ClientSocket, (const char*)compressedBuffer, destLen, 0 );

//Reset the stream for next cycle
zliberr = deflateReset(&zlibstream);
//==============================================================================


Regards,

-KK-
 
Share this answer
 
Comments
kdimunge 5-Sep-13 9:47am    
This issue is not fully resolved it seems. Though it works with Ultra VNC, eggplant viewer still draws empty screen for subsequent framebuffer updates.

-KK-
Finally the issue is resolved and here is the updated code if someone is interested in.

C++
//==============================================================================
if(!bFirstUpdateSent)
{
	zlibstream.zalloc = (alloc_func)0;
	zlibstream.zfree = (free_func)0;
	zlibstream.opaque = (voidpf)0;

	//Initialize the ZLIB for the first time
	printf("before deflateInit \r\n");
	zliberr = deflateInit(&zlibstream, Z_DEFAULT_COMPRESSION);
	if (zliberr != Z_OK) 
	{
		printf("deflateInit failed \r\n");
	}
}
bFirstUpdateSent = TRUE;

//reduce the BMP header size from total length
uLongf sourceLen = DATA_SIZE-0x436;
//add sufficient length for encoding algorithm
uLongf destLen = (sourceLen*1.001)+12;
unsigned char* compressedBuffer = (unsigned char*)malloc(destLen);
zlibstream.next_in = (Bytef*)pixelDataBuffer;
zlibstream.avail_in = (uInt)sourceLen;
zlibstream.next_out = compressedBuffer;
zlibstream.avail_out = (uInt)destLen;		
previous_out = zlibstream.total_out; 

printf("before deflate \r\n");
//Apply ZLIB encoding to the pixel buffer
zliberr = deflate(&zlibstream, Z_SYNC_FLUSH);
	
destLen = zlibstream.total_out - previous_out;

printf("zlib data length = %d \r\n", destLen);
unsigned char zlibHeader[4]; 
UINT32 zlibLength = destLen;
zlibHeader[0] = zlibLength>>24; zlibHeader[1] = zlibLength>>16; zlibHeader[2] = zlibLength>>8; zlibHeader[3] = zlibLength;

//Send length of the zlib buffer
iSendResult = send( ClientSocket, (const char*)zlibHeader, 4, 0 );
if(iSendResult==SOCKET_ERROR){return 1;}

//send zlib encoded pixel data
iSendResult = send( ClientSocket, (const char*)compressedBuffer, destLen, 0 );

//Free the buffer
free(compressedBuffer);
//==============================================================================


Regards,

-KK-
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900