From 2941545d2d485d99a85bd0723e9764147ced5114 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 17 Nov 2016 16:14:52 +0000 Subject: [PATCH] #1341: * enable Broadway h264 JS decoder using the new video toggle on the connection page * add video scaling support * clients can tweak codec scoring: use it to select native video ahead of plain h264 (if mediasource video is enabled) git-svn-id: https://xpra.org/svn/Xpra/trunk@14441 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- src/html5/connect.html | 18 +++++++++----- src/html5/index.html | 9 +++++-- src/html5/js/Client.js | 24 +++++++++++-------- src/xpra/server/window/video_scoring.py | 9 +++---- src/xpra/server/window/window_video_source.py | 3 ++- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/html5/connect.html b/src/html5/connect.html index a8759ac6d1..8e1b0e16f9 100644 --- a/src/html5/connect.html +++ b/src/html5/connect.html @@ -204,7 +204,7 @@

Advanced options

Share session
  • - Native video (experimental) + Video (experimental) Native decoding
  • Normal fullscreen windows @@ -308,7 +308,7 @@

    Advanced options

    url = url + "&start="+encodeData(start); } - var bool_props = ["sound", "exit_with_children", "exit_with_client", "sharing", "mediasource_video", "normal_fullscreen", "debug", "insecure"]; + var bool_props = ["sound", "exit_with_children", "exit_with_client", "sharing", "video", "mediasource_video", "normal_fullscreen", "debug", "insecure"]; for (var i = 0; i < bool_props.length; i++) { var prop = bool_props[i]; if(document.getElementById(prop).checked) { @@ -371,11 +371,10 @@

    Advanced options

    $('input#exit_with_client').prop("checked", false); } } - function on_action_change() { + $(document).on('click', '[name="action"]', function() { var action = $(this).val(); set_exit_actions(action=="connect"); - } - $(document).on('click', '[name="action"]', on_action_change); + }); $('input:radio[value="'+action+'"]').click(); var encoding = getparam("encoding") || "jpeg"; @@ -444,7 +443,14 @@

    Advanced options

    var sound = getboolparam("sound"); $('input#sound').prop("checked", sound && codecs_supported.length>0); - var bool_props = ["exit_with_children", "exit_with_client", "sharing", "mediasource_video", "normal_fullscreen", "debug", "insecure"]; + var video = document.getElementById("video"); + function toggle_mediasource_video() { + $('#mediasource_video').prop("disabled", !video.checked); + } + video.onchange = toggle_mediasource_video; + toggle_mediasource_video(); + + var bool_props = ["exit_with_children", "exit_with_client", "sharing", "video", "mediasource_video", "normal_fullscreen", "debug", "insecure"]; for (var i = 0; i < bool_props.length; i++) { var prop = bool_props[i]; document.getElementById(prop).checked = getparam(prop); diff --git a/src/html5/index.html b/src/html5/index.html index 2b71bb6354..00da5faf1b 100644 --- a/src/html5/index.html +++ b/src/html5/index.html @@ -117,6 +117,7 @@ var exit_with_children = getparam("exit_with_children") || ""; var exit_with_client = getparam("exit_with_client") || ""; var sharing = getboolparam("sharing", false); + var video = getboolparam("video", false); var mediasource_video = getboolparam("mediasource_video", false); var normal_fullscreen = getboolparam("normal_fullscreen", false); var remote_logging = getboolparam("remote_logging", true); @@ -131,8 +132,11 @@ client.insecure = insecure; // mediasource video - if(mediasource_video) { - client.supported_encodings.push("vp8+webm", "h264+mp4", "mpeg4+mp4"); + if(video) { + client.supported_encodings.push("h264"); + if(mediasource_video) { + client.supported_encodings.push("vp8+webm", "h264+mp4", "mpeg4+mp4"); + } } else if(encoding) { // the primary encoding can be set @@ -215,6 +219,7 @@ "exit_with_client" : exit_with_client, "sharing" : sharing, "normal_fullscreen" : normal_fullscreen, + "video" : video, "mediasource_video" : mediasource_video, "debug" : debug, "remote_logging" : remote_logging, diff --git a/src/html5/js/Client.js b/src/html5/js/Client.js index 0fb341e613..751ff81310 100644 --- a/src/html5/js/Client.js +++ b/src/html5/js/Client.js @@ -29,9 +29,7 @@ function XpraClient(container) { // some client stuff this.capabilities = {}; this.RGB_FORMATS = ["RGBX", "RGBA"]; - //for broadway: - //this.supported_encodings = ["jpeg", "png", "rgb", "rgb32", "h264"]; - this.supported_encodings = ["jpeg", "png", "rgb", "rgb32"]; //"vp8+webm", "h264+mp4", "mpeg4+mp4", "h264"]; + this.supported_encodings = ["jpeg", "png", "rgb", "rgb32"]; //"h264", "vp8+webm", "h264+mp4", "mpeg4+mp4"]; this.enabled_encodings = []; this.normal_fullscreen_mode = false; this.start_new_session = null; @@ -723,20 +721,26 @@ XpraClient.prototype._make_hello = function() { "encoding.csc_atoms" : true, "encoding.scrolling" : true, //video stuff: - "encoding.video_scaling" : false, + "encoding.video_scaling" : true, "encoding.full_csc_modes" : { - //"h264" : ["YUV420P"], + "h264" : ["YUV420P"], "mpeg4+mp4" : ["YUV420P"], "h264+mp4" : ["YUV420P"], "vp8+webm" : ["YUV420P"], }, - //"encoding.x264.YUV420P.profile" : "baseline", - //"encoding.h264.YUV420P.profile" : "baseline", - //"encoding.h264.YUV420P.level" : "2.1", - //"encoding.h264.cabac" : false, - //"encoding.h264.deblocking-filter" : false, + "encoding.x264.YUV420P.profile" : "baseline", + "encoding.h264.YUV420P.profile" : "baseline", + "encoding.h264.YUV420P.level" : "2.1", + "encoding.h264.cabac" : false, + "encoding.h264.deblocking-filter" : false, "encoding.h264+mp4.YUV420P.profile" : "main", "encoding.h264+mp4.YUV420P.level" : "3.0", + //prefer native video in mp4/webm container to broadway plain h264: + "encoding.h264.score-delta" : -20, + "encoding.h264+mp4.score-delta" : 50, + "encoding.mpeg4+mp4.score-delta" : 50, + "encoding.vp8+webm.score-delta" : 50, + "sound.receive" : true, "sound.send" : false, "sound.decoders" : Object.keys(this.audio_codecs), diff --git a/src/xpra/server/window/video_scoring.py b/src/xpra/server/window/video_scoring.py index b65ab77f70..0015ccec5b 100644 --- a/src/xpra/server/window/video_scoring.py +++ b/src/xpra/server/window/video_scoring.py @@ -73,7 +73,8 @@ def get_speed_score(csc_format, csc_spec, encoder_spec, scaling, target_speed=10 def get_pipeline_score(enc_in_format, csc_spec, encoder_spec, width, height, scaling, target_quality, min_quality, target_speed, min_speed, - current_csce, current_ve): + current_csce, current_ve, + client_score_delta): """ Given an optional csc step (csc_format and csc_spec), and and a required encoding step (encoder_spec and width/height), @@ -165,10 +166,10 @@ def clamp(v): ee_score += encoder_spec.score_boost #edge resistance score: average of csc and encoder score: er_score = (ecsc_score + ee_score) / 2.0 - score = int((qscore+sscore+er_score+sizescore)*runtime_score/100.0/4.0) - scorelog("get_score(%-7s, %-24r, %-24r, %5i, %5i) quality: %2i, speed: %2i, setup: %2i runtime: %2i scaling: %s / %s, encoder dimensions=%sx%s, sizescore=%3i, score=%2i", + score = int((qscore+sscore+er_score+sizescore+client_score_delta)*runtime_score/100.0/4.0) + scorelog("get_score(%-7s, %-24r, %-24r, %5i, %5i) quality: %2i, speed: %2i, setup: %2i runtime: %2i scaling: %s / %s, encoder dimensions=%sx%s, sizescore=%3i, client score delta=%3i, score=%2i", enc_in_format, csc_spec, encoder_spec, width, height, - qscore, sscore, er_score, runtime_score, scaling, encoder_scaling, enc_width, enc_height, sizescore, score) + qscore, sscore, er_score, runtime_score, scaling, encoder_scaling, enc_width, enc_height, sizescore, client_score_delta, score) return score, scaling, csc_scaling, csc_width, csc_height, csc_spec, enc_in_format, encoder_scaling, enc_width, enc_height, encoder_spec def get_encoder_dimensions(csc_spec, encoder_spec, width, height, scaling=(1,1)): diff --git a/src/xpra/server/window/window_video_source.py b/src/xpra/server/window/window_video_source.py index 548924b2be..48e1dbc302 100644 --- a/src/xpra/server/window/window_video_source.py +++ b/src/xpra/server/window/window_video_source.py @@ -1090,9 +1090,10 @@ def add_scores(info, csc_spec, enc_in_format): scorelog("add_scores: no matches for %s (%s and %s)", encoder_spec, encoder_spec.output_colorspaces, supported_csc_modes) continue scaling = self.calculate_scaling(width, height, encoder_spec.max_w, encoder_spec.max_h) + client_score_delta = self.encoding_options.get("%s.score-delta" % encoding, 0) score_data = get_pipeline_score(enc_in_format, csc_spec, encoder_spec, width, height, scaling, target_q, min_q, target_s, min_s, - self._csc_encoder, self._video_encoder) + self._csc_encoder, self._video_encoder, client_score_delta) if score_data: scores.append(score_data) if not FORCE_CSC or src_format==FORCE_CSC_MODE: