Skip to content

Commit

Permalink
#800: take delayed frames into account when adjusting the av-sync delay
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@12868 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jun 19, 2016
1 parent d32f842 commit 316029f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 12 deletions.
22 changes: 12 additions & 10 deletions src/xpra/codecs/enc_x264/encoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ cdef class Encoder:
cdef int quality
cdef int speed
cdef int b_frames
cdef int delayed_frames
cdef unsigned long long bytes_in
cdef unsigned long long bytes_out
cdef object last_frame_times
Expand Down Expand Up @@ -530,6 +531,7 @@ cdef class Encoder:
"src_format": self.src_format,
"version" : get_version(),
"frame-types" : self.frame_types,
"delayed" : self.delayed_frames,
})
if self.bytes_in>0 and self.bytes_out>0:
info["bytes_in"] = self.bytes_in
Expand Down Expand Up @@ -649,18 +651,18 @@ cdef class Encoder:
if frame_size < 0:
log.error("x264 encoding error: frame_size is invalid!")
return None
cdef int delayed = x264_encoder_delayed_frames(self.context)
self.delayed_frames = x264_encoder_delayed_frames(self.context)
if i_nals==0:
if self.b_frames and delayed>0:
log("x264 encode %i delayed frames after %i", delayed, self.frames)
if self.b_frames and self.delayed_frames>0:
log("x264 encode %i delayed frames after %i", self.delayed_frames, self.frames)
return None, {
"delayed" : delayed,
"delayed" : self.delayed_frames,
"frame" : self.frames,
}
raise Exception("x264_encoder_encode produced no data!")
slice_type = SLICE_TYPES.get(pic_out.i_type, pic_out.i_type)
self.frame_types[slice_type] = self.frame_types.get(slice_type, 0)+1
log("x264 encode frame %i as %4s slice with %i nals, total %7i bytes, keyframe=%s, delayed=%i", self.frames, slice_type, i_nals, frame_size, pic_out.b_keyframe, delayed)
log("x264 encode frame %i as %4s slice with %i nals, total %7i bytes, keyframe=%s, delayed=%i", self.frames, slice_type, i_nals, frame_size, pic_out.b_keyframe, self.delayed_frames)
if LOG_NALS:
for i in range(i_nals):
log.info(" nal %s priority:%10s, type:%10s, payload=%#x, payload size=%i",
Expand All @@ -676,8 +678,8 @@ cdef class Encoder:
"quality" : max(0, min(100, quality)),
"speed" : max(0, min(100, speed)),
"type" : slice_type}
if delayed>0:
client_options["delayed"] = delayed
if self.delayed_frames>0:
client_options["delayed"] = self.delayed_frames
#accounting:
end = time.time()
self.time += end-start
Expand All @@ -692,9 +694,9 @@ cdef class Encoder:
def flush(self, unsigned long frame_no):
if self.frames>frame_no or self.context==NULL:
return None, {}
cdef int i = x264_encoder_delayed_frames(self.context)
log("x264 flush(%i) %i delayed frames", frame_no, i)
if i<=0:
self.delayed_frames = x264_encoder_delayed_frames(self.context)
log("x264 flush(%i) %i delayed frames", frame_no, self.delayed_frames)
if self.delayed_frames<=0:
return None, {}
cdef x264_nal_t *nals = NULL
cdef int i_nals = 0
Expand Down
17 changes: 15 additions & 2 deletions src/xpra/server/window/window_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ def __init__(self, queue_size, call_in_encode_thread, queue_packet, compressed_w
self.av_sync = av_sync
self.av_sync_delay = av_sync_delay
self.av_sync_delay_target = av_sync_delay
self.av_sync_delay_total = 0
self.av_sync_frame_delay = 0
self.av_sync_timer = None
self.encode_queue = []
self.encode_queue_max_size = 10
Expand Down Expand Up @@ -625,8 +627,14 @@ def do_set_client_properties(self, properties):
def set_auto_refresh_delay(self, d):
self.auto_refresh_delay = d

def set_av_sync_delay(self, new_delay):
self.av_sync_delay_target = new_delay
def set_av_sync_delay_total(self, new_delay):
self.av_sync_delay_total = new_delay
self.set_av_sync_delay()

def set_av_sync_delay(self):
#set the target then schedule a timer to gradually
#get the actual value "av_sync_delay" moved towards it
self.av_sync_delay_target = max(0, self.av_sync_delay_total - self.av_sync_frame_delay)
self.schedule_av_sync_update()

def schedule_av_sync_update(self, delay=0):
Expand Down Expand Up @@ -881,6 +889,11 @@ def calculate_batch_delay(self, has_focus, other_is_fullscreen, other_is_maximiz
statslog("calculate_batch_delay for wid=%i, %i bytes sent since the last update", self.wid, nbytes)
calculate_batch_delay(self.wid, self.window_dimensions, has_focus, other_is_fullscreen, other_is_maximized, self.is_OR, self.soft_expired, self.batch_config, self.global_statistics, self.statistics)
self.statistics.last_recalculate = now
self.update_av_sync_frame_delay()

def update_av_sync_frame_delay(self):
self.av_sync_frame_delay = self.batch_config.delay
self.set_av_sync_delay()

def update_speed(self):
if self.suspended or self._mmap:
Expand Down
10 changes: 10 additions & 0 deletions src/xpra/server/window/window_video_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
scalinglog = Logger("scaling")
sublog = Logger("subregion")
videolog = Logger("video")
avsynclog = Logger("av-sync")


def envint(name, d):
Expand Down Expand Up @@ -126,6 +127,15 @@ def calculate_batch_delay(self, has_focus, other_is_fullscreen, other_is_maximiz
d = 2 * int(max(100, self.auto_refresh_delay * max(50, pct) / 50, bc.delay*4))
vsr.set_auto_refresh_delay(d)

def update_av_sync_frame_delay(self):
self.av_sync_frame_delay = self.batch_config.delay
ve = self._video_encoder
if ve:
d = ve.get_info().get("delayed", 0)
self.av_sync_frame_delay += 40 * d
avsynclog("update_av_sync_frame_delay() video encoder=%s, delayed frames=%i, frame delay=%i", ve, d, self.av_sync_frame_delay)
self.set_av_sync_delay()


def get_client_info(self):
info = {
Expand Down

0 comments on commit 316029f

Please sign in to comment.