mirror of https://github.com/mpv-player/mpv
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).
This commit is contained in:
parent
a1771ed0d4
commit
0c9ac5835b
|
@ -1108,8 +1108,10 @@ void write_video(struct MPContext *mpctx)
|
||||||
struct mp_image_params p = mpctx->next_frames[0]->params;
|
struct mp_image_params p = mpctx->next_frames[0]->params;
|
||||||
if (!vo->params || !mp_image_params_equal(&p, vo->params)) {
|
if (!vo->params || !mp_image_params_equal(&p, vo->params)) {
|
||||||
// Changing config deletes the current frame; wait until it's finished.
|
// Changing config deletes the current frame; wait until it's finished.
|
||||||
if (vo_still_displaying(vo))
|
if (vo_still_displaying(vo)) {
|
||||||
|
vo_request_wakeup_on_done(vo);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const struct vo_driver *info = mpctx->video_out->driver;
|
const struct vo_driver *info = mpctx->video_out->driver;
|
||||||
char extra[20] = {0};
|
char extra[20] = {0};
|
||||||
|
|
|
@ -128,6 +128,7 @@ struct vo_internal {
|
||||||
bool want_redraw; // redraw request from VO to player
|
bool want_redraw; // redraw request from VO to player
|
||||||
bool send_reset; // send VOCTRL_RESET
|
bool send_reset; // send VOCTRL_RESET
|
||||||
bool paused;
|
bool paused;
|
||||||
|
bool wakeup_on_done;
|
||||||
int queued_events; // event mask for the user
|
int queued_events; // event mask for the user
|
||||||
int internal_events; // event mask for us
|
int internal_events; // event mask for us
|
||||||
|
|
||||||
|
@ -747,6 +748,41 @@ void vo_wakeup(struct vo *vo)
|
||||||
pthread_mutex_unlock(&in->lock);
|
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
|
// 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
|
// function will return false, and the VO will call the wakeup callback once
|
||||||
// it's ready.
|
// it's ready.
|
||||||
|
@ -897,6 +933,7 @@ static bool render_frame(struct vo *vo)
|
||||||
|
|
||||||
if (in->dropped_frame) {
|
if (in->dropped_frame) {
|
||||||
in->drop_count += 1;
|
in->drop_count += 1;
|
||||||
|
wakeup_core(vo);
|
||||||
} else {
|
} else {
|
||||||
in->rendering = true;
|
in->rendering = true;
|
||||||
in->hasframe_rendered = 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()
|
pthread_cond_broadcast(&in->wakeup); // for vo_wait_frame()
|
||||||
wakeup_core(vo);
|
|
||||||
|
|
||||||
got_frame = true;
|
got_frame = true;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
talloc_free(frame);
|
talloc_free(frame);
|
||||||
|
if (in->wakeup_on_done && !still_displaying(vo)) {
|
||||||
|
in->wakeup_on_done = false;
|
||||||
|
wakeup_core(vo);
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&in->lock);
|
pthread_mutex_unlock(&in->lock);
|
||||||
|
|
||||||
return got_frame || (in->frame_queued && in->frame_queued->display_synced);
|
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);
|
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.
|
// Whether at least 1 frame was queued or rendered since last seek or reconfig.
|
||||||
bool vo_has_frame(struct vo *vo)
|
bool vo_has_frame(struct vo *vo)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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_queue_frame(struct vo *vo, struct vo_frame *frame);
|
||||||
void vo_wait_frame(struct vo *vo);
|
void vo_wait_frame(struct vo *vo);
|
||||||
bool vo_still_displaying(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);
|
bool vo_has_frame(struct vo *vo);
|
||||||
void vo_redraw(struct vo *vo);
|
void vo_redraw(struct vo *vo);
|
||||||
bool vo_want_redraw(struct vo *vo);
|
bool vo_want_redraw(struct vo *vo);
|
||||||
|
|
Loading…
Reference in New Issue