xpra icon
Bug tracker and wiki

Ticket #445: x265.2.patch

File x265.2.patch, 16.9 KB (added by Antoine Martin, 6 years ago)

better enc_x265 stub patch, removes generated files

  • setup.py

     
    5151sound_ENABLED = True
    5252
    5353enc_x264_ENABLED = True
     54enc_x265_ENABLED = False
    5455x264_static_ENABLED = False
     56x265_static_ENABLED = False
    5557vpx_ENABLED = True
    5658vpx_static_ENABLED = False
    5759dec_avcodec_ENABLED = True
     
    7072
    7173#allow some of these flags to be modified on the command line:
    7274SWITCHES = ("enc_x264", "x264_static",
     75            "enc_x265", "x265_static",
    7376            "nvenc", "dec_avcodec", "avcodec_static",
    7477            "csc_swscale", "swscale_static",
    7578            "csc_nvcuda", "csc_opencl",
     
    480483                   "xpra/codecs/nvenc/constants.pxi",
    481484                   "xpra/codecs/enc_x264/encoder.c",
    482485                   "xpra/codecs/enc_x264/constants.pxi",
     486                   "xpra/codecs/enc_x265/encoder.c",
     487                   "xpra/codecs/enc_x265/constants.pxi",
    483488                   "xpra/codecs/dec_avcodec/decoder.c",
    484489                   "xpra/codecs/dec_avcodec/constants.pxi",
    485490                   "xpra/codecs/csc_swscale/colorspace_converter.c",
     
    570575    libffmpeg_include_dir   = os.path.join(libffmpeg_path, "include")
    571576    libffmpeg_lib_dir       = os.path.join(libffmpeg_path, "lib")
    572577    libffmpeg_bin_dir       = os.path.join(libffmpeg_path, "bin")
     578    #x265
     579    x265_path ="C:\\x265"
     580    x265_include_dir    = x265_path
     581    x265_lib_dir        = x265_path
     582    x265_bin_dir        = x265_path
    573583    #x264 (direct from build dir.. yuk - sorry!):
    574584    x264_path ="C:\\x264"
    575585    x264_include_dir    = x264_path
     
    648658            add_to_keywords(kw, 'extra_link_args', "/LIBPATH:%s" % x264_lib_dir)
    649659            add_to_keywords(kw, 'extra_link_args', "/OPT:NOREF")
    650660            checkdirs(x264_include_dir, x264_lib_dir)
     661        elif "x265" in packages[0]:
     662            add_to_PATH(libffmpeg_bin_dir)
     663            add_to_PATH(x265_bin_dir)
     664            add_to_keywords(kw, 'include_dirs', win32_include_dir, x265_include_dir)
     665            add_to_keywords(kw, 'libraries', "libx265")
     666            add_to_keywords(kw, 'extra_link_args', "/LIBPATH:%s" % x265_lib_dir)
     667            add_to_keywords(kw, 'extra_link_args', "/OPT:NOREF")
     668            checkdirs(x265_include_dir, x265_lib_dir)
    651669        elif "vpx" in packages[0]:
    652670            add_to_PATH(libffmpeg_bin_dir)
    653671            add_to_keywords(kw, 'include_dirs', win32_include_dir, vpx_include_dir)
     
    9951013                ["xpra/codecs/enc_x264/encoder.pyx", "xpra/codecs/enc_x264/enc_x264.c"],
    9961014                **x264_pkgconfig), min_version=(0, 16))
    9971015
     1016toggle_packages(enc_x265_ENABLED, "xpra.codecs.enc_x265")
     1017if enc_x265_ENABLED:
     1018    make_constants("xpra", "codecs", "enc_x265", "constants")
     1019    if x265_static_ENABLED:
     1020        x265_pkgconfig = STATIC_COMMON_DEFS.copy()
     1021        x265_pkgconfig['extra_link_args'] = ["-Wl,-soname,x265lib.so", "-Wl,-Bstatic", "-Wl,-Bsymbolic",
     1022                                 "-lx265", "-Wl,-Bdynamic"]
     1023    else:
     1024        x265_pkgconfig = pkgconfig("x265")
     1025    cython_add(Extension("xpra.codecs.enc_x265.encoder",
     1026                ["xpra/codecs/enc_x265/encoder.pyx", "xpra/codecs/enc_x265/enc_x265.c"],
     1027                **x265_pkgconfig), min_version=(0, 16))
     1028
    9981029toggle_packages(dec_avcodec_ENABLED, "xpra.codecs.dec_avcodec")
    9991030if dec_avcodec_ENABLED:
    10001031    make_constants("xpra", "codecs", "dec_avcodec", "constants")
  • xpra/codecs/enc_x265/__init__.py

     
     1# This file is part of Xpra.
     2# Copyright (C) 2013 Antoine Martin <antoine@devloop.org.uk>
     3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
  • xpra/codecs/enc_x265/constants.txt

     
     1# This file is part of Xpra.
     2# Copyright (C) 2013 Antoine Martin <antoine@devloop.org.uk>
     3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
     5
     6## This file is processed by setup.py to create a .pxi
     7##
     8## The resulting .pxi file will make all the constants available to
     9## Cython code under their own names, and also create a python-exposed
     10## dictionary through which the constants can be accessed like
     11## constants["AV_..."].
     12
     13X265_LOG_NONE
     14X265_LOG_ERROR
     15X265_LOG_WARNING
     16X265_LOG_INFO
     17X265_LOG_DEBUG
     18
     19X265_B_ADAPT_NONE
     20X265_B_ADAPT_FAST
     21X265_B_ADAPT_TRELLIS
     22
     23X265_RC_ABR
     24X265_RC_CQP
     25X265_RC_CRF
  • xpra/codecs/enc_x265/enc_x265.c

     
     1/* This file is part of Xpra.
     2 * Copyright (C) 2012, 2013 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
     3 * Copyright (C) 2012, 2013 Antoine Martin <antoine@devloop.org.uk>
     4 * Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     5 * later version. See the file COPYING for details.
     6 */
     7
     8
     9const char * const *get_preset_names(void);
     10
     11void set_f_rf(x264_param_t *param, float v);
  • xpra/codecs/enc_x265/enc_x265.h

     
     1/* This file is part of Xpra.
     2 * Copyright (C) 2012 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
     3 * Copyright (C) 2012, 2013 Antoine Martin <antoine@devloop.org.uk>
     4 * Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     5 * later version. See the file COPYING for details.
     6 */
     7 
     8//NOTE: this file is only here because accessing those structures
     9//from Cython would be too tedious!
     10 
     11#include <stdint.h>
     12#include <inttypes.h>
     13 
     14#include <x265.h>
     15 
     16 
     17void set_f_rf(x265_param_t *param, float v) {
     18        param->rc.f_rf_constant = v;
     19}
  • xpra/codecs/enc_x265/encoder.pyx

     
     1# This file is part of Xpra.
     2# Copyright (C) 2012, 2013 Antoine Martin <antoine@devloop.org.uk>
     3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
     5
     6import time
     7import os
     8
     9from xpra.log import Logger, debug_if_env
     10log = Logger()
     11debug = debug_if_env(log, "XPRA_X265_DEBUG")
     12error = log.error
     13
     14include "constants.pxi"
     15
     16from xpra.codecs.codec_constants import get_subsampling_divs, RGB_FORMATS, codec_spec
     17
     18cdef extern from "string.h":
     19    void * memcpy ( void * destination, void * source, size_t num )
     20    void * memset ( void * ptr, int value, size_t num )
     21
     22from libc.stdint cimport int64_t, uint8_t
     23
     24cdef extern from *:
     25    ctypedef unsigned long size_t
     26
     27cdef extern from "stdint.h":
     28    pass
     29cdef extern from "inttypes.h":
     30    pass
     31
     32cdef extern from "Python.h":
     33    ctypedef int Py_ssize_t
     34    ctypedef object PyObject
     35    int PyObject_AsReadBuffer(object obj, void ** buffer, Py_ssize_t * buffer_len) except -1
     36
     37
     38cdef extern from "x265.h":
     39    ctypedef struct x265_param_t:
     40        int         logLevel
     41        int         bEnableWavefront                #enable wavefront parallel processing
     42        int         poolNumThreads                  #number of threads to allocate for thread pool
     43        int         frameNumThreads                 #number of concurrently encoded frames
     44        int         internalBitDepth                #bit-depth the codec operates at
     45
     46        int         frameRate                       #source frame-rate in Hz
     47        int         sourceWidth                     #source width in pixels
     48        int         sourceHeight                    #source height in pixels
     49
     50        int         decodingRefreshType             #Intra refresh type (0:none, 1:CDR, 2:IDR) default: 1
     51        int         keyframeMin                     #Minimum intra period in frames
     52        int         keyframeMax                     #Maximum intra period in frames
     53        int         bOpenGOP                        #Enable Open GOP referencing
     54        int         bframes                         #Max number of consecutive B-frames
     55        int         lookaheadDepth                  #Number of frames to use for lookahead, determines encoder latency
     56        int         bFrameAdaptive                  #0 - none, 1 - fast, 2 - full (trellis) adaptive B frame scheduling
     57        int         bFrameBias
     58        int         scenecutThreshold               #how aggressively to insert extra I frames
     59
     60        int         searchMethod                    #ME search method (DIA, HEX, UMH, STAR, FULL)
     61        int         searchRange                     #ME search range
     62        int         bipredSearchRange               #ME search range for bipred refinement
     63        uint32_t    maxNumMergeCand                 #Max number of merge candidates
     64        int         bEnableWeightedPred             #enable weighted prediction in P slices
     65        int         bEnableWeightedBiPred           #enable bi-directional weighted prediction in B slices
     66
     67    ctypedef struct x265_t:
     68        pass
     69    ctypedef struct x265_picture_t:
     70        void        planes[3]
     71        int         stride[3]
     72        int         bitDepth
     73        int         poc
     74
     75    #void x265_setup_primitives(x265_param_t *param, int cpulevel)
     76    void x265_param_default(x265_param_t *param)
     77    int x265_param_apply_profile(x265_param_t *, const char *profile)
     78    #extern const int x265_max_bit_depth;
     79    x265_t *x265_encoder_open(x265_param_t *)
     80    int x265_encoder_headers(x265_t *, x265_nal_t **pp_nal, int *pi_nal)
     81    int x265_encoder_encode(x265_t *encoder, x265_nal_t **pp_nal, int *pi_nal, x265_picture_t *pic_in, x265_picture_t *pic_out)
     82    void x265_encoder_close(x265_t *, double *globalPsnr)
     83    void x265_cleanup(void)
     84
     85cdef extern from "enc_x264.h":
     86
     87    void set_f_rf(x265_param_t *param, float v)
     88
     89
     90def get_version():
     91    return 1
     92
     93def get_type():
     94    return "x265"
     95
     96def get_encodings():
     97    return ["h265"]
     98
     99def init_module():
     100    #nothing to do!
     101    pass
     102
     103
     104cdef char *PROFILE_MAIN     = "main"
     105cdef char *PROFILE_MAIN10   = "main10"
     106cdef char *PROFILE_MAINSTILLPICTURE = "mainstillpicture"
     107PROFILES = [PROFILE_MAIN, PROFILE_MAIN10, PROFILE_MAINSTILLPICTURE]
     108
     109COLORSPACES = {}
     110
     111#copy C list of colorspaces to a python list:
     112def get_colorspaces():
     113    global COLORSPACES
     114    return  COLORSPACES.keys()
     115
     116def get_spec(encoding, colorspace):
     117    assert encoding in get_encodings(), "invalid encoding: %s (must be one of %s" % (encoding, get_encodings())
     118    assert colorspace in COLORSPACES, "invalid colorspace: %s (must be one of %s)" % (colorspace, COLORSPACES.keys())
     119    #ratings: quality, speed, setup cost, cpu cost, gpu cost, latency, max_w, max_h, max_pixels
     120    #we can handle high quality and any speed
     121    #setup cost is moderate (about 10ms)
     122    return codec_spec(Encoder, codec_type=get_type(), encoding=encoding, setup_cost=70, width_mask=0xFFFE, height_mask=0xFFFE)
     123
     124
     125cdef class Encoder:
     126    cdef int frames
     127    cdef x265_t *context
     128    cdef int width
     129    cdef int height
     130    cdef object src_format
     131    cdef object profile
     132    cdef double time
     133    cdef int colorspace
     134    cdef int preset
     135    cdef int quality
     136    cdef int speed
     137
     138    def init_context(self, int width, int height, src_format, encoding, int quality, int speed, options):    #@DuplicatedSignature
     139        global COLORSPACES
     140        cs_info = COLORSPACES.get(src_format)
     141        assert cs_info is not None, "invalid source format: %s, must be one of: %s" % (src_format, COLORSPACES.keys())
     142        assert encoding=="x264", "invalid encoding: %s" % encoding
     143        self.width = width
     144        self.height = height
     145        self.quality = quality
     146        self.speed = speed
     147        self.preset = get_preset_for_speed(speed)
     148        self.src_format = src_format
     149        self.colorspace = cs_info[0]
     150        self.frames = 0
     151        self.time = 0
     152        self.profile = MAIN10
     153        self.init_encoder()
     154
     155    cdef init_encoder(self):
     156        cdef x265_param_t param
     157        cdef const char *preset
     158        x265_param_default(&param)
     159        param.sourceWidth = self.width
     160        param.sourceHeight = self.height
     161        param.i_log_level = constants["X265_LOG_DEBUG"]
     162        self.context = x264_encoder_open(&param)
     163        assert self.context!=NULL,  "context initialization failed for format %s" % self.src_format
     164
     165    def get_info(self):
     166        cdef float pps
     167        if self.profile is None:
     168            return {}
     169        info = {"profile"   : self.profile,
     170                "preset"    : get_preset_names()[self.preset],
     171                "frames"    : self.frames,
     172                "width"     : self.width,
     173                "height"    : self.height,
     174                "speed"     : self.speed,
     175                "quality"   : self.quality,
     176                "src_format": self.src_format}
     177        if self.frames>0 and self.time>0:
     178            pps = float(self.width) * float(self.height) * float(self.frames) / self.time
     179            info["total_time_ms"] = int(self.time*1000.0)
     180            info["pixels_per_second"] = int(pps)
     181        return info
     182
     183    def __str__(self):
     184        if self.src_format is None:
     185            return "x264_encoder(uninitialized)"
     186        return "x264_encoder(%s - %sx%s)" % (self.src_format, self.width, self.height)
     187
     188    def is_closed(self):
     189        return self.context==NULL
     190
     191    def get_encoding(self):
     192        return "h265"
     193
     194    def __dealloc__(self):
     195        self.clean()
     196
     197    def get_width(self):
     198        return self.width
     199
     200    def get_height(self):
     201        return self.height
     202
     203    def get_type(self):                     #@DuplicatedSignature
     204        return  "x265"
     205
     206    def get_src_format(self):
     207        return self.src_format
     208
     209    def clean(self):                        #@DuplicatedSignature
     210        if self.context!=NULL:
     211            x265_encoder_close(self.context)
     212            self.context = NULL
     213
     214    def get_client_options(self, options):
     215        q = options.get("quality", -1)
     216        if q<0:
     217            q = self.quality
     218        s = options.get("speed", -1)
     219        if s<0:
     220            s = self.speed
     221        return {
     222                "frame"     : self.frames,
     223                "quality"   : q,
     224                "speed"     : s,
     225                }
     226
     227    def compress_image(self, image, options={}):
     228        cdef int i_nals = 0
     229        cdef x265_picture_t pic_out
     230        cdef x265_picture_t pic_in
     231        cdef int frame_size = 0
     232
     233        cdef uint8_t *pic_buf
     234        cdef Py_ssize_t pic_buf_len = 0
     235        cdef char *out
     236
     237        cdef int quality_override = options.get("quality", -1)
     238        cdef int speed_override = options.get("speed", -1)
     239        cdef int saved_quality = self.quality
     240        cdef int saved_speed = self.speed
     241        cdef int i                        #@DuplicatedSignature
     242        start = time.time()
     243
     244        assert self.context!=NULL
     245        pixels = image.get_pixels()
     246        istrides = image.get_rowstride()
     247
     248        memset(&pic_out, 0, sizeof(x265_picture_t))
     249        memset(&pic_in, 0, sizeof(x265_picture_t))
     250
     251        if self.src_format.find("RGB")>=0 or self.src_format.find("BGR")>=0:
     252            assert len(pixels)>0
     253            assert istrides>0
     254            PyObject_AsReadBuffer(pixels, <const void**> &pic_buf, &pic_buf_len)
     255            for i in range(3):
     256                pic_in.img.plane[i] = pic_buf
     257                pic_in.img.i_stride[i] = istrides
     258        else:
     259            assert len(pixels)==3, "image pixels does not have 3 planes! (found %s)" % len(pixels)
     260            assert len(istrides)==3, "image strides does not have 3 values! (found %s)" % len(istrides)
     261            for i in range(3):
     262                PyObject_AsReadBuffer(pixels[i], <const void**> &pic_buf, &pic_buf_len)
     263                pic_in.img.plane[i] = pic_buf
     264                pic_in.img.i_stride[i] = istrides[i]
     265
     266        pic_in.img.i_csp = self.colorspace
     267        pic_in.img.i_plane = 3
     268        pic_in.i_pts = 1
     269
     270        with nogil:
     271            frame_size = x264_encoder_encode(self.context, &nals, &i_nals, &pic_in, &pic_out)
     272        if frame_size < 0:
     273            log.error("x264 encoding error: frame_size is invalid!")
     274            return None
     275        out = <char *>nals[0].p_payload
     276        cdata = out[:frame_size]
     277        end = time.time()
     278        self.time += end-start
     279        self.frames += 1
     280        return  cdata, self.get_client_options(options)
     281
     282
     283    def set_encoding_speed(self, int pct):
     284        pass
     285
     286    def set_encoding_quality(self, int pct):
     287        pass