From 5220725ca506bc40f1f0c3f0507fa337605f1dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Thu, 9 Nov 2023 03:18:48 +0100 Subject: [PATCH] vo: add params mutex This mostly is added to resolve player command synchronization with VO thread discussed in 477a0f83. The current uses does not necessarily need this as they are all managed by playloop. But for future use with other params that will be handy. Those params are mostly to observe current state of VO and does not necessarly need to be locked along with frame drawing, that changes the params once at the end. --- video/out/vo.c | 10 ++++++++-- video/out/vo.h | 10 +++++++++- video/out/vo_gpu_next.c | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/video/out/vo.c b/video/out/vo.c index 50129fb306..7581d9680e 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -270,6 +270,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 +302,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), @@ -613,8 +615,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 +629,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); @@ -1433,9 +1439,9 @@ 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; } diff --git a/video/out/vo.h b/video/out/vo.h index e38dcf8010..40c5746992 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -29,6 +29,7 @@ #include "video/img_format.h" #include "common/common.h" #include "options/options.h" +#include "osdep/threads.h" enum { // VO needs to redraw @@ -470,7 +471,14 @@ struct vo { // be accessed unsynchronized (read-only). int config_ok; // Last config call was successful? - struct mp_image_params *params; // Configured parameters (as in vo_reconfig) + + // --- The following fields are synchronized by params_mutex, most of + // the params are set only in the vo_reconfig and safe to read + // unsynchronized. Some of the parameters are updated in draw_frame, + // which are still safe to read in the play loop, but for correctness + // generic getter is protected by params_mutex. + mp_mutex params_mutex; + struct mp_image_params *params; // Configured parameters (changed in vo_reconfig) // --- The following fields can be accessed only by the VO thread, or from // anywhere _if_ the VO thread is suspended (use vo->dispatch). diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 1dc1b181ae..77ab0113bb 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -1079,11 +1079,13 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) } const struct pl_frame *cur_frame = pl_frame_mix_nearest(&mix); + mp_mutex_lock(&vo->params_mutex); if (cur_frame && vo->params) { vo->params->color.hdr = cur_frame->color.hdr; // Augment metadata with peak detection max_pq_y / avg_pq_y pl_renderer_get_hdr_metadata(p->rr, &vo->params->color.hdr); } + mp_mutex_unlock(&vo->params_mutex); p->is_interpolated = pts_offset != 0 && mix.num_frames > 1; valid = true;