diff options
-rw-r--r-- | DOCS/man/options.rst | 5 | ||||
-rw-r--r-- | video/out/vo.c | 17 | ||||
-rw-r--r-- | video/out/vo.h | 12 | ||||
-rw-r--r-- | video/out/vo_lavc.c | 4 | ||||
-rw-r--r-- | video/out/vo_vdpau.c | 12 |
5 files changed, 31 insertions, 19 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index a0e5f59a41..44ed680d49 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -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 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) |