示例#1
0
文件: src.py 项目: rudresh2319/Xpra
 def __init__(self, src_type=None, src_options={}, codecs=get_codecs(), codec_options={}, volume=1.0):
     if not src_type:
         from xpra.sound.pulseaudio_util import get_pa_device_options
         monitor_devices = get_pa_device_options(True, False)
         log.info("found pulseaudio monitor devices: %s", monitor_devices)
         if len(monitor_devices)==0:
             log.warn("could not detect any pulseaudio monitor devices")
             log.warn(" a test source will be used instead")
             src_type = "audiotestsrc"
             default_src_options = {"wave":2, "freq":100, "volume":0.4}
         else:
             monitor_device = monitor_devices.items()[0][0]
             log.info("using pulseaudio source device:")
             log.info(" '%s'", monitor_device)
             src_type = "pulsesrc"
             default_src_options = {"device" : monitor_device}
         src_options = default_src_options
     if src_type not in get_source_plugins():
         raise InitExit(1, "invalid source plugin '%s', valid options are: %s" % (src_type, ",".join(get_source_plugins())))
     matching = [x for x in CODEC_ORDER if (x in codecs and x in get_codecs())]
     log("SoundSource(..) found matching codecs %s", matching)
     if not matching:
         raise InitExit(1, "no matching codecs between arguments '%s' and supported list '%s'" % (csv(codecs), csv(get_codecs().keys())))
     codec = matching[0]
     encoder, fmt = get_encoder_formatter(codec)
     SoundPipeline.__init__(self, codec)
     self.src_type = src_type
     source_str = plugin_str(src_type, src_options)
     #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work!
     encoder_str = plugin_str(encoder, codec_options or ENCODER_DEFAULT_OPTIONS.get(encoder, {}))
     fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
     pipeline_els = [source_str]
     if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT:
         pipeline_els += ["audioconvert"]
     pipeline_els.append("volume name=volume volume=%s" % volume)
     pipeline_els += [encoder_str,
                     fmt_str,
                     APPSINK]
     self.setup_pipeline_and_bus(pipeline_els)
     self.volume = self.pipeline.get_by_name("volume")
     self.sink = self.pipeline.get_by_name("sink")
     try:
         if get_gst_version()<(1,0):
             self.sink.set_property("enable-last-buffer", False)
         else:
             self.sink.set_property("enable-last-sample", False)
     except Exception as e:
         log("failed to disable last buffer: %s", e)
     self.caps = None
     self.skipped_caps = set()
     if JITTER>0:
         self.jitter_queue = Queue()
     try:
         #Gst 1.0:
         self.sink.connect("new-sample", self.on_new_sample)
         self.sink.connect("new-preroll", self.on_new_preroll1)
     except:
         #Gst 0.10:
         self.sink.connect("new-buffer", self.on_new_buffer)
         self.sink.connect("new-preroll", self.on_new_preroll0)
示例#2
0
def run_sound(mode, error_cb, options, args):
    """ this function just parses command line arguments to feed into the sound subprocess class,
        which in turn just feeds them into the sound pipeline class (sink.py or src.py)
    """
    from xpra.gtk_common.gobject_compat import want_gtk3
    want_gtk3(True)
    gst = import_gst()
    if not gst:
        return 1
    info = mode.replace("_sound_", "")  #ie: "_sound_record" -> "record"
    from xpra.platform import program_context
    with program_context("Xpra-Audio-%s" % info, "Xpra Audio %s" % info):
        log("run_sound(%s, %s, %s, %s) gst=%s", mode, error_cb, options, args, gst)
        if mode=="_sound_record":
            subproc = sound_record
        elif mode=="_sound_play":
            subproc = sound_play
        elif mode=="_sound_query":
            plugins = get_all_plugin_names()
            sources = [x for x in get_source_plugins() if x in plugins]
            sinks = [x for x in get_sink_plugins() if x in plugins]
            from xpra.sound.gstreamer_util import gst_version, pygst_version
            import struct
            bits = struct.calcsize("P")*8
            d = {
                 "encoders"         : can_encode(),
                 "decoders"         : can_decode(),
                 "sources"          : sources,
                 "source.default"   : get_default_source() or "",
                 "sinks"            : sinks,
                 "sink.default"     : get_default_sink() or "",
                 "muxers"           : get_muxers(),
                 "demuxers"         : get_demuxers(),
                 "gst.version"      : [int(x) for x in gst_version],
                 "pygst.version"    : pygst_version,
                 "plugins"          : plugins,
                 "python.version"   : sys.version_info[:3],
                 "python.bits"      : bits,
                }
            if BUNDLE_METADATA:
                d["bundle-metadata"] = True
            for k,v in d.items():
                if type(v) in (list, tuple):
                    v = ",".join(str(x) for x in v)
                print("%s=%s" % (k, v))
            return 0
        else:
            log.error("unknown mode: %s" % mode)
            return 1
        assert len(args)>=6, "not enough arguments"

        #the plugin to use (ie: 'pulsesrc' for src.py or 'autoaudiosink' for sink.py)
        plugin = args[2]
        #plugin options (ie: "device=monitor_device,something=value")
        options = parse_simple_dict(args[3])
        #codecs:
        codecs = [x.strip() for x in args[4].split(",")]
        #codec options:
        codec_options = parse_simple_dict(args[5])
        #volume (optional):
        try:
            volume = int(args[6])
        except:
            volume = 1.0

        ss = None
        try:
            ss = subproc(plugin, options, codecs, codec_options, volume)
            ss.start()
            return 0
        except InitExit as e:
            log.error("%s: %s", info, e)
            return e.status
        except InitException as e:
            log.error("%s: %s", info, e)
            return 1
        except Exception:
            log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True)
            return 1
        finally:
            if ss:
                ss.stop()
示例#3
0
def run_sound(mode, error_cb, options, args):
    """ this function just parses command line arguments to feed into the sound subprocess class,
        which in turn just feeds them into the sound pipeline class (sink.py or src.py)
    """
    #we have to import gstreamer before init() on OSX,
    #because init will end up import gobject,
    #which means choosing between gi and gtk2 bindings
    from xpra.sound.gstreamer_util import import_gst, get_pygst_version
    gst = import_gst()
    from xpra.gtk_common.gobject_compat import want_gtk3
    want_gtk3(get_pygst_version()[0]>0)
    from xpra.platform import program_context
    with program_context("Xpra"):
        log("run_sound(%s, %s, %s, %s) gst=%s", mode, error_cb, options, args, gst)
        if not gst:
            return 1
        if mode=="_sound_record":
            subproc = sound_record
            info = "record"
        elif mode=="_sound_play":
            subproc = sound_play
            info = "play"
        elif mode=="_sound_query":
            plugins = get_all_plugin_names()
            sources = [x for x in get_source_plugins() if x in plugins]
            from xpra.sound.gstreamer_util import gst_version, pygst_version
            d = {"encoders"         : can_encode(),
                 "decoders"         : can_decode(),
                 "sources"          : sources,
                 "muxers"           : get_muxers(),
                 "demuxers"         : get_demuxers(),
                 "gst.version"      : gst_version,
                 "pygst.version"    : pygst_version,
                 "plugins"          : plugins,
                 "python.version"   : sys.version_info[:3],
                }
            for k,v in d.items():
                print("%s=%s" % (k, ",".join(str(x) for x in v)))
            return 0
        else:
            log.error("unknown mode: %s" % mode)
            return 1
        assert len(args)>=6, "not enough arguments"

        #the plugin to use (ie: 'pulsesrc' for src.py or 'autoaudiosink' for sink.py)
        plugin = args[2]
        #plugin options (ie: "device=monitor_device,something=value")
        options = parse_simple_dict(args[3])
        #codecs:
        codecs = [x.strip() for x in args[4].split(",")]
        #codec options:
        codec_options = parse_simple_dict(args[5])
        #volume (optional):
        try:
            volume = int(args[6])
        except:
            volume = 1.0

        ss = None
        try:
            ss = subproc(plugin, options, codecs, codec_options, volume)
            ss.start()
            return 0
        except InitExit as e:
            log.error("%s: %s", info, e)
            return e.status
        except InitException as e:
            log.error("%s: %s", info, e)
            return 1
        except Exception:
            log.error("run_sound%s error", (mode, error_cb, options, args), exc_info=True)
            return 1
        finally:
            if ss:
                ss.stop()
示例#4
0
文件: src.py 项目: svn2github/Xpra
 def __init__(self, src_type=None, src_options={}, codecs=get_codecs(), codec_options={}, volume=1.0):
     if not src_type:
         try:
             from xpra.sound.pulseaudio.pulseaudio_util import get_pa_device_options
             monitor_devices = get_pa_device_options(True, False)
             log.info("found pulseaudio monitor devices: %s", monitor_devices)
         except ImportError as e:
             log.warn("Warning: pulseaudio is not available!")
             log.warn(" %s", e)
             monitor_devices = []
         if len(monitor_devices)==0:
             log.warn("could not detect any pulseaudio monitor devices")
             log.warn(" a test source will be used instead")
             src_type = "audiotestsrc"
             default_src_options = {"wave":2, "freq":100, "volume":0.4}
         else:
             monitor_device = monitor_devices.items()[0][0]
             log.info("using pulseaudio source device:")
             log.info(" '%s'", monitor_device)
             src_type = "pulsesrc"
             default_src_options = {"device" : monitor_device}
         src_options = default_src_options
     if src_type not in get_source_plugins():
         raise InitExit(1, "invalid source plugin '%s', valid options are: %s" % (src_type, ",".join(get_source_plugins())))
     matching = [x for x in CODEC_ORDER if (x in codecs and x in get_codecs())]
     log("SoundSource(..) found matching codecs %s", matching)
     if not matching:
         raise InitExit(1, "no matching codecs between arguments '%s' and supported list '%s'" % (csv(codecs), csv(get_codecs().keys())))
     codec = matching[0]
     encoder, fmt = get_encoder_formatter(codec)
     self.queue = None
     self.caps = None
     self.volume = None
     self.sink = None
     self.src = None
     self.src_type = src_type
     self.buffer_latency = False
     self.jitter_queue = None
     self.file = None
     SoundPipeline.__init__(self, codec)
     src_options["name"] = "src"
     source_str = plugin_str(src_type, src_options)
     #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work!
     encoder_str = plugin_str(encoder, codec_options or get_encoder_default_options(encoder))
     fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
     pipeline_els = [source_str]
     if SOURCE_QUEUE_TIME>0:
         queue_el = ["queue",
                     "name=queue",
                     "min-threshold-time=0",
                     "max-size-buffers=0",
                     "max-size-bytes=0",
                     "max-size-time=%s" % (SOURCE_QUEUE_TIME*MS_TO_NS),
                     "leaky=%s" % GST_QUEUE_LEAK_DOWNSTREAM]
         pipeline_els += [" ".join(queue_el)]
     if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT:
         pipeline_els += ["audioconvert"]
     pipeline_els.append("volume name=volume volume=%s" % volume)
     pipeline_els += [encoder_str,
                     fmt_str,
                     APPSINK]
     if not self.setup_pipeline_and_bus(pipeline_els):
         return
     self.volume = self.pipeline.get_by_name("volume")
     self.sink = self.pipeline.get_by_name("sink")
     if SOURCE_QUEUE_TIME>0:
         self.queue  = self.pipeline.get_by_name("queue")
     if self.queue:
         try:
             self.queue.set_property("silent", True)
         except Exception as e:
             log("cannot make queue silent: %s", e)
     try:
         if get_gst_version()<(1,0):
             self.sink.set_property("enable-last-buffer", False)
         else:
             self.sink.set_property("enable-last-sample", False)
     except Exception as e:
         log("failed to disable last buffer: %s", e)
     self.skipped_caps = set()
     if JITTER>0:
         self.jitter_queue = Queue()
     try:
         #Gst 1.0:
         self.sink.connect("new-sample", self.on_new_sample)
         self.sink.connect("new-preroll", self.on_new_preroll1)
     except:
         #Gst 0.10:
         self.sink.connect("new-buffer", self.on_new_buffer)
         self.sink.connect("new-preroll", self.on_new_preroll0)
     self.src = self.pipeline.get_by_name("src")
     try:
         for x in ("actual-buffer-time", "actual-latency-time"):
             #don't comment this out, it is used to verify the attributes are present:
             gstlog("initial %s: %s", x, self.src.get_property(x))
         self.buffer_latency = True
     except Exception as e:
         log.info("source %s does not support 'buffer-time' or 'latency-time':", self.src_type)
         log.info(" %s", e)
     else:
         #if the env vars have been set, try to honour the settings:
         global BUFFER_TIME, LATENCY_TIME
         if BUFFER_TIME>0:
             if BUFFER_TIME<LATENCY_TIME:
                 log.warn("Warning: latency (%ims) must be lower than the buffer time (%ims)", LATENCY_TIME, BUFFER_TIME)
             else:
                 log("latency tuning for %s, will try to set buffer-time=%i, latency-time=%i", src_type, BUFFER_TIME, LATENCY_TIME)
                 def settime(attr, v):
                     try:
                         cval = self.src.get_property(attr)
                         gstlog("default: %s=%i", attr, cval//1000)
                         if v>=0:
                             self.src.set_property(attr, v*1000)
                             gstlog("overriding with: %s=%i", attr, v)
                     except Exception as e:
                         log.warn("source %s does not support '%s': %s", self.src_type, attr, e)
                 settime("buffer-time", BUFFER_TIME)
                 settime("latency-time", LATENCY_TIME)
     gen = generation.increase()
     if SAVE_TO_FILE is not None:
         parts = codec.split("+")
         if len(parts)>1:
             filename = SAVE_TO_FILE+str(gen)+"-"+parts[0]+".%s" % parts[1]
         else:
             filename = SAVE_TO_FILE+str(gen)+".%s" % codec
         self.file = open(filename, 'wb')
         log.info("saving %s stream to %s", codec, filename)
示例#5
0
    def __init__(self,
                 src_type=None,
                 src_options={},
                 codecs=get_encoders(),
                 codec_options={},
                 volume=1.0):
        if not src_type:
            try:
                from xpra.sound.pulseaudio.pulseaudio_util import get_pa_device_options
                monitor_devices = get_pa_device_options(True, False)
                log.info("found pulseaudio monitor devices: %s",
                         monitor_devices)
            except ImportError as e:
                log.warn("Warning: pulseaudio is not available!")
                log.warn(" %s", e)
                monitor_devices = []
            if len(monitor_devices) == 0:
                log.warn("could not detect any pulseaudio monitor devices")
                log.warn(" a test source will be used instead")
                src_type = "audiotestsrc"
                default_src_options = {"wave": 2, "freq": 100, "volume": 0.4}
            else:
                monitor_device = monitor_devices.items()[0][0]
                log.info("using pulseaudio source device:")
                log.info(" '%s'", monitor_device)
                src_type = "pulsesrc"
                default_src_options = {"device": monitor_device}
            src_options = default_src_options
        if src_type not in get_source_plugins():
            raise InitExit(
                1, "invalid source plugin '%s', valid options are: %s" %
                (src_type, ",".join(get_source_plugins())))
        matching = [
            x for x in CODEC_ORDER if (x in codecs and x in get_encoders())
        ]
        log("SoundSource(..) found matching codecs %s", matching)
        if not matching:
            raise InitExit(
                1,
                "no matching codecs between arguments '%s' and supported list '%s'"
                % (csv(codecs), csv(get_encoders().keys())))
        codec = matching[0]
        encoder, fmt, stream_compressor = get_encoder_elements(codec)
        SoundPipeline.__init__(self, codec)
        self.queue = None
        self.caps = None
        self.volume = None
        self.sink = None
        self.src = None
        self.src_type = src_type
        self.pending_metadata = []
        self.buffer_latency = True
        self.jitter_queue = None
        self.file = None
        self.container_format = (fmt or "").replace("mux",
                                                    "").replace("pay", "")
        self.stream_compressor = stream_compressor
        src_options["name"] = "src"
        source_str = plugin_str(src_type, src_options)
        #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work!
        pipeline_els = [source_str]
        if SOURCE_QUEUE_TIME > 0:
            queue_el = [
                "queue", "name=queue", "min-threshold-time=0",
                "max-size-buffers=0", "max-size-bytes=0",
                "max-size-time=%s" % (SOURCE_QUEUE_TIME * MS_TO_NS),
                "leaky=%s" % GST_QUEUE_LEAK_DOWNSTREAM
            ]
            pipeline_els += [" ".join(queue_el)]
        if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT:
            pipeline_els += ["audioconvert"]
        pipeline_els.append("volume name=volume volume=%s" % volume)
        if encoder:
            encoder_str = plugin_str(
                encoder, codec_options or get_encoder_default_options(encoder))
            pipeline_els.append(encoder_str)
        if fmt:
            fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
            pipeline_els.append(fmt_str)
        pipeline_els.append(APPSINK)
        if not self.setup_pipeline_and_bus(pipeline_els):
            return
        self.volume = self.pipeline.get_by_name("volume")
        self.sink = self.pipeline.get_by_name("sink")
        if SOURCE_QUEUE_TIME > 0:
            self.queue = self.pipeline.get_by_name("queue")
        if self.queue:
            try:
                self.queue.set_property("silent", True)
            except Exception as e:
                log("cannot make queue silent: %s", e)
        try:
            if get_gst_version() < (1, 0):
                self.sink.set_property("enable-last-buffer", False)
            else:
                self.sink.set_property("enable-last-sample", False)
        except Exception as e:
            log("failed to disable last buffer: %s", e)
        self.skipped_caps = set()
        if JITTER > 0:
            self.jitter_queue = Queue()
        try:
            #Gst 1.0:
            self.sink.connect("new-sample", self.on_new_sample)
            self.sink.connect("new-preroll", self.on_new_preroll1)
        except:
            #Gst 0.10:
            self.sink.connect("new-buffer", self.on_new_buffer)
            self.sink.connect("new-preroll", self.on_new_preroll0)
        self.src = self.pipeline.get_by_name("src")
        try:
            for x in ("actual-buffer-time", "actual-latency-time"):
                #don't comment this out, it is used to verify the attributes are present:
                try:
                    gstlog("initial %s: %s", x, self.src.get_property(x))
                except Exception as e:
                    self.buffer_latency = False
        except Exception as e:
            log.info(
                "source %s does not support 'buffer-time' or 'latency-time':",
                self.src_type)
            log.info(" %s", e)
        else:
            #if the env vars have been set, try to honour the settings:
            global BUFFER_TIME, LATENCY_TIME
            if BUFFER_TIME > 0:
                if BUFFER_TIME < LATENCY_TIME:
                    log.warn(
                        "Warning: latency (%ims) must be lower than the buffer time (%ims)",
                        LATENCY_TIME, BUFFER_TIME)
                else:
                    log(
                        "latency tuning for %s, will try to set buffer-time=%i, latency-time=%i",
                        src_type, BUFFER_TIME, LATENCY_TIME)

                    def settime(attr, v):
                        try:
                            cval = self.src.get_property(attr)
                            gstlog("default: %s=%i", attr, cval // 1000)
                            if v >= 0:
                                self.src.set_property(attr, v * 1000)
                                gstlog("overriding with: %s=%i", attr, v)
                        except Exception as e:
                            log.warn("source %s does not support '%s': %s",
                                     self.src_type, attr, e)

                    settime("buffer-time", BUFFER_TIME)
                    settime("latency-time", LATENCY_TIME)
        gen = generation.increase()
        if SAVE_TO_FILE is not None:
            parts = codec.split("+")
            if len(parts) > 1:
                filename = SAVE_TO_FILE + str(
                    gen) + "-" + parts[0] + ".%s" % parts[1]
            else:
                filename = SAVE_TO_FILE + str(gen) + ".%s" % codec
            self.file = open(filename, 'wb')
            log.info("saving %s stream to %s", codec, filename)
示例#6
0
文件: src.py 项目: svn2github/Xpra
 def __init__(self, src_type=None, src_options={}, codecs=CODECS, codec_options={}, volume=1.0):
     if not src_type:
         from xpra.sound.pulseaudio_util import get_pa_device_options
         monitor_devices = get_pa_device_options(True, False)
         log.info("found pulseaudio monitor devices: %s", monitor_devices)
         if len(monitor_devices)==0:
             log.warn("could not detect any pulseaudio monitor devices - will use a test source")
             src_type = "audiotestsrc"
             default_src_options = {"wave":2, "freq":100, "volume":0.4}
         else:
             monitor_device = monitor_devices.items()[0][0]
             log.info("using pulseaudio source device: %s", monitor_device)
             src_type = "pulsesrc"
             default_src_options = {"device" : monitor_device}
         src_options = default_src_options
         src_options.update(src_options)
     assert src_type in get_source_plugins(), "invalid source plugin '%s'" % src_type
     matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)]
     log("SoundSource(..) found matching codecs %s", matching)
     assert len(matching)>0, "no matching codecs between arguments %s and supported list %s" % (codecs, CODECS)
     codec = matching[0]
     encoder, fmt = get_encoder_formatter(codec)
     SoundPipeline.__init__(self, codec)
     self.src_type = src_type
     source_str = plugin_str(src_type, src_options)
     encoder_str = plugin_str(encoder, codec_options)
     fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
     pipeline_els = [source_str]
     if AUDIOCONVERT:
         pipeline_els += ["audioconvert"]
     if AUDIORESAMPLE:
         pipeline_els += [
                      "audioresample",
                      "audio/x-raw-int,rate=44100,channels=2"]
     pipeline_els.append("volume name=volume volume=%s" % volume)
     if QUEUE_TIME>0:
         queue_el =  ["queue",
                      "name=queue",
                      "max-size-buffers=0",
                      "max-size-bytes=0",
                      "max-size-time=%s" % QUEUE_TIME,
                      "leaky=%s" % QUEUE_LEAK]
         pipeline_els.append(" ".join(queue_el))
     pipeline_els += [encoder_str,
                     fmt_str,
                     "appsink name=sink"]
     self.setup_pipeline_and_bus(pipeline_els)
     self.volume = self.pipeline.get_by_name("volume")
     self.sink = self.pipeline.get_by_name("sink")
     self.sink.set_property("emit-signals", True)
     self.sink.set_property("max-buffers", 10)       #0?
     self.sink.set_property("drop", False)
     self.sink.set_property("sync", True)            #False?
     self.sink.set_property("qos", False)
     try:
         #Gst 1.0:
         self.sink.connect("new-sample", self.on_new_sample)
         self.sink.connect("new-preroll", self.on_new_preroll1)
     except:
         #Gst 0.10:
         self.sink.connect("new-buffer", self.on_new_buffer)
         self.sink.connect("new-preroll", self.on_new_preroll0)
示例#7
0
文件: src.py 项目: frostbane/xpra
    def __init__(self,
                 src_type=None,
                 src_options=None,
                 codecs=(),
                 codec_options=None,
                 volume=1.0):
        if not src_type:
            try:
                from xpra.sound.pulseaudio.pulseaudio_util import get_pa_device_options
                monitor_devices = get_pa_device_options(True, False)
                log.info("found pulseaudio monitor devices: %s",
                         monitor_devices)
            except ImportError as e:
                log.warn("Warning: pulseaudio is not available!")
                log.warn(" %s", e)
                monitor_devices = []
            if not monitor_devices:
                log.warn("could not detect any pulseaudio monitor devices")
                log.warn(" a test source will be used instead")
                src_type = "audiotestsrc"
                default_src_options = {"wave": 2, "freq": 100, "volume": 0.4}
            else:
                monitor_device = monitor_devices.items()[0][0]
                log.info("using pulseaudio source device:")
                log.info(" '%s'", monitor_device)
                src_type = "pulsesrc"
                default_src_options = {"device": monitor_device}
            src_options = default_src_options
        if src_type not in get_source_plugins():
            raise InitExit(
                1, "invalid source plugin '%s', valid options are: %s" %
                (src_type, ",".join(get_source_plugins())))
        matching = [
            x for x in CODEC_ORDER if (x in codecs and x in get_encoders())
        ]
        log("SoundSource(..) found matching codecs %s", matching)
        if not matching:
            raise InitExit(
                1,
                "no matching codecs between arguments '%s' and supported list '%s'"
                % (csv(codecs), csv(get_encoders().keys())))
        codec = matching[0]
        encoder, fmt, stream_compressor = get_encoder_elements(codec)
        super().__init__(codec)
        self.queue = None
        self.caps = None
        self.volume = None
        self.sink = None
        self.src = None
        self.src_type = src_type
        self.timestamp = None
        self.min_timestamp = 0
        self.max_timestamp = 0
        self.pending_metadata = []
        self.buffer_latency = True
        self.jitter_queue = None
        self.container_format = (fmt or "").replace("mux",
                                                    "").replace("pay", "")
        self.stream_compressor = stream_compressor
        if src_options is None:
            src_options = {}
        src_options["name"] = "src"
        source_str = plugin_str(src_type, src_options)
        #FIXME: this is ugly and relies on the fact that we don't pass any codec options to work!
        pipeline_els = [source_str]
        log("has plugin(timestamp)=%s", has_plugins("timestamp"))
        if has_plugins("timestamp"):
            pipeline_els.append("timestamp name=timestamp")
        if SOURCE_QUEUE_TIME > 0:
            queue_el = [
                "queue", "name=queue", "min-threshold-time=0",
                "max-size-buffers=0", "max-size-bytes=0",
                "max-size-time=%s" % (SOURCE_QUEUE_TIME * MS_TO_NS),
                "leaky=%s" % GST_QUEUE_LEAK_DOWNSTREAM
            ]
            pipeline_els += [" ".join(queue_el)]
        if encoder in ENCODER_NEEDS_AUDIOCONVERT or src_type in SOURCE_NEEDS_AUDIOCONVERT:
            pipeline_els += ["audioconvert"]
        if CUTTER_THRESHOLD > 0 and encoder not in ENCODER_CANNOT_USE_CUTTER and not fmt:
            pipeline_els.append(
                "cutter threshold=%.4f run-length=%i pre-length=%i leaky=false name=cutter"
                % (CUTTER_THRESHOLD, CUTTER_RUN_LENGTH * MS_TO_NS,
                   CUTTER_PRE_LENGTH * MS_TO_NS))
            if encoder in CUTTER_NEEDS_CONVERT:
                pipeline_els.append("audioconvert")
            if encoder in CUTTER_NEEDS_RESAMPLE:
                pipeline_els.append("audioresample")
        pipeline_els.append("volume name=volume volume=%s" % volume)
        if encoder:
            encoder_str = plugin_str(
                encoder, codec_options or get_encoder_default_options(encoder))
            pipeline_els.append(encoder_str)
        if fmt:
            fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
            pipeline_els.append(fmt_str)
        pipeline_els.append(APPSINK)
        if not self.setup_pipeline_and_bus(pipeline_els):
            return
        self.timestamp = self.pipeline.get_by_name("timestamp")
        self.volume = self.pipeline.get_by_name("volume")
        self.sink = self.pipeline.get_by_name("sink")
        if SOURCE_QUEUE_TIME > 0:
            self.queue = self.pipeline.get_by_name("queue")
        if self.queue:
            try:
                self.queue.set_property("silent", True)
            except Exception as e:
                log("cannot make queue silent: %s", e)
        self.sink.set_property("enable-last-sample", False)
        self.skipped_caps = set()
        if JITTER > 0:
            self.jitter_queue = Queue()
        #Gst 1.0:
        self.sink.connect("new-sample", self.on_new_sample)
        self.sink.connect("new-preroll", self.on_new_preroll)
        self.src = self.pipeline.get_by_name("src")
        for x in ("actual-buffer-time", "actual-latency-time"):
            try:
                gstlog("initial %s: %s", x, self.src.get_property(x))
            except Exception as e:
                gstlog("no %s property on %s: %s", x, self.src, e)
                self.buffer_latency = False
        #if the env vars have been set, try to honour the settings:
        global BUFFER_TIME, LATENCY_TIME
        if BUFFER_TIME > 0:
            if BUFFER_TIME < LATENCY_TIME:
                log.warn(
                    "Warning: latency (%ims) must be lower than the buffer time (%ims)",
                    LATENCY_TIME, BUFFER_TIME)
            else:
                log(
                    "latency tuning for %s, will try to set buffer-time=%i, latency-time=%i",
                    src_type, BUFFER_TIME, LATENCY_TIME)

                def settime(attr, v):
                    try:
                        cval = self.src.get_property(attr)
                        gstlog("default: %s=%i", attr, cval // 1000)
                        if v >= 0:
                            self.src.set_property(attr, v * 1000)
                            gstlog("overriding with: %s=%i", attr, v)
                    except Exception as e:
                        log.warn("source %s does not support '%s': %s",
                                 self.src_type, attr, e)

                settime("buffer-time", BUFFER_TIME)
                settime("latency-time", LATENCY_TIME)
        self.init_file(codec)
示例#8
0
文件: src.py 项目: rudresh2319/Xpra
 def __init__(self,
              src_type=None,
              src_options={},
              codecs=CODECS,
              codec_options={},
              volume=1.0):
     if not src_type:
         from xpra.sound.pulseaudio_util import get_pa_device_options
         monitor_devices = get_pa_device_options(True, False)
         log.info("found pulseaudio monitor devices: %s", monitor_devices)
         if len(monitor_devices) == 0:
             log.warn(
                 "could not detect any pulseaudio monitor devices - will use a test source"
             )
             src_type = "audiotestsrc"
             default_src_options = {"wave": 2, "freq": 100, "volume": 0.4}
         else:
             monitor_device = monitor_devices.items()[0][0]
             log.info("using pulseaudio source device: %s", monitor_device)
             src_type = "pulsesrc"
             default_src_options = {"device": monitor_device}
         src_options = default_src_options
         src_options.update(src_options)
     assert src_type in get_source_plugins(
     ), "invalid source plugin '%s'" % src_type
     matching = [x for x in CODEC_ORDER if (x in codecs and x in CODECS)]
     log("SoundSource(..) found matching codecs %s", matching)
     assert len(
         matching
     ) > 0, "no matching codecs between arguments %s and supported list %s" % (
         codecs, CODECS)
     codec = matching[0]
     encoder, fmt = get_encoder_formatter(codec)
     SoundPipeline.__init__(self, codec)
     self.src_type = src_type
     source_str = plugin_str(src_type, src_options)
     encoder_str = plugin_str(encoder, codec_options)
     fmt_str = plugin_str(fmt, MUXER_DEFAULT_OPTIONS.get(fmt, {}))
     pipeline_els = [source_str]
     if AUDIOCONVERT:
         pipeline_els += ["audioconvert"]
     if AUDIORESAMPLE:
         pipeline_els += [
             "audioresample", "audio/x-raw-int,rate=44100,channels=2"
         ]
     pipeline_els.append("volume name=volume volume=%s" % volume)
     if QUEUE_TIME > 0:
         queue_el = [
             "queue", "name=queue", "max-size-buffers=0",
             "max-size-bytes=0",
             "max-size-time=%s" % QUEUE_TIME,
             "leaky=%s" % QUEUE_LEAK
         ]
         pipeline_els.append(" ".join(queue_el))
     pipeline_els += [encoder_str, fmt_str, "appsink name=sink"]
     self.setup_pipeline_and_bus(pipeline_els)
     self.volume = self.pipeline.get_by_name("volume")
     self.sink = self.pipeline.get_by_name("sink")
     self.sink.set_property("emit-signals", True)
     self.sink.set_property("max-buffers", 10)  #0?
     self.sink.set_property("drop", False)
     self.sink.set_property("sync", True)  #False?
     self.sink.set_property("qos", False)
     try:
         #Gst 1.0:
         self.sink.connect("new-sample", self.on_new_sample)
         self.sink.connect("new-preroll", self.on_new_preroll1)
     except:
         #Gst 0.10:
         self.sink.connect("new-buffer", self.on_new_buffer)
         self.sink.connect("new-preroll", self.on_new_preroll0)