xpra icon
Bug tracker and wiki

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


Ticket #849: sound-autotune-queue-v2.patch

File sound-autotune-queue-v2.patch, 6.9 KB (added by Antoine Martin, 6 years ago)

updated patch

  • xpra/sound/sink.py

     
    44# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
    55# later version. See the file COPYING for details.
    66
    7 import sys, os, time
     7import sys, os
    88
    99from xpra.sound.sound_pipeline import SoundPipeline, gobject, one_arg_signal
    1010from xpra.sound.pulseaudio_util import has_pa
     
    4646    DEFAULT_SINK = SINKS[0]
    4747QUEUE_SILENT = 0
    4848QUEUE_TIME = get_queue_time(450)
    49 QUEUE_MIN_TIME = get_queue_time(QUEUE_TIME//10//MS_TO_NS, "MIN")
    50 assert QUEUE_MIN_TIME<=QUEUE_TIME
    5149
    52 VARIABLE_MIN_QUEUE = os.environ.get("XPRA_VARIABLE_MIN_QUEUE", "1")=="1"
    53 
    54 
    5550GST_FORMAT_BUFFERS = 4
    5651
    5752def sink_has_device_attribute(sink):
     
    9489        pipeline_els.append("volume name=volume volume=%s" % volume)
    9590        queue_el = ["queue",
    9691                    "name=queue",
    97                     "min-threshold-time=%s" % QUEUE_MIN_TIME,
     92                    "min-threshold-time=0",
    9893                    "max-size-buffers=0",
    9994                    "max-size-bytes=0",
    10095                    "max-size-time=%s" % QUEUE_TIME,
     
    131126    def queue_pushing(self, *args):
    132127        ltime = self.queue.get_property("current-level-time")/MS_TO_NS
    133128        log("queue pushing: level=%i", ltime)
     129        self.check_levels()
    134130        self.queue_state = "pushing"
    135         self.emit_info()
     131        #self.emit_info()
    136132        return 0
    137133
    138134    def queue_running(self, *args):
    139135        ltime = self.queue.get_property("current-level-time")/MS_TO_NS
    140136        log("queue running: level=%s", ltime)
    141         if self.queue_state=="underrun" and VARIABLE_MIN_QUEUE:
     137        self.check_levels()
     138        self.queue_state = "running"
     139        return 0
     140
     141    def check_levels(self):
     142        if True:
     143            return
     144        if self.queue_state=="underrun":
    142145            #lift min time restrictions:
    143146            self.queue.set_property("min-threshold-time", 0)
    144147        elif self.queue_state == "overrun":
    145148            clt = self.queue.get_property("current-level-time")
    146149            qpct = min(QUEUE_TIME, clt)*100//QUEUE_TIME
    147             log("resetting max-size-time back to %ims (level=%ims, %i%%)", QUEUE_TIME//MS_TO_NS, clt//MS_TO_NS, qpct)
     150            log.info("resetting max-size-time back to %ims (level=%ims, %i%%)", QUEUE_TIME//MS_TO_NS, clt//MS_TO_NS, qpct)
    148151            self.queue.set_property("max-size-time", QUEUE_TIME)
    149152        self.queue_state = "running"
    150153        self.emit_info()
    151         return 0
    152154
     155
    153156    def queue_underrun(self, *args):
     157        if self.queue_state=="underrun" or self.queue_state=="starting":
     158            return
    154159        ltime = self.queue.get_property("current-level-time")/MS_TO_NS
    155         log("queue underrun: level=%i", ltime)
    156         if self.queue_state!="underrun" and VARIABLE_MIN_QUEUE:
    157             #lift min time restrictions:
    158             self.queue.set_property("min-threshold-time", QUEUE_MIN_TIME)
     160        log.info("queue underrun: level=%i, previous state=%s", ltime, self.queue_state)
    159161        self.queue_state = "underrun"
    160         self.emit_info()
     162        MIN_QUEUE = QUEUE_TIME//2
     163        mts = self.queue.get_property("min-threshold-time")
     164        if mts==MIN_QUEUE:
     165            return 0
     166        #set min time restrictions to fill up queue:
     167        log.info("increasing the min-threshold-time to %ims", MIN_QUEUE//MS_TO_NS)
     168        self.queue.set_property("min-threshold-time", MIN_QUEUE)
     169        def restore():
     170            if self.queue.get_property("min-threshold-time")==0:
     171                log.info("min-threshold-time already restored!")
     172                return False
     173            ltime = self.queue.get_property("current-level-time")//MS_TO_NS
     174            if ltime==0:
     175                log.info("not restored! (still underrun: %ims)", ltime)
     176                return True
     177            log.info("resetting the min-threshold-time back to %ims", 0)
     178            self.queue.set_property("min-threshold-time", 0)
     179            self.queue_state = "running"
     180            return False
     181        import glib
     182        glib.timeout_add(1000, restore)
     183        #self.emit_info()
    161184        return 0
    162185
    163186    def queue_overrun(self, *args):
     187        if self.queue_state=="overrun":
     188            return
    164189        ltime = self.queue.get_property("current-level-time")//MS_TO_NS
    165         pqs = self.queue_state
     190        log("queue overrun: level=%i, previous state=%s", ltime, self.queue_state)
    166191        self.queue_state = "overrun"
    167         #no overruns for the first 2 seconds:
    168         if ltime<QUEUE_TIME//MS_TO_NS//2*75//100:
    169             elapsed = time.time()-self.start_time
    170             log("queue overrun ignored: level=%i, elapsed time=%.1f", ltime, elapsed)
    171             return 0
    172         log("queue overrun: level=%i, previous state=%s", ltime//MS_TO_NS, pqs)
    173         if pqs!="overrun":
    174             log("halving the max-size-time to %ims", QUEUE_TIME//2//MS_TO_NS)
    175             self.queue.set_property("max-size-time", QUEUE_TIME//2)
    176             self.overruns += 1
    177             self.emit("overrun", ltime)
    178             self.emit_info()
     192        REDUCED_QT = QUEUE_TIME//2
     193        #empty the queue by reducing its max size:
     194        log.info("queue overrun: halving the max-size-time to %ims", REDUCED_QT//MS_TO_NS)
     195        self.queue.set_property("max-size-time", REDUCED_QT)
     196        self.overruns += 1
     197        self.emit("overrun", ltime)
     198        def restore():
     199            if self.queue.get_property("max-size-time")==QUEUE_TIME:
     200                log.info("max-size-time already restored!")
     201                return False
     202            ltime = self.queue.get_property("current-level-time")//MS_TO_NS
     203            if ltime>=REDUCED_QT:
     204                log.info("max-size-time not restored! (still overrun: %ims)", ltime)
     205                return True
     206            log.info("raising the max-size-time back to %ims", QUEUE_TIME//MS_TO_NS)
     207            self.queue.set_property("max-size-time", QUEUE_TIME)
     208            self.queue_state = "running"
     209            return False
     210        import glib
     211        glib.timeout_add(1000, restore)
     212        #self.emit_info()
    179213        return 0
    180214
    181215    def eos(self):
     
    191225            clt = self.queue.get_property("current-level-time")
    192226            updict(info, "queue", {
    193227                "time"          : QUEUE_TIME//MS_TO_NS,
    194                 "min_time"      : QUEUE_MIN_TIME//MS_TO_NS,
    195228                "used_pct"      : min(QUEUE_TIME, clt)*100//QUEUE_TIME,
    196229                "used"          : clt//MS_TO_NS,
    197230                "overruns"      : self.overruns,
     
    202235        if not self.src:
    203236            log("add_data(..) dropped")
    204237            return
     238        if self.queue_state=="overrun":
     239            log.info("add_data(..) queue in overrun, data dropped")
     240            return
    205241        #having a timestamp causes problems with the queue and overruns:
    206242        if "timestamp" in metadata:
    207243            del metadata["timestamp"]