From a790009a630ebf12772ead2915ca9d59ee7fdf72 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 14 Nov 2015 21:44:59 +0100 Subject: [PATCH] player: account for minor VO underruns If the player sends a frame with duration==0 to the VO, it can trivially underrun. Don't panic, but keep the correct time. Also, returning the absolute time from vo_get_next_frame_start_time() just to turn it into a float with relative time was silly. Rename it and make it return what the caller needs. --- player/video.c | 4 ++-- video/out/vo.c | 24 +++++++++++++++--------- video/out/vo.h | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/player/video.c b/player/video.c index 043abeb3b1..531ad2ee06 100644 --- a/player/video.c +++ b/player/video.c @@ -1025,8 +1025,8 @@ static void handle_display_sync_frame(struct MPContext *mpctx, // Estimate the video position, so we can calculate a good A/V difference // value below. This is used to estimate A/V drift. - double time_left = (vo_get_next_frame_start_time(vo) - mp_time_us()) / 1e6; - time_left = MPMAX(time_left, 0); + double time_left = vo_get_delay(vo); + // We also know that the timing is (necessarily) off, because we have to // align frame timings on the vsync boundaries. This is unavoidable, and // for the sake of the A/V sync calculations we pretend it's perfect. diff --git a/video/out/vo.c b/video/out/vo.c index 81537e80d9..767f6bab7d 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -868,8 +868,11 @@ void vo_set_paused(struct vo *vo, bool paused) pthread_mutex_lock(&in->lock); if (in->paused != paused) { in->paused = paused; - if (in->paused && in->dropped_frame) - in->request_redraw = true; + if (in->paused) { + if (in->dropped_frame) + in->request_redraw = true; + in->last_flip = 0; + } } pthread_mutex_unlock(&in->lock); vo_control(vo, paused ? VOCTRL_PAUSE : VOCTRL_RESUME, NULL); @@ -913,11 +916,13 @@ bool vo_want_redraw(struct vo *vo) void vo_seek_reset(struct vo *vo) { - pthread_mutex_lock(&vo->in->lock); + struct vo_internal *in = vo->in; + pthread_mutex_lock(&in->lock); forget_frames(vo); - vo->in->send_reset = true; + in->last_flip = 0; + in->send_reset = true; wakeup_locked(vo); - pthread_mutex_unlock(&vo->in->lock); + pthread_mutex_unlock(&in->lock); } // Return true if there is still a frame being displayed (or queued). @@ -1026,12 +1031,13 @@ int64_t vo_get_vsync_interval(struct vo *vo) return res; } -// Get the mp_time_us() time at which the currently rendering frame will end -// (i.e. time of the last flip call needed to display it). +// Get the time in seconds at after which the currently rendering frame will +// end. Returns positive values if the frame is yet to be finished, negative +// values if it already finished. // This can only be called while no new frame is queued (after // vo_is_ready_for_frame). Returns 0 for non-display synced frames, or if the // deadline for continuous display was missed. -int64_t vo_get_next_frame_start_time(struct vo *vo) +double vo_get_delay(struct vo *vo) { struct vo_internal *in = vo->in; pthread_mutex_lock(&in->lock); @@ -1047,7 +1053,7 @@ int64_t vo_get_next_frame_start_time(struct vo *vo) res = 0; } pthread_mutex_unlock(&in->lock); - return res; + return res ? (res - mp_time_us()) / 1e6 : 0; } int64_t vo_get_delayed_count(struct vo *vo) diff --git a/video/out/vo.h b/video/out/vo.h index c7bcccd778..30948e149b 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -342,7 +342,7 @@ void vo_set_queue_params(struct vo *vo, int64_t offset_us, bool vsync_timed, int vo_get_num_req_frames(struct vo *vo); int64_t vo_get_vsync_interval(struct vo *vo); double vo_get_display_fps(struct vo *vo); -int64_t vo_get_next_frame_start_time(struct vo *vo); +double vo_get_delay(struct vo *vo); void vo_wakeup(struct vo *vo);