Commit 29cb15f9 authored by Joel Martin's avatar Joel Martin

TIGHT_PNG encoding and timing refactor.

Also, generate encodings array to send from a list of encodings
instead of being hardcoded generator function.
parent af183e63
...@@ -25,7 +25,7 @@ var VNC_native_ws, RFB; ...@@ -25,7 +25,7 @@ var VNC_native_ws, RFB;
// Uncomment to activate firebug lite // Uncomment to activate firebug lite
//extra += start + "http://getfirebug.com/releases/lite/1.2/" + //extra += start + "http://getfirebug.com/releases/lite/1.2/" +
// firebug-lite-compressed.js" + end; // "firebug-lite-compressed.js" + end;
extra += start + "include/mootools.js" + end; extra += start + "include/mootools.js" + end;
extra += start + "include/base64.js" + end; extra += start + "include/base64.js" + end;
...@@ -56,6 +56,16 @@ RFB = { ...@@ -56,6 +56,16 @@ RFB = {
*/ */
clipboardFocus : false, clipboardFocus : false,
encodings : [
0x17, // TIGHT_PNG
Math.pow(2,32) - 32, // JPEG quality pseudo-encoding
5, // HEXTILE
2, // RRE
1, // COPYRECT
0 // RAW
],
setUpdateState: function(externalUpdateState) { setUpdateState: function(externalUpdateState) {
RFB.externalUpdateState = externalUpdateState; RFB.externalUpdateState = externalUpdateState;
}, },
...@@ -421,7 +431,7 @@ init_msg: function () { ...@@ -421,7 +431,7 @@ init_msg: function () {
} }
response = RFB.pixelFormat(); response = RFB.pixelFormat();
response = response.concat(RFB.encodings()); response = response.concat(RFB.clientEncodings());
response = response.concat(RFB.fbUpdateRequest(0)); response = response.concat(RFB.fbUpdateRequest(0));
RFB.timing.fbu_rt_start = (new Date()).getTime(); RFB.timing.fbu_rt_start = (new Date()).getTime();
RFB.send_array(response); RFB.send_array(response);
...@@ -464,6 +474,10 @@ normal_msg: function () { ...@@ -464,6 +474,10 @@ normal_msg: function () {
//console.log("FramebufferUpdate, rects:" + FBU.rects); //console.log("FramebufferUpdate, rects:" + FBU.rects);
RFB.timing.cur_fbu = 0; RFB.timing.cur_fbu = 0;
FBU.bytes = 0; FBU.bytes = 0;
if (RFB.timing.fbu_rt_start > 0) {
now = (new Date()).getTime();
console.log("First FBU latency: " + (now - RFB.timing.fbu_rt_start));
}
} }
while ((FBU.rects > 0) && (RQ.length >= FBU.bytes)) { while ((FBU.rects > 0) && (RQ.length >= FBU.bytes)) {
...@@ -485,9 +499,10 @@ normal_msg: function () { ...@@ -485,9 +499,10 @@ normal_msg: function () {
" encoding:" + FBU.encoding " encoding:" + FBU.encoding
switch (FBU.encoding) { switch (FBU.encoding) {
case 0: msg += "(RAW)"; break; case 0: msg += "(RAW)"; break;
case 1: msg += "(COPY-RECT)"; break; case 1: msg += "(COPYRECT)"; break;
case 2: msg += "(RRE)"; break; case 2: msg += "(RRE)"; break;
case 5: msg += "(HEXTILE " + FBU.tiles + " tiles)"; break; case 5: msg += "(HEXTILE)"; break;
case 7: msg += "(TIGHT_PNG)"; break;
default: default:
RFB.updateState('failed', RFB.updateState('failed',
"Disconnected: unsupported encoding " + "Disconnected: unsupported encoding " +
...@@ -502,15 +517,17 @@ normal_msg: function () { ...@@ -502,15 +517,17 @@ normal_msg: function () {
RFB.timing.last_fbu = (new Date()).getTime(); RFB.timing.last_fbu = (new Date()).getTime();
switch (FBU.encoding) { switch (FBU.encoding) {
case 0: ret = RFB.display_raw(); break; // Raw case 0: ret = RFB.display_raw(); break; // Raw
case 1: ret = RFB.display_copy_rect(); break; // Copy-Rect case 1: ret = RFB.display_copy_rect(); break; // CopyRect
case 2: ret = RFB.display_rre(); break; // RRE case 2: ret = RFB.display_rre(); break; // RRE
case 5: ret = RFB.display_hextile(); break; // hextile case 5: ret = RFB.display_hextile(); break; // hextile
case 7: ret = RFB.display_tight_png(); break; // tight_png
} }
now = (new Date()).getTime(); now = (new Date()).getTime();
RFB.timing.cur_fbu += (now - RFB.timing.last_fbu); RFB.timing.cur_fbu += (now - RFB.timing.last_fbu);
if (FBU.rects === 0) { if (FBU.rects === 0) {
if ((FBU.width === RFB.fb_width) && if (((FBU.width === RFB.fb_width) &&
(FBU.height === RFB.fb_height)) { (FBU.height === RFB.fb_height)) ||
(RFB.timing.fbu_rt_start > 0)) {
RFB.timing.full_fbu_total += RFB.timing.cur_fbu; RFB.timing.full_fbu_total += RFB.timing.cur_fbu;
RFB.timing.full_fbu_cnt += 1; RFB.timing.full_fbu_cnt += 1;
console.log("Timing of full FBU, cur: " + console.log("Timing of full FBU, cur: " +
...@@ -519,18 +536,18 @@ normal_msg: function () { ...@@ -519,18 +536,18 @@ normal_msg: function () {
RFB.timing.full_fbu_cnt + ", avg: " + RFB.timing.full_fbu_cnt + ", avg: " +
(RFB.timing.full_fbu_total / (RFB.timing.full_fbu_total /
RFB.timing.full_fbu_cnt)); RFB.timing.full_fbu_cnt));
if (RFB.timing.fbu_rt_start > 0) { }
fbu_rt_diff = now - RFB.timing.fbu_rt_start; if (RFB.timing.fbu_rt_start > 0) {
RFB.timing.fbu_rt_total += fbu_rt_diff; fbu_rt_diff = now - RFB.timing.fbu_rt_start;
RFB.timing.fbu_rt_cnt += 1; RFB.timing.fbu_rt_total += fbu_rt_diff;
console.log("full FBU round-trip, cur: " + RFB.timing.fbu_rt_cnt += 1;
fbu_rt_diff + ", total: " + console.log("full FBU round-trip, cur: " +
RFB.timing.fbu_rt_total + ", cnt: " + fbu_rt_diff + ", total: " +
RFB.timing.fbu_rt_cnt + ", avg: " + RFB.timing.fbu_rt_total + ", cnt: " +
(RFB.timing.fbu_rt_total / RFB.timing.fbu_rt_cnt + ", avg: " +
RFB.timing.fbu_rt_cnt)); (RFB.timing.fbu_rt_total /
RFB.timing.fbu_rt_start = 0; RFB.timing.fbu_rt_cnt));
} RFB.timing.fbu_rt_start = 0;
} }
} }
if (RFB.state !== "normal") { return true; } if (RFB.state !== "normal") { return true; }
...@@ -630,7 +647,7 @@ display_copy_rect: function () { ...@@ -630,7 +647,7 @@ display_copy_rect: function () {
if (RQ.length < 4) { if (RQ.length < 4) {
//console.log(" waiting for " + //console.log(" waiting for " +
// (FBU.bytes - RQ.length) + " COPY-RECT bytes"); // (FBU.bytes - RQ.length) + " COPYRECT bytes");
return; return;
} }
old_x = RQ.shift16(); old_x = RQ.shift16();
...@@ -814,6 +831,101 @@ display_hextile: function() { ...@@ -814,6 +831,101 @@ display_hextile: function() {
}, },
display_tight_png: function() {
//console.log(">> display_tight_png");
var RQ = RFB.RQ, FBU = RFB.FBU,
ctl, cmode, i, clength, color, strdata, img;
//console.log(" FBU.rects: " + FBU.rects);
//console.log(" RQ.length: " + RQ.length);
//console.log(" RQ.slice(0,20): " + RQ.slice(0,20));
FBU.bytes = 1; // compression-control byte
if (RQ.length < FBU.bytes) {
console.log(" waiting for TIGHT compression-control byte");
return;
}
// Get 'compact length' header and data size
getCLength = function (arr, offset) {
var header = 1, data = 0;
data += arr[offset + 0] & 0x7f;
if (arr[offset + 0] & 0x80) {
header++;
data += (arr[offset + 1] & 0x7f) << 7;
if (arr[offset + 1] & 0x80) {
header++;
data += arr[offset + 2] << 14;
}
}
return [header, data];
}
ctl = RQ[0];
switch (ctl >> 4) {
case 0x08: cmode = "fill"; break;
case 0x09: cmode = "jpeg"; break;
case 0x0A: cmode = "png"; break;
default: throw("Illegal ctl: " + ctl); break;
}
switch (cmode) {
// fill uses fb_depth because TPIXELs drop the padding byte
case "fill": FBU.bytes += RFB.fb_depth; break; // TPIXEL
case "jpeg": FBU.bytes += 3; break; // max clength
case "png": FBU.bytes += 3; break; // max clength
}
if (RQ.length < FBU.bytes) {
console.log(" waiting for TIGHT " + cmode + " bytes");
return;
}
//console.log(" cmode: " + cmode);
// Determine FBU.bytes
switch (cmode) {
case "fill":
RQ.shift8(); // shift off ctl
color = RQ.shiftBytes(RFB.fb_depth);
Canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
break;
case "jpeg":
case "png":
clength = getCLength(RQ, 1);
FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data
if (RQ.length < FBU.bytes) {
console.log(" waiting for TIGHT " + cmode + " bytes");
return;
}
// We have everything, render it
//console.log(" png, RQ.length: " + RQ.length + ", clength[0]: " + clength[0] + ", clength[1]: " + clength[1]);
RQ.shiftBytes(1 + clength[0]); // shift off ctl + compact length
img = new Image();
/*
strdata = RQ.shiftBytes(clength[1]).map(function (num) {
return String.fromCharCode(num); } ).join('');
img.src = "data:image/" + cmode + "," + escape(strdata);
*/
img.src = "data:image/" + cmode + "," +
RFB.extract_data_uri(RQ.shiftBytes(clength[1]));
img.onload = (function () {
var x = FBU.x, y = FBU.y;
return function () { Canvas.ctx.drawImage(this, x, y); };
})();
break;
}
FBU.bytes = 0;
FBU.rects --;
//console.log(" ending RQ.length: " + RQ.length);
//console.log(" ending RQ.slice(0,20): " + RQ.slice(0,20));
},
extract_data_uri : function (arr) {
return escape(arr.map(function (num) {
return String.fromCharCode(num); } ).join('') );
},
/* /*
* Client message routines * Client message routines
...@@ -849,20 +961,18 @@ pixelFormat: function () { ...@@ -849,20 +961,18 @@ pixelFormat: function () {
fixColourMapEntries: function () { fixColourMapEntries: function () {
}, },
encodings: function () { clientEncodings: function () {
//console.log(">> setEncodings"); //console.log(">> setEncodings");
var arr; var arr, i;
arr = [2]; // msg-type arr = [2]; // msg-type
arr.push8(0); // padding arr.push8(0); // padding
//arr.push16(3); // encoding count arr.push16(RFB.encodings.length); // encoding count
arr.push16(4); // encoding count
arr.push32(5); // hextile encoding
arr.push32(2); // RRE encoding for (i=0; i<RFB.encodings.length; i++) {
arr.push32(1); // copy-rect encoding arr.push32(RFB.encodings[i]);
arr.push32(0); // raw encoding }
//console.log("<< setEncodings"); console.log("<< setEncodings: " + arr);
return arr; return arr;
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment