diff --git a/rpmbuild/x264-xpra.spec b/rpmbuild/x264-xpra.spec index a363476bc6..940ba69ae4 100644 --- a/rpmbuild/x264-xpra.spec +++ b/rpmbuild/x264-xpra.spec @@ -51,6 +51,7 @@ This package contains the development files for %{name}. --prefix="%{_prefix}" \ --libdir="%{_libdir}/xpra" \ --includedir="%{_includedir}/xpra" \ + --bit-depth=all \ --enable-shared \ --enable-static diff --git a/src/xpra/codecs/argb/argb.pyx b/src/xpra/codecs/argb/argb.pyx index a9e11e8c6c..68ba629fed 100644 --- a/src/xpra/codecs/argb/argb.pyx +++ b/src/xpra/codecs/argb/argb.pyx @@ -192,6 +192,40 @@ cdef r210data_to_rgb(unsigned int* r210, return memoryview(output_buf) +def r210_to_bgr48(buf, + const unsigned int w, const unsigned int h, + const unsigned int src_stride, const unsigned int dst_stride): + assert buf, "no buffer" + assert w*4<=src_stride, "invalid source stride %i for width %i" % (src_stride, w) + assert w*6<=dst_stride, "invalid destination stride %i for width %i" % (dst_stride, w) + assert (dst_stride%2)==0, "invalid destination stride %i (odd number)" % (dst_stride) + cdef unsigned int* cbuf = 0 + cdef Py_ssize_t cbuf_len = 0 + assert as_buffer(buf, &cbuf, &cbuf_len)==0, "cannot convert %s to a readable buffer" % type(buf) + assert cbuf_len>0, "invalid buffer size: %i" % cbuf_len + assert cbuf_len>=h*src_stride, "source buffer is %i bytes, which is too small for %ix%i" % (cbuf_len, src_stride, h) + return r210data_to_bgr48(cbuf, w, h, src_stride, dst_stride) + +cdef r210data_to_bgr48(unsigned int* r210, + const unsigned int w, const unsigned int h, + const unsigned int src_stride, const unsigned int dst_stride): + cdef MemBuf output_buf = getbuf(h*dst_stride*10) + cdef unsigned short* rgba = output_buf.get_mem() + cdef unsigned int y = 0 + cdef unsigned int i = 0 + cdef unsigned int v + for y in range(h): + i = y*dst_stride//2 + for x in range(w): + v = r210[x] + rgba[i] = v&0x000003ff + rgba[i+1] = (v&0x000ffc00) >> 10 + rgba[i+2] = (v&0x3ff00000) >> 20 + i = i + 3 + r210 = (( r210) + src_stride) + return memoryview(output_buf) + + def argb_to_rgba(buf): assert len(buf) % 4 == 0, "invalid buffer size: %s is not a multiple of 4" % len(buf) # buf is a Python buffer object diff --git a/src/xpra/codecs/codec_constants.py b/src/xpra/codecs/codec_constants.py index b9d278ebdc..6a284f6c15 100644 --- a/src/xpra/codecs/codec_constants.py +++ b/src/xpra/codecs/codec_constants.py @@ -51,6 +51,7 @@ "YUV422P" : ((1, 1), (2, 1), (2, 1)), "YUV444P" : ((1, 1), (1, 1), (1, 1)), "GBRP" : ((1, 1), (1, 1), (1, 1)), + "GBRP10" : ((1, 1), (1, 1), (1, 1)), } def get_subsampling_divs(pixel_format): # Return size dividers for the given pixel format diff --git a/src/xpra/codecs/enc_x264/encoder.pyx b/src/xpra/codecs/enc_x264/encoder.pyx index 0353ef7bec..91b9310afb 100644 --- a/src/xpra/codecs/enc_x264/encoder.pyx +++ b/src/xpra/codecs/enc_x264/encoder.pyx @@ -26,6 +26,7 @@ MIN_SLICED_THREADS_SPEED = envint("XPRA_X264_SLICED_THREADS", 60) LOGGING = os.environ.get("XPRA_X264_LOGGING", "WARNING") PROFILE = os.environ.get("XPRA_X264_PROFILE") SUPPORT_24BPP = envbool("XPRA_X264_SUPPORT_24BPP") +SUPPORT_30BPP = envbool("XPRA_X264_SUPPORT_30BPP", True) TUNE = os.environ.get("XPRA_X264_TUNE") LOG_NALS = envbool("XPRA_X264_LOG_NALS") SAVE_TO_FILE = os.environ.get("XPRA_SAVE_TO_FILE") @@ -63,6 +64,9 @@ cdef extern from "x264.h": int X264_CSP_BGR int X264_CSP_BGRA int X264_CSP_RGB + int X264_CSP_NV12 + int X264_CSP_V210 + int X264_CSP_HIGH_DEPTH int X264_RC_CQP int X264_RC_CRF @@ -168,6 +172,7 @@ cdef extern from "x264.h": int i_width int i_height int i_csp #CSP of encoded bitstream + int i_bitdepth int i_level_idc int i_frame_total #number of frames to encode if known, else 0 @@ -344,6 +349,7 @@ COLORSPACE_FORMATS = { "YUV444P" : (X264_CSP_I444, PROFILE_HIGH444_PREDICTIVE, I444_PROFILES), "BGRA" : (X264_CSP_BGRA, PROFILE_HIGH444_PREDICTIVE, RGB_PROFILES), "BGRX" : (X264_CSP_BGRA, PROFILE_HIGH444_PREDICTIVE, RGB_PROFILES), + "r210" : (X264_CSP_BGR | X264_CSP_HIGH_DEPTH, PROFILE_HIGH444_PREDICTIVE, RGB_PROFILES), } if SUPPORT_24BPP: COLORSPACE_FORMATS.update({ @@ -358,6 +364,8 @@ COLORSPACES = { "BGRA" : ("BGRA",), "BGRX" : ("BGRX",), } +if SUPPORT_30BPP: + COLORSPACES["r210"] = ("r210", ) if SUPPORT_24BPP: COLORSPACES.update({ "BGR" : ("BGR",), @@ -610,6 +618,10 @@ cdef class Encoder: param.i_width = self.width param.i_height = self.height param.i_csp = self.colorspace + if (self.colorspace & X264_CSP_HIGH_DEPTH)>0: + param.i_bitdepth = 10 + else: + param.i_bitdepth = 8 #logging hook: param.pf_log = X264_log param.i_log_level = LOG_LEVEL @@ -818,14 +830,20 @@ cdef class Encoder: x264_picture_init(&pic_in) - if self.src_format.find("RGB")>=0 or self.src_format.find("BGR")>=0: + if self.src_format.find("RGB")>=0 or self.src_format.find("BGR")>=0 or self.src_format=="r210": assert len(pixels)>0 assert istrides>0 + if self.src_format=="r210": + #CSC should be moved elsewhere! + from xpra.codecs.argb.argb import r210_to_bgr48 + pixels = r210_to_bgr48(pixels, self.width, self.height, istrides, self.width*6) + istrides = self.width*6 assert object_as_buffer(pixels, &pic_buf, &pic_buf_len)==0, "unable to convert %s to a buffer" % type(pixels) for i in range(3): pic_in.img.plane[i] = pic_buf pic_in.img.i_stride[i] = istrides self.bytes_in += pic_buf_len + pic_in.img.i_plane = 1 else: assert len(pixels)==3, "image pixels does not have 3 planes! (found %s)" % len(pixels) assert len(istrides)==3, "image strides does not have 3 values! (found %s)" % len(istrides) @@ -833,9 +851,9 @@ cdef class Encoder: assert object_as_buffer(pixels[i], &pic_buf, &pic_buf_len)==0, "unable to convert %s to a buffer (plane=%s)" % (type(pixels[i]), i) pic_in.img.plane[i] = pic_buf pic_in.img.i_stride[i] = istrides[i] + pic_in.img.i_plane = 3 pic_in.img.i_csp = self.colorspace - pic_in.img.i_plane = 3 pic_in.i_pts = image.get_timestamp()-self.first_frame_timestamp return self.do_compress_image(&pic_in, quality, speed) @@ -990,6 +1008,7 @@ cdef class Encoder: def selftest(full=False): + log("enc_x264 selftest: %s", get_info()) global SAVE_TO_FILE from xpra.codecs.codec_checks import testencoder, get_encoder_max_sizes from xpra.codecs.enc_x264 import encoder diff --git a/src/xpra/server/window/window_video_source.py b/src/xpra/server/window/window_video_source.py index ada7cb9d0a..03496f9e4a 100644 --- a/src/xpra/server/window/window_video_source.py +++ b/src/xpra/server/window/window_video_source.py @@ -2130,7 +2130,7 @@ def do_video_encode(self, encoding, image, options): if not self.common_video_encodings: #we have to send using a non-video encoding as that's all we have! return self.video_fallback(image, options) - if self.image_depth not in (24, 32): + if self.image_depth not in (24, 30, 32): #this image depth is not supported for video return self.video_fallback(image, options)