C# better compression for remote desktop broadcast application

Mafahir Fairoze picture Mafahir Fairoze · Nov 4, 2010 · Viewed 7k times · Source

I am in the process of creating a TCP remote desktop broadcasting application. (Something like Team Viewer or VNC) the server application will

1. run on a PC listening for multiple clients on one Thread
2. and on another thread it will record the desktop every second
3. and it will broadcast the desktop for each connected client.

i need to make this application possible to run on a connections with a 12KBps upload and 50KBps download DSL connection (client's and server).

so.. i have to reduce the size of the data/image i send per second.

i tried to reduce by doing the following.

I. first i send a Bitmap frame of the desktop and each other time i send only the difference of the previously sent frame.

II. the second way i tried was, each time i send a JPEG frame.

i was unsuccessful to send a JPEG frame and then each next time send the difference of the previously sent JPEG frame.

i tried using lzma compression (7zip SDK) for the when i was transmitting the difference of the Bitmap.

But i was unsuccessful to reduce the data into 12KBps. the maximum i was able to achieve was around 50KBps.

Can someone advice me an algorithm/procedure for doing this?

Answer

Gabriel Magana picture Gabriel Magana · Nov 4, 2010

What you want to do is do what image compression formats do, but in a custom way (Send only the changes, not the whole image over and over). Here is what I would do, in two phases (phase 1: get it done, prove it works, phase 2: optimize)

Proof of concept phase

1) Capture an image of the screen in bitmap format

2) Section the image into blocks of contiguous bytes. You need to play around to find out what the optimal block size is; it will vary by uplink/downlink speed.

3) Get a short hash (crc32, maybe md5, experiment with this as well) for each block

4) Compress (don't forget to do this!) and transfer each changed block (If the hash changed, the block changed and needs to be transferred). Stitch the image together at the receiving end to display it.

5) Use UDP packets for data transfer.

Optimization phase

These are things you can do to optimize for speed:

1) Gather stats and hard code transfer speed vs frame size and hash method for optimal transfer speed

2) Make a self-adjusting mechanism for #1

3) Images compress better in square areas rather then contiguous blocks of bytes, as I explained in #2 of the first phase above. Change your algorithm so you are getting a visual square area rather than sequential blocks of lines. This square method is how the image and video compression people do it.

4) Play around with the compression algorithm. This will give you lots of variables to play with (CPU load vs internet access speed vs compression algorithm choice vs frequency of screen updates)

This is basically a summary of how (roughly) compressed video streaming works (you can see the similarities with your task if you think about it), so it's not an unproven concept.

HTH

EDIT: One more thing you can experiment with: After you capture a bitmap of the screen, reduce the number of colors in it. You can save half the image size if you go from 32 bit color depth to 16 bit, for example.