diff options
author | wm4 <wm4@nowhere> | 2017-08-22 15:50:33 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2017-08-22 15:50:33 +0200 |
commit | d2bdb72b69536370c3046107fc593896e74803c3 (patch) | |
tree | 09d5913f981ee5f5e0d43fbfd24b06f67eb8dd5e /video/out | |
parent | 5361c0b5d897ec7c969d2a75bb2dde345d62a59c (diff) | |
download | mpv-d2bdb72b69536370c3046107fc593896e74803c3.tar.bz2 mpv-d2bdb72b69536370c3046107fc593896e74803c3.tar.xz |
options: add a thread-safe way to notify option updates
So far, we had a thread-safe way to read options, but no option update
notification mechanism. Everything was funneled though the main thread's
central mp_option_change_callback() function. For example, if the
panscan options were changed, the function called vo_control() with
VOCTRL_SET_PANSCAN to manually notify the VO thread of updates. This
worked, but's pretty inconvenient. Most of these problems come from the
fact that MPlayer was written as a single-threaded program.
This commit works towards a more flexible mechanism. It adds an update
callback to m_config_cache (the thing that is already used for
thread-safe access of global options).
This alone would still be rather inconvenient, at least in context of
VOs. Add another mechanism on top of it that uses mp_dispatch_queue, and
takes care of some annoying synchronization issues. We extend
mp_dispatch_queue itself to make this easier and slightly more
efficient.
As a first application, use this to reimplement certain VO scaling and
renderer options. The update_opts() function translates these to the
"old" VOCTRLs, though.
An annoyingly subtle issue is that m_config_cache's destructor now
releases pending notifications, and must be released before the
associated dispatch queue. Otherwise, it could happen that option
updates during e.g. VO destruction queue or run stale entries, which is
not expected.
Rather untested. The singly-linked list code in dispatch.c is probably
buggy, and I bet some aspects about synchronization are not entirely
sane.
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/opengl/video.c | 1 | ||||
-rw-r--r-- | video/out/vo.c | 36 | ||||
-rw-r--r-- | video/out/vo.h | 1 |
3 files changed, 36 insertions, 2 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index bb3730022a..bbf88e2747 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -414,7 +414,6 @@ const struct m_sub_options gl_video_conf = { }, .size = sizeof(struct gl_video_opts), .defaults = &gl_video_opts_def, - .change_flags = UPDATE_RENDERER, }; static void uninit_rendering(struct gl_video *p); diff --git a/video/out/vo.c b/video/out/vo.c index e52495e195..217baac632 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -167,6 +167,8 @@ struct vo_internal { int opt_framedrop; }; +extern const struct m_sub_options gl_video_conf; + static void forget_frames(struct vo *vo); static void *vo_thread(void *ptr); @@ -210,10 +212,33 @@ static void dispatch_wakeup_cb(void *ptr) vo_wakeup(vo); } +static void update_opts(void *p) +{ + struct vo *vo = p; + + if (m_config_cache_update(vo->opts_cache)) { + // "Legacy" update of video position related options. + if (vo->driver->control) + 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); + } +} + // Does not include thread- and VO uninit. static void dealloc_vo(struct vo *vo) { forget_frames(vo); // implicitly synchronized + + // These must be free'd before vo->in->dispatch. + talloc_free(vo->opts_cache); + talloc_free(vo->gl_opts_cache); + pthread_mutex_destroy(&vo->in->lock); pthread_cond_destroy(&vo->in->wakeup); talloc_free(vo); @@ -254,9 +279,18 @@ static struct vo *vo_create(bool probing, struct mpv_global *global, pthread_mutex_init(&vo->in->lock, NULL); pthread_cond_init(&vo->in->wakeup, NULL); - vo->opts_cache = m_config_cache_alloc(vo, global, &vo_sub_opts); + vo->opts_cache = m_config_cache_alloc(NULL, global, &vo_sub_opts); vo->opts = vo->opts_cache->opts; + m_config_cache_set_dispatch_change_cb(vo->opts_cache, vo->in->dispatch, + update_opts, vo); + +#if HAVE_GL + 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); +#endif + mp_input_set_mouse_transform(vo->input_ctx, NULL, NULL); if (vo->driver->encode != !!vo->encode_lavc_ctx) goto error; diff --git a/video/out/vo.h b/video/out/vo.h index 82ec284219..c3145d5a5d 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -400,6 +400,7 @@ struct vo { struct m_config_cache *opts_cache; // cache for ->opts struct mp_vo_opts *opts; + struct m_config_cache *gl_opts_cache; bool want_redraw; // redraw as soon as possible |