mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
vo_vdpau: better integration with the generic framedrop code
vo_vdpau uses its own framedrop code, mostly for historic reasons. It has some tricky heuristics, of which I'm not sure how they work, or if they have any effect at all, but in any case, I want to keep this code for now. One day it might get fully ported to the vo.c framedrop code, or just removed. But improve its interaction with the user-visible framedrop controls. Make --framedrop actually enable and disable the vo_vdpau framedrop code, and increment the number of dropped frames correctly. The code path for other VOs should be equivalent. The vo_vdpau behavior should, except for the improvements mentioned above, be mostly equivalent as well. One minor change is that frames "shown" during preemption are always count as dropped. Remove the statement from the manpage that vo_vdpau is the default; this hasn't been the case for a while.
This commit is contained in:
@@ -452,9 +452,8 @@ Video
|
||||
|
||||
.. note::
|
||||
|
||||
``--vo=vdpau`` (also the default VO) always has the ``vo`` framedrop
|
||||
mode enabled. It doesn't increment the ``D:`` field in the status line
|
||||
either.
|
||||
``--vo=vdpau`` has its own code for the ``vo`` framedrop mode. Slight
|
||||
differences to other VOs are possible.
|
||||
|
||||
``--display-fps=<fps>``
|
||||
Set the maximum assumed display FPS used with ``--framedrop``. By default
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user