diff options
Diffstat (limited to 'video/out/vo.c')
-rw-r--r-- | video/out/vo.c | 127 |
1 files changed, 89 insertions, 38 deletions
diff --git a/video/out/vo.c b/video/out/vo.c index 50129fb..db29690 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -63,14 +63,12 @@ extern const struct vo_driver video_out_sdl; extern const struct vo_driver video_out_vaapi; extern const struct vo_driver video_out_dmabuf_wayland; extern const struct vo_driver video_out_wlshm; -extern const struct vo_driver video_out_rpi; extern const struct vo_driver video_out_tct; extern const struct vo_driver video_out_sixel; extern const struct vo_driver video_out_kitty; static const struct vo_driver *const video_out_drivers[] = { - &video_out_libmpv, #if HAVE_ANDROID &video_out_mediacodec_embed, #endif @@ -100,6 +98,7 @@ static const struct vo_driver *const video_out_drivers[] = #if HAVE_X11 &video_out_x11, #endif + &video_out_libmpv, &video_out_null, // should not be auto-selected &video_out_image, @@ -110,9 +109,6 @@ static const struct vo_driver *const video_out_drivers[] = #if HAVE_DRM &video_out_drm, #endif -#if HAVE_RPI_MMAL - &video_out_rpi, -#endif #if HAVE_SIXEL &video_out_sixel, #endif @@ -138,6 +134,7 @@ struct vo_internal { bool want_redraw; // redraw request from VO to player bool send_reset; // send VOCTRL_RESET bool paused; + bool wakeup_on_done; int queued_events; // event mask for the user int internal_events; // event mask for us @@ -239,7 +236,6 @@ static void update_opts(void *p) if (m_config_cache_update(vo->opts_cache)) { read_opts(vo); - if (vo->driver->control) { vo->driver->control(vo, VOCTRL_VO_OPTS_CHANGED, NULL); // "Legacy" update of video position related options. @@ -247,18 +243,6 @@ static void update_opts(void *p) vo->driver->control(vo, VOCTRL_SET_PANSCAN, NULL); } } - - if (vo->gl_opts_cache && m_config_cache_update(vo->gl_opts_cache)) { - // "Legacy" update of video GL renderer related options. - if (vo->driver->control) - vo->driver->control(vo, VOCTRL_UPDATE_RENDER_OPTS, NULL); - } - - if (m_config_cache_update(vo->eq_opts_cache)) { - // "Legacy" update of video equalizer related options. - if (vo->driver->control) - vo->driver->control(vo, VOCTRL_SET_EQUALIZER, NULL); - } } // Does not include thread- and VO uninit. @@ -270,6 +254,7 @@ static void dealloc_vo(struct vo *vo) talloc_free(vo->opts_cache); talloc_free(vo->gl_opts_cache); talloc_free(vo->eq_opts_cache); + mp_mutex_destroy(&vo->params_mutex); mp_mutex_destroy(&vo->in->lock); mp_cond_destroy(&vo->in->wakeup); @@ -301,6 +286,7 @@ static struct vo *vo_create(bool probing, struct mpv_global *global, .probing = probing, .in = talloc(vo, struct vo_internal), }; + mp_mutex_init(&vo->params_mutex); talloc_steal(vo, log); *vo->in = (struct vo_internal) { .dispatch = mp_dispatch_create(vo), @@ -319,12 +305,7 @@ static struct vo *vo_create(bool probing, struct mpv_global *global, update_opts, vo); vo->gl_opts_cache = m_config_cache_alloc(NULL, global, &gl_video_conf); - m_config_cache_set_dispatch_change_cb(vo->gl_opts_cache, vo->in->dispatch, - update_opts, vo); - vo->eq_opts_cache = m_config_cache_alloc(NULL, global, &mp_csp_equalizer_conf); - m_config_cache_set_dispatch_change_cb(vo->eq_opts_cache, vo->in->dispatch, - update_opts, vo); mp_input_set_mouse_transform(vo->input_ctx, NULL, NULL); if (vo->driver->encode != !!vo->encode_lavc_ctx) @@ -613,8 +594,10 @@ static void run_reconfig(void *p) mp_image_params_get_dsize(params, &vo->dwidth, &vo->dheight); + mp_mutex_lock(&vo->params_mutex); talloc_free(vo->params); vo->params = talloc_dup(vo, params); + mp_mutex_unlock(&vo->params_mutex); if (vo->driver->reconfig2) { *ret = vo->driver->reconfig2(vo, img); @@ -625,8 +608,10 @@ static void run_reconfig(void *p) if (vo->config_ok) { check_vo_caps(vo); } else { + mp_mutex_lock(&vo->params_mutex); talloc_free(vo->params); vo->params = NULL; + mp_mutex_unlock(&vo->params_mutex); } mp_mutex_lock(&in->lock); @@ -765,6 +750,52 @@ void vo_wakeup(struct vo *vo) mp_mutex_unlock(&in->lock); } +static int64_t get_current_frame_end(struct vo *vo) +{ + struct vo_internal *in = vo->in; + if (!in->current_frame) + return -1; + return in->current_frame->pts + MPMAX(in->current_frame->duration, 0); +} + +static bool still_displaying(struct vo *vo) +{ + struct vo_internal *in = vo->in; + bool working = in->rendering || in->frame_queued; + if (working) + goto done; + + int64_t frame_end = get_current_frame_end(vo); + if (frame_end < 0) + goto done; + working = mp_time_ns() < frame_end; + +done: + return working && in->hasframe; +} + +// Return true if there is still a frame being displayed (or queued). +bool vo_still_displaying(struct vo *vo) +{ + mp_mutex_lock(&vo->in->lock); + bool res = still_displaying(vo); + mp_mutex_unlock(&vo->in->lock); + return res; +} + +// Make vo issue a wakeup once vo_still_displaying() becomes false. +void vo_request_wakeup_on_done(struct vo *vo) +{ + struct vo_internal *in = vo->in; + mp_mutex_lock(&vo->in->lock); + if (still_displaying(vo)) { + in->wakeup_on_done = true; + } else { + wakeup_core(vo); + } + mp_mutex_unlock(&vo->in->lock); +} + // 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 // it's ready. @@ -923,6 +954,7 @@ static bool render_frame(struct vo *vo) if (in->dropped_frame) { in->drop_count += 1; + wakeup_core(vo); } else { in->rendering = true; in->hasframe_rendered = true; @@ -994,10 +1026,9 @@ static bool render_frame(struct vo *vo) more_frames = true; mp_cond_broadcast(&in->wakeup); // for vo_wait_frame() - wakeup_core(vo); done: - if (!vo->driver->frame_owner) + if (!vo->driver->frame_owner || in->dropped_frame) talloc_free(frame); mp_mutex_unlock(&in->lock); @@ -1074,6 +1105,8 @@ static MP_THREAD_VOID vo_thread(void *ptr) bool working = render_frame(vo); int64_t now = mp_time_ns(); int64_t wait_until = now + MP_TIME_S_TO_NS(working ? 0 : 1000); + bool wakeup_on_done = false; + int64_t wakeup_core_after = 0; mp_mutex_lock(&in->lock); if (in->wakeup_pts) { @@ -1088,6 +1121,14 @@ static MP_THREAD_VOID vo_thread(void *ptr) in->want_redraw = true; wakeup_core(vo); } + if ((!working && !in->rendering && !in->frame_queued) && in->wakeup_on_done) { + // At this point we know VO is going to sleep + int64_t frame_end = get_current_frame_end(vo); + if (frame_end >= 0) + wakeup_core_after = frame_end; + wakeup_on_done = true; + in->wakeup_on_done = false; + } vo->want_redraw = false; bool redraw = in->request_redraw; bool send_reset = in->send_reset; @@ -1110,6 +1151,17 @@ static MP_THREAD_VOID vo_thread(void *ptr) if (wait_until <= now) continue; + if (wakeup_on_done) { + // At this point wait_until should be longer than frame duration + if (wakeup_core_after >= 0 && wait_until >= wakeup_core_after) { + wait_vo(vo, wakeup_core_after); + mp_mutex_lock(&in->lock); + in->need_wakeup = true; + mp_mutex_unlock(&in->lock); + } + wakeup_core(vo); + } + wait_vo(vo, wait_until); } forget_frames(vo); // implicitly synchronized @@ -1185,17 +1237,6 @@ void vo_seek_reset(struct vo *vo) mp_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; - mp_mutex_lock(&in->lock); - bool working = in->rendering || in->frame_queued; - mp_mutex_unlock(&in->lock); - return working && in->hasframe; -} - // Whether at least 1 frame was queued or rendered since last seek or reconfig. bool vo_has_frame(struct vo *vo) { @@ -1433,9 +1474,19 @@ int lookup_keymap_table(const struct mp_keymap *map, int key) struct mp_image_params vo_get_current_params(struct vo *vo) { struct mp_image_params p = {0}; - mp_mutex_lock(&vo->in->lock); + mp_mutex_lock(&vo->params_mutex); if (vo->params) p = *vo->params; - mp_mutex_unlock(&vo->in->lock); + mp_mutex_unlock(&vo->params_mutex); + return p; +} + +struct mp_image_params vo_get_target_params(struct vo *vo) +{ + struct mp_image_params p = {0}; + mp_mutex_lock(&vo->params_mutex); + if (vo->target_params) + p = *vo->target_params; + mp_mutex_unlock(&vo->params_mutex); return p; } |