diff --git a/video/out/vo.h b/video/out/vo.h index a3b2ac1556..77efe7f58a 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -407,8 +407,12 @@ struct vo_driver { * frame is freed by the caller if the callee did not assume ownership * of the frames, but in any case the callee can still modify the * contained data and references. + * + * Return false to signal to the core that rendering is being skipped for + * this particular frame. vo.c will sleep for the expected duration of that + * frame before advancing forward. */ - void (*draw_frame)(struct vo *vo, struct vo_frame *frame); + bool (*draw_frame)(struct vo *vo, struct vo_frame *frame); /* * Blit/Flip buffer to the screen. Must be called after each frame! diff --git a/video/out/vo_caca.c b/video/out/vo_caca.c index 0625de0e5f..8ce4322a4e 100644 --- a/video/out/vo_caca.c +++ b/video/out/vo_caca.c @@ -111,15 +111,18 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) return resize(vo); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *priv = vo->priv; struct mp_image *mpi = frame->current; if (!mpi) - return; + goto done; memcpy_pic(priv->dither_buffer, mpi->planes[0], priv->image_width * depth, priv->image_height, priv->image_width * depth, mpi->stride[0]); caca_dither_bitmap(priv->canvas, 0, 0, priv->screen_w, priv->screen_h, priv->dither, priv->dither_buffer); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_direct3d.c b/video/out/vo_direct3d.c index 91e962faa1..e3a5fc5417 100644 --- a/video/out/vo_direct3d.c +++ b/video/out/vo_direct3d.c @@ -1003,18 +1003,18 @@ static bool get_video_buffer(d3d_priv *priv, struct mp_image *out) return true; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { d3d_priv *priv = vo->priv; if (!priv->d3d_device) - return; + goto done; struct mp_image buffer; if (!get_video_buffer(priv, &buffer)) - return; + goto done; if (!frame->current) - return; + goto done; mp_image_copy(&buffer, frame->current); @@ -1024,6 +1024,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) priv->osd_pts = frame->current->pts; d3d_draw_frame(priv); + +done: + return VO_TRUE; } static mp_image_t *get_window_screenshot(d3d_priv *priv) diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c index 733a011cd9..1a12c32ddb 100644 --- a/video/out/vo_dmabuf_wayland.c +++ b/video/out/vo_dmabuf_wayland.c @@ -592,7 +592,7 @@ done: return draw; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; struct vo_wayland_state *wl = vo->wl; @@ -603,7 +603,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (!vo_wayland_check_visible(vo)) { if (frame->current) talloc_free(frame); - return; + return VO_FALSE; } if (p->destroy_buffers) @@ -641,6 +641,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) p->osd_surface_is_mapped = false; } } + + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c index 34726a3c02..cf8c6a8ee1 100644 --- a/video/out/vo_drm.c +++ b/video/out/vo_drm.c @@ -300,13 +300,13 @@ static void swapchain_step(struct vo *vo) } } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct vo_drm_state *drm = vo->drm; struct priv *p = vo->priv; if (!drm->active) - return; + goto done; drm->still = frame->still; @@ -319,6 +319,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) } enqueue_frame(vo, fb); + +done: + return VO_TRUE; } static void queue_flip(struct vo *vo, struct drm_frame *frame) diff --git a/video/out/vo_gpu.c b/video/out/vo_gpu.c index 837292b248..53b0fb4087 100644 --- a/video/out/vo_gpu.c +++ b/video/out/vo_gpu.c @@ -70,25 +70,27 @@ static void resize(struct vo *vo) vo->want_redraw = true; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct gpu_priv *p = vo->priv; struct ra_swapchain *sw = p->ctx->swapchain; struct ra_fbo fbo; if (!sw->fns->start_frame(sw, &fbo)) - return; + return VO_FALSE; gl_video_render_frame(p->renderer, frame, &fbo, RENDER_FRAME_DEF); if (!sw->fns->submit_frame(sw, frame)) { MP_ERR(vo, "Failed presenting frame!\n"); - return; + return VO_FALSE; } struct mp_image_params *params = gl_video_get_target_params_ptr(p->renderer); mp_mutex_lock(&vo->params_mutex); vo->target_params = params; mp_mutex_unlock(&vo->params_mutex); + + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 9706e92f0a..118df140fc 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -904,7 +904,7 @@ static void update_tm_viz(struct pl_color_map_params *params, static void update_hook_opts_dynamic(struct priv *p, const struct pl_hook *hook, const struct mp_image *mpi); -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; pl_options pars = p->pars; @@ -1029,7 +1029,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) #endif pl_queue_update(p->queue, NULL, &qparams); } - return; + return VO_FALSE; } bool valid = false; @@ -1173,6 +1173,7 @@ done: pl_gpu_flush(gpu); p->frame_pending = true; + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_image.c b/video/out/vo_image.c index 84e164f6e5..ea289dcea6 100644 --- a/video/out/vo_image.c +++ b/video/out/vo_image.c @@ -90,16 +90,19 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) return 0; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; if (!frame->current) - return; + goto done; p->current = frame->current; struct mp_osd_res dim = osd_res_from_image_params(vo->params); osd_draw_on_image(vo->osd, dim, frame->current->pts, OSD_DRAW_SUB_ONLY, p->current); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_kitty.c b/video/out/vo_kitty.c index a5f716a0bd..208f2b6d2d 100644 --- a/video/out/vo_kitty.c +++ b/video/out/vo_kitty.c @@ -239,7 +239,7 @@ static int create_shm(struct vo *vo) #endif } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; mp_image_t *mpi = NULL; @@ -273,7 +273,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (p->opts.use_shm && !create_shm(vo)) - return; + goto done; memcpy_pic(p->buffer, p->frame->planes[0], p->width * BYTES_PER_PX, p->height, p->width * BYTES_PER_PX, p->frame->stride[0]); @@ -282,6 +282,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) av_base64_encode(p->output, p->output_size, p->buffer, p->buffer_size); talloc_free(mpi); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 8e643c65a8..839c9f7db4 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -182,7 +182,7 @@ static int query_format(struct vo *vo, int format) return 0; } -static void draw_frame(struct vo *vo, struct vo_frame *voframe) +static bool draw_frame(struct vo *vo, struct vo_frame *voframe) { struct priv *vc = vo->priv; struct encoder_context *enc = vc->enc; @@ -190,7 +190,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe) AVCodecContext *avc = enc->encoder; if (voframe->redraw || voframe->repeat || voframe->num_frames < 1) - return; + goto done; struct mp_image *mpi = voframe->frames[0]; @@ -198,7 +198,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe) osd_draw_on_image(vo->osd, dim, mpi->pts, OSD_DRAW_SUB_ONLY, mpi); if (vc->shutdown) - return; + goto done; // Lock for shared timestamp fields. mp_mutex_lock(&ectx->lock); @@ -241,6 +241,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *voframe) frame->quality = avc->global_quality; encoder_encode(enc, frame); av_frame_free(&frame); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_libmpv.c b/video/out/vo_libmpv.c index 7974eed3f7..a42cfa65ca 100644 --- a/video/out/vo_libmpv.c +++ b/video/out/vo_libmpv.c @@ -485,7 +485,7 @@ int mpv_render_context_get_info(mpv_render_context *ctx, return res; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct vo_priv *p = vo->priv; struct mpv_render_context *ctx = p->ctx; @@ -498,6 +498,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) mp_mutex_unlock(&ctx->lock); update(ctx); + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_mediacodec_embed.c b/video/out/vo_mediacodec_embed.c index 08d3866d57..00ac659f62 100644 --- a/video/out/vo_mediacodec_embed.c +++ b/video/out/vo_mediacodec_embed.c @@ -76,7 +76,7 @@ static void flip_page(struct vo *vo) mp_image_unrefp(&p->next_image); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; @@ -86,6 +86,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) talloc_free(p->next_image); p->next_image = mpi; + return VO_TRUE; } static int query_format(struct vo *vo, int format) diff --git a/video/out/vo_null.c b/video/out/vo_null.c index 0c49062e23..bf2ce0b775 100644 --- a/video/out/vo_null.c +++ b/video/out/vo_null.c @@ -32,8 +32,9 @@ struct priv { double cfg_fps; }; -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c index cce07d3d7d..d1e3734e35 100644 --- a/video/out/vo_sdl.c +++ b/video/out/vo_sdl.c @@ -879,7 +879,7 @@ static int query_format(struct vo *vo, int format) return 0; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *vc = vo->priv; @@ -894,7 +894,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) mp_image_t texmpi; if (!lock_texture(vo, &texmpi)) - return; + goto done; mp_image_copy(&texmpi, frame->current); @@ -914,6 +914,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) SDL_RenderCopy(vc->renderer, vc->tex, &src, &dst); draw_osd(vo); + +done: + return VO_TRUE; } static struct mp_image *get_window_screenshot(struct vo *vo) diff --git a/video/out/vo_sixel.c b/video/out/vo_sixel.c index f4ad675540..9d58a0a4a3 100644 --- a/video/out/vo_sixel.c +++ b/video/out/vo_sixel.c @@ -378,7 +378,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) return ret; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *priv = vo->priv; SIXELSTATUS status; @@ -391,7 +391,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) bool resized = false; update_canvas_dimensions(vo); if (!priv->canvas_ok) - return; + goto done; if (prev_rows != priv->num_rows || prev_cols != priv->num_cols || prev_width != vo->dwidth || prev_height != vo->dheight) @@ -409,7 +409,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (frame->repeat && !frame->redraw && !resized) { // Frame is repeated, and no need to update OSD either priv->skip_frame_draw = true; - return; + goto done; } else { // Either frame is new, or OSD has to be redrawn priv->skip_frame_draw = false; @@ -457,6 +457,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (mpi) talloc_free(mpi); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_tct.c b/video/out/vo_tct.c index f42e568831..07aefe4b3d 100644 --- a/video/out/vo_tct.c +++ b/video/out/vo_tct.c @@ -253,14 +253,17 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) return 0; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; struct mp_image *src = frame->current; if (!src) - return; + goto done; // XXX: pan, crop etc. mp_sws_scale(p->sws, p->frame, src); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c index 84ca4a7a42..cb8b1560c5 100644 --- a/video/out/vo_vaapi.c +++ b/video/out/vo_vaapi.c @@ -555,7 +555,7 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info) present_sync_get_info(x11->present, info); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; struct mp_image *mpi = frame->current; @@ -564,7 +564,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) struct mp_image *dst = p->swdec_surfaces[p->output_surface]; if (!dst || va_surface_upload(p, dst, mpi) < 0) { MP_WARN(vo, "Could not upload surface.\n"); - return; + goto done; } mp_image_copy_attributes(dst, mpi); mpi = dst; @@ -573,6 +573,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) p->output_surfaces[p->output_surface] = mpi; draw_osd(vo); + +done: + return VO_TRUE; } static void free_subpicture(struct priv *p, struct vaapi_osd_image *img) diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c index b22dcba0ce..4b28106624 100644 --- a/video/out/vo_vdpau.c +++ b/video/out/vo_vdpau.c @@ -870,7 +870,7 @@ drop: vo_increment_drop_count(vo, 1); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct vdpctx *vc = vo->priv; @@ -893,6 +893,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) video_to_output_surface(vo, vc->current_image); draw_osd(vo); } + return VO_TRUE; } // warning: the size and pixel format of surface must match that of the diff --git a/video/out/vo_wlshm.c b/video/out/vo_wlshm.c index 3132d7a563..708963e55a 100644 --- a/video/out/vo_wlshm.c +++ b/video/out/vo_wlshm.c @@ -239,7 +239,7 @@ static int control(struct vo *vo, uint32_t request, void *data) return ret; } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; struct vo_wayland_state *wl = vo->wl; @@ -248,7 +248,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) bool render = vo_wayland_check_visible(vo); if (!render) - return; + return VO_FALSE; buf = p->free_buffers; if (buf) { @@ -257,7 +257,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) buf = buffer_create(vo, vo->dwidth, vo->dheight); if (!buf) { wl_surface_attach(wl->surface, NULL, 0, 0); - return; + goto done; } } if (src) { @@ -289,6 +289,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) osd_draw_on_image(vo->osd, p->osd, 0, 0, &buf->mpi); } wl_surface_attach(wl->surface, buf->buffer, 0, 0); + +done: + return VO_TRUE; } static void flip_page(struct vo *vo) diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c index b637b59e23..8391b431f4 100644 --- a/video/out/vo_x11.c +++ b/video/out/vo_x11.c @@ -327,14 +327,14 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info) present_sync_get_info(x11->present, info); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct priv *p = vo->priv; wait_for_completion(vo, 1); bool render = vo_x11_check_visible(vo); if (!render) - return; + return VO_FALSE; struct mp_image *img = &p->mp_ximages[p->current_buf]; @@ -359,6 +359,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (frame->current != p->original_image) p->original_image = frame->current; + + return VO_TRUE; } static int query_format(struct vo *vo, int format) diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c index 38b903a72f..ecd6e34477 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -708,14 +708,14 @@ static void get_vsync(struct vo *vo, struct vo_vsync_info *info) present_sync_get_info(x11->present, info); } -static void draw_frame(struct vo *vo, struct vo_frame *frame) +static bool draw_frame(struct vo *vo, struct vo_frame *frame) { struct xvctx *ctx = vo->priv; wait_for_completion(vo, ctx->num_buffers - 1); bool render = vo_x11_check_visible(vo); if (!render) - return; + return VO_FALSE; struct mp_image xv_buffer = get_xv_buffer(vo, ctx->current_buf); if (frame->current) { @@ -729,6 +729,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (frame->current != ctx->original_image) ctx->original_image = frame->current; + + return VO_TRUE; } static int query_format(struct vo *vo, int format)