xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #1462: csc-cython-r210.patch

File csc-cython-r210.patch, 14.5 KB (added by Antoine Martin, 12 months ago)

restore csc_cython so we have a r210 csc module

  • xpra/codecs/csc_cython/colorspace_converter.pyx

     
    11# This file is part of Xpra.
    22# Copyright (C) 2013 Arthur Huillet
    3 # Copyright (C) 2012-2014 Antoine Martin <antoine@devloop.org.uk>
     3# Copyright (C) 2012-2020 Antoine Martin <antoine@devloop.org.uk>
    44# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
    55# later version. See the file COPYING for details.
    66
    77#!python
    8 #cython: boundscheck=False, wraparound=False, overflowcheck=False, cdivision=True, unraisable_tracebacks=True
     8#cython: language_level=3, boundscheck=False, wraparound=False, overflowcheck=False, cdivision=True, unraisable_tracebacks=True
    99
    1010import os
     11import sys
    1112import time
    12 import struct
    13 try:
    14     from xpra.build_info import CYTHON_VERSION as CYTHON_VERSION_STR
    15     CYTHON_VERSION = CYTHON_VERSION_STR.split(".")
    16 except ImportError:
    17     CYTHON_VERSION = []
    1813
    19 
    2014from xpra.log import Logger
    2115log = Logger("csc", "cython")
    2216
     
    2317from xpra.codecs.codec_constants import csc_spec
    2418from xpra.codecs.image_wrapper import ImageWrapper
    2519
     20from libc.stdint cimport uint8_t
     21from xpra.buffers.membuf cimport memory_as_pybuffer, memalign, object_as_buffer
     22
     23
    2624cdef extern from "stdlib.h":
    2725    void free(void *ptr)
    2826
    29 
    30 cdef extern from "../../buffers/buffers.h":
    31     object memory_as_pybuffer(void* ptr, Py_ssize_t buf_len, int readonly)
    32     int    object_as_buffer(object obj, const void ** buffer, Py_ssize_t * buffer_len)
    33     int get_buffer_api_version()
    34 
    35 cdef extern from "../../buffers/memalign.h":
    36     int pad(int size) nogil
    37     void *xmemalign(size_t size) nogil
    38 
    39 from libc.stdint cimport uint8_t
    40 
    4127cdef inline int roundup(int n, int m):
    4228    return (n + m - 1) & ~(m - 1)
    4329
     
    4632cdef uint8_t RGBX_R, RGBX_G, RGBX_B, RGBX_X
    4733cdef uint8_t RGB_R, RGB_G, RGB_B
    4834cdef uint8_t BGR_R, BGR_G, BGR_B
    49 import sys
     35
    5036if sys.byteorder=="little":
    5137    BGRX_B, BGRX_G, BGRX_R, BGRX_X = 0, 1, 2, 3
    5238    RGBX_R, RGBX_G, RGBX_B, RGBX_X = 0, 1, 2, 3
     
    8470               "RGB"        : get_CS("RGB",     ["YUV420P"]),
    8571               "YUV420P"    : get_CS("YUV420P", ["RGB", "BGR", "RGBX", "BGRX"]),
    8672               "GBRP"       : get_CS("GBRP",    ["RGBX", "BGRX"]),
    87                "r210"       : get_CS("r210",    ["YUV420P"]),
     73               "r210"       : get_CS("r210",    ["YUV420P", "BGR48"]),
    8874               }
    8975
    9076DEBUG_POINTS = []
     
    11298    return "cython"
    11399
    114100def get_version():
    115     return tuple([str(x) for x in CSC_CYTHON_VERSION] + CYTHON_VERSION)
     101    return "4.1"
    116102
    117103def get_info():
    118104    info = {
    119             "version"   : CSC_CYTHON_VERSION,
    120             "buffer_api": get_buffer_api_version(),
     105            "version"   : (4, 1),
    121106            }
    122     if CYTHON_VERSION:
    123         info["Cython"] = CYTHON_VERSION
    124107    return info
    125108
    126109def get_input_colorspaces():
     
    133116    assert in_colorspace in COLORSPACES, "invalid input colorspace: %s (must be one of %s)" % (in_colorspace, get_input_colorspaces())
    134117    assert out_colorspace in COLORSPACES.get(in_colorspace), "invalid output colorspace: %s (must be one of %s)" % (out_colorspace, get_output_colorspaces(in_colorspace))
    135118    #low score as this should be used as fallback only:
    136     return csc_spec(ColorspaceConverter, codec_type=get_type(), quality=50, speed=10, setup_cost=10, min_w=2, min_h=2, max_w=16*1024, max_h=16*1024, can_scale=True)
     119    can_scale = True
     120    if in_colorspace=="r210" and out_colorspace=="BGR48":
     121        can_scale = False
     122    return csc_spec(ColorspaceConverter, codec_type=get_type(), quality=50, speed=10, setup_cost=10, min_w=2, min_h=2, max_w=16*1024, max_h=16*1024, can_scale=can_scale)
    137123
    138124
    139125class CythonImageWrapper(ImageWrapper):
     
    281267            else:
    282268                assert src_format=="r210"
    283269                self.convert_image_function = self.r210_to_YUV420P
     270        elif src_format=="r210" and dst_format=="BGR48":
     271            self.dst_strides[0] = roundup(self.dst_width*6, STRIDE_ROUNDUP)
     272            self.dst_sizes[0] = self.dst_strides[0] * self.dst_height
     273            self.buffer_size = self.dst_sizes[0]+self.dst_strides[0]
     274            self.convert_image_function = self.r210_to_BGR48
     275            assert src_width==dst_width
     276            assert src_height==dst_height
    284277        elif src_format=="YUV420P" and dst_format in ("RGBX", "BGRX", "RGB", "BGR"):
    285278            #3 or 4 bytes per pixel:
    286279            self.dst_strides[0] = roundup(self.dst_width*len(dst_format), STRIDE_ROUNDUP)
     
    341334                "src_width" : self.src_width,
    342335                "src_height": self.src_height,
    343336                "dst_width" : self.dst_width,
    344                 "dst_height": self.dst_height}
     337                "dst_height": self.dst_height,
     338                }
    345339        if self.src_format:
    346340            info["src_format"] = self.src_format
    347341        if self.dst_format:
     
    430424
    431425        assert object_as_buffer(pixels, <const void**> &input_image, &pic_buf_len)==0
    432426        #allocate output buffer:
    433         output_image = <unsigned char*> xmemalign(self.buffer_size)
     427        output_image = <unsigned char*> memalign(self.buffer_size)
    434428        Y = output_image + self.offsets[0]
    435429        U = output_image + self.offsets[1]
    436430        V = output_image + self.offsets[2]
     
    545539        log("%s took %.1fms", self, 1000.0*elapsed)
    546540        self.time += elapsed
    547541        self.frames += 1
    548         out_image = CythonImageWrapper(0, 0, dst_width, dst_height, planes, self.dst_format, 24, strides, ImageWrapper._3_PLANES)
     542        out_image = CythonImageWrapper(0, 0, dst_width, dst_height, planes, self.dst_format, 24, strides, ImageWrapper.PLANAR_3)
    549543        out_image.cython_buffer = <unsigned long> output_image
    550544        return out_image
    551545
    552546
     547    def r210_to_BGR48(self, image):
     548        cdef double start = time.time()
     549        cdef unsigned int iplanes = image.get_planes()
     550        assert iplanes==ImageWrapper.PACKED, "invalid input format: %s planes" % iplanes
     551        assert image.get_width()>=self.src_width, "invalid image width: %s (minimum is %s)" % (image.get_width(), self.src_width)
     552        assert image.get_height()>=self.src_height, "invalid image height: %s (minimum is %s)" % (image.get_height(), self.src_height)
     553        pixels = image.get_pixels()
     554        assert pixels, "failed to get pixels from %s" % image
     555        input_stride = image.get_rowstride()
     556        log("convert_image(%s) input=%s, strides=%s" % (image, len(pixels), input_stride))
     557
     558        cdef Py_ssize_t pic_buf_len = 0
     559        cdef const unsigned int *r210
     560        assert object_as_buffer(pixels, <const void**> &r210, &pic_buf_len)==0
     561
     562        #allocate output buffer:
     563        cdef unsigned char* bgr48_buffer = <unsigned char*> memalign(self.buffer_size)
     564        cdef unsigned short *bgr48data = <unsigned short*> bgr48_buffer
     565
     566        cdef unsigned int src_width = self.src_width
     567        cdef unsigned int src_height = self.src_height
     568        cdef unsigned int dst_width = self.dst_width
     569        cdef unsigned int dst_height = self.dst_height
     570
     571        cdef unsigned int y = 0
     572        cdef unsigned int i = 0
     573        cdef unsigned int v
     574        #enable nogil if image is thread safe?
     575        #with nogil:
     576        for y in range(h):
     577            i = y*dst_stride//2
     578            for x in range(w):
     579                v = r210[x]
     580                rgba[i] = v&0x000003ff
     581                rgba[i+1] = (v&0x000ffc00) >> 10
     582                rgba[i+2]   = (v&0x3ff00000) >> 20
     583                i = i + 3
     584            r210 = <unsigned int*> ((<uintptr_t> r210) + src_stride)
     585
     586        planes = memoryview(output_buf)
     587        strides = self.rowstride
     588
     589        cdef double elapsed = time.time()-start
     590        log("%s took %.1fms", self, 1000.0*elapsed)
     591        self.time += elapsed
     592        self.frames += 1
     593        out_image = CythonImageWrapper(0, 0, dst_width, dst_height, planes, "BGR48", 24, strides, ImageWrapper.PACKED)
     594        out_image.cython_buffer = <unsigned long> bgr48_buffer
     595        return out_image
     596
     597
     598
    553599    def YUV420P_to_RGBX(self, image):
    554600        return self.do_YUV420P_to_RGB(image, 4, RGBX_R, RGBX_G, RGBX_B, RGBX_X)
    555601
     
    579625
    580626        start = time.time()
    581627        iplanes = image.get_planes()
    582         assert iplanes==ImageWrapper._3_PLANES, "invalid input format: %s planes" % iplanes
     628        assert iplanes==ImageWrapper.PLANAR_3, "invalid input format: %s planes" % iplanes
    583629        assert image.get_width()>=self.src_width, "invalid image width: %s (minimum is %s)" % (image.get_width(), self.src_width)
    584630        assert image.get_height()>=self.src_height, "invalid image height: %s (minimum is %s)" % (image.get_height(), self.src_height)
    585631        planes = image.get_pixels()
     
    605651        assert buf_len>=Vstride*image.get_height()//2, "buffer for V plane is too small: %s bytes, expected at least %s" % (buf_len, Vstride*image.get_height()/2)
    606652
    607653        #allocate output buffer:
    608         output_image = <unsigned char*> xmemalign(self.buffer_size)
     654        output_image = <unsigned char*> memalign(self.buffer_size)
    609655
    610656        #we process 4 pixels at a time:
    611657        workw = roundup(dst_width//2, 2)
     
    688734
    689735        start = time.time()
    690736        iplanes = image.get_planes()
    691         assert iplanes==ImageWrapper._3_PLANES, "invalid input format: %s planes" % iplanes
     737        assert iplanes==ImageWrapper.PLANAR_3, "invalid input format: %s planes" % iplanes
    692738        assert image.get_width()>=self.src_width, "invalid image width: %s (minimum is %s)" % (image.get_width(), self.src_width)
    693739        assert image.get_height()>=self.src_height, "invalid image height: %s (minimum is %s)" % (image.get_height(), self.src_height)
    694740        planes = image.get_pixels()
     
    714760        assert buf_len>=Bstride*image.get_height(), "buffer for B plane is too small: %s bytes, expected at least %s" % (buf_len, Bstride*image.get_height())
    715761
    716762        #allocate output buffer:
    717         output_image = <unsigned char*> xmemalign(self.buffer_size)
     763        output_image = <unsigned char*> memalign(self.buffer_size)
    718764
    719765        #from now on, we can release the gil:
    720766        with nogil:
  • xpra/codecs/loader.py

     
    159159    #csc:
    160160    "csc_swscale"   : ("swscale colorspace conversion", "csc_swscale", "colorspace_converter", "ColorspaceConverter"),
    161161    "csc_libyuv"    : ("libyuv colorspace conversion", "csc_libyuv", "colorspace_converter", "ColorspaceConverter"),
     162    "csc_cython"    : ("cython colorspace conversion", "csc_cython", "colorspace_converter", "ColorspaceConverter"),
    162163    #decoders:
    163164    "dec_pillow"    : ("Pillow decoder",    "pillow",       "decoder", "decompress"),
    164165    "dec_webp"      : ("webp decoder",      "webp",         "decoder", "decompress"),
     
    228229    return name in codecs
    229230
    230231
    231 CSC_CODECS = "csc_swscale", "csc_libyuv"
     232CSC_CODECS = "csc_swscale", "csc_cython", "csc_libyuv"
    232233ENCODER_CODECS = "enc_pillow", "enc_webp", "enc_jpeg"
    233234ENCODER_VIDEO_CODECS = "enc_vpx", "enc_x264", "enc_x265", "nvenc", "enc_ffmpeg"
    234235DECODER_CODECS = "dec_pillow", "dec_webp", "dec_jpeg"
  • xpra/codecs/video_helper.py

     
    2222    "x265"       : "enc_x265",
    2323    "nvenc"      : "nvenc",
    2424    "swscale"    : "csc_swscale",
     25    "cython"     : "csc_cython",
    2526    "libyuv"     : "csc_libyuv",
    2627    "avcodec2"   : "dec_avcodec2",
    2728    "ffmpeg"     : "enc_ffmpeg",
     
    4950#try to import the module that contains them (cheap check):
    5051ALL_VIDEO_ENCODER_OPTIONS = try_import_modules("x264", "vpx", "x265", "nvenc", "ffmpeg")
    5152HARDWARE_ENCODER_OPTIONS = try_import_modules("nvenc")
    52 ALL_CSC_MODULE_OPTIONS = try_import_modules("swscale", "libyuv")
     53ALL_CSC_MODULE_OPTIONS = try_import_modules("swscale", "cython", "libyuv")
    5354NO_GFX_CSC_OPTIONS = []
    5455ALL_VIDEO_DECODER_OPTIONS = try_import_modules("avcodec2", "vpx")
    5556
  • setup.py

     
    197197#ffmpeg 3.1 or later is required
    198198dec_avcodec2_ENABLED    = DEFAULT and pkg_config_version("57", "libavcodec")
    199199csc_swscale_ENABLED     = DEFAULT and pkg_config_ok("--exists", "libswscale")
     200csc_cython_ENABLED      = DEFAULT
    200201nvenc_ENABLED = DEFAULT and BITS==64 and pkg_config_version("7", "nvenc")
    201202nvfbc_ENABLED = DEFAULT and BITS==64 and pkg_config_ok("--exists", "nvfbc")
    202203cuda_kernels_ENABLED    = DEFAULT
     
    223224    "vpx", "webp", "pillow", "jpeg_encoder", "jpeg_decoder",
    224225    "v4l2",
    225226    "dec_avcodec2", "csc_swscale",
    226     "csc_libyuv",
     227    "csc_cython", "csc_libyuv",
    227228    "bencode", "cython_bencode", "vsock", "netdev", "mdns",
    228229    "clipboard",
    229230    "scripts",
     
    933934                   "xpra/codecs/dec_avcodec2/decoder.c",
    934935                   "xpra/codecs/csc_libyuv/colorspace_converter.cpp",
    935936                   "xpra/codecs/csc_swscale/colorspace_converter.c",
     937                   "xpra/codecs/csc_cython/colorspace_converter.c",
    936938                   "xpra/codecs/xor/cyxor.c",
    937939                   "xpra/codecs/argb/argb.c",
    938940                   "xpra/codecs/nvapi_version.c",
     
    22092211                ["xpra/codecs/csc_swscale/colorspace_converter.pyx"],
    22102212                **swscale_pkgconfig))
    22112213
     2214toggle_packages(csc_cython_ENABLED, "xpra.codecs.csc_cython")
     2215if csc_cython_ENABLED:
     2216    csc_cython_pkgconfig = pkgconfig(optimize=3)
     2217    cython_add(Extension("xpra.codecs.csc_cython.colorspace_converter",
     2218                         ["xpra/codecs/csc_cython/colorspace_converter.pyx"]+membuffers_c,
     2219                         **csc_cython_pkgconfig))
    22122220
    22132221toggle_packages(vpx_ENABLED, "xpra.codecs.vpx")
    22142222if vpx_ENABLED:
  • etc/xpra/conf.d/30_picture.conf.in

     
    2525video-encoders = all
    2626
    2727# Used by both the client and server for colourspace conversion:
    28 # csc-modules = swscale, libyuv
     28# csc-modules = swscale, cython, libyuv
    2929# csc-modules = none
    3030# csc-modules = all
    3131csc-modules = all