KASM-1834 expose quality settings

This commit is contained in:
matt 2021-08-02 17:13:01 +00:00
parent 67466077c0
commit 30326f7c11
3 changed files with 403 additions and 52 deletions

View File

@ -188,6 +188,18 @@ const UI = {
UI.initSetting('view_clip', false);
/* UI.initSetting('resize', 'off'); */
UI.initSetting('quality', 6);
UI.initSetting('dynamic_quality_min', 3);
UI.initSetting('dynamic_quality_max', 9);
UI.initSetting('treat_lossless', 7);
UI.initSetting('jpeg_video_quality', 5);
UI.initSetting('webp_video_quality', 5);
UI.initSetting('video_area', 65);
UI.initSetting('video_time', 5);
UI.initSetting('video_out_time', 3);
UI.initSetting('video_scaling', 2);
UI.initSetting('max_video_resolution_x', 960);
UI.initSetting('max_video_resolution_y', 540);
UI.initSetting('framerate', 30);
UI.initSetting('compression', 2);
UI.initSetting('shared', true);
UI.initSetting('view_only', false);
@ -394,6 +406,30 @@ const UI = {
UI.addSettingChangeHandler('resize', UI.updateViewClip);
UI.addSettingChangeHandler('quality');
UI.addSettingChangeHandler('quality', UI.updateQuality);
UI.addSettingChangeHandler('dynamic_quality_min');
UI.addSettingChangeHandler('dynamic_quality_min', UI.updateQuality);
UI.addSettingChangeHandler('dynamic_quality_max');
UI.addSettingChangeHandler('dynamic_quality_max', UI.updateQuality);
UI.addSettingChangeHandler('treat_lossless');
UI.addSettingChangeHandler('treat_lossless', UI.updateQuality);
UI.addSettingChangeHandler('jpeg_video_quality');
UI.addSettingChangeHandler('jpeg_video_quality', UI.updateQuality);
UI.addSettingChangeHandler('webp_video_quality');
UI.addSettingChangeHandler('webp_video_quality', UI.updateQuality);
UI.addSettingChangeHandler('video_area');
UI.addSettingChangeHandler('video_area', UI.updateQuality);
UI.addSettingChangeHandler('video_time');
UI.addSettingChangeHandler('video_time', UI.updateQuality);
UI.addSettingChangeHandler('video_out_time');
UI.addSettingChangeHandler('video_out_time', UI.updateQuality);
UI.addSettingChangeHandler('video_scaling');
UI.addSettingChangeHandler('video_scaling', UI.updateQuality);
UI.addSettingChangeHandler('max_video_resolution_x');
UI.addSettingChangeHandler('max_video_resolution_x', UI.updateQuality);
UI.addSettingChangeHandler('max_video_resolution_y');
UI.addSettingChangeHandler('max_video_resolution_y', UI.updateQuality);
UI.addSettingChangeHandler('framerate');
UI.addSettingChangeHandler('framerate', UI.updateQuality);
UI.addSettingChangeHandler('compression');
UI.addSettingChangeHandler('compression', UI.updateCompression);
UI.addSettingChangeHandler('view_clip');
@ -833,7 +869,11 @@ const UI = {
}
}
} else {
let value_label = document.getElementById('noVNC_setting_' + name + '_output');
ctrl.value = value;
if (value_label) {
value_label.value = value;
}
}
},
@ -910,6 +950,18 @@ const UI = {
UI.updateSetting('view_clip');
UI.updateSetting('resize');
UI.updateSetting('quality');
UI.updateSetting('dynamic_quality_min', 3);
UI.updateSetting('dynamic_quality_max', 9);
UI.updateSetting('treat_lossless', 7);
UI.updateSetting('jpeg_video_quality', 5);
UI.updateSetting('webp_video_quality', 5);
UI.updateSetting('video_area', 65);
UI.updateSetting('video_time', 5);
UI.updateSetting('video_out_time', 3);
UI.updateSetting('video_scaling', 2);
UI.updateSetting('max_video_resolution_x', 960);
UI.updateSetting('max_video_resolution_y', 540);
UI.updateSetting('framerate', 30);
UI.updateSetting('compression');
UI.updateSetting('shared');
UI.updateSetting('view_only');
@ -1214,6 +1266,18 @@ const UI = {
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
UI.rfb.dynamicQualityMin = parseInt(UI.getSetting('dynamic_quality_min'));
UI.rfb.dynamicQualityMax = parseInt(UI.getSetting('dynamic_quality_max'));
UI.rfb.jpegVideoQuality = parseInt(UI.getSetting('jpeg_video_quality'));
UI.rfb.webpVideoQuality = parseInt(UI.getSetting('webp_video_quality'));
UI.rfb.videoArea = parseInt(UI.getSetting('video_area'));
UI.rfb.videoTime = parseInt(UI.getSetting('video_time'));
UI.rfb.videoOutTime = parseInt(UI.getSetting('video_out_time'));
UI.rfb.videoScaling = parseInt(UI.getSetting('video_scaling'));
UI.rfb.treatLossless = parseInt(UI.getSetting('treat_lossless'));
UI.rfb.maxVideoResolutionX = parseInt(UI.getSetting('max_video_resolution_x'));
UI.rfb.maxVideoResolutionY = parseInt(UI.getSetting('max_video_resolution_y'));
UI.rfb.frameRate = parseInt(UI.getSetting('framerate'));
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
UI.rfb.showDotCursor = UI.getSetting('show_dot');
UI.rfb.idleDisconnect = UI.getSetting('idle_disconnect');
@ -1624,7 +1688,26 @@ const UI = {
updateQuality() {
if (!UI.rfb) return;
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
if (!UI.updatingSettings) {
// avoid sending too many, will only apply when there are changes
setTimeout(function() {
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
UI.rfb.dynamicQualityMin = parseInt(UI.getSetting('dynamic_quality_min'));
UI.rfb.dynamicQualityMax = parseInt(UI.getSetting('dynamic_quality_max'));
UI.rfb.jpegVideoQuality = parseInt(UI.getSetting('jpeg_video_quality'));
UI.rfb.webpVideoQuality = parseInt(UI.getSetting('webp_video_quality'));
UI.rfb.videoArea = parseInt(UI.getSetting('video_area'));
UI.rfb.videoTime = parseInt(UI.getSetting('video_time'));
UI.rfb.videoOutTime = parseInt(UI.getSetting('video_out_time'));
UI.rfb.videoScaling = parseInt(UI.getSetting('video_scaling'));
UI.rfb.treatLossless = parseInt(UI.getSetting('treat_lossless'));
UI.rfb.maxVideoResolutionX = parseInt(UI.getSetting('max_video_resolution_x'));
UI.rfb.maxVideoResolutionY = parseInt(UI.getSetting('max_video_resolution_y'));
UI.rfb.frameRate = parseInt(UI.getSetting('framerate'));
UI.rfb.enableWebP = UI.getSetting('enable_webp');
}, 2000);
}
},
/* ------^-------

View File

@ -337,48 +337,9 @@ export default class RFB extends EventTargetMixin {
get videoQuality() { return this._videoQuality; }
set videoQuality(quality) { this._videoQuality = quality; }
get enableWebP() { return this._enableWebP; }
set enableWebP(enabled) { this._enableWebP = enabled; }
get jpegVideoQuality() { return this._jpegVideoQuality; }
set jpegVideoQuality(val) { this._jpegVideoQuality = val; }
get webpVideoQuality() { return this._webpVideoQuality; }
set webpVideoQuality(val) { this._webpVideoQuality = val; }
get treatLossless() { return this._treatLossless; }
set treatLossless(val) { this._treatLossless = val; }
get preferBandwidth() { return this._preferBandwidth; }
set preferBandwidth(val) { this._preferBandwidth = val; }
get dynamicQualityMin() { return this._dynamicQualityMin; }
set dynamicQualityMin(val) { this._dynamicQualityMin = val; }
get dynamicQualityMax() { return this._dynamicQualityMax; }
set dynamicQualityMax(val) { this._dynamicQualityMax = val; }
get videoArea() { return this._videoArea; }
set videoArea(val) { this._videoArea = val; }
get videoTime() { return this._videoTime; }
set videoTime(val) { this._videoTime = val; }
get videoOutTime() { return this._videoOutTime; }
set videoOutTime(val) { this._videoOutTime = val; }
get videoScaling() { return this._videoScaling; }
set videoScaling(val) { this._videoScaling = val; }
get frameRate() { return this._frameRate; }
set frameRate(val) { this._frameRate = val; }
get maxVideoResolutionX() { return this._maxVideoResolutionX; }
set maxVideoResolutionX(val) { this._maxVideoResolutionX = val; }
get maxVideoResolutionY() { return this._maxVideoResolutionY; }
set maxVideoResolutionY(val) { this._maxVideoResolutionY = val; }
get viewOnly() { return this._viewOnly; }
set viewOnly(viewOnly) {
this._viewOnly = viewOnly;
@ -436,6 +397,246 @@ export default class RFB extends EventTargetMixin {
get background() { return this._screen.style.background; }
set background(cssValue) { this._screen.style.background = cssValue; }
get enableWebP() { return this._enableWebP; }
set enableWebP(enabled) {
if (this._enableWebP === enabled) {
return;
}
this._enableWebP = enabled;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get jpegVideoQuality() { return this._jpegVideoQuality; }
set jpegVideoQuality(qualityLevel) {
if (!Number.isInteger(qualityLevel) || qualityLevel < 0 || qualityLevel > 9) {
Log.Error("qualityLevel must be an integer between 0 and 9");
return;
}
if (this._jpegVideoQuality === qualityLevel) {
return;
}
this._jpegVideoQuality = qualityLevel;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get webpVideoQuality() { return this._webpVideoQuality; }
set webpVideoQuality(qualityLevel) {
if (!Number.isInteger(qualityLevel) || qualityLevel < 0 || qualityLevel > 9) {
Log.Error("qualityLevel must be an integer between 0 and 9");
return;
}
if (this._webpVideoQuality === qualityLevel) {
return;
}
this._webpVideoQuality = qualityLevel;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get treatLossless() { return this._treatLossless; }
set treatLossless(qualityLevel) {
if (!Number.isInteger(qualityLevel) || qualityLevel < 0 || qualityLevel > 9) {
Log.Error("qualityLevel must be an integer between 0 and 9");
return;
}
if (this._treatLossless === qualityLevel) {
return;
}
this._treatLossless = qualityLevel;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get dynamicQualityMin() { return this._dynamicQualityMin; }
set dynamicQualityMin(qualityLevel) {
if (!Number.isInteger(qualityLevel) || qualityLevel < 0 || qualityLevel > 9) {
Log.Error("qualityLevel must be an integer between 0 and 9");
return;
}
if (this._dynamicQualityMin === qualityLevel) {
return;
}
this._dynamicQualityMin = qualityLevel;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get dynamicQualityMax() { return this._dynamicQualityMax; }
set dynamicQualityMax(qualityLevel) {
if (!Number.isInteger(qualityLevel) || qualityLevel < 0 || qualityLevel > 9) {
Log.Error("qualityLevel must be an integer between 0 and 9");
return;
}
if (this._dynamicQualityMax === qualityLevel) {
return;
}
this._dynamicQualityMax = qualityLevel;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get videoArea() {
return this._videoArea;
}
set videoArea(area) {
if (!Number.isInteger(area) || area < 0 || area > 100) {
Log.Error("video area must be an integer between 0 and 100");
return;
}
if (this._videoArea === area) {
return;
}
this._videoArea = area;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get videoTime() {
return this._videoTime;
}
set videoTime(value) {
if (!Number.isInteger(value) || value < 0 || value > 100) {
Log.Error("video time must be an integer between 0 and 100");
return;
}
if (this._videoTime === value) {
return;
}
this._videoTime = value;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get videoOutTime() {
return this._videoOutTime;
}
set videoOutTime(value) {
if (!Number.isInteger(value) || value < 0 || value > 100) {
Log.Error("video out time must be an integer between 0 and 100");
return;
}
if (this._videoOutTime === value) {
return;
}
this._videoOutTime = value;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get videoScaling() {
return this._videoScaling;
}
set videoScaling(value) {
if (!Number.isInteger(value) || value < 0 || value > 2) {
Log.Error("video scaling must be an integer between 0 and 2");
return;
}
if (this._videoScaling === value) {
return;
}
this._videoScaling = value;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get frameRate() { return this._frameRate; }
set frameRate(value) {
if (!Number.isInteger(value) || value < 1 || value > 120) {
Log.Error("frame rate must be an integer between 1 and 120");
return;
}
if (this._frameRate === value) {
return;
}
this._frameRate = value;
if (this._rfbConnectionState === 'connected') {
this._sendEncodings();
}
}
get maxVideoResolutionX() { return this._maxVideoResolutionX; }
set maxVideoResolutionX(value) {
if (!Number.isInteger(value) || value < 100 ) {
Log.Error("max video resolution must be an integer greater than 100");
return;
}
if (this._maxVideoResolutionX === value) {
return;
}
this._maxVideoResolutionX = value;
if (this._rfbConnectionState === 'connected') {
RFB.messages.setMaxVideoResolution(this._sock,
this._maxVideoResolutionX,
this._maxVideoResolutionY);
}
}
get maxVideoResolutionY() { return this._maxVideoResolutionY; }
set maxVideoResolutionY(value) {
if (!Number.isInteger(value) || value < 100 ) {
Log.Error("max video resolution must be an integer greater than 100");
return;
}
if (this._maxVideoResolutionY === value) {
return;
}
this._maxVideoResolutionY = value;
if (this._rfbConnectionState === 'connected') {
RFB.messages.setMaxVideoResolution(this._sock,
this._maxVideoResolutionX,
this._maxVideoResolutionY);
}
}
get qualityLevel() {
return this._qualityLevel;
}
@ -1878,7 +2079,6 @@ export default class RFB extends EventTargetMixin {
_sendEncodings() {
const encs = [];
var hasWebp;
// In preference order
encs.push(encodings.encodingCopyRect);
@ -1932,6 +2132,7 @@ export default class RFB extends EventTargetMixin {
encs.push(encodings.pseudoEncodingVideoScalingLevel0 + this.videoScaling);
encs.push(encodings.pseudoEncodingFrameRateLevel10 + this.frameRate - 10);
encs.push(encodings.pseudoEncodingMaxVideoResolution);
// preferBandwidth choses preset settings. Since we expose all the settings, lets not pass this
if (this.preferBandwidth) // must be last - server processes in reverse order
encs.push(encodings.pseudoEncodingPreferBandwidth);

View File

@ -48,7 +48,7 @@
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/368_kasm_logo_only_152x152.png">
<!-- Stylesheets -->
<link rel="stylesheet" href="app/styles/base.css">
<!--link rel="stylesheet" href="app/styles/base.css">
<script src="app/error-handler.js"></script>
@ -67,7 +67,7 @@
}
</script>
<script type="module" crossorigin="use-credentials" src="app/ui.js"></script>
<script type="module" crossorigin="use-credentials" src="app/ui.js"></script-->
</head>
<body>
@ -197,14 +197,6 @@
<label><input id="noVNC_setting_enable_perf_stats" type="checkbox" /> Enable Performance Stats</label></li>
<li>
<label><input id="noVNC_setting_toggle_control_panel" type="checkbox" /> Toggle Control Panel via Keystrokes</label></li>
<li>
<label for="noVNC_setting_video_quality">Video Quality:</label>
<select id="noVNC_setting_video_quality" name="vncVideoQuality">
<option value=0>Low</option>
<option value=1>Medium</option>
<option value=2>High</option>
</select>
</li>
<li>
<label for="noVNC_setting_idle_disconnect">Idle Timeout:</label>
<select id="noVNC_setting_idle_disconnect" name="vncIdleDisconnect">
@ -224,12 +216,87 @@
</select>
</li>
<li><hr></li>
<li>
<div class="noVNC_expander">Video Mode Settings</div>
<div><ul>
<li>
<label for="noVNC_setting_video_quality">Video Quality:</label>
<select id="noVNC_setting_video_quality" name="vncVideoQuality">
<option value=0>Low</option>
<option value=1>Medium</option>
<option value=2>High</option>
</select>
</li>
<li>
<label for="noVNC_setting_jpeg_video_quality">JPEG Quality:</label>
<input id="noVNC_setting_jpeg_video_quality" type="range" min="0" max="9" value="5" onchange="noVNC_setting_jpeg_video_quality_output.value=value">
<output id="noVNC_setting_jpeg_video_quality_output">5</output>
</li>
<li>
<label for="noVNC_setting_webp_video_quality">WEBP Quality:</label>
<input id="noVNC_setting_webp_video_quality" type="range" min="0" max="9" value="5" onchange="noVNC_setting_webp_video_quality_output.value=value">
<output id="noVNC_setting_webp_video_quality_output">5</output>
</li>
<li>
<label for="noVNC_setting_video_area">Video Area:</label>
<input id="noVNC_setting_video_area" type="range" min="0" max="100" value="65" onchange="noVNC_setting_video_area_output.value=value">
<output id="noVNC_setting_video_area_output">65</output>
</li>
<li>
<label for="noVNC_setting_video_time">Video Time:</label>
<input id="noVNC_setting_video_time" type="range" min="0" max="60" value="5" onchange="noVNC_setting_video_time_output.value=value">
<output id="noVNC_setting_video_time_output">5</output>
</li>
<li>
<label for="noVNC_setting_video_out_time">Video Out Time:</label>
<input id="noVNC_setting_video_out_time" type="range" min="0" max="60" value="3" onchange="noVNC_setting_video_out_time_output.value=value">
<output id="noVNC_setting_video_out_time_output">3</output>
</li>
<li>
<label for="noVNC_setting_video_scaling">Scaling Mode:</label>
<select id="noVNC_setting_video_scaling" name="vncVideoModeScaling">
<option value="0">Nearest</option>
<option value="1">Bilinear</option>
<option value="2">Progressive Bilinear</option>
</select>
</li>
<li>
<label for="noVNC_setting_max_video_resolution_x">Max Width:</label>
<input id="noVNC_setting_max_video_resolution_x" type="number" min="100" max="3840" value="960">
</li>
<li>
<label for="noVNC_setting_max_video_resolution_y">Max Height:</label>
<input id="noVNC_setting_max_video_resolution_y" type="number" min="100" max="2160" value="540">
</li>
</ul></div>
</li>
<li><hr></li>
<li>
<div class="noVNC_expander">Advanced</div>
<div><ul>
<li>
<li style="display: none;">
<label for="noVNC_setting_quality">Quality:</label>
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
</li>
<li title="Dynamic image quality minimum level.">
<label for="noVNC_setting_dynamic_quality_min">Dynamic Quality Min:</label>
<input id="noVNC_setting_dynamic_quality_min" type="range" min="0" max="9" value="3" onchange="noVNC_setting_dynamic_quality_min_output.value=value">
<output id="noVNC_setting_dynamic_quality_min_output">3</output>
</li>
<li>
<label for="noVNC_setting_dynamic_quality_max">Dynamic Quality Max:</label>
<input id="noVNC_setting_dynamic_quality_max" type="range" min="0" max="9" value="9" onchange="noVNC_setting_dynamic_quality_max_output.value=value">
<output id="noVNC_setting_dynamic_quality_max_output">9</output>
</li>
<li>
<label for="noVNC_setting_treat_lossless">Treat Lossless:</label>
<input id="noVNC_setting_treat_lossless" type="range" min="0" max="9" value="7" onchange="noVNC_setting_treat_lossless_output.value=value">
<output id="noVNC_setting_treat_lossless_output">7</output>
</li>
<li>
<label for="noVNC_setting_framerate">Frame Rate:</label>
<input id="noVNC_setting_framerate" type="number" min="1" max="120" value="30">
</li>
<li>
<label for="noVNC_setting_compression">Compression level:</label>