summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-04-10 01:33:38 +0200
committerwm4 <wm4@nowhere>2020-04-10 01:33:38 +0200
commit0c9ac5835be70ae26e4aa875e833fe2c7b3b3bf3 (patch)
tree1b1e0cb5445240bafd2985b77af8013a05c844c2 /video
parenta1771ed0d451a0af75529429fee2c370671950e4 (diff)
downloadmpv-0c9ac5835be70ae26e4aa875e833fe2c7b3b3bf3.tar.bz2
mpv-0c9ac5835be70ae26e4aa875e833fe2c7b3b3bf3.tar.xz
video: remove another redundant wakeup
The wakeup at the end of VO frame rendering seems redundant, because after rendering almost no state changes. The player core can queue a new frame once frame rendering begins, and there's a separate wakeup for this. The only thing that actually changes is in->rendering. The only thing that seems to depend on it and can trigger a wakeup is the vo_still_displaying() function. Change it so that it needs an explicit call to a new API function, so we can avoid wakeups in the common case. The vo_still_displaying() code is mostly just moved around due to locking and for avoiding forward declarations. Also a somewhat risky change (tasty new bugs).
Diffstat (limited to 'video')
-rw-r--r--video/out/vo.c61
-rw-r--r--video/out/vo.h1
2 files changed, 43 insertions, 19 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 52325ac953..e01bb055d3 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -128,6 +128,7 @@ 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
@@ -747,6 +748,41 @@ 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.
@@ -897,6 +933,7 @@ 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;
@@ -952,13 +989,17 @@ static bool render_frame(struct vo *vo)
}
pthread_cond_broadcast(&in->wakeup); // for vo_wait_frame()
- wakeup_core(vo);
got_frame = true;
done:
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 got_frame || (in->frame_queued && in->frame_queued->display_synced);
}
@@ -1146,24 +1187,6 @@ 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 c983667725..1b7a239798 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -485,6 +485,7 @@ 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);