summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
Diffstat (limited to 'video/out')
-rw-r--r--video/out/vo.c17
-rw-r--r--video/out/vo.h12
-rw-r--r--video/out/vo_lavc.c4
-rw-r--r--video/out/vo_vdpau.c12
4 files changed, 29 insertions, 16 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 890052d67f..774d2e2bd4 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -558,17 +558,17 @@ static bool render_frame(struct vo *vo)
int64_t next_vsync = prev_sync(vo, mp_time_us()) + in->vsync_interval;
int64_t end_time = pts + duration;
+ if (!(vo->global->opts->frame_dropping & 1) || !in->hasframe_rendered ||
+ vo->driver->untimed || vo->driver->encode)
+ duration = -1; // disable framedrop
+
in->dropped_frame = duration >= 0 && end_time < next_vsync;
- in->dropped_frame &= in->hasframe_rendered;
- in->dropped_frame &= !!(vo->global->opts->frame_dropping & 1);
- in->dropped_frame &= !(vo->driver->caps & VO_CAP_FRAMEDROP) &&
- !vo->driver->untimed && !vo->driver->encode;
+ in->dropped_frame &= !(vo->driver->caps & VO_CAP_FRAMEDROP);
// Even if we're hopelessly behind, rather degrade to 10 FPS playback,
// instead of just freezing the display forever.
in->dropped_frame &= mp_time_us() - in->last_flip < 100 * 1000;
if (in->dropped_frame) {
- in->drop_count += 1;
in->dropped_image = img;
} else {
in->hasframe_rendered = true;
@@ -587,8 +587,9 @@ static bool render_frame(struct vo *vo)
mp_sleep_us(target - now);
}
+ bool drop = false;
if (vo->driver->flip_page_timed)
- vo->driver->flip_page_timed(vo, pts, duration);
+ drop = vo->driver->flip_page_timed(vo, pts, duration) < 1;
else
vo->driver->flip_page(vo);
@@ -606,8 +607,12 @@ static bool render_frame(struct vo *vo)
MP_STATS(vo, "end video");
pthread_mutex_lock(&in->lock);
+ in->dropped_frame = drop;
}
+ if (in->dropped_frame)
+ in->drop_count += 1;
+
vo->want_redraw = false;
in->request_redraw = false;
diff --git a/video/out/vo.h b/video/out/vo.h
index 602a4cc8c4..0b6c0a5144 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -195,13 +195,19 @@ struct vo_driver {
/*
* Blit/Flip buffer to the screen. Must be called after each frame!
+ */
+ void (*flip_page)(struct vo *vo);
+
+ /*
+ * Timed version of flip_page (optional).
* pts_us is the frame presentation time, linked to mp_time_us().
* pts_us is 0 if the frame should be presented immediately.
* duration is estimated time in us until the next frame is shown.
- * duration is -1 if it is unknown or unset.
+ * duration is -1 if it is unknown or unset (also: disable framedrop).
+ * If the VO does manual framedropping, VO_CAP_FRAMEDROP should be set.
+ * Returns 1 on display, or 0 if the frame was dropped.
*/
- void (*flip_page)(struct vo *vo);
- void (*flip_page_timed)(struct vo *vo, int64_t pts_us, int duration);
+ int (*flip_page_timed)(struct vo *vo, int64_t pts_us, int duration);
/* These optional callbacks can be provided if the GUI framework used by
* the VO requires entering a message loop for receiving events, does not
diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c
index da6817d0ca..706fb53ef7 100644
--- a/video/out/vo_lavc.c
+++ b/video/out/vo_lavc.c
@@ -501,7 +501,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
pthread_mutex_unlock(&vo->encode_lavc_ctx->lock);
}
-static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
+static void flip_page(struct vo *vo)
{
}
@@ -531,7 +531,7 @@ const struct vo_driver video_out_lavc = {
.control = control,
.uninit = uninit,
.draw_image = draw_image,
- .flip_page_timed = flip_page_timed,
+ .flip_page = flip_page,
};
// vim: sw=4 ts=4 et tw=80
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index f5f3121504..e6acc4067e 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -711,14 +711,16 @@ static inline uint64_t prev_vsync(struct vdpctx *vc, uint64_t ts)
return ts - offset;
}
-static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
+static int flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
VdpStatus vdp_st;
+ vc->dropped_frame = true; // changed at end if false
+
if (!check_preemption(vo))
- return;
+ return 0;
vc->vsync_interval = 1;
if (vc->user_fps > 0) {
@@ -798,13 +800,12 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
|| vc->dropped_frame && vsync > vc->dropped_time))
pts -= vc->vsync_interval / 2;
- vc->dropped_frame = true; // changed at end if false
vc->dropped_time = ideal_pts;
pts = FFMAX(pts, vc->last_queue_time + vc->vsync_interval);
pts = FFMAX(pts, now);
if (npts < PREV_VSYNC(pts) + vc->vsync_interval)
- return;
+ return 0;
int num_flips = update_presentation_queue_status(vo);
vsync = vc->recent_vsync_time + num_flips * vc->vsync_interval;
@@ -812,7 +813,7 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
pts = FFMAX(pts, vsync + (vc->vsync_interval >> 2));
vsync = PREV_VSYNC(pts);
if (npts < vsync + vc->vsync_interval)
- return;
+ return 0;
pts = vsync + (vc->vsync_interval >> 2);
VdpOutputSurface frame = vc->output_surfaces[vc->surface_num];
vdp_st = vdp->presentation_queue_display(vc->flip_queue, frame,
@@ -827,6 +828,7 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
vc->last_ideal_time = ideal_pts;
vc->dropped_frame = false;
vc->surface_num = WRAP_ADD(vc->surface_num, 1, vc->num_output_surfaces);
+ return 1;
}
static void draw_image(struct vo *vo, struct mp_image *mpi)