示例#1
0
文件: src.py 项目: svn2github/Xpra
 def _emit_buffer(self, data, metadata={}):
     if self.stream_compressor and data:
         data = compressed_wrapper("sound", data, level=9, zlib=False, lz4=(self.stream_compressor=="lz4"), lzo=(self.stream_compressor=="lzo"), can_inline=True)
         #log("compressed using %s from %i bytes down to %i bytes", self.stream_compressor, len(odata), len(data))
         metadata["compress"] = self.stream_compressor
     f = self.file
     if f:
         for x in self.pending_metadata:
             self.file.write(x)
         if data:
             self.file.write(data)
         self.file.flush()
     if self.state=="stopped":
         #don't bother
         return 0
     if JITTER>0:
         #will actually emit the buffer after a random delay
         if self.jitter_queue.empty():
             #queue was empty, schedule a timer to flush it
             from random import randint
             jitter = randint(1, JITTER)
             self.timeout_add(jitter, self.flush_jitter_queue)
             log("emit_buffer: will flush jitter queue in %ims", jitter)
         for x in self.pending_metadata:
             self.jitter_queue.put((x, {}))
         self.pending_metadata = []
         self.jitter_queue.put((data, metadata))
         return 0
     log("emit_buffer data=%s, len=%i, metadata=%s", type(data), len(data), metadata)
     return self.do_emit_buffer(data, metadata)
示例#2
0
文件: client.py 项目: svn2github/Xpra
    def compressed_wrapper(self, datatype, data):
        # FIXME: ugly assumptions here, should pass by name!
        from xpra.net import compression

        zlib = "zlib" in self.server_compressors and compression.use_zlib
        lz4 = "lz4" in self.server_compressors and compression.use_lz4
        lzo = "lzo" in self.server_compressors and compression.use_lzo
        if zlib or lz4 or lzo:
            return compression.compressed_wrapper(datatype, data, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
        # we can't compress, so at least avoid warnings in the protocol layer:
        return compression.Compressed("raw %s" % datatype, data, can_inline=True)
示例#3
0
 def _packet_recompress(self, packet, index, name):
     if len(packet) > index:
         data = packet[index]
         if len(data) < MIN_COMPRESS_SIZE:
             return
         #this is ugly and not generic!
         kw = dict((k, self.caps.boolget(k)) for k in ("zlib", "lz4"))
         packet[index] = compressed_wrapper(name,
                                            data,
                                            can_inline=False,
                                            **kw)
示例#4
0
 def compress_clipboard(self, packet):
     from xpra.net.compression import Compressible, compressed_wrapper
     #Note: this runs in the 'encode' thread!
     packet = list(packet)
     for i, item in enumerate(packet):
         if isinstance(item, Compressible):
             if self.brotli:
                 packet[i] = compressed_wrapper(item.datatype, item.data,
                                                            level=9, brotli=True, can_inline=False)
             else:
                 packet[i] = self.compressed_wrapper(item.datatype, item.data)
     self.queue_packet(packet)
示例#5
0
 def compressed_wrapper(self, datatype, data, level=5):
     #FIXME: ugly assumptions here, should pass by name!
     zlib = "zlib" in self.server_compressors and compression.use_zlib
     lz4 = "lz4" in self.server_compressors and compression.use_lz4
     lzo = "lzo" in self.server_compressors and compression.use_lzo
     if level>0 and len(data)>=256 and (zlib or lz4 or lzo):
         cw = compression.compressed_wrapper(datatype, data, level=level, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
         if len(cw)<len(data):
             #the compressed version is smaller, use it:
             return cw
     #we can't compress, so at least avoid warnings in the protocol layer:
     return compression.Compressed("raw %s" % datatype, data, can_inline=True)
示例#6
0
 def compressed_wrapper(self, datatype, data, level=5):
     #FIXME: ugly assumptions here, should pass by name!
     zlib = "zlib" in self.server_compressors and compression.use_zlib
     lz4 = "lz4" in self.server_compressors and compression.use_lz4
     lzo = "lzo" in self.server_compressors and compression.use_lzo
     if level>0 and len(data)>=256 and (zlib or lz4 or lzo):
         cw = compression.compressed_wrapper(datatype, data, level=level, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
         if len(cw)<len(data):
             #the compressed version is smaller, use it:
             return cw
     #we can't compress, so at least avoid warnings in the protocol layer:
     return compression.Compressed("raw %s" % datatype, data, can_inline=True)
示例#7
0
 def compressed_wrapper(self, datatype, data, min_saving=128):
     if self.zlib or self.lz4 or self.lzo:
         cw = compressed_wrapper(datatype,
                                 data,
                                 zlib=self.zlib,
                                 lz4=self.lz4,
                                 lzo=self.lzo,
                                 can_inline=False)
         if len(cw) + min_saving <= len(data):
             #the compressed version is smaller, use it:
             return cw
         #skip compressed version: fall through
     #we can't compress, so at least avoid warnings in the protocol layer:
     return Compressed(datatype, data, can_inline=True)
示例#8
0
 def compress_clipboard():
     log(
         "compress_clipboard() compressing %s, server compressors=%s",
         compressible, self.server_compressors)
     from xpra.net import compression
     if "brotli" in self.server_compressors and compression.use_brotli:
         return compression.compressed_wrapper(
             compressible.datatype,
             compressible.data,
             level=9,
             brotli=True,
             can_inline=False)
     return self.compressed_wrapper(compressible.datatype,
                                    compressible.data)
示例#9
0
 def test_compressed_wrapper(self):
     try:
         compression.compressed_wrapper("test", b"abc")
     except compression.InvalidCompressionException:
         pass
     else:
         raise Exception("should not be able to use the wrapper without enabling a compressor")
     for x in ("lz4", "lzo", "brotli", "zlib", "none"):
         if not compression.use(x):
             continue
         kwargs = {x : True}
         for level in (0, 1, 5, 10):
             for data in (
                 b"0"*1024,
                 b"0"*16,
                 b"\0",
                 memoryview(b"hello"),
                 b"1"*1024*1024*16,
                 ):
                 v = compression.compressed_wrapper("test", data, level=level, **kwargs)
                 assert v
                 assert repr(v)
                 assert compression.get_compression_type(v.level)
                 #and back:
                 try:
                     d = compression.decompress_by_name(v.data, v.algorithm)
                     assert d
                     if x!="none":
                         #we can't do none,
                         #because it would be mistaken for "zlib"
                         #(for historical reasons - 'zlib' uses level=0, and 'none' has no level)
                         d = compression.decompress(v.data, v.level)
                         assert d
                 except Exception:
                     print("error decompressing %s - generated with settings: %s" % (v, kwargs))
                     raise
示例#10
0
 def _packet_recompress(self, packet, index, name):
     if len(packet)>index:
         data = packet[index]
         if len(data)<512:
             packet[index] = str(data)
             return
         #FIXME: this is ugly and not generic!
         zlib = compression.use_zlib and self.caps.boolget("zlib", True)
         lz4 = compression.use_lz4 and self.caps.boolget("lz4", False)
         lzo = compression.use_lzo and self.caps.boolget("lzo", False)
         if zlib or lz4 or lzo:
             packet[index] = compressed_wrapper(name, data, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
         else:
             #prevent warnings about large uncompressed data
             packet[index] = Compressed("raw %s" % name, data, can_inline=True)
示例#11
0
 def _packet_recompress(self, packet, index, name):
     if len(packet)>index:
         data = packet[index]
         if len(data)<512:
             packet[index] = str(data)
             return
         #FIXME: this is ugly and not generic!
         zlib = compression.use_zlib and self.caps.boolget("zlib", True)
         lz4 = compression.use_lz4 and self.caps.boolget("lz4", False)
         lzo = compression.use_lzo and self.caps.boolget("lzo", False)
         if zlib or lz4 or lzo:
             packet[index] = compressed_wrapper(name, data, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
         else:
             #prevent warnings about large uncompressed data
             packet[index] = Compressed("raw %s" % name, data, can_inline=True)
示例#12
0
 def compressed_wrapper(self, datatype, data):
     #FIXME: ugly assumptions here, should pass by name!
     from xpra.net import compression
     zlib = "zlib" in self.server_compressors and compression.use_zlib
     lz4 = "lz4" in self.server_compressors and compression.use_lz4
     lzo = "lzo" in self.server_compressors and compression.use_lzo
     if zlib or lz4 or lzo:
         return compression.compressed_wrapper(datatype,
                                               data,
                                               zlib=zlib,
                                               lz4=lz4,
                                               lzo=lzo,
                                               can_inline=False)
     #we can't compress, so at least avoid warnings in the protocol layer:
     return compression.Compressed("raw %s" % datatype,
                                   data,
                                   can_inline=True)
示例#13
0
 def compressed_wrapper(self, datatype, data, level=5, **kwargs):
     if level>0 and len(data)>=256:
         kw = {}
         #brotli is not enabled by default as a generic compressor
         #but callers may choose to enable it via kwargs:
         for algo, defval in {
             "zlib" : True,
             "lz4" : True,
             "brotli" : False,
             }.items():
             kw[algo] = algo in self.server_compressors and compression.use(algo) and kwargs.get(algo, defval)
         cw = compression.compressed_wrapper(datatype, data, level=level, can_inline=False, **kw)
         if len(cw)<len(data):
             #the compressed version is smaller, use it:
             return cw
     #we can't compress, so at least avoid warnings in the protocol layer:
     return compression.Compressed("raw %s" % datatype, data, can_inline=True)
示例#14
0
 def _emit_buffer(self, data, metadata={}):
     if self.stream_compressor and data:
         cdata = compressed_wrapper("sound",
                                    data,
                                    level=9,
                                    zlib=False,
                                    lz4=(self.stream_compressor == "lz4"),
                                    lzo=(self.stream_compressor == "lzo"),
                                    can_inline=True)
         if len(cdata) < len(data) * 90 // 100:
             log("compressed using %s from %i bytes down to %i bytes",
                 self.stream_compressor, len(data), len(cdata))
             metadata["compress"] = self.stream_compressor
             data = cdata
         else:
             log(
                 "skipped inefficient %s stream compression: %i bytes down to %i bytes",
                 self.stream_compressor, len(data), len(cdata))
     f = self.file
     if f:
         for x in self.pending_metadata:
             self.file.write(x)
         if data:
             self.file.write(data)
         self.file.flush()
     if self.state == "stopped":
         #don't bother
         return 0
     if JITTER > 0:
         #will actually emit the buffer after a random delay
         if self.jitter_queue.empty():
             #queue was empty, schedule a timer to flush it
             from random import randint
             jitter = randint(1, JITTER)
             self.timeout_add(jitter, self.flush_jitter_queue)
             log("emit_buffer: will flush jitter queue in %ims", jitter)
         for x in self.pending_metadata:
             self.jitter_queue.put((x, {}))
         self.pending_metadata = []
         self.jitter_queue.put((data, metadata))
         return 0
     log("emit_buffer data=%s, len=%i, metadata=%s", type(data), len(data),
         metadata)
     return self.do_emit_buffer(data, metadata)
示例#15
0
 def compressed_wrapper(self, datatype, data, level=5):
     if level > 0 and len(data) >= 256:
         #ugly assumptions here, should pass by name
         zlib = "zlib" in self.server_compressors
         lz4 = "lz4" in self.server_compressors
         lzo = "lzo" in self.server_compressors
         #never use brotli as a generic compressor
         #brotli = "brotli" in self.server_compressors and compression.use_brotli
         cw = compression.compressed_wrapper(datatype,
                                             data,
                                             level=level,
                                             zlib=zlib,
                                             lz4=lz4,
                                             lzo=lzo,
                                             brotli=False,
                                             none=True,
                                             can_inline=False)
         if len(cw) < len(data):
             #the compressed version is smaller, use it:
             return cw
     #we can't compress, so at least avoid warnings in the protocol layer:
     return compression.Compressed("raw %s" % datatype,
                                   data,
                                   can_inline=True)
示例#16
0
 def compressed_wrapper(self, datatype, data, **kwargs):
     #set compression flags based on self.zlib and self.lz4:
     kw = dict((k, getattr(self, k, False)) for k in ("zlib", "lz4"))
     kw.update(kwargs)
     return compressed_wrapper(datatype, data, can_inline=False, **kw)
示例#17
0
def rgb_encode(coding, image, rgb_formats, supports_transparency, speed, rgb_zlib=True, rgb_lz4=True, rgb_lzo=False):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        log("rgb_encode reformatting because %s not in %s", pixel_format, rgb_formats)
        if not rgb_reformat(image, rgb_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()
        #switch encoding if necessary:
        if len(pixel_format)==4 and coding=="rgb24":
            coding = "rgb32"
        elif len(pixel_format)==3 and coding=="rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format" : pixel_format}

    #we may want to re-stride:
    image.restride()

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()

    #compression stage:
    level = 0
    algo = "not"
    if len(pixels)>=256:
        level = max(0, min(5, int(115-speed)/20))
        if len(pixels)<1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level // 2
    if level>0:
        if rgb_lz4 and compression.use_lz4:
            cwrapper = compression.compressed_wrapper(coding, pixels, lz4=True)
            algo = "lz4"
            level = 1
        elif rgb_lzo and compression.use_lzo:
            cwrapper = compression.compressed_wrapper(coding, pixels, lzo=True)
            algo = "lzo"
            level = 1
        elif rgb_zlib and compression.use_zlib:
            cwrapper = compression.compressed_wrapper(coding, pixels, zlib=True, level=level)
            algo = "zlib"
        else:
            cwrapper = None
        if cwrapper is None or len(cwrapper)>=(len(pixels)-32):
            #no compression is enabled, or compressed is actually bigger!
            #(fall through to uncompressed)
            level = 0
        else:
            #add compressed marker:
            options[algo] = level
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
    if level==0:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        cwrapper = compression.Compressed(coding, pixels_to_bytes(pixels), True)
    if pixel_format.upper().find("A")>=0 or pixel_format.upper().find("X")>=0:
        bpp = 32
    else:
        bpp = 24
    log("rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s", level, algo, image.get_width(), image.get_height(), coding, pixel_format, len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, options, width, height, stride, bpp
示例#18
0
def rgb_encode(coding,
               image,
               rgb_formats,
               supports_transparency,
               speed,
               rgb_zlib=True,
               rgb_lz4=True,
               rgb_lzo=False):
    pixel_format = bytestostr(image.get_pixel_format())
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s",
    #    (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        log(
            "rgb_encode reformatting because %s not in %s, supports_transparency=%s",
            pixel_format, rgb_formats, supports_transparency)
        if not rgb_reformat(image, rgb_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 = bytestostr(image.get_pixel_format())
        #switch encoding if necessary:
        if len(pixel_format) == 4:
            coding = "rgb32"
        elif len(pixel_format) == 3:
            coding = "rgb24"
        else:
            raise Exception("invalid pixel format %s" % pixel_format)
    #we may still want to re-stride:
    image.may_restride()
    #always tell client which pixel format we are sending:
    options = {"rgb_format": pixel_format}

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()

    #compression stage:
    level = 0
    algo = "not"
    l = len(pixels)
    if l >= 512 and speed < 100:
        if l >= 4096:
            #speed=99 -> level=1, speed=0 -> level=9
            level = 1 + max(0, min(8, int(100 - speed) // 12))
        else:
            #fewer pixels, make it more likely we won't bother compressing
            #and use a lower level (max=5)
            level = max(0, min(5, int(115 - speed) // 20))
    if level > 0:
        cwrapper = compression.compressed_wrapper(coding,
                                                  pixels,
                                                  level=level,
                                                  zlib=rgb_zlib,
                                                  lz4=rgb_lz4,
                                                  lzo=rgb_lzo,
                                                  brotli=False,
                                                  none=True)
        algo = cwrapper.algorithm
        if algo == "none" or len(cwrapper) >= (len(pixels) - 32):
            #no compression is enabled, or compressed is actually bigger!
            #(fall through to uncompressed)
            level = 0
        else:
            #add compressed marker:
            options[algo] = level
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
    if level == 0:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        algo = "not"
        cwrapper = compression.Compressed(coding, pixels_to_bytes(pixels),
                                          True)
    if pixel_format.find("A") >= 0 or pixel_format.find("X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s for %5i bytes at %3i speed, %s compressed %4sx%-4s in %s/%s: %5s bytes down to %5s",
        level, l, speed, algo, image.get_width(), image.get_height(), coding,
        pixel_format, len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, options, width, height, stride, bpp
示例#19
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        log("process_server_packet: %s", packet_type)
        if packet_type==Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type=="disconnect":
            log("got disconnect from server: %s", packet[1])
            if self.exit:
                self.server_protocol.close()
            else:
                self.stop("disconnect from server: %s" % packet[1])
        elif packet_type=="hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw*maxh*4*4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher, self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type=="info-response":
            #adds proxy info:
            #note: this is only seen by the client application
            #"xpra info" is a new connection, which talks to the proxy server...
            info = packet[1]
            info.update(self.get_proxy_info(proto))
        elif packet_type=="lost-window":
            wid = packet[1]
            #mark it as lost so we can drop any current/pending frames
            self.lost_windows.add(wid)
            #queue it so it gets cleaned safely (for video encoders mostly):
            self.encode_queue.put(packet)
            #and fall through so tell the client immediately
        elif packet_type=="draw":
            #use encoder thread:
            self.encode_queue.put(packet)
            #which will queue the packet itself when done:
            return
        #we do want to reformat cursor packets...
        #as they will have been uncompressed by the network layer already:
        elif packet_type=="cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet)>=9:
                pixels = packet[8]
                if len(pixels)<512:
                    packet[8] = str(pixels)
                else:
                    #FIXME: this is ugly and not generic!
                    zlib = compression.use_zlib and self.caps.get("zlib", True) 
                    lz4 = compression.use_lz4 and self.caps.get("lz4", False) 
                    lzo = compression.use_lzo and self.caps.get("lzo", False)
                    if zlib or lz4 or lzo:
                        packet[8] = compressed_wrapper("cursor", pixels, zlib=zlib, lz4=lz4, lzo=lzo, can_inline=False)
                    else:
                        #prevent warnings about large uncompressed data
                        packet[8] = Compressed("raw cursor", pixels, can_inline=True)
        self.queue_client_packet(packet)
示例#20
0
文件: encoder.py 项目: chewi/xpra
def encode(coding: str, image, options: dict):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s",
    #    (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format in ("BGRX", "BGRA", "RGBA"):
        rgb_formats = options.get("rgb_formats", ("BGRX", "BGRA", "RGBA"))
    elif pixel_format in ("RGB", "BGR"):
        rgb_formats = options.get("rgb_formats", ("RGB", "BGR"))
    else:
        raise Exception("unsupported pixel format %s" % pixel_format)
    supports_transparency = options.get("alpha", True)
    if pixel_format not in rgb_formats:
        log(
            "rgb_encode reformatting because %s not in %s, supports_transparency=%s",
            pixel_format, rgb_formats, supports_transparency)
        if not rgb_reformat(image, rgb_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()
        #switch encoding if necessary:
        if len(pixel_format) == 4:
            coding = "rgb32"
        elif len(pixel_format) == 3:
            coding = "rgb24"
        else:
            raise Exception("invalid pixel format %s" % pixel_format)
    #we may still want to re-stride:
    image.may_restride()
    #always tell client which pixel format we are sending:
    client_options = {"rgb_format": pixel_format}

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()
    speed = options.get("speed", 50)

    #compression stage:
    level = 0
    algo = "not"
    l = len(pixels)
    lz4 = options.get("lz4", False)
    if l >= 512 and (lz4 or speed < 100):
        if l >= 4096:
            level = 1 + max(0, min(7, int(100 - speed) // 14))
        else:
            #fewer pixels, make it more likely we won't bother compressing
            #and use a lower level (max=3)
            level = max(0, min(3, int(125 - speed) // 35))
    if level > 0:
        zlib = options.get("zlib", False)
        can_inline = l <= 32768
        cwrapper = compressed_wrapper(coding,
                                      pixels,
                                      level=level,
                                      zlib=zlib,
                                      lz4=lz4,
                                      brotli=False,
                                      none=False,
                                      can_inline=can_inline)
        if isinstance(cwrapper, LevelCompressed):
            #add compressed marker:
            client_options[cwrapper.algorithm] = cwrapper.level & 0xF
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
        elif can_inline and isinstance(pixels, memoryview):
            assert isinstance(cwrapper, Compressed)
            assert cwrapper.data == pixels
            #compression either did not work or was not enabled
            #and memoryview pixel data cannot be handled by the packet encoders
            #so we convert it to bytes so it can still be inlined with the packet data:
            cwrapper.data = rgb_transform.pixels_to_bytes(pixels)
    else:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        algo = "not"
        cwrapper = Compressed(coding, rgb_transform.pixels_to_bytes(pixels),
                              True)
    if pixel_format.find("A") >= 0 or pixel_format.find("X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s for %5i bytes at %3i speed, %s compressed %4sx%-4s in %s/%s: %5s bytes down to %5s",
        level, l, speed, algo, width, height, coding, pixel_format,
        len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, client_options, width, height, stride, bpp
示例#21
0
    def process_server_packet(self, proto, packet):
        packet_type = packet[0]
        log("process_server_packet: %s", packet_type)
        if packet_type == Protocol.CONNECTION_LOST:
            self.stop("server connection lost", proto)
            return
        elif packet_type == "disconnect":
            log("got disconnect from server: %s", packet[1])
            if self.exit:
                self.server_protocol.close()
            else:
                self.stop("disconnect from server: %s" % packet[1])
        elif packet_type == "hello":
            c = typedict(packet[1])
            maxw, maxh = c.intpair("max_desktop_size", (4096, 4096))
            proto.max_packet_size = maxw * maxh * 4 * 4

            caps = self.filter_server_caps(c)
            #add new encryption caps:
            if self.cipher:
                auth_caps = new_cipher_caps(self.client_protocol, self.cipher,
                                            self.encryption_key)
                caps.update(auth_caps)
            packet = ("hello", caps)
        elif packet_type == "info-response":
            #adds proxy info:
            #note: this is only seen by the client application
            #"xpra info" is a new connection, which talks to the proxy server...
            info = packet[1]
            info.update(self.get_proxy_info(proto))
        elif packet_type == "lost-window":
            wid = packet[1]
            #mark it as lost so we can drop any current/pending frames
            self.lost_windows.add(wid)
            #queue it so it gets cleaned safely (for video encoders mostly):
            self.encode_queue.put(packet)
            #and fall through so tell the client immediately
        elif packet_type == "draw":
            #use encoder thread:
            self.encode_queue.put(packet)
            #which will queue the packet itself when done:
            return
        #we do want to reformat cursor packets...
        #as they will have been uncompressed by the network layer already:
        elif packet_type == "cursor":
            #packet = ["cursor", x, y, width, height, xhot, yhot, serial, pixels, name]
            #or:
            #packet = ["cursor", ""]
            if len(packet) >= 9:
                pixels = packet[8]
                if len(pixels) < 512:
                    packet[8] = str(pixels)
                else:
                    #FIXME: this is ugly and not generic!
                    zlib = compression.use_zlib and self.caps.get("zlib", True)
                    lz4 = compression.use_lz4 and self.caps.get("lz4", False)
                    lzo = compression.use_lzo and self.caps.get("lzo", False)
                    if zlib or lz4 or lzo:
                        packet[8] = compressed_wrapper("cursor",
                                                       pixels,
                                                       zlib=zlib,
                                                       lz4=lz4,
                                                       lzo=lzo,
                                                       can_inline=False)
                    else:
                        #prevent warnings about large uncompressed data
                        packet[8] = Compressed("raw cursor",
                                               pixels,
                                               can_inline=True)
        self.queue_client_packet(packet)
示例#22
0
def rgb_encode(coding,
               image,
               rgb_formats,
               supports_transparency,
               speed,
               rgb_zlib=True,
               rgb_lz4=True,
               rgb_lzo=False,
               encoding_client_options=True,
               supports_rgb24zlib=True):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4, encoding_client_options, supports_rgb24zlib), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        if not rgb_reformat(image, rgb_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()
        #switch encoding if necessary:
        if len(pixel_format) == 4 and coding == "rgb24":
            coding = "rgb32"
        elif len(pixel_format) == 3 and coding == "rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format": pixel_format}
    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()

    #special case for when rowstride is so much bigger than the width
    #that we would end up sending large chunks of padding with each row of pixels
    #this happens with XShm pixel data (the default)
    stride = image.get_rowstride()
    width = image.get_width()
    rstride = roundup(width * len(pixel_format),
                      4)  #a reasonable stride: rounded up to 4
    height = image.get_height()
    if stride > 8 and rstride < stride:
        al = len(pixels)  #current buffer size
        el = rstride * height  #desirable size we could have
        if al - el > 1024 and el * 110 / 100 < al:  #is it worth re-striding to save space?
            #we'll save at least 1KB and 10%, do it
            #Note: we could also change the pixel format whilst we're at it
            # and convert BGRX to RGB for example (assuming RGB is also supported by the client)
            rows = []
            for y in range(height):
                rows.append(
                    memoryview_to_bytes(pixels[stride * y:stride * y +
                                               rstride]))
            pixels = "".join(rows)
            log(
                "rgb_encode: %s pixels re-stride saving %i%% from %s (%s bytes) to %s (%s bytes)",
                pixel_format, 100 - 100 * el / al, stride, al, rstride, el)
            stride = rstride

    #compression
    #by default, wire=raw:
    raw_data = str(pixels)
    wire_data = raw_data
    level = 0
    algo = "not"
    if len(pixels) >= 256 and (rgb_zlib and compression.use_zlib) or (
            rgb_lz4 and compression.use_lz4) or (rgb_lzo
                                                 and compression.use_lzo):
        level = max(0, min(5, int(115 - speed) / 20))
        if len(pixels) < 1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level / 2
    if level > 0:
        if rgb_lz4 and compression.use_lz4:
            wire_data = compression.compressed_wrapper(coding,
                                                       pixels,
                                                       lz4=True)
            algo = "lz4"
            level = 1
        elif rgb_lzo and compression.use_lzo:
            wire_data = compression.compressed_wrapper(coding,
                                                       pixels,
                                                       lzo=True)
            algo = "lzo"
            level = 1
        else:
            assert rgb_zlib and compression.use_zlib
            wire_data = compression.compressed_wrapper(coding,
                                                       pixels,
                                                       zlib=True,
                                                       level=level)
            algo = "zlib"
        raw_data = wire_data.data
        #log("%s/%s data compressed from %s bytes down to %s (%s%%) with lz4=%s",
        #         coding, pixel_format, len(pixels), len(raw_data), int(100.0*len(raw_data)/len(pixels)), self.rgb_lz4)
        if len(raw_data) >= (len(pixels) - 32):
            #compressed is actually bigger! (use uncompressed)
            level = 0
            wire_data = str(pixels)
            raw_data = wire_data
        else:
            #add compressed marker:
            options[algo] = level
    if pixel_format.upper().find("A") >= 0 or pixel_format.upper().find(
            "X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s",
        level, algo, image.get_width(), image.get_height(), coding,
        pixel_format, len(pixels), len(raw_data))
    if not encoding_client_options or not supports_rgb24zlib:
        return coding, wire_data, {}, width, height, stride, bpp
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, compression.Compressed(
        coding, raw_data, True), options, width, height, stride, bpp
示例#23
0
def rgb_encode(coding, image, rgb_formats, supports_transparency, speed, rgb_zlib=True, rgb_lz4=True, rgb_lzo=False, encoding_client_options=True, supports_rgb24zlib=True):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4, encoding_client_options, supports_rgb24zlib), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        if not rgb_reformat(image, rgb_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()
        #switch encoding if necessary:
        if len(pixel_format)==4 and coding=="rgb24":
            coding = "rgb32"
        elif len(pixel_format)==3 and coding=="rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format" : pixel_format}
    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()

    #special case for when rowstride is so much bigger than the width
    #that we would end up sending large chunks of padding with each row of pixels
    #this happens with XShm pixel data (the default)
    stride = image.get_rowstride()
    width = image.get_width()
    rstride = roundup(width*len(pixel_format), 4)   #a reasonable stride: rounded up to 4
    height = image.get_height()
    if stride>8 and rstride<stride:
        al = len(pixels)                    #current buffer size
        el = rstride*height                 #desirable size we could have
        if al-el>1024 and el*110/100<al:    #is it worth re-striding to save space?
            #we'll save at least 1KB and 10%, do it
            #Note: we could also change the pixel format whilst we're at it
            # and convert BGRX to RGB for example (assuming RGB is also supported by the client)
            rows = []
            for y in range(height):
                rows.append(memoryview_to_bytes(pixels[stride*y:stride*y+rstride]))
            pixels = "".join(rows)
            log("rgb_encode: %s pixels re-stride saving %i%% from %s (%s bytes) to %s (%s bytes)", pixel_format, 100-100*el/al, stride, al, rstride, el)
            stride = rstride

    #compression
    #by default, wire=raw:
    raw_data = str(pixels)
    wire_data = raw_data
    level = 0
    algo = "not"
    if len(pixels)>=256 and (rgb_zlib and compression.use_zlib) or (rgb_lz4 and compression.use_lz4) or (rgb_lzo and compression.use_lzo):
        level = max(0, min(5, int(115-speed)/20))
        if len(pixels)<1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level / 2
    if level>0:
        if rgb_lz4 and compression.use_lz4:
            wire_data = compression.compressed_wrapper(coding, pixels, lz4=True)
            algo = "lz4"
            level = 1
        elif rgb_lzo and compression.use_lzo:
            wire_data = compression.compressed_wrapper(coding, pixels, lzo=True)
            algo = "lzo"
            level = 1
        else:
            assert rgb_zlib and compression.use_zlib
            wire_data = compression.compressed_wrapper(coding, pixels, zlib=True, level=level)
            algo = "zlib"
        raw_data = wire_data.data
        #log("%s/%s data compressed from %s bytes down to %s (%s%%) with lz4=%s",
        #         coding, pixel_format, len(pixels), len(raw_data), int(100.0*len(raw_data)/len(pixels)), self.rgb_lz4)
        if len(raw_data)>=(len(pixels)-32):
            #compressed is actually bigger! (use uncompressed)
            level = 0
            wire_data = str(pixels)
            raw_data = wire_data
        else:
            #add compressed marker:
            options[algo] = level
    if pixel_format.upper().find("A")>=0 or pixel_format.upper().find("X")>=0:
        bpp = 32
    else:
        bpp = 24
    log("rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s", level, algo, image.get_width(), image.get_height(), coding, pixel_format, len(pixels), len(raw_data))
    if not encoding_client_options or not supports_rgb24zlib:
        return  coding, wire_data, {}, width, height, stride, bpp
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, compression.Compressed(coding, raw_data, True), options, width, height, stride, bpp
示例#24
0
def rgb_encode(coding,
               image,
               rgb_formats,
               supports_transparency,
               speed,
               rgb_zlib=True,
               rgb_lz4=True,
               rgb_lzo=False):
    pixel_format = image.get_pixel_format()
    #log("rgb_encode%s pixel_format=%s, rgb_formats=%s", (coding, image, rgb_formats, supports_transparency, speed, rgb_zlib, rgb_lz4), pixel_format, rgb_formats)
    if pixel_format not in rgb_formats:
        log("rgb_encode reformatting because %s not in %s", pixel_format,
            rgb_formats)
        if not rgb_reformat(image, rgb_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()
        #switch encoding if necessary:
        if len(pixel_format) == 4 and coding == "rgb24":
            coding = "rgb32"
        elif len(pixel_format) == 3 and coding == "rgb32":
            coding = "rgb24"
    #always tell client which pixel format we are sending:
    options = {"rgb_format": pixel_format}

    #we may want to re-stride:
    image.may_restride()

    #compress here and return a wrapper so network code knows it is already zlib compressed:
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    width = image.get_width()
    height = image.get_height()
    stride = image.get_rowstride()

    #compression stage:
    level = 0
    algo = "not"
    if len(pixels) >= 256:
        level = max(0, min(5, int(115 - speed) / 20))
        if len(pixels) < 1024:
            #fewer pixels, make it more likely we won't bother compressing:
            level = level // 2
    if level > 0:
        if rgb_lz4 and compression.use_lz4:
            cwrapper = compression.compressed_wrapper(coding, pixels, lz4=True)
            algo = "lz4"
            level = 1
        elif rgb_lzo and compression.use_lzo:
            cwrapper = compression.compressed_wrapper(coding, pixels, lzo=True)
            algo = "lzo"
            level = 1
        elif rgb_zlib and compression.use_zlib:
            cwrapper = compression.compressed_wrapper(coding,
                                                      pixels,
                                                      zlib=True,
                                                      level=level)
            algo = "zlib"
        else:
            cwrapper = None
        if cwrapper is None or len(cwrapper) >= (len(pixels) - 32):
            #no compression is enabled, or compressed is actually bigger!
            #(fall through to uncompressed)
            level = 0
        else:
            #add compressed marker:
            options[algo] = level
            #remove network layer compression marker
            #so that this data will be decompressed by the decode thread client side:
            cwrapper.level = 0
    if level == 0:
        #can't pass a raw buffer to bencode / rencode,
        #and even if we could, the image containing those pixels may be freed by the time we get to the encoder
        algo = "not"
        cwrapper = compression.Compressed(coding, pixels_to_bytes(pixels),
                                          True)
    if pixel_format.upper().find("A") >= 0 or pixel_format.upper().find(
            "X") >= 0:
        bpp = 32
    else:
        bpp = 24
    log(
        "rgb_encode using level=%s, %s compressed %sx%s in %s/%s: %s bytes down to %s",
        level, algo, image.get_width(), image.get_height(), coding,
        pixel_format, len(pixels), len(cwrapper.data))
    #wrap it using "Compressed" so the network layer receiving it
    #won't decompress it (leave it to the client's draw thread)
    return coding, cwrapper, options, width, height, stride, bpp