Merge pull request #1398 from novnc/compressionlevel

Add ability to set Tight compression level
This commit is contained in:
Samuel Mannehed 2020-05-01 20:49:49 +02:00 committed by GitHub
commit 776cda5dc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 155 additions and 1 deletions

View File

@ -162,6 +162,7 @@ const UI = {
UI.initSetting('view_clip', false); UI.initSetting('view_clip', false);
UI.initSetting('resize', 'off'); UI.initSetting('resize', 'off');
UI.initSetting('quality', 6); UI.initSetting('quality', 6);
UI.initSetting('compression', 2);
UI.initSetting('shared', true); UI.initSetting('shared', true);
UI.initSetting('view_only', false); UI.initSetting('view_only', false);
UI.initSetting('show_dot', false); UI.initSetting('show_dot', false);
@ -350,6 +351,8 @@ const UI = {
UI.addSettingChangeHandler('resize', UI.updateViewClip); UI.addSettingChangeHandler('resize', UI.updateViewClip);
UI.addSettingChangeHandler('quality'); UI.addSettingChangeHandler('quality');
UI.addSettingChangeHandler('quality', UI.updateQuality); UI.addSettingChangeHandler('quality', UI.updateQuality);
UI.addSettingChangeHandler('compression');
UI.addSettingChangeHandler('compression', UI.updateCompression);
UI.addSettingChangeHandler('view_clip'); UI.addSettingChangeHandler('view_clip');
UI.addSettingChangeHandler('view_clip', UI.updateViewClip); UI.addSettingChangeHandler('view_clip', UI.updateViewClip);
UI.addSettingChangeHandler('shared'); UI.addSettingChangeHandler('shared');
@ -841,6 +844,7 @@ const UI = {
UI.updateSetting('view_clip'); UI.updateSetting('view_clip');
UI.updateSetting('resize'); UI.updateSetting('resize');
UI.updateSetting('quality'); UI.updateSetting('quality');
UI.updateSetting('compression');
UI.updateSetting('shared'); UI.updateSetting('shared');
UI.updateSetting('view_only'); UI.updateSetting('view_only');
UI.updateSetting('path'); UI.updateSetting('path');
@ -1043,6 +1047,7 @@ const UI = {
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale'; UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote'; UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality')); UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
UI.rfb.showDotCursor = UI.getSetting('show_dot'); UI.rfb.showDotCursor = UI.getSetting('show_dot');
UI.updateViewOnly(); // requires UI.rfb UI.updateViewOnly(); // requires UI.rfb
@ -1349,6 +1354,18 @@ const UI = {
/* ------^------- /* ------^-------
* /QUALITY * /QUALITY
* ============== * ==============
* COMPRESSION
* ------v------*/
updateCompression() {
if (!UI.rfb) return;
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
},
/* ------^-------
* /COMPRESSION
* ==============
* KEYBOARD * KEYBOARD
* ------v------*/ * ------v------*/

View File

@ -278,6 +278,7 @@ export default class RFB extends EventTargetMixin {
} }
this._qualityLevel = 6; this._qualityLevel = 6;
this._compressionLevel = 2;
} }
// ===== PROPERTIES ===== // ===== PROPERTIES =====
@ -360,6 +361,26 @@ export default class RFB extends EventTargetMixin {
} }
} }
get compressionLevel() {
return this._compressionLevel;
}
set compressionLevel(compressionLevel) {
if (!Number.isInteger(compressionLevel) || compressionLevel < 0 || compressionLevel > 9) {
Log.Error("compressionLevel must be an integer between 0 and 9");
return;
}
if (this._compressionLevel === compressionLevel) {
return;
}
this._compressionLevel = compressionLevel;
if (this._rfb_connection_state === 'connected') {
this._sendEncodings();
}
}
// ===== PUBLIC METHODS ===== // ===== PUBLIC METHODS =====
disconnect() { disconnect() {
@ -1411,7 +1432,7 @@ export default class RFB extends EventTargetMixin {
// Psuedo-encoding settings // Psuedo-encoding settings
encs.push(encodings.pseudoEncodingQualityLevel0 + this._qualityLevel); encs.push(encodings.pseudoEncodingQualityLevel0 + this._qualityLevel);
encs.push(encodings.pseudoEncodingCompressLevel0 + 2); encs.push(encodings.pseudoEncodingCompressLevel0 + this._compressionLevel);
encs.push(encodings.pseudoEncodingDesktopSize); encs.push(encodings.pseudoEncodingDesktopSize);
encs.push(encodings.pseudoEncodingLastRect); encs.push(encodings.pseudoEncodingLastRect);

View File

@ -69,6 +69,14 @@ protocol stream.
Value `0` implies low quality and `9` implies high quality. Value `0` implies low quality and `9` implies high quality.
Default value is `6`. Default value is `6`.
`compressionLevel`
- Is an `int` in range `[0-9]` controlling the desired compression
level. Value `0` means no compression. Level 1 uses a minimum of CPU
resources and achieves weak compression ratios, while level 9 offers
best compression but is slow in terms of CPU consumption on the server
side. Use high levels with very slow network connections.
Default value is `2`.
`capabilities` *Read only* `capabilities` *Read only*
- Is an `Object` indicating which optional extensions are available - Is an `Object` indicating which optional extensions are available
on the server. Some methods may only be called if the corresponding on the server. Some methods may only be called if the corresponding

View File

@ -63,6 +63,8 @@ query string. Currently the following options are available:
* `quality` - The session JPEG quality level. Can be `0` to `9`. * `quality` - The session JPEG quality level. Can be `0` to `9`.
* `compression` - The session compression level. Can be `0` to `9`.
* `show_dot` - If a dot cursor should be shown when the remote server provides * `show_dot` - If a dot cursor should be shown when the remote server provides
no local cursor, or provides a fully-transparent (invisible) cursor. no local cursor, or provides a fully-transparent (invisible) cursor.

View File

@ -2967,6 +2967,108 @@ describe('Remote Frame Buffer Protocol Client', function () {
expect(RFB.messages.clientEncodings.getCall(0).args[1]).to.include(encodings.pseudoEncodingQualityLevel0 + newQuality); expect(RFB.messages.clientEncodings.getCall(0).args[1]).to.include(encodings.pseudoEncodingQualityLevel0 + newQuality);
}); });
}); });
describe('Compression level setting', function () {
const defaultCompression = 2;
let client;
beforeEach(function () {
client = make_rfb();
sinon.spy(RFB.messages, "clientEncodings");
});
afterEach(function () {
RFB.messages.clientEncodings.restore();
});
it(`should equal ${defaultCompression} by default`, function () {
expect(client._compressionLevel).to.equal(defaultCompression);
});
it('should ignore non-integers when set', function () {
client.compressionLevel = '1';
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = 1.5;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = null;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = undefined;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = {};
expect(RFB.messages.clientEncodings).to.not.have.been.called;
});
it('should ignore integers out of range [0, 9]', function () {
client.compressionLevel = -1;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = 10;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
});
it('should send clientEncodings with new compression value', function () {
let newCompression;
newCompression = 5;
client.compressionLevel = newCompression;
expect(client.compressionLevel).to.equal(newCompression);
expect(RFB.messages.clientEncodings).to.have.been.calledOnce;
expect(RFB.messages.clientEncodings.getCall(0).args[1]).to.include(encodings.pseudoEncodingCompressLevel0 + newCompression);
});
it('should not send clientEncodings if compression is the same', function () {
let newCompression;
newCompression = 9;
client.compressionLevel = newCompression;
expect(RFB.messages.clientEncodings).to.have.been.calledOnce;
expect(RFB.messages.clientEncodings.getCall(0).args[1]).to.include(encodings.pseudoEncodingCompressLevel0 + newCompression);
RFB.messages.clientEncodings.resetHistory();
client.compressionLevel = newCompression;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
});
it('should not send clientEncodings if not in connected state', function () {
let newCompression;
client._rfb_connection_state = '';
newCompression = 7;
client.compressionLevel = newCompression;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client._rfb_connection_state = 'connnecting';
newCompression = 6;
client.compressionLevel = newCompression;
expect(RFB.messages.clientEncodings).to.not.have.been.called;
RFB.messages.clientEncodings.resetHistory();
client._rfb_connection_state = 'connected';
newCompression = 5;
client.compressionLevel = newCompression;
expect(RFB.messages.clientEncodings).to.have.been.calledOnce;
expect(RFB.messages.clientEncodings.getCall(0).args[1]).to.include(encodings.pseudoEncodingCompressLevel0 + newCompression);
});
});
}); });
describe('RFB messages', function () { describe('RFB messages', function () {

View File

@ -211,6 +211,10 @@
<label for="noVNC_setting_quality">Quality:</label> <label for="noVNC_setting_quality">Quality:</label>
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6"> <input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
</li> </li>
<li>
<label for="noVNC_setting_compression">Compression level:</label>
<input id="noVNC_setting_compression" type="range" min="0" max="9" value="2">
</li>
<li><hr></li> <li><hr></li>
<li> <li>
<label for="noVNC_setting_repeaterID">Repeater ID:</label> <label for="noVNC_setting_repeaterID">Repeater ID:</label>