diff mbox

vnc: allow fall back to RAW encoding

Message ID 1440679585-13984-1-git-send-email-pl@kamp.de
State New
Headers show

Commit Message

Peter Lieven Aug. 27, 2015, 12:46 p.m. UTC
I have observed that depending on the contents and the encoding it happens
that sending data as RAW sometimes would take less space than the encoded data.
This is especially the case for small updates or areas with high color images.
If sending RAW encoded data is beneficial allow a fall back to RAW encoding
for the framebuffer update.

Signed-off-by: Peter Lieven <pl@kamp.de>
---
 ui/vnc.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

Comments

Gerd Hoffmann Aug. 28, 2015, 11:56 a.m. UTC | #1
On Do, 2015-08-27 at 14:46 +0200, Peter Lieven wrote:
> I have observed that depending on the contents and the encoding it happens
> that sending data as RAW sometimes would take less space than the encoded data.
> This is especially the case for small updates or areas with high color images.
> If sending RAW encoded data is beneficial allow a fall back to RAW encoding
> for the framebuffer update.

Do you happen to have some stats for this, especially the "small update"
case?  We might want to go straight to raw (without trying other
encodings) for small updates, to avoid encoding things twice.

cheers,
  Gerd
Peter Lieven Aug. 28, 2015, 6:24 p.m. UTC | #2
Am 28.08.2015 um 13:56 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 14:46 +0200, Peter Lieven wrote:
>> I have observed that depending on the contents and the encoding it happens
>> that sending data as RAW sometimes would take less space than the encoded data.
>> This is especially the case for small updates or areas with high color images.
>> If sending RAW encoded data is beneficial allow a fall back to RAW encoding
>> for the framebuffer update.
> Do you happen to have some stats for this, especially the "small update"
> case?  We might want to go straight to raw (without trying other
> encodings) for small updates, to avoid encoding things twice.

Interesting idea. I think this magic number is different for each encoding though.
I think its possible to calculate it and then know that a update ip to a given
size cannot be smaller than encoded in raw - no matter what contents
are in that update.

Peter
Peter Lieven Aug. 31, 2015, 8:55 a.m. UTC | #3
Am 28.08.2015 um 13:56 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 14:46 +0200, Peter Lieven wrote:
>> I have observed that depending on the contents and the encoding it happens
>> that sending data as RAW sometimes would take less space than the encoded data.
>> This is especially the case for small updates or areas with high color images.
>> If sending RAW encoded data is beneficial allow a fall back to RAW encoding
>> for the framebuffer update.
> Do you happen to have some stats for this, especially the "small update"
> case?  We might want to go straight to raw (without trying other
> encodings) for small updates, to avoid encoding things twice.

I had a look at hextile, zrle, tight and zlib encoding. It seems that the case
that raw encoding is smaller never happens for zrle and tight. For zlib and
hextile its quite common, but there is no obvious mark for the size of the
update. It seems to heavily depend on the contents as assumed earlier.

I understand your concern of twice encoding, but I think there is no easy
way to avoid this. However, sending the data as raw later on is a cheap
operation because the patch only does it when no pixel conversion has to be made.

Peter
Gerd Hoffmann Sept. 3, 2015, 8:54 a.m. UTC | #4
On Mo, 2015-08-31 at 10:55 +0200, Peter Lieven wrote:
> Am 28.08.2015 um 13:56 schrieb Gerd Hoffmann:
> > On Do, 2015-08-27 at 14:46 +0200, Peter Lieven wrote:
> >> I have observed that depending on the contents and the encoding it happens
> >> that sending data as RAW sometimes would take less space than the encoded data.
> >> This is especially the case for small updates or areas with high color images.
> >> If sending RAW encoded data is beneficial allow a fall back to RAW encoding
> >> for the framebuffer update.
> > Do you happen to have some stats for this, especially the "small update"
> > case?  We might want to go straight to raw (without trying other
> > encodings) for small updates, to avoid encoding things twice.
> 
> I had a look at hextile, zrle, tight and zlib encoding. It seems that the case
> that raw encoding is smaller never happens for zrle and tight. For zlib and
> hextile its quite common, but there is no obvious mark for the size of the
> update. It seems to heavily depend on the contents as assumed earlier.

Ok, taking patch as-is then.

cheers,
  Gerd
diff mbox

Patch

diff --git a/ui/vnc.c b/ui/vnc.c
index 57f0e54..5bf2875 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -899,6 +899,8 @@  int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     int n = 0;
+    bool encode_raw = false;
+    size_t saved_offs = vs->output.offset;
 
     switch(vs->vnc_encoding) {
         case VNC_ENCODING_ZLIB:
@@ -921,10 +923,24 @@  int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
             n = vnc_zywrle_send_framebuffer_update(vs, x, y, w, h);
             break;
         default:
-            vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
-            n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+            encode_raw = true;
             break;
     }
+
+    /* If the client has the same pixel format as our internal buffer and
+     * a RAW encoding would need less space fall back to RAW encoding to
+     * save bandwidth and processing power in the client. */
+    if (!encode_raw && vs->write_pixels == vnc_write_pixels_copy &&
+        12 + h * w * VNC_SERVER_FB_BYTES <= (vs->output.offset - saved_offs)) {
+        vs->output.offset = saved_offs;
+        encode_raw = true;
+    }
+
+    if (encode_raw) {
+        vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
+        n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+    }
+
     return n;
 }