xpra icon
Bug tracker and wiki

Ticket #1218: track-nonvideo.patch

File track-nonvideo.patch, 8.6 KB (added by Antoine Martin, 4 years ago)

when we exclude non-video regions from the window paint, make sure they eventually get refreshed too

  • xpra/server/window/window_source.py

     
    12121212            self.do_send_delayed_regions(damage_time, window, regions, coding, options)
    12131213
    12141214    def do_send_delayed_regions(self, damage_time, window, regions, coding, options, exclude_region=None, get_best_encoding=None):
     1215        #if we have an exclude_region
     1216        #this method returns the regions that were excluded (intersection with the exclude region)
    12151217        ww,wh = window.get_dimensions()
    12161218        speed = options.get("speed") or self._current_speed
    12171219        quality = options.get("quality") or self._current_quality
     
    12241226            log("send_delayed_regions: using full window update %sx%s with %s", ww, wh, actual_encoding)
    12251227            assert actual_encoding is not None
    12261228            self.process_damage_region(damage_time, window, 0, 0, ww, wh, actual_encoding, options)
     1229            return []
    12271230
    12281231        if exclude_region is None:
    12291232            if self.full_frames_only:
    1230                 send_full_window_update()
    1231                 return
     1233                return send_full_window_update()
    12321234
    12331235            if len(regions)>self.max_small_regions:
    12341236                #too many regions!
    1235                 send_full_window_update()
    1236                 return
     1237                return send_full_window_update()
    12371238            if ww*wh<=MIN_WINDOW_REGION_SIZE:
    12381239                #size is too small to bother with regions:
    1239                 send_full_window_update()
    1240                 return
     1240                return send_full_window_update()
    12411241
    12421242        regions = list(set(regions))
    12431243        if MERGE_REGIONS:
     
    12481248            if bytes_cost>=bytes_threshold:
    12491249                #too many bytes to send lots of small regions..
    12501250                if exclude_region is None:
    1251                     send_full_window_update()
    1252                     return
     1251                    return send_full_window_update()
    12531252                #make regions out of the rest of the window area:
    12541253                non_exclude = rectangle(0, 0, ww, wh).substract_rect(exclude_region)
    12551254                #and keep those that have damage areas in them:
     
    12801279                if pixel_count>=ww*wh or self.must_encode_full_frame(window, actual_encoding):
    12811280                    #use full screen dimensions:
    12821281                    self.process_damage_region(damage_time, window, 0, 0, ww, wh, actual_encoding, options)
    1283                     return
     1282                    return []
    12841283
    12851284        #we're processing a number of regions separately,
    12861285        #start by removing the exclude region if there is one:
     1286        excluded = []
    12871287        if exclude_region:
    12881288            e_regions = []
    12891289            for r in regions:
    1290                 for v in r.substract_rect(exclude_region):
    1291                     e_regions.append(v)
     1290                ex = r.intersects_rect(exclude_region)
     1291                if ex:
     1292                    excluded.append(ex)
     1293                    for v in r.substract_rect(exclude_region):
     1294                        e_regions.append(v)
     1295                else:
     1296                    e_regions.append(r)
    12921297            regions = e_regions
    12931298        #then figure out which encoding will get used,
    12941299        #and shortcut out if this needs to be a full window update:
     
    12981303            if self.must_encode_full_frame(window, actual_encoding):
    12991304                self.process_damage_region(damage_time, window, 0, 0, ww, wh, actual_encoding, options)
    13001305                #we can stop here (full screen update will include the other regions)
    1301                 return
     1306                return []
    13021307            i_reg_enc.append((i, region, actual_encoding))
    13031308
    13041309        #reversed so that i=0 is last for flushing
    13051310        for i, region, actual_encoding in reversed(i_reg_enc):
    13061311            self.process_damage_region(damage_time, window, region.x, region.y, region.width, region.height, actual_encoding, options, flush=i)
     1312        return excluded
    13071313
    13081314
    13091315    def must_encode_full_frame(self, window, encoding):
  • xpra/server/window/window_video_source.py

     
    532532        """
    533533            Overriden here so we can try to intercept the video_subregion if one exists.
    534534        """
     535        def send_excluded(excluded):
     536            #decide if we want to send the rest now or delay some more:
     537            event_count = max(0, self.statistics.damage_events_count - self.video_subregion.set_at)
     538            #only delay once the video encoder has dealt with a few frames:
     539            if event_count>100:
     540                elapsed = int(1000.0*(time.time()-damage_time)) + self.video_subregion.non_waited
     541                if elapsed>=self.video_subregion.non_max_wait:
     542                    #send now, reset delay:
     543                    sublog("send_delayed_regions: non video regions have waited %sms already, sending", elapsed)
     544                    self.video_subregion.non_waited = 0
     545                else:
     546                    #delay further: just create new delayed region:
     547                    sublog("send_delayed_regions: delaying non video regions some more")
     548                    self._damage_delayed = time.time(), window, excluded, coding, options or {}
     549                    delay = self.video_subregion.non_max_wait-elapsed
     550                    self.expire_timer = self.timeout_add(int(delay), self.expire_delayed_region, delay)
     551                    return []
     552            return send_nonvideo(regions=excluded, encoding=None)
    535553        #overrides the default method for finding the encoding of a region
    536554        #so we can ensure we don't use the video encoder when we don't want to:
    537555        def send_nonvideo(regions=regions, encoding=coding, exclude_region=None, get_best_encoding=self.get_best_nonvideo_encoding):
    538             WindowSource.do_send_delayed_regions(self, damage_time, window, regions, encoding, options, exclude_region=exclude_region, get_best_encoding=get_best_encoding)
     556            excluded = WindowSource.do_send_delayed_regions(self, damage_time, window, regions, encoding, options, exclude_region=exclude_region, get_best_encoding=get_best_encoding)
     557            if excluded:
     558                send_excluded(excluded)
     559            return []
    539560
    540561        if self.is_tray:
    541562            sublog("BUG? video for tray - don't use video region!")
     
    555576        if not vr or not self.video_subregion.enabled:
    556577            sublog("no video region, we may use the video encoder for something else")
    557578            WindowSource.do_send_delayed_regions(self, damage_time, window, regions, coding, options)
    558             return
     579            return []
    559580        assert not self.full_frames_only
    560581
    561582        actual_vr = None
     
    605626            trimmed += r.substract_rect(actual_vr)
    606627        if len(trimmed)==0:
    607628            sublog("send_delayed_regions: nothing left after removing video region %s", actual_vr)
    608             return
     629            return []
    609630        sublog("send_delayed_regions: substracted %s from %s gives us %s", actual_vr, regions, trimmed)
     631        return send_excluded(trimmed)
    610632
    611         #decide if we want to send the rest now or delay some more:
    612         event_count = max(0, self.statistics.damage_events_count - self.video_subregion.set_at)
    613         #only delay once the video encoder has dealt with a few frames:
    614         if event_count>100:
    615             elapsed = int(1000.0*(time.time()-damage_time)) + self.video_subregion.non_waited
    616             if elapsed>=self.video_subregion.non_max_wait:
    617                 #send now, reset delay:
    618                 sublog("send_delayed_regions: non video regions have waited %sms already, sending", elapsed)
    619                 self.video_subregion.non_waited = 0
    620             else:
    621                 #delay further: just create new delayed region:
    622                 sublog("send_delayed_regions: delaying non video regions some more")
    623                 self._damage_delayed = time.time(), window, trimmed, coding, options or {}
    624                 delay = self.video_subregion.non_max_wait-elapsed
    625                 self.expire_timer = self.timeout_add(int(delay), self.expire_delayed_region, delay)
    626                 return
    627         send_nonvideo(regions=trimmed, encoding=None, exclude_region=actual_vr)
    628633
    629 
    630634    def process_damage_region(self, damage_time, window, x, y, w, h, coding, options, flush=None):
    631635        #now figure out if we need to send edges separately:
    632636        if coding in self.video_encodings: