diff --git a/player/video.c b/player/video.c
index 4f68a97515..390cc26a9c 100644
--- a/player/video.c
+++ b/player/video.c
@@ -1160,10 +1160,8 @@ void write_video(struct MPContext *mpctx)
     struct mp_image_params *p = &mpctx->next_frames[0]->params;
     if (!vo->params || !mp_image_params_equal(p, vo->params)) {
         // Changing config deletes the current frame; wait until it's finished.
-        if (vo_still_displaying(vo)) {
-            vo_request_wakeup_on_done(vo);
+        if (vo_still_displaying(vo))
             return;
-        }
 
         const struct vo_driver *info = mpctx->video_out->driver;
         char extra[20] = {0};
diff --git a/video/out/vo.c b/video/out/vo.c
index 7b2e0976fe..0130ae4387 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -141,7 +141,6 @@ struct vo_internal {
     bool want_redraw;               // redraw request from VO to player
     bool send_reset;                // send VOCTRL_RESET
     bool paused;
-    bool wakeup_on_done;
     int queued_events;              // event mask for the user
     int internal_events;            // event mask for us
 
@@ -760,41 +759,6 @@ void vo_wakeup(struct vo *vo)
     pthread_mutex_unlock(&in->lock);
 }
 
-static bool still_displaying(struct vo *vo)
-{
-    struct vo_internal *in = vo->in;
-    int64_t now = mp_time_us();
-    int64_t frame_end = 0;
-    if (in->current_frame) {
-        frame_end = in->current_frame->pts + MPMAX(in->current_frame->duration, 0);
-        if (in->current_frame->display_synced)
-            frame_end = in->current_frame->num_vsyncs > 0 ? INT64_MAX : 0;
-    }
-    return (now < frame_end || in->rendering || in->frame_queued) && in->hasframe;
-}
-
-// Return true if there is still a frame being displayed (or queued).
-bool vo_still_displaying(struct vo *vo)
-{
-    pthread_mutex_lock(&vo->in->lock);
-    bool res = still_displaying(vo);
-    pthread_mutex_unlock(&vo->in->lock);
-    return res;
-}
-
-// Make vo issue a wakeup once vo_still_displaying() becomes true.
-void vo_request_wakeup_on_done(struct vo *vo)
-{
-    struct vo_internal *in = vo->in;
-    pthread_mutex_lock(&vo->in->lock);
-    if (still_displaying(vo)) {
-        in->wakeup_on_done = true;
-    } else {
-        wakeup_core(vo);
-    }
-    pthread_mutex_unlock(&vo->in->lock);
-}
-
 // Whether vo_queue_frame() can be called. If the VO is not ready yet, the
 // function will return false, and the VO will call the wakeup callback once
 // it's ready.
@@ -951,7 +915,6 @@ static bool render_frame(struct vo *vo)
 
     if (in->dropped_frame) {
         in->drop_count += 1;
-        wakeup_core(vo);
     } else {
         in->rendering = true;
         in->hasframe_rendered = true;
@@ -1023,14 +986,11 @@ static bool render_frame(struct vo *vo)
         more_frames = true;
 
     pthread_cond_broadcast(&in->wakeup); // for vo_wait_frame()
+    wakeup_core(vo);
 
 done:
     if (!vo->driver->frame_owner)
         talloc_free(frame);
-    if (in->wakeup_on_done && !still_displaying(vo)) {
-        in->wakeup_on_done = false;
-        wakeup_core(vo);
-    }
     pthread_mutex_unlock(&in->lock);
 
     return more_frames;
@@ -1217,6 +1177,24 @@ void vo_seek_reset(struct vo *vo)
     pthread_mutex_unlock(&in->lock);
 }
 
+// Return true if there is still a frame being displayed (or queued).
+// If this returns true, a wakeup some time in the future is guaranteed.
+bool vo_still_displaying(struct vo *vo)
+{
+    struct vo_internal *in = vo->in;
+    pthread_mutex_lock(&vo->in->lock);
+    int64_t now = mp_time_us();
+    int64_t frame_end = 0;
+    if (in->current_frame) {
+        frame_end = in->current_frame->pts + MPMAX(in->current_frame->duration, 0);
+        if (in->current_frame->display_synced)
+            frame_end = in->current_frame->num_vsyncs > 0 ? INT64_MAX : 0;
+    }
+    bool working = now < frame_end || in->rendering || in->frame_queued;
+    pthread_mutex_unlock(&vo->in->lock);
+    return working && in->hasframe;
+}
+
 // Whether at least 1 frame was queued or rendered since last seek or reconfig.
 bool vo_has_frame(struct vo *vo)
 {
diff --git a/video/out/vo.h b/video/out/vo.h
index e0b24d4cf7..ca120672f6 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -495,7 +495,6 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts);
 void vo_queue_frame(struct vo *vo, struct vo_frame *frame);
 void vo_wait_frame(struct vo *vo);
 bool vo_still_displaying(struct vo *vo);
-void vo_request_wakeup_on_done(struct vo *vo);
 bool vo_has_frame(struct vo *vo);
 void vo_redraw(struct vo *vo);
 bool vo_want_redraw(struct vo *vo);