Skip to content

Commit

Permalink
#1694: let the client tell the server which RGB modes it can handle f…
Browse files Browse the repository at this point in the history
…or webp

git-svn-id: https://xpra.org/svn/Xpra/trunk@17697 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Dec 18, 2017
1 parent 51d7c0f commit ed80fa0
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/html5/js/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,7 @@ XpraClient.prototype._make_hello = function() {
"mpeg4+mp4" : ["YUV420P"],
"h264+mp4" : ["YUV420P"],
"vp8+webm" : ["YUV420P"],
"webp" : ["BGRX", "BGRA"],
},
"encoding.x264.YUV420P.profile" : "baseline",
"encoding.h264.YUV420P.profile" : "baseline",
Expand Down
5 changes: 5 additions & 0 deletions src/xpra/client/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,11 @@ def make_hello(self):
encoding_caps["rgb_formats"] = rgb_formats
#figure out which CSC modes (usually YUV) can give us those RGB modes:
full_csc_modes = getVideoHelper().get_server_full_csc_modes_for_rgb(*rgb_formats)
if has_codec("dec_webp"):
if self.opengl_enabled:
full_csc_modes["webp"] = ("BGRX", "BGRA", "RGBX", "RGBA")
else:
full_csc_modes["webp"] = ("BGRX", "BGRA", )
log("supported full csc_modes=%s", full_csc_modes)
encoding_caps["full_csc_modes"] = full_csc_modes

Expand Down
11 changes: 2 additions & 9 deletions src/xpra/server/picture_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,9 @@ def warn_encoding_once(key, message):
encoding_warnings.add(key)


def webp_encode(image, rgb_formats, supports_transparency, quality, speed, content_type):
pixel_format = image.get_pixel_format()
#the native webp encoder only takes this pixel format as input:
if pixel_format not in ("BGRA", "BGRX", "RGBX", "RGBA"):
wanted_formats = [x for x in rgb_formats if x in ("BGRA", "BGRX", "RGBA", "RGBX")]
if not rgb_reformat(image, wanted_formats, supports_transparency):
raise Exception("cannot find compatible rgb format to use for %s! (supported: %s)" % (pixel_format, rgb_formats))
#get the new format:
pixel_format = image.get_pixel_format()
def webp_encode(image, supports_transparency, quality, speed, content_type):
stride = image.get_rowstride()
pixel_format = image.get_pixel_format()
enc_webp = get_codec("enc_webp")
#log("WEBP_PILLOW=%s, enc_webp=%s, stride=%s, pixel_format=%s", WEBP_PILLOW, enc_webp, stride, pixel_format)
if not WEBP_PILLOW and enc_webp and stride>0 and stride%4==0 and pixel_format in ("BGRA", "BGRX", "RGBA", "RGBX"):
Expand Down
31 changes: 29 additions & 2 deletions src/xpra/server/window/window_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
from xpra.server.cystats import time_weighted_average, logp #@UnresolvedImport
from xpra.server.window.region import rectangle, add_rectangle, remove_rectangle, merge_all #@UnresolvedImport
from xpra.codecs.xor.cyxor import xor_str #@UnresolvedImport
from xpra.server.picture_encode import rgb_encode, webp_encode, mmap_send, argb_swap
from xpra.server.picture_encode import rgb_encode, webp_encode, mmap_send, argb_swap, rgb_reformat
from xpra.codecs.loader import PREFERED_ENCODING_ORDER, get_codec
from xpra.codecs.codec_constants import LOSSY_PIXEL_FORMATS
from xpra.net import compression
Expand Down Expand Up @@ -262,6 +262,8 @@ def init_encoders(self):
self._encoders["jpeg"] = self.jpeg_encode
if self._mmap and self._mmap_size>0:
self._encoders["mmap"] = self.mmap_encode
self.full_csc_modes = {}
self.parse_csc_modes(self.encoding_options.dictget("full_csc_modes", default_value=None))

def init_vars(self):
self.server_core_encodings = ()
Expand All @@ -272,6 +274,7 @@ def init_vars(self):
self.auto_refresh_encodings = ()
self.core_encodings = ()
self.rgb_formats = ()
self.full_csc_modes = {}
self.client_refresh_encodings = ()
self.encoding_options = {}
self.rgb_zlib = False
Expand Down Expand Up @@ -360,6 +363,13 @@ def ui_cleanup(self):
self.global_statistics = None


def get_client_info(self):
info = {}
if self.full_csc_modes:
for enc, csc_modes in self.full_csc_modes.items():
info["csc_modes.%s" % enc] = csc_modes
return info

def get_info(self):
#should get prefixed with "client[M].window[N]." by caller
"""
Expand Down Expand Up @@ -704,8 +714,17 @@ def do_set_client_properties(self, properties):
#remove rgb formats with alpha
rgb_formats = [x for x in rgb_formats if x.find("A")<0]
self.rgb_formats = rgb_formats
self.parse_csc_modes(properties.dictget("encoding.full_csc_modes", default_value=None))
self.update_encoding_selection(self.encoding, [])


def parse_csc_modes(self, full_csc_modes):
#only override if values are specified:
log("parse_csc_modes(%s) current value=%s", full_csc_modes, self.full_csc_modes)
if full_csc_modes is not None and type(full_csc_modes)==dict:
self.full_csc_modes = full_csc_modes


def set_auto_refresh_delay(self, d):
self.auto_refresh_delay = d
self.update_refresh_attributes()
Expand Down Expand Up @@ -2143,7 +2162,15 @@ def make_draw_packet(self, x, y, outw, outh, coding, data, outstride, client_opt
def webp_encode(self, coding, image, options):
q = options.get("quality") or self.get_quality(coding)
s = options.get("speed") or self.get_speed(coding)
return webp_encode(image, self.rgb_formats, self.supports_transparency, q, s, self.content_type)
pixel_format = image.get_pixel_format()
#the native webp encoder only takes BGRX / BGRA as input,
#but the client may be able to swap channels,
#so it may be able to process RGBX / RGBA:
client_rgb_formats = self.full_csc_modes.get("webp", ("BGRA", "BGRX", ))
if pixel_format not in client_rgb_formats:
if not rgb_reformat(image, client_rgb_formats, self.supports_transparency):
raise Exception("cannot find compatible rgb format to use for %s! (supported: %s)" % (pixel_format, self.rgb_formats))
return webp_encode(image, self.supports_transparency, q, s, self.content_type)

def rgb_encode(self, coding, image, options):
s = options.get("speed") or self._current_speed
Expand Down
18 changes: 2 additions & 16 deletions src/xpra/server/window/window_video_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ def __init__(self, *args):
def init_encoders(self):
WindowSource.init_encoders(self)
#for 0.12 onwards: per encoding lists:
self.full_csc_modes = {}
self.parse_csc_modes(self.encoding_options.dictget("full_csc_modes", default_value=None))

self.video_encodings = self.video_helper.get_encodings()
for x in self.video_encodings:
Expand Down Expand Up @@ -126,7 +124,6 @@ def init_vars(self):

self.supports_video_scaling = False

self.full_csc_modes = {} #for 0.12 onwards: per encoding lists
self.video_encodings = ()
self.common_video_encodings = ()
self.non_video_encodings = ()
Expand Down Expand Up @@ -157,11 +154,8 @@ def update_av_sync_frame_delay(self):


def get_client_info(self):
info = {
"supports_video_scaling" : self.supports_video_scaling,
}
for enc, csc_modes in (self.full_csc_modes or {}).items():
info["csc_modes.%s" % enc] = csc_modes
info = WindowSource.get_client_info(self)
info["supports_video_scaling"] = self.supports_video_scaling
return info

def get_property_info(self):
Expand Down Expand Up @@ -286,13 +280,6 @@ def ui_cleanup(self):
self.video_subregion = None


def parse_csc_modes(self, full_csc_modes):
#only override if values are specified:
csclog("parse_csc_modes(%s) current value=%s", full_csc_modes, self.full_csc_modes)
if full_csc_modes is not None and type(full_csc_modes)==dict:
self.full_csc_modes = full_csc_modes


def set_new_encoding(self, encoding, strict=None):
if self.encoding!=encoding:
#ensure we re-init the codecs asap:
Expand Down Expand Up @@ -320,7 +307,6 @@ def update_encoding_selection(self, encoding=None, exclude=[], init=False):

def do_set_client_properties(self, properties):
#client may restrict csc modes for specific windows
self.parse_csc_modes(properties.dictget("encoding.full_csc_modes", default_value=None))
self.supports_scrolling = self.scroll_encoding and properties.boolget("encoding.scrolling", self.supports_scrolling) and not STRICT_MODE
self.scroll_min_percent = properties.intget("scrolling.min-percent", self.scroll_min_percent)
self.supports_video_scaling = properties.boolget("encoding.video_scaling", self.supports_video_scaling)
Expand Down

0 comments on commit ed80fa0

Please sign in to comment.