示例#1
0
    def init_state(self):
        self.wants_encodings = False
        self.wants_features = False

        #contains default values, some of which may be supplied by the client:
        self.default_batch_config = batch_config.DamageBatchConfig()
        self.global_batch_config = self.default_batch_config.clone()      #global batch config

        self.supports_transparency = False
        self.encoding = None                        #the default encoding for all windows
        self.encodings = ()                         #all the encodings supported by the client
        self.core_encodings = ()
        self.encodings_packet = False               #supports delayed encodings initialization?
        self.window_icon_encodings = ["premult_argb32"]
        self.rgb_formats = ("RGB",)
        self.encoding_options = typedict()
        self.icons_encoding_options = typedict()
        self.default_encoding_options = typedict()
        self.auto_refresh_delay = 0

        self.zlib = True
        self.lz4 = use("lz4")

        #for managing the recalculate_delays work:
        self.calculate_window_pixels = {}
        self.calculate_window_ids = set()
        self.calculate_timer = 0
        self.calculate_last_time = 0

        #if we "proxy video", we will modify the video helper to add
        #new encoders, so we must make a deep copy to preserve the original
        #which may be used by other clients (other ServerSource instances)
        self.video_helper = getVideoHelper().clone()
        self.cuda_device_context = None
示例#2
0
    def __init__(self, core_encodings, encodings, default_encoding,
                 scaling_control, default_quality, default_min_quality,
                 default_speed, default_min_speed):
        log("ServerSource%s",
            (core_encodings, encodings, default_encoding, scaling_control,
             default_quality, default_min_quality, default_speed,
             default_min_speed))
        self.server_core_encodings = core_encodings
        self.server_encodings = encodings
        self.default_encoding = default_encoding
        self.scaling_control = scaling_control

        self.default_quality = default_quality  #default encoding quality for lossy encodings
        self.default_min_quality = default_min_quality  #default minimum encoding quality
        self.default_speed = default_speed  #encoding speed (only used by x264)
        self.default_min_speed = default_min_speed  #default minimum encoding speed

        self.default_batch_config = DamageBatchConfig(
        )  #contains default values, some of which may be supplied by the client
        self.global_batch_config = self.default_batch_config.clone(
        )  #global batch config

        self.vrefresh = -1
        self.supports_transparency = False
        self.encoding = None  #the default encoding for all windows
        self.encodings = ()  #all the encodings supported by the client
        self.core_encodings = ()
        self.window_icon_encodings = ["premult_argb32"]
        self.rgb_formats = ("RGB", )
        self.encoding_options = typedict()
        self.icons_encoding_options = typedict()
        self.default_encoding_options = typedict()
        self.auto_refresh_delay = 0

        self.zlib = True
        self.lz4 = use_lz4
        self.lzo = use_lzo

        #for managing the recalculate_delays work:
        self.calculate_window_pixels = {}
        self.calculate_window_ids = set()
        self.calculate_timer = 0
        self.calculate_last_time = 0

        #if we "proxy video", we will modify the video helper to add
        #new encoders, so we must make a deep copy to preserve the original
        #which may be used by other clients (other ServerSource instances)
        self.video_helper = getVideoHelper().clone()

        # the queues of damage requests we work through:
        self.encode_work_queue = Queue(
        )  #holds functions to call to compress data (pixels, clipboard)
        #items placed in this queue are picked off by the "encode" thread,
        #the functions should add the packets they generate to the 'packet_queue'
        self.packet_queue = deque(
        )  #holds actual packets ready for sending (already encoded)
        #these packets are picked off by the "protocol" via 'next_packet()'
        #format: packet, wid, pixels, start_send_cb, end_send_cb
        #(only packet is required - the rest can be 0/None for clipboard packets)
        self.encode_thread = start_thread(self.encode_loop, "encode")
示例#3
0
 def get_full_csc_modes(self):
     #initialize just once per class
     if GLClientWindow.full_csc_modes is None:
         GLClientWindow.full_csc_modes = getVideoHelper(
         ).get_server_full_csc_modes("YUV420P", "YUV422P", "YUV444P",
                                     "GBRP")
     return GLClientWindow.full_csc_modes
示例#4
0
 def do_get_core_encodings(self):
     """
         This method returns the actual encodings supported.
         ie: ["rgb24", "vp8", "webp", "png", "png/L", "png/P", "jpeg", "jpeg2000", "h264", "vpx"]
         It is often overriden in the actual client class implementations,
         where extra encodings can be added (generally just 'rgb32' for transparency),
         or removed if the toolkit implementation class is more limited.
     """
     #we always support rgb:
     core_encodings = ["rgb24", "rgb32"]
     for codec in ("dec_pillow", "dec_webp"):
         if has_codec(codec):
             c = get_codec(codec)
             for e in c.get_encodings():
                 if e not in core_encodings:
                     core_encodings.append(e)
     #we enable all the video decoders we know about,
     #what will actually get used by the server will still depend on the csc modes supported
     video_decodings = getVideoHelper().get_decodings()
     log("video_decodings=%s", video_decodings)
     for encoding in video_decodings:
         if encoding not in core_encodings:
             core_encodings.append(encoding)
     #remove duplicates and use prefered encoding order:
     core_encodings = [
         x for x in PREFERED_ENCODING_ORDER
         if x in set(core_encodings) and x in self.allowed_encodings
     ]
     return core_encodings
示例#5
0
    def __init__(self, *args):
        WindowSource.__init__(self, *args)
        #client uses uses_swscale (has extra limits on sizes)
        self.uses_swscale = self.encoding_options.get("uses_swscale", True)
        self.uses_csc_atoms = self.encoding_options.get("csc_atoms", False)
        self.video_scaling = self.encoding_options.get("video_scaling", False)
        self.video_reinit = self.encoding_options.get("video_reinit", False)
        if not self.encoding_client_options:
            #old clients can only use 420P:
            def_csc_modes = ("YUV420P")
        else:
            #default for newer clients that don't specify "csc_modes":
            def_csc_modes = ("YUV420P", "YUV422P", "YUV444P")
        #0.10 onwards should have specified csc_modes:
        self.csc_modes = self.encoding_options.get("csc_modes", def_csc_modes)

        self.video_encodings = ("vp8", "vp9", "h264")
        for x in self.video_encodings:
            if x in self.server_core_encodings:
                self._encoders[x] = self.video_encode

        #these constraints get updated with real values
        #when we construct the video pipeline:
        self.min_w = 1
        self.min_h = 1
        self.max_w = 16384
        self.max_h = 16384
        self.width_mask = 0xFFFF
        self.height_mask = 0xFFFF
        self.actual_scaling = (1, 1)

        self._csc_encoder = None
        self._video_encoder = None
        self._lock = Lock()               #to ensure we serialize access to the encoder and its internals

        self.last_pipeline_params = None
        self.last_pipeline_scores = []
        self.video_helper = getVideoHelper()
        if self.encoding_options.get("proxy.video", False):
            #if we "proxy video", we will modify the video helper to add
            #new encoders, so we must make a deep copy to preserve the original:
            self.video_helper = getVideoHelper().clone(deep=True)
            #enabling video proxy:
            try:
                self.parse_proxy_video()
            except:
                log.error("failed to parse proxy video", exc_info=True)
示例#6
0
def load_csc_options():
    global CSC_OPTIONS
    if CSC_OPTIONS is None:
        CSC_OPTIONS = {}
        vh = getVideoHelper()
        for csc_in in vh.get_csc_inputs():
            CSC_OPTIONS[csc_in] = vh.get_csc_specs(csc_in)
    return CSC_OPTIONS
示例#7
0
def load_csc_options():
    global CSC_OPTIONS
    if CSC_OPTIONS is None:
        CSC_OPTIONS = {}
        vh = getVideoHelper()
        for csc_in in vh.get_csc_inputs():
            CSC_OPTIONS[csc_in] = vh.get_csc_specs(csc_in)
    return CSC_OPTIONS
示例#8
0
 def get_info(self, _proto):
     info = {
         "encodings": self.get_encoding_info(),
         "video": getVideoHelper().get_info(),
     }
     for k, v in codec_versions.items():
         info.setdefault("encoding", {}).setdefault(k, {})["version"] = v
     return info
示例#9
0
 def _get_full_csc_modes(self, rgb_modes):
     #calculate the server CSC modes the server is allowed to use
     #based on the client CSC modes we can convert to in the backing class we use
     #and trim the transparency if we cannot handle it
     target_rgb_modes = list(rgb_modes)
     if not self._alpha_enabled:
         target_rgb_modes = [x for x in target_rgb_modes if x.find("A")<0]
     full_csc_modes = getVideoHelper().get_server_full_csc_modes_for_rgb(*target_rgb_modes)
     log("full csc modes (%s)=%s", target_rgb_modes, full_csc_modes)
     return full_csc_modes
示例#10
0
 def _get_full_csc_modes(self, rgb_modes):
     #calculate the server CSC modes the server is allowed to use
     #based on the client CSC modes we can convert to in the backing class we use
     #and trim the transparency if we cannot handle it
     target_rgb_modes = list(rgb_modes)
     if not self._alpha_enabled:
         target_rgb_modes = [x for x in target_rgb_modes if x.find("A")<0]
     full_csc_modes = getVideoHelper().get_server_full_csc_modes_for_rgb(*target_rgb_modes)
     log("_get_full_csc_modes(%s)=%s (target_rgb_modes=%s)", rgb_modes, full_csc_modes, target_rgb_modes)
     return full_csc_modes
示例#11
0
def test_load():
    #NOTE: we assume that the scores:
    # - make nvenc less desirable at HQ (maybe not?)
    # - make cuda csc beat swscale
    vep = getVideoHelper()
    try:
        vep.cleanup()
    except Exception:
        pass
    vep.init()
示例#12
0
 def load_codecs(self):
     log("load_codecs()")
     from xpra.codecs.video_helper import getVideoHelper, NO_GFX_CSC_OPTIONS  #pylint: disable=import-outside-toplevel
     vh = getVideoHelper()
     vh.set_modules(video_decoders=self.session_options.video_decoders,
                    csc_modules=self.session_options.csc_modules or NO_GFX_CSC_OPTIONS)
     vh.init()
     from xpra.codecs.loader import load_codecs, show_codecs  #pylint: disable=import-outside-toplevel
     load_codecs()
     show_codecs()
     log("load_codecs() done")
示例#13
0
 def video_helper_init(self):
     #all threads will use just use the same settings anyway,
     #so don't re-initialize the video helper:
     self.video_helper = getVideoHelper()
     #only use video encoders (no CSC supported in proxy)
     try:
         self.video_helper.set_modules(video_encoders=self.video_encoder_modules)
     except AssertionError as e:
         log("video_helper_init() ignored: %s", e)
     else:
         self.video_helper.init()
示例#14
0
 def get_full_csc_modes(self):
     #initialize just once per class
     if ClientWindow.full_csc_modes is None:
         #plain GTK2 window needs to use CSC modules to paint video
         #so calculate the server CSC modes the server is allowed to use
         #based on the client CSC modes we can convert to RGB(A):
         target_rgb_modes = ["RGB", "RGBX"]
         if HAS_ALPHA:
             target_rgb_modes.append("RGBA")
         ClientWindow.full_csc_modes = getVideoHelper().get_server_full_csc_modes_for_rgb(*target_rgb_modes)
         log("full csc modes (%s)=%s", target_rgb_modes, ClientWindow.full_csc_modes)
     return ClientWindow.full_csc_modes
示例#15
0
    def video_init(self):
        enclog("video_init() loading codecs")
        load_codecs(decoders=False)
        enclog("video_init() will try video encoders: %s",
               csv(self.video_encoder_modules) or "none")
        self.video_helper = getVideoHelper()
        #only use video encoders (no CSC supported in proxy)
        self.video_helper.set_modules(
            video_encoders=self.video_encoder_modules)
        self.video_helper.init()

        self.video_encoding_defs = {}
        self.video_encoders = {}
        self.video_encoders_dst_formats = []
        self.video_encoders_last_used_time = {}
        self.video_encoder_types = []

        #figure out which encoders we want to proxy for (if any):
        encoder_types = set()
        for encoding in self.video_helper.get_encodings():
            colorspace_specs = self.video_helper.get_encoder_specs(encoding)
            for colorspace, especs in colorspace_specs.items():
                if colorspace not in ("BGRX", "BGRA", "RGBX", "RGBA"):
                    #only deal with encoders that can handle plain RGB directly
                    continue

                for spec in especs:  #ie: video_spec("x264")
                    spec_props = spec.to_dict()
                    del spec_props["codec_class"]  #not serializable!
                    spec_props[
                        "score_boost"] = 50  #we want to win scoring so we get used ahead of other encoders
                    spec_props[
                        "max_instances"] = 3  #limit to 3 video streams we proxy for (we really want 2,
                    # but because of races with garbage collection, we need to allow more)
                    #store it in encoding defs:
                    self.video_encoding_defs.setdefault(
                        encoding, {}).setdefault(colorspace,
                                                 []).append(spec_props)
                    encoder_types.add(spec.codec_type)

        enclog("encoder types found: %s", tuple(encoder_types))
        #remove duplicates and use preferred order:
        order = PREFERRED_ENCODER_ORDER[:]
        for x in tuple(encoder_types):
            if x not in order:
                order.append(x)
        self.video_encoder_types = [x for x in order if x in encoder_types]
        enclog.info("proxy video encoders: %s",
                    ", ".join(self.video_encoder_types or [
                        "none",
                    ]))
示例#16
0
 def get_full_csc_modes(self):
     #initialize just once per class
     if ClientWindow.full_csc_modes is None:
         #plain GTK2 window needs to use CSC modules to paint video
         #so calculate the server CSC modes the server is allowed to use
         #based on the client CSC modes we can convert to RGB(A):
         target_rgb_modes = ["RGB", "RGBX"]
         if HAS_ALPHA:
             target_rgb_modes.append("RGBA")
         ClientWindow.full_csc_modes = getVideoHelper(
         ).get_server_full_csc_modes_for_rgb(*target_rgb_modes)
         log("full csc modes (%s)=%s", target_rgb_modes,
             ClientWindow.full_csc_modes)
     return ClientWindow.full_csc_modes
示例#17
0
 def _get_full_csc_modes(self, rgb_modes):
     #calculate the server CSC modes the server is allowed to use
     #based on the client CSC modes we can convert to in the backing class we use
     #and trim the transparency if we cannot handle it
     target_rgb_modes = tuple(rgb_modes)
     if not self._alpha_enabled:
         target_rgb_modes = tuple(x for x in target_rgb_modes if x.find("A")<0)
     full_csc_modes = getVideoHelper().get_server_full_csc_modes_for_rgb(*target_rgb_modes)
     full_csc_modes["webp"] = [x for x in rgb_modes if x in ("BGRX", "BGRA", "RGBX", "RGBA")]
     videolog("_get_full_csc_modes(%s) with target_rgb_modes=%s", rgb_modes, target_rgb_modes)
     for e in sorted(full_csc_modes.keys()):
         modes = full_csc_modes.get(e)
         videolog(" * %s : %s", e, modes)
     return full_csc_modes
示例#18
0
def load_video_decoders():
    global VIDEO_DECODERS
    if VIDEO_DECODERS is None:
        VIDEO_DECODERS = {}
        vh = getVideoHelper()
        for encoding in vh.get_decodings():
            specs = vh.get_decoder_specs(encoding)
            for colorspace, decoders in specs.items():
                log("%s decoders for %s: %s", encoding, colorspace, decoders)
                assert len(decoders)>0
                #use the first one:
                _, decoder_module = decoders[0]
                VIDEO_DECODERS[encoding] = decoder_module
        log("video decoders: %s", VIDEO_DECODERS)
    return VIDEO_DECODERS
示例#19
0
def load_video_decoders():
    global VIDEO_DECODERS
    if VIDEO_DECODERS is None:
        VIDEO_DECODERS = {}
        vh = getVideoHelper()
        for encoding in vh.get_decodings():
            specs = vh.get_decoder_specs(encoding)
            for colorspace, decoders in specs.items():
                log("%-5s decoders for %7s: %s", encoding, colorspace, csv([d.get_type() for _, d in decoders]))
                assert len(decoders) > 0
                # use the first one:
                _, decoder_module = decoders[0]
                VIDEO_DECODERS[encoding] = decoder_module
        log("video decoders: %s", dict((e, d.get_type()) for e, d in VIDEO_DECODERS.items()))
    return VIDEO_DECODERS
示例#20
0
def load_video_decoders():
    global VIDEO_DECODERS
    if VIDEO_DECODERS is None:
        VIDEO_DECODERS = {}
        vh = getVideoHelper()
        for encoding in vh.get_decodings():
            specs = vh.get_decoder_specs(encoding)
            for colorspace, decoders in specs.items():
                log("%-5s decoders for %7s: %s", encoding, colorspace, csv([d.get_type() for _,d in decoders]))
                assert decoders
                #use the first one:
                _, decoder_module = decoders[0]
                VIDEO_DECODERS[encoding] = decoder_module
        log("video decoders: %s", dict((e,d.get_type()) for e,d in VIDEO_DECODERS.items()))
    return VIDEO_DECODERS
示例#21
0
def load_video_decoders():
    global VIDEO_DECODERS
    if VIDEO_DECODERS is None:
        VIDEO_DECODERS = {}
        vh = getVideoHelper()
        for encoding in vh.get_decodings():
            specs = vh.get_decoder_specs(encoding)
            for colorspace, decoders in specs.items():
                log("%s decoders for %s: %s", encoding, colorspace, decoders)
                assert len(decoders) > 0
                #use the first one:
                _, decoder_module = decoders[0]
                VIDEO_DECODERS[encoding] = decoder_module
        log("video decoders: %s", VIDEO_DECODERS)
    return VIDEO_DECODERS
示例#22
0
 def init(self, opts):
     self.allowed_encodings = opts.encodings
     self.encoding = opts.encoding
     self.video_scaling = parse_bool_or_int("video-scaling",
                                            opts.video_scaling)
     self.quality = opts.quality
     self.min_quality = opts.min_quality
     self.speed = opts.speed
     self.min_speed = opts.min_speed
     #until we add the ability to choose decoders, use all of them:
     #(and default to non grahics card csc modules if not specified)
     load_codecs(encoders=False)
     vh = getVideoHelper()
     vh.set_modules(video_decoders=opts.video_decoders,
                    csc_modules=opts.csc_modules or NO_GFX_CSC_OPTIONS)
     vh.init()
示例#23
0
    def __init__(self):
        self.server_core_encodings = []
        self.server_encodings = []
        self.default_encoding = None
        self.scaling_control = None

        self.default_quality = 40  #default encoding quality for lossy encodings
        self.default_min_quality = 10  #default minimum encoding quality
        self.default_speed = 40  #encoding speed (only used by x264)
        self.default_min_speed = 10  #default minimum encoding speed

        self.default_batch_config = DamageBatchConfig(
        )  #contains default values, some of which may be supplied by the client
        self.global_batch_config = self.default_batch_config.clone(
        )  #global batch config

        self.vrefresh = -1
        self.supports_transparency = False
        self.encoding = None  #the default encoding for all windows
        self.encodings = ()  #all the encodings supported by the client
        self.core_encodings = ()
        self.window_icon_encodings = ["premult_argb32"]
        self.rgb_formats = ("RGB", )
        self.encoding_options = typedict()
        self.icons_encoding_options = typedict()
        self.default_encoding_options = typedict()
        self.auto_refresh_delay = 0

        self.zlib = True
        self.lz4 = use_lz4
        self.lzo = use_lzo

        #for managing the recalculate_delays work:
        self.calculate_window_pixels = {}
        self.calculate_window_ids = set()
        self.calculate_timer = 0
        self.calculate_last_time = 0

        #if we "proxy video", we will modify the video helper to add
        #new encoders, so we must make a deep copy to preserve the original
        #which may be used by other clients (other ServerSource instances)
        self.video_helper = getVideoHelper().clone()
示例#24
0
    def video_init(self):
        enclog("video_init() loading codecs")
        load_codecs(decoders=False)
        enclog("video_init() will try video encoders: %s", csv(self.video_encoder_modules) or "none")
        self.video_helper = getVideoHelper()
        #only use video encoders (no CSC supported in proxy)
        self.video_helper.set_modules(video_encoders=self.video_encoder_modules)
        self.video_helper.init()

        self.video_encoding_defs = {}
        self.video_encoders = {}
        self.video_encoders_dst_formats = []
        self.video_encoders_last_used_time = {}
        self.video_encoder_types = []

        #figure out which encoders we want to proxy for (if any):
        encoder_types = set()
        for encoding in self.video_helper.get_encodings():
            colorspace_specs = self.video_helper.get_encoder_specs(encoding)
            for colorspace, especs in colorspace_specs.items():
                if colorspace not in ("BGRX", "BGRA", "RGBX", "RGBA"):
                    #only deal with encoders that can handle plain RGB directly
                    continue

                for spec in especs:                             #ie: video_spec("x264")
                    spec_props = spec.to_dict()
                    del spec_props["codec_class"]               #not serializable!
                    spec_props["score_boost"] = 50              #we want to win scoring so we get used ahead of other encoders
                    spec_props["max_instances"] = 3             #limit to 3 video streams we proxy for (we really want 2,
                                                                # but because of races with garbage collection, we need to allow more)
                    #store it in encoding defs:
                    self.video_encoding_defs.setdefault(encoding, {}).setdefault(colorspace, []).append(spec_props)
                    encoder_types.add(spec.codec_type)

        enclog("encoder types found: %s", tuple(encoder_types))
        #remove duplicates and use preferred order:
        order = PREFERRED_ENCODER_ORDER[:]
        for x in list(encoder_types):
            if x not in order:
                order.append(x)
        self.video_encoder_types = [x for x in order if x in encoder_types]
        enclog.info("proxy video encoders: %s", ", ".join(self.video_encoder_types))
示例#25
0
 def init(self, opts):
     self.allowed_encodings = opts.encodings
     self.encoding = opts.encoding
     if opts.video_scaling.lower() in ("auto", "on"):
         self.video_scaling = None
     else:
         self.video_scaling = parse_bool_or_int("video-scaling", opts.video_scaling)
     self.quality = opts.quality
     self.min_quality = opts.min_quality
     self.speed = opts.speed
     self.min_speed = opts.min_speed
     load_codec("dec_pillow")
     ae = self.allowed_encodings
     if "jpeg" in ae:
         #try to load the fast jpeg encoder:
         load_codec("dec_jpeg")
     if "webp" in ae:
         #try to load the fast webp encoder:
         load_codec("dec_webp")
     vh = getVideoHelper()
     vh.set_modules(video_decoders=opts.video_decoders, csc_modules=opts.csc_modules or NO_GFX_CSC_OPTIONS)
     vh.init()
示例#26
0
 def filter_client_caps(self, caps):
     fc = self.filter_caps(caps, ("cipher", "digest", "aliases", "compression", "lz4"))
     #update with options provided via config if any:
     fc.update(self.session_options)
     if self.video_encoder_types:
         #pass list of encoding specs to client:
         from xpra.codecs.video_helper import getVideoHelper
         self.video_helper = getVideoHelper()
         self.video_helper.init()
         #serialize encodings defs into a dict:
         encoding_defs = {}
         e_found = []
         #encoding: "h264" or "vp8", etc
         for encoding in self.video_helper.get_encodings():
             #ie: colorspace_specs = {"BGRX" : [codec_spec("x264"), codec_spec("nvenc")], "YUV422P" : ...
             colorspace_specs = self.video_helper.get_encoder_specs(encoding)
             #ie: colorspace="BGRX", especs=[codec_spec("x264"), codec_spec("nvenc")]
             for colorspace, especs in colorspace_specs.items():
                 if colorspace not in ("BGRX", "BGRA", "RGBX", "RGBA"):
                     #don't bother with formats that require a CSC step for now
                     continue
                 for spec in especs:                             #ie: codec_spec("x264")
                     if spec.codec_type not in self.video_encoder_types:
                         debug("skipping encoder %s", spec.codec_type)
                         continue
                     spec_props = spec.to_dict()
                     del spec_props["codec_class"]               #not serializable!
                     spec_props["score_boost"] = 50              #we want to win scoring so we get used ahead of other encoders
                     #store it in encoding defs:
                     encoding_defs.setdefault(encoding, {}).setdefault(colorspace, []).append(spec_props)
                     e_found.append(spec.codec_type)
         missing = [x for x in self.video_encoder_types if x not in e_found]
         if len(missing)>0:
             log.warn("the following proxy encoders were not found or did not match: %s", ", ".join(missing))
         fc["encoding.proxy.video.encodings"] = encoding_defs
         fc["encoding.proxy.video"] = True
     return fc
示例#27
0
文件: server.py 项目: svn2github/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write("current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding=="help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting  = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying  = mode == "proxy"
    clobber   = upgrading or opts.use_display

    if upgrading or shadowing:
        #there should already be one running
        opts.pulseaudio = False

    #get the display name:
    if shadowing and len(extra_args)==0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            #just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display
            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args)==0:
        from xpra.scripts.main import guess_xpra_display
        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb("too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb("you must specify a free virtual display name to use with the proxy server")
            if not opts.displayfd:
                error_cb("displayfd support is not enabled on this system, you must specify the display to use")
            if opts.use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display     #@Reimport
                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb("--exit-with-children specified without any children to spawn; exiting immediately")

    atexit.register(run_cleanups)
    #the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write("Entering daemon mode; "
                 + "any further errors will be reported to:\n"
                 + ("  %s\n" % log_filename0))
        except:
            #this can happen if stderr is closed by the caller already
            pass

    if os.name=="posix":
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger
    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception as e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1

    # Do this after writing out the shell script:
    if display_name[0] != 'S':
        os.environ["DISPLAY"] = display_name
    sanitize_env()
    configure_imsettings_env(opts.input_method)

    # Start the Xvfb server first to get the display_name if needed
    xvfb = None
    xvfb_pid = None
    if not shadowing and not proxying and not clobber:
        try:
            xvfb, display_name = start_Xvfb(opts.xvfb, display_name)
        except OSError as e:
            log.error("Error starting Xvfb: %s\n", e)
            return  1
        xvfb_pid = xvfb.pid
        #always update as we may now have the "real" display name:
        os.environ["DISPLAY"] = display_name

    if opts.daemon:
        log_filename1 = select_log_file(dotxpra, opts.log_file, display_name)
        if log_filename0 != log_filename1:
            # we now have the correct log filename, so use it:
            os.rename(log_filename0, log_filename1)
            stderr.write("Actual log file name is now: %s\n" % log_filename1)
        stdout.close()
        stderr.close()

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return  1

    #setup unix domain socket:
    socket, cleanup_socket = setup_local_socket(dotxpra, display_name, clobber, opts.mmap_group, opts.socket_permissions)
    if socket:      #win32 returns None!
        sockets.append(socket)
        if opts.mdns:
            ssh_port = get_ssh_port()
            if ssh_port:
                mdns_recs.append(("ssh", [("", ssh_port)]))

    #publish mdns records:
    if opts.mdns:
        from xpra.platform.info import get_username
        mdns_info = {"display" : display_name,
                     "username": get_username()}
        if opts.session_name:
            mdns_info["session"] = opts.session_name
        for mode, listen_on in mdns_recs:
            mdns_publish(display_name, mode, listen_on, mdns_info)

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return  1

    display = None
    if not sys.platform.startswith("win") and not sys.platform.startswith("darwin") and not proxying:
        display = verify_display_ready(xvfb, display_name, shadowing)
        if not display:
            return 1
    elif not proxying:
        assert "gtk" not in sys.modules
        import gtk          #@Reimport
        assert gtk

    if shadowing:
        from xpra.platform.shadow_server import ShadowServer
        app = ShadowServer()
        info = "shadow"
    elif proxying:
        from xpra.server.proxy_server import ProxyServer
        app = ProxyServer()
        info = "proxy"
    else:
        assert starting or upgrading
        from xpra.x11.gtk_x11 import gdk_display_source
        assert gdk_display_source
        #(now we can access the X11 server)

        if clobber:
            #get the saved pid (there should be one):
            xvfb_pid = get_xvfb_pid()
        elif xvfb_pid is not None:
            #save the new pid (we should have one):
            save_xvfb_pid(xvfb_pid)

        #check for an existing window manager:
        from xpra.x11.gtk_x11.wm import wm_check
        if not wm_check(display, opts.wm_name, upgrading):
            return 1
        try:
            # This import is delayed because the module depends on gtk:
            from xpra.x11.server import XpraServer
            from xpra.x11.bindings.window_bindings import X11WindowBindings     #@UnresolvedImport
            X11Window = X11WindowBindings()
        except ImportError as e:
            log.error("Failed to load Xpra server components, check your installation: %s" % e)
            return 1
        if not X11Window.displayHasXComposite():
            log.error("Xpra is a compositing manager, it cannot use a display which lacks the XComposite extension!")
            return 1
        app = XpraServer(clobber)
        info = "xpra"

    try:
        app.exec_cwd = cwd
        app.init(opts)
    except Exception as e:
        log.error("Error: cannot start the %s server", info, exc_info=True)
        log.error(str(e))
        log.info("")
        return 1

    #honour start child, html webserver, and setup child reaper
    if os.name=="posix" and not proxying and not upgrading and not shadowing:
        # start websockify?
        try:
            start_websockify(app.child_reaper, opts, bind_tcp)
            #websockify overrides the tcp proxy, so we must re-set it:
            app._tcp_proxy = opts.tcp_proxy
        except Exception as e:
            error_cb("failed to setup websockify html server: %s" % e)
        if opts.exit_with_children:
            assert opts.start_child, "exit-with-children was specified but start-child is missing!"
        if opts.start:
            for x in opts.start:
                if x:
                    app.start_child(x, x, True)
        if opts.start_child:
            for x in opts.start_child:
                if x:
                    app.start_child(x, x, False)

    log("%s(%s)", app.init_sockets, sockets)
    app.init_sockets(sockets)
    log("%s(%s)", app.init_when_ready, _when_ready)
    app.init_when_ready(_when_ready)

    #we got this far so the sockets have initialized and
    #the server should be able to manage the display
    #from now on, if we exit without upgrading we will also kill the Xvfb
    def kill_xvfb():
        # Close our display(s) first, so the server dying won't kill us.
        log.info("killing xvfb with pid %s" % xvfb_pid)
        import gtk  #@Reimport
        for display in gtk.gdk.display_manager_get().list_displays():
            display.close()
        os.kill(xvfb_pid, signal.SIGTERM)
    if xvfb_pid is not None and not opts.use_display and not shadowing:
        _cleanups.append(kill_xvfb)

    try:
        log("running %s", app.run)
        e = app.run()
        log("%s()=%s", app.run, e)
    except KeyboardInterrupt:
        log.info("stopping on KeyboardInterrupt")
        e = 0
    except Exception as e:
        log.error("server error", exc_info=True)
        e = -128
    if e>0:
        # Upgrading/exiting, so leave X server running
        if kill_xvfb in _cleanups:
            _cleanups.remove(kill_xvfb)
        from xpra.server.server_core import ServerCore
        if e==ServerCore.EXITING_CODE:
            log.info("exiting: not cleaning up Xvfb")
        elif cleanup_socket in _cleanups:
            log.info("upgrading: not cleaning up Xvfb or socket")
            # don't delete the new socket (not ours)
            _cleanups.remove(cleanup_socket)
        log("cleanups=%s", _cleanups)
        e = 0
    return e
示例#28
0
 def cleanup(self):
     try:
         getVideoHelper().cleanup()
     except:
         log.error("error on video cleanup", exc_info=True)
示例#29
0
文件: server.py 项目: svn2github/Xpra
def run_server(parser, opts, mode, xpra_file, extra_args):
    if opts.encoding and opts.encoding=="help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting  = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying  = mode == "proxy"
    clobber   = upgrading or opts.use_display

    #get the display name:
    if shadowing and len(extra_args)==0:
        from xpra.scripts.main import guess_X11_display
        display_name = guess_X11_display()
    else:
        if len(extra_args) != 1:
            parser.error("need exactly 1 extra argument")
        display_name = extra_args.pop(0)

    if not shadowing and not proxying:
        display_name_check(display_name)

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        sys.stderr.write("--exit-with-children specified without any children to spawn; exiting immediately")
        return  1

    atexit.register(run_cleanups)
    #the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)

        logfd = open_log_file(dotxpra, opts.log_file, display_name)
        assert logfd > 2
        daemonize(logfd)

    # Write out a shell-script so that we can start our proxy in a clean
    # environment:
    write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger
    log = Logger("server")

    try:
        # Initialize the sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)

        sockets = []
        mdns_info = {"display" : display_name,
                     "username": getpass.getuser()}
        if opts.session_name:
            mdns_info["session"] = opts.session_name
        #tcp:
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        #unix:
        socket, cleanup_socket = setup_local_socket(dotxpra, display_name, clobber, opts.mmap_group)
        if socket:      #win32 returns None!
            sockets.append(socket)
            if opts.mdns:
                ssh_port = get_ssh_port()
                if ssh_port:
                    mdns_publish(display_name, "ssh", [("", ssh_port)], mdns_info)
        if opts.mdns:
            mdns_publish(display_name, "tcp", bind_tcp, mdns_info)
    except Exception, e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1
示例#30
0
    def get_encodings_caps(self):
        if B_FRAMES:
            video_b_frames = ["h264"]  #only tested with dec_avcodec2
        else:
            video_b_frames = []
        caps = {
            "flush":
            PAINT_FLUSH,
            "scaling.control":
            self.video_scaling,
            "client_options":
            True,
            "csc_atoms":
            True,
            #TODO: check for csc support (swscale only?)
            "video_reinit":
            True,
            "video_scaling":
            True,
            "video_b_frames":
            video_b_frames,
            "webp_leaks":
            False,
            "transparency":
            self.has_transparency(),
            "rgb24zlib":
            True,
            "max-soft-expired":
            MAX_SOFT_EXPIRED,
            "send-timestamps":
            SEND_TIMESTAMPS,
            "supports_delta":
            tuple(x for x in ("png", "rgb24", "rgb32")
                  if x in self.get_core_encodings()),
        }
        if self.encoding:
            caps[""] = self.encoding
        for k, v in codec_versions.items():
            caps["%s.version" % k] = v
        if self.quality > 0:
            caps["quality"] = self.quality
        if self.min_quality > 0:
            caps["min-quality"] = self.min_quality
        if self.speed >= 0:
            caps["speed"] = self.speed
        if self.min_speed >= 0:
            caps["min-speed"] = self.min_speed

        #generic rgb compression flags:
        for x in compression.ALL_COMPRESSORS:
            caps["rgb_%s" % x] = x in compression.get_enabled_compressors()
        #these are the defaults - when we instantiate a window,
        #we can send different values as part of the map event
        #these are the RGB modes we want (the ones we are expected to be able to paint with):
        rgb_formats = ["RGB", "RGBX", "RGBA"]
        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)
        caps["full_csc_modes"] = full_csc_modes

        if "h264" in self.get_core_encodings():
            # some profile options: "baseline", "main", "high", "high10", ...
            # set the default to "high10" for I420/YUV420P
            # as the python client always supports all the profiles
            # whereas on the server side, the default is baseline to accomodate less capable clients.
            # I422/YUV422P requires high422, and
            # I444/YUV444P requires high444,
            # so we don't bother specifying anything for those two.
            for old_csc_name, csc_name, default_profile in (("I420", "YUV420P",
                                                             "high10"),
                                                            ("I422", "YUV422P",
                                                             ""), ("I444",
                                                                   "YUV444P",
                                                                   "")):
                profile = default_profile
                #try with the old prefix (X264) as well as the more correct one (H264):
                for H264_NAME in ("X264", "H264"):
                    profile = os.environ.get(
                        "XPRA_%s_%s_PROFILE" % (H264_NAME, old_csc_name),
                        profile)
                    profile = os.environ.get(
                        "XPRA_%s_%s_PROFILE" % (H264_NAME, csc_name), profile)
                if profile:
                    #send as both old and new names:
                    for h264_name in ("x264", "h264"):
                        caps["%s.%s.profile" %
                             (h264_name, old_csc_name)] = profile
                        caps["%s.%s.profile" % (h264_name, csc_name)] = profile
            log(
                "x264 encoding options: %s",
                str([(k, v) for k, v in caps.items()
                     if k.startswith("x264.")]))
        log("encoding capabilities: %s", caps)
        return caps
示例#31
0
    def get_encodings_caps(self) -> dict:
        if B_FRAMES:
            video_b_frames = ("h264", ) #only tested with dec_avcodec2
        else:
            video_b_frames = ()
        caps = {
            "flush"                     : PAINT_FLUSH,      #v4 servers assume this is available
            "video_scaling"             : True,             #v4 servers assume this is available
            "video_b_frames"            : video_b_frames,
            "video_max_size"            : self.video_max_size,
            "max-soft-expired"          : MAX_SOFT_EXPIRED,
            "send-timestamps"           : SEND_TIMESTAMPS,
            }
        if self.video_scaling is not None:
            caps["scaling.control"] = self.video_scaling
        if self.encoding:
            caps[""] = self.encoding
        for k,v in codec_versions.items():
            caps["%s.version" % k] = v
        if self.quality>0:
            caps["quality"] = self.quality
        if self.min_quality>0:
            caps["min-quality"] = self.min_quality
        if self.speed>=0:
            caps["speed"] = self.speed
        if self.min_speed>=0:
            caps["min-speed"] = self.min_speed

        #generic rgb compression flags:
        for x in compression.ALL_COMPRESSORS:
            caps["rgb_%s" % x] = x in compression.get_enabled_compressors()
        #these are the defaults - when we instantiate a window,
        #we can send different values as part of the map event
        #these are the RGB modes we want (the ones we are expected to be able to paint with):
        rgb_formats = ["RGB", "RGBX", "RGBA"]
        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", )
        if has_codec("dec_jpeg") or has_codec("dec_pillow"):
            full_csc_modes["jpeg"] = ("BGRX", "BGRA", "YUV420P")
        if has_codec("dec_jpeg"):
            full_csc_modes["jpega"] = ("BGRA", "RGBA", )
        log("supported full csc_modes=%s", full_csc_modes)
        caps["full_csc_modes"] = full_csc_modes

        if "h264" in self.get_core_encodings():
            # some profile options: "baseline", "main", "high", "high10", ...
            # set the default to "high10" for YUV420P
            # as the python client always supports all the profiles
            # whereas on the server side, the default is baseline to accomodate less capable clients.
            # YUV422P requires high422, and
            # YUV444P requires high444,
            # so we don't bother specifying anything for those two.
            h264_caps = {}
            for csc_name, default_profile in (
                        ("YUV420P", "high"),
                        ("YUV422P", ""),
                        ("YUV444P", "")):
                profile = os.environ.get("XPRA_H264_%s_PROFILE" % (csc_name), default_profile)
                if profile:
                    h264_caps["%s.profile" % (csc_name)] = profile
            h264_caps["fast-decode"] = envbool("XPRA_X264_FAST_DECODE", False)
            log("x264 encoding options: %s", h264_caps)
            updict(caps, "h264", h264_caps)
        log("encoding capabilities: %s", caps)
        return caps
示例#32
0
 def cleanup(self):
     try:
         getVideoHelper().cleanup()
     except Exception:   # pragma: no cover
         log.error("error on video cleanup", exc_info=True)
示例#33
0
 def cleanup(self):
     getVideoHelper().cleanup()
示例#34
0
    def do_start_XpraClient(self, conn, display_desc={}):
        log("do_start_XpraClient(%s, %s) client=%s", conn, display_desc, self.client)
        self.client.encoding = self.config.encoding
        self.client.display_desc = display_desc
        self.client.setup_connection(conn)
        #we have already initialized it,
        #but calling client.init will do it again - so we have to clear it:
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().cleanup()
        self.client.init(self.config)
        self.client.init_ui(self.config)
        log("start_XpraClient() client initialized")

        if self.config.password:
            #pass the password to the class directly:
            def load_password():
                return self.config.password
            self.client.password_file = "FAKE-PASSWORD-FILE-FOR-LAUNCHER"
            self.client.load_password = load_password
        #override exit code:
        warn_and_quit_save = self.client.warn_and_quit
        quit_save = self.client.quit
        def do_quit(*_args):
            self.client.warn_and_quit = warn_and_quit_save
            self.client.quit = quit_save
            self.client.cleanup()
            self.destroy()
            gtk.main_quit()
        def warn_and_quit_override(exit_code, warning):
            log("warn_and_quit_override(%s, %s)", exit_code, warning)
            if self.exit_code == None:
                self.exit_code = exit_code
            password_warning = warning.find("invalid password")>=0
            if password_warning:
                self.password_warning()
            err = exit_code!=0 or password_warning
            if not self.current_error:
                self.current_error = warning
                self.set_info_color(err)
                self.set_info_text(warning)
            if err:
                def ignore_further_quit_events(*args):
                    pass
                if self.client:
                    self.client.cleanup()
                    self.client.warn_and_quit = ignore_further_quit_events
                    self.client.quit = ignore_further_quit_events
                w = self.window
                if w:
                    self.set_sensitive(True)
                    self.reset_client()
                    glib.idle_add(w.show)
            else:
                do_quit()

        def quit_override(exit_code):
            log("quit_override(%s)", exit_code)
            if self.exit_code == None:
                self.exit_code = exit_code
            self.client.cleanup()
            if self.exit_code==0:
                do_quit()
            else:
                self.reset_client()

        self.client.warn_and_quit = warn_and_quit_override
        self.client.quit = quit_override
        try:
            self.client.run()
        except Exception as e:
            log.error("client error", exc_info=True)
            self.handle_exception(e)
示例#35
0
 def threaded_setup(self):
     getVideoHelper().init()
     #re-init encodings now that we have video:
     self.init_encodings()
示例#36
0
文件: server.py 项目: svn2github/Xpra
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write("current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding == "help":
        # avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        # disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging

        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase

        sb = ServerBase()
        sb.init(opts)
        # ensures that the threaded video helper init has completed
        # (by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper

        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help

        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"
    clobber = upgrading or opts.use_display

    # get the display name:
    if shadowing and len(extra_args) == 0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            # just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display

            display_name = guess_X11_display(opts.socket_dir)
    elif upgrading and len(extra_args) == 0:
        from xpra.scripts.main import guess_xpra_display

        display_name = guess_xpra_display(opts.socket_dir)
    else:
        if len(extra_args) > 1:
            error_cb("too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb("you must specify a free virtual display name to use with the proxy server")
            if not opts.displayfd:
                error_cb("displayfd support is not enabled on this system, you must specify the display to use")
            if opts.use_display:
                # only use automatic guess for xpra displays and not X11 displays:
                from xpra.scripts.main import guess_xpra_display  # @Reimport

                display_name = guess_xpra_display(opts.socket_dir)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = "S" + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb("--exit-with-children specified without any children to spawn; exiting immediately")

    atexit.register(run_cleanups)
    # the server class will usually override those:
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    dotxpra = DotXpra(opts.socket_dir)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        # daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(dotxpra, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write(
                "Entering daemon mode; " + "any further errors will be reported to:\n" + ("  %s\n" % log_filename0)
            )
        except:
            # this can happen if stderr is closed by the caller already
            pass

    # Write out a shell-script so that we can start our proxy in a clean
    # environment:
    write_runner_shell_script(dotxpra, script)

    from xpra.log import Logger

    log = Logger("server")

    mdns_recs = []
    sockets = []
    try:
        # Initialize the TCP sockets before the display,
        # That way, errors won't make us kill the Xvfb
        # (which may not be ours to kill at that point)
        bind_tcp = parse_bind_tcp(opts.bind_tcp)
        for host, iport in bind_tcp:
            socket = setup_tcp_socket(host, iport)
            sockets.append(socket)
        if opts.mdns:
            mdns_recs.append(("tcp", bind_tcp))
    except Exception, e:
        log.error("cannot start server: failed to setup sockets: %s", e)
        return 1
示例#37
0
    def init_encodings(self):
        encs, core_encs = [], []
        log("init_encodings() allowed_encodings=%s", self.allowed_encodings)

        def add_encoding(encoding):
            log("add_encoding(%s)", encoding)
            e = {"rgb32": "rgb", "rgb24": "rgb"}.get(encoding, encoding)
            if self.allowed_encodings is not None:
                if e not in self.allowed_encodings and encoding not in self.allowed_encodings:
                    #not in whitelist (if it exists)
                    return
            if e not in encs:
                encs.append(e)
            if encoding not in core_encs:
                core_encs.append(encoding)

        def add_encodings(*encodings):
            log("add_encodings%s", encodings)
            for encoding in encodings:
                add_encoding(encoding)

        add_encodings("rgb24", "rgb32", "scroll")
        lossless = []
        if "scroll" in self.allowed_encodings and "scroll" not in self.lossless_mode_encodings:
            #scroll is lossless, but it also uses other picture codecs
            #and those allow changes in quality
            lossless.append("scroll")

        #video encoders (empty when first called - see threaded_init)
        ve = getVideoHelper().get_encodings()
        log("init_encodings() adding video encodings: %s", ve)
        add_encodings(*ve)  #ie: ["vp8", "h264"]
        #Pithon Imaging Libary:
        enc_pillow = get_codec("enc_pillow")
        log("enc_pillow=%s", enc_pillow)
        if enc_pillow:
            pil_encs = enc_pillow.get_encodings()
            log("pillow encodings: %s", pil_encs)
            for encoding in pil_encs:
                if encoding != "webp":
                    add_encoding(encoding)
            #Note: webp will only be enabled if we have a Python-PIL fallback
            #(either "webp" or "png")
            if has_codec("enc_webp") and ("webp" in pil_encs
                                          or "png" in pil_encs):
                add_encodings("webp")
                if "webp" not in lossless:
                    lossless.append("webp")
        for codec_name in ("avif", "enc_jpeg", "enc_nvjpeg"):
            codec = get_codec(codec_name)
            if codec:
                add_encodings(*codec.get_encodings())
        #look for video encodings with lossless mode:
        for e in ve:
            for colorspace, especs in getVideoHelper().get_encoder_specs(
                    e).items():
                for espec in especs:
                    if espec.has_lossless_mode:
                        if e not in lossless:
                            log(
                                "found lossless mode for encoding %s with %s and colorspace %s",
                                e, espec, colorspace)
                            lossless.append(e)
                            break
        #now update the variables:
        encs.append("grayscale")
        self.encodings = encs
        self.core_encodings = tuple(core_encs)
        self.lossless_mode_encodings = tuple(lossless)
        self.lossless_encodings = tuple(
            x for x in self.core_encodings
            if (x.startswith("png") or x.startswith("rgb") or x == "webp"))
        log(
            "allowed encodings=%s, encodings=%s, core encodings=%s, lossless encodings=%s",
            self.allowed_encodings, encs, core_encs, self.lossless_encodings)
        pref = [x for x in PREFERRED_ENCODING_ORDER if x in self.encodings]
        if pref:
            self.default_encoding = pref[0]
        else:
            self.default_encoding = None
        #default encoding:
        if not self.encoding or str(self.encoding).lower() in ("auto", "none"):
            self.default_encoding = None
        elif self.encoding in self.encodings:
            self.default_encoding = self.encoding
        else:
            log.warn("ignored invalid default encoding option: %s",
                     self.encoding)
示例#38
0
    def do_start_XpraClient(self, conn, display_desc={}):
        log("do_start_XpraClient(%s, %s) client=%s", conn, display_desc, self.client)
        self.client.encoding = self.config.encoding
        self.client.display_desc = display_desc
        self.client.setup_connection(conn)
        #we have already initialized it,
        #but calling client.init will do it again - so we have to clear it:
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().cleanup()
        self.client.init(self.config)
        self.client.init_ui(self.config)
        log("start_XpraClient() client initialized")

        if self.config.password:
            #pass the password to the class directly:
            def load_password():
                return self.config.password
            self.client.password_file = "FAKE-PASSWORD-FILE-FOR-LAUNCHER"
            self.client.load_password = load_password
        #override exit code:
        warn_and_quit_save = self.client.warn_and_quit
        quit_save = self.client.quit
        def do_quit(*args):
            self.client.warn_and_quit = warn_and_quit_save
            self.client.quit = quit_save
            self.client.cleanup()
            self.destroy()
            gtk.main_quit()
        def warn_and_quit_override(exit_code, warning):
            log("warn_and_quit_override(%s, %s)", exit_code, warning)
            if self.exit_code == None:
                self.exit_code = exit_code
            password_warning = warning.find("invalid password")>=0
            if password_warning:
                self.password_warning()
            err = exit_code!=0 or password_warning
            if not self.current_error:
                self.current_error = warning
                self.set_info_color(err)
                self.set_info_text(warning)
            if err:
                def ignore_further_quit_events(*args):
                    pass
                if self.client:
                    self.client.cleanup()
                    self.client.warn_and_quit = ignore_further_quit_events
                    self.client.quit = ignore_further_quit_events
                self.set_sensitive(True)
                self.reset_client()
                glib.idle_add(self.window.show)
            else:
                do_quit()

        def quit_override(exit_code):
            log("quit_override(%s)", exit_code)
            if self.exit_code == None:
                self.exit_code = exit_code
            self.client.cleanup()
            if self.exit_code==0:
                do_quit()
            else:
                self.reset_client()

        self.client.warn_and_quit = warn_and_quit_override
        self.client.quit = quit_override
        try:
            self.client.run()
        except Exception as e:
            log.error("client error", exc_info=True)
            self.handle_exception(e)
示例#39
0
def run_server(error_cb, opts, mode, xpra_file, extra_args):
    try:
        cwd = os.getcwd()
    except:
        cwd = os.path.expanduser("~")
        sys.stderr.write(
            "current working directory does not exist, using '%s'\n" % cwd)
    if opts.encoding and opts.encoding == "help":
        #avoid errors and warnings:
        opts.encoding = ""
        opts.clipboard = False
        opts.notifications = False
        print("xpra server supports the following encodings:")
        print("(please wait, encoder initialization may take a few seconds)")
        #disable info logging which would be confusing here
        from xpra.log import get_all_loggers, set_default_level
        import logging
        set_default_level(logging.WARN)
        logging.root.setLevel(logging.WARN)
        for x in get_all_loggers():
            x.logger.setLevel(logging.WARN)
        from xpra.server.server_base import ServerBase
        sb = ServerBase()
        sb.init(opts)
        #ensures that the threaded video helper init has completed
        #(by running it again, which will block on the init lock)
        from xpra.codecs.video_helper import getVideoHelper
        getVideoHelper().init()
        sb.init_encodings()
        from xpra.codecs.loader import encoding_help
        for e in sb.encodings:
            print(" * %s" % encoding_help(e))
        return 0

    assert mode in ("start", "upgrade", "shadow", "proxy")
    starting = mode == "start"
    upgrading = mode == "upgrade"
    shadowing = mode == "shadow"
    proxying = mode == "proxy"
    clobber = upgrading or opts.use_display
    start_vfb = not shadowing and not proxying and not clobber

    if upgrading or shadowing:
        #there should already be one running
        opts.pulseaudio = False

    #get the display name:
    if shadowing and len(extra_args) == 0:
        if sys.platform.startswith("win") or sys.platform.startswith("darwin"):
            #just a virtual name for the only display available:
            display_name = ":0"
        else:
            from xpra.scripts.main import guess_X11_display
            display_name = guess_X11_display(opts.socket_dir, opts.socket_dirs)
    elif upgrading and len(extra_args) == 0:
        display_name = guess_xpra_display(opts.socket_dir, opts.socket_dirs)
    else:
        if len(extra_args) > 1:
            error_cb(
                "too many extra arguments: only expected a display number")
        if len(extra_args) == 1:
            display_name = extra_args[0]
            if not shadowing and not proxying:
                display_name_check(display_name)
        else:
            if proxying:
                error_cb(
                    "you must specify a free virtual display name to use with the proxy server"
                )
            if not opts.displayfd:
                error_cb(
                    "displayfd support is not enabled on this system, you must specify the display to use"
                )
            if opts.use_display:
                #only use automatic guess for xpra displays and not X11 displays:
                display_name = guess_xpra_display(opts.socket_dir,
                                                  opts.socket_dirs)
            else:
                # We will try to find one automaticaly
                # Use the temporary magic value 'S' as marker:
                display_name = 'S' + str(os.getpid())

    if not shadowing and not proxying and not upgrading and opts.exit_with_children and not opts.start_child:
        error_cb(
            "--exit-with-children specified without any children to spawn; exiting immediately"
        )

    atexit.register(run_cleanups)
    #the server class will usually override those:
    #SIGINT breaks GTK3.. (but there are no py3k servers!)
    signal.signal(signal.SIGINT, deadly_signal)
    signal.signal(signal.SIGTERM, deadly_signal)

    # Generate the script text now, because os.getcwd() will
    # change if/when we daemonize:
    script = xpra_runner_shell_script(xpra_file, os.getcwd(), opts.socket_dir)

    if start_vfb or opts.daemon:
        #we will probably need a log dir
        #either for the vfb, or for our own log file
        log_dir = os.path.expanduser(opts.log_dir)
        if not os.path.exists(log_dir):
            try:
                os.mkdir(log_dir, 0o700)
            except OSError as e:
                raise InitException(
                    "failed to create the Xorg log directory '%s': %s" %
                    (xorg_log_dir, e))

    stdout = sys.stdout
    stderr = sys.stderr
    # Daemonize:
    if opts.daemon:
        #daemonize will chdir to "/", so try to use an absolute path:
        if opts.password_file:
            opts.password_file = os.path.abspath(opts.password_file)
        # At this point we may not know the display name,
        # so log_filename0 may point to a temporary file which we will rename later
        log_filename0 = select_log_file(log_dir, opts.log_file, display_name)
        logfd = open_log_file(log_filename0)
        assert logfd > 2
        stdout, stderr = daemonize(logfd)
        try:
            stderr.write("Entering daemon mode; " +
                         "any further errors will be reported to:\n" +
                         ("  %s\n" % log_filename0))
        except:
            #this can happen if stderr is closed by the caller already
            pass

    if os.name == "posix":
        # Write out a shell-script so that we can start our proxy in a clean
        # environment:
        write_runner_shell_script(script)

    from xpra.log import Logger
    log = Logger("server")

    #warn early about this:
    if starting:
        de = os.environ.get("XDG_SESSION_DESKTOP") or os.environ.get(
            "SESSION_DESKTOP")
        if de and (opts.pulseaudio or opts.notifications):
            log.warn(
                "Warning: xpra start from an existing '%s' desktop session",
                de)
            log.warn(" pulseaudio and notifications forwarding may not work")
            log.warn(
                " try using a clean environment, a dedicated user, or turn off those options"
            )

    mdns_recs = []
    sockets = []
    # Initialize the TCP sockets before the display,
    # That way, errors won't make us kill the Xvfb
    # (which may not be ours to kill at that point)
    bind_tcp = parse_bind_tcp(opts.bind_tcp)
    for host, iport in bind_tcp:
        socket = setup_tcp_socket(host, iport)
        sockets.append(socket)
        if opts.mdns:
            rec = "tcp", [(host, iport)]
            mdns_recs.append(rec)

    # Do this after writing out the shell script:
    if display_name[0] != 'S':
        os.environ["DISPLAY"] = display_name
    sanitize_env()
    configure_imsettings_env(opts.input_method)

    # Start the Xvfb server first to get the display_name if needed
    xvfb = None
    xvfb_pid = None
    if start_vfb:
        try:
            xvfb, display_name = start_Xvfb(opts.xvfb, display_name)
        except OSError as e:
            log.error("Error starting Xvfb: %s\n", e)
            return 1
        xvfb_pid = xvfb.pid
        #always update as we may now have the "real" display name:
        os.environ["DISPLAY"] = display_name

    if opts.daemon:
        log_filename1 = select_log_file(log_dir, opts.log_file, display_name)
        if log_filename0 != log_filename1:
            # we now have the correct log filename, so use it:
            os.rename(log_filename0, log_filename1)
            stderr.write("Actual log file name is now: %s\n" % log_filename1)
        stdout.close()
        stderr.close()

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return 1

    #setup unix domain socket:
    socket, cleanup_socket = setup_local_socket(opts.socket_dir,
                                                opts.socket_dirs, display_name,
                                                clobber, opts.mmap_group,
                                                opts.socket_permissions)
    if socket:  #win32 returns None!
        sockets.append(socket)
        if opts.mdns:
            ssh_port = get_ssh_port()
            if ssh_port:
                mdns_recs.append(("ssh", [("", ssh_port)]))

    #publish mdns records:
    if opts.mdns:
        from xpra.platform.info import get_username
        mdns_info = {"display": display_name, "username": get_username()}
        if opts.session_name:
            mdns_info["session"] = opts.session_name
        for mode, listen_on in mdns_recs:
            mdns_publish(display_name, mode, listen_on, mdns_info)

    if not check_xvfb_process(xvfb):
        #xvfb problem: exit now
        return 1

    display = None
    if not sys.platform.startswith("win") and not sys.platform.startswith(
            "darwin") and not proxying:
        display = verify_display_ready(xvfb, display_name, shadowing)
        if not display:
            return 1
    elif not proxying:
        no_gtk()
        import gtk  #@Reimport
        assert gtk

    if shadowing:
        from xpra.platform.shadow_server import ShadowServer
        app = ShadowServer()
        info = "shadow"
    elif proxying:
        from xpra.server.proxy.proxy_server import ProxyServer
        app = ProxyServer()
        info = "proxy"
    else:
        assert starting or upgrading
        from xpra.x11.gtk2 import gdk_display_source
        assert gdk_display_source
        #(now we can access the X11 server)

        if clobber:
            #get the saved pid (there should be one):
            xvfb_pid = get_xvfb_pid()
        elif xvfb_pid is not None:
            #save the new pid (we should have one):
            save_xvfb_pid(xvfb_pid)

        #check for an existing window manager:
        from xpra.x11.gtk2.wm import wm_check
        if not wm_check(display, opts.wm_name, upgrading):
            return 1
        try:
            # This import is delayed because the module depends on gtk:
            from xpra.x11.server import XpraServer
            from xpra.x11.bindings.window_bindings import X11WindowBindings  #@UnresolvedImport
            X11Window = X11WindowBindings()
        except ImportError as e:
            log.error(
                "Failed to load Xpra server components, check your installation: %s"
                % e)
            return 1
        if not X11Window.displayHasXComposite():
            log.error(
                "Xpra is a compositing manager, it cannot use a display which lacks the XComposite extension!"
            )
            return 1
        log("XShape=%s", X11Window.displayHasXShape())
        app = XpraServer(clobber)
        info = "xpra"

    #we got this far so the sockets have initialized and
    #the server should be able to manage the display
    #from now on, if we exit without upgrading we will also kill the Xvfb
    def kill_xvfb():
        # Close our display(s) first, so the server dying won't kill us.
        log.info("killing xvfb with pid %s" % xvfb_pid)
        import gtk  #@Reimport
        for display in gtk.gdk.display_manager_get().list_displays():
            display.close()
        os.kill(xvfb_pid, signal.SIGTERM)

    if xvfb_pid is not None and not opts.use_display and not shadowing:
        _cleanups.append(kill_xvfb)

    try:
        app.exec_cwd = cwd
        app.init(opts)
    except InitException as e:
        log.error("xpra server initialization error:")
        log.error(" %s", e)
        return 1
    except Exception as e:
        log.error("Error: cannot start the %s server", info, exc_info=True)
        log.error(str(e))
        log.info("")
        return 1

    #honour start child, html webserver, and setup child reaper
    if os.name == "posix" and not proxying and not upgrading and not shadowing:
        # start websockify?
        try:
            start_websockify(app.child_reaper, opts, bind_tcp)
            #websockify overrides the tcp proxy, so we must re-set it:
            app._tcp_proxy = opts.tcp_proxy
        except Exception as e:
            error_cb("failed to setup websockify html server: %s" % e)
        if opts.exit_with_children:
            assert opts.start_child, "exit-with-children was specified but start-child is missing!"
        if opts.start:
            for x in opts.start:
                if x:
                    app.start_child(x, x, True)
        if opts.start_child:
            for x in opts.start_child:
                if x:
                    app.start_child(x, x, False)

    log("%s(%s)", app.init_sockets, sockets)
    app.init_sockets(sockets)
    log("%s(%s)", app.init_when_ready, _when_ready)
    app.init_when_ready(_when_ready)

    try:
        log("running %s", app.run)
        e = app.run()
        log("%s()=%s", app.run, e)
    except KeyboardInterrupt:
        log.info("stopping on KeyboardInterrupt")
        e = 0
    except Exception as e:
        log.error("server error", exc_info=True)
        e = -128
    if e > 0:
        # Upgrading/exiting, so leave X server running
        if kill_xvfb in _cleanups:
            _cleanups.remove(kill_xvfb)
        from xpra.server.server_core import ServerCore
        if e == ServerCore.EXITING_CODE:
            log.info("exiting: not cleaning up Xvfb")
        elif cleanup_socket in _cleanups:
            log.info("upgrading: not cleaning up Xvfb or socket")
            # don't delete the new socket (not ours)
            _cleanups.remove(cleanup_socket)
        log("cleanups=%s", _cleanups)
        e = 0
    return e
示例#40
0
    def init_encodings(self):
        encs, core_encs = [], []
        log("init_encodings() allowed_encodings=%s", self.allowed_encodings)

        def add_encodings(encodings):
            log("add_encodings(%s)", encodings)
            for ce in encodings:
                e = {"rgb32": "rgb", "rgb24": "rgb"}.get(ce, ce)
                if self.allowed_encodings is not None and e not in self.allowed_encodings:
                    #not in whitelist (if it exists)
                    continue
                if e not in encs:
                    encs.append(e)
                if ce not in core_encs:
                    core_encs.append(ce)

        add_encodings(["rgb24", "rgb32"])

        #video encoders (empty when first called - see threaded_init)
        ve = getVideoHelper().get_encodings()
        log("init_encodings() adding video encodings: %s", ve)
        add_encodings(ve)  #ie: ["vp8", "h264"]
        #Pithon Imaging Libary:
        enc_pillow = get_codec("enc_pillow")
        if enc_pillow:
            pil_encs = enc_pillow.get_encodings()
            add_encodings(x for x in pil_encs if x != "webp")
            #Note: webp will only be enabled if we have a Python-PIL fallback
            #(either "webp" or "png")
            if has_codec("enc_webp") and ("webp" in pil_encs
                                          or "png" in pil_encs):
                add_encodings(["webp"])
                if "webp" not in self.lossless_mode_encodings:
                    self.lossless_mode_encodings.append("webp")
        #look for video encodings with lossless mode:
        for e in ve:
            for colorspace, especs in getVideoHelper().get_encoder_specs(
                    e).items():
                for espec in especs:
                    if espec.has_lossless_mode:
                        if e not in self.lossless_mode_encodings:
                            log(
                                "found lossless mode for encoding %s with %s and colorspace %s",
                                e, espec, colorspace)
                            self.lossless_mode_encodings.append(e)
                            break
        #now update the variables:
        self.encodings = encs
        self.core_encodings = core_encs
        self.lossless_encodings = [
            x for x in self.core_encodings
            if (x.startswith("png") or x.startswith("rgb") or x == "webp")
        ]
        log(
            "allowed encodings=%s, encodings=%s, core encodings=%s, lossless encodings=%s",
            self.allowed_encodings, encs, core_encs, self.lossless_encodings)
        pref = [x for x in PREFERED_ENCODING_ORDER if x in self.encodings]
        if pref:
            self.default_encoding = pref[0]
        else:
            self.default_encoding = None
        #default encoding:
        if not self.encoding or str(self.encoding).lower() in ("auto", "none"):
            self.default_encoding = None
        elif self.encoding in self.encodings:
            self.default_encoding = self.encoding
        else:
            log.warn("ignored invalid default encoding option: %s",
                     self.encoding)
示例#41
0
def test_load():
    #NOTE: we assume that the scores:
    # - make nvenc less desirable at HQ (maybe not?)
    # - make cuda csc beat swscale
    vep = getVideoHelper()
    vep.may_init()
示例#42
0
def test_load():
    #NOTE: we assume that the scores:
    # - make nvenc less desirable at HQ (maybe not?)
    # - make cuda csc beat swscale
    vep = getVideoHelper()
    vep.may_init()
示例#43
0
 def video_helper_init(self):
     self.video_helper = getVideoHelper()
     #only use video encoders (no CSC supported in proxy)
     self.video_helper.set_modules(
         video_encoders=self.video_encoder_modules)
     self.video_helper.init()