diff options
authorwm4 <wm4@nowhere>2020-03-05 21:30:21 +0100
committerwm4 <wm4@nowhere>2020-03-05 22:00:50 +0100
commitc5eb2f2ac428e6ebacfe225acd9b0344dd3838bd (patch)
parent12375f67b415587ccf9504a8cfcd1830b06f8801 (diff)
f_decoder_wrapper: make decoder thread responsive while filling queue
The mp_filter_run() invocation blocks as long as the demuxer provides packets and the queue can be filled. That means it may block quite a long time of the decoder queue size is large (since we use libavcodec in a blocking manner; it regrettably does not have an async. API). This made the main thread freeze in certain situations, because it has to wait on the decoder thread. Other than I suspected (I wrote that code, but that doesn't mean I know how the hell it works), this did not freeze during seeking: seek resets flushed the queue, which also prevented the decoder thread from adding more frames to it, thus stopping decoding and responding to the main thread in time. But it does fix the issue that exiting the player waited for the decoder to finish filling the queue when stopping playback. (This happened because it called mp_decoder_wrapper_set_play_dir() before any resets. Related to the somewhat messy way play_dir is generally set. But it affects all "synchronous" decoder wrapper API calls.) This uses pretty weird mechanisms in filter.h and dispatch.h. The resulting durr hurr interactions are probably hard to follow, and this whole thing is a sin. On the other hand, this is a _very_ user visible issue, and I'm happy that it can be fixed in such an unintrusive way.
2 files changed, 8 insertions, 3 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 71b6d86603..cc74a4d8fd 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -4521,9 +4521,6 @@ Cache
affecting the playback logic). In other situations, it will simply make
seeking slower and use significantly more memory.
- In specific situations, this still makes the player wait on the decoder,
- such as seeking, switching hardware decoding modes, and more.
The queue size is restricted by the other ``--vd-queue-...`` options. The
final queue size is the minimum as indicated by the option with the lowest
limit. Each decoder/track has its own queue that may use the full configured
diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c
index cc8af967df..b919db4d4d 100644
--- a/filters/f_decoder_wrapper.c
+++ b/filters/f_decoder_wrapper.c
@@ -1141,6 +1141,13 @@ static void wakeup_dec_thread(void *ptr)
+static void onlock_dec_thread(void *ptr)
+ struct priv *p = ptr;
+ mp_filter_graph_interrupt(p->dec_root_filter);
struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent,
struct sh_stream *src)
@@ -1185,6 +1192,7 @@ struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent,
p->dec_dispatch = mp_dispatch_create(p);
p->dec_root_filter = mp_filter_create_root(public_f->global);
mp_filter_root_set_wakeup_cb(p->dec_root_filter, wakeup_dec_thread, p);
+ mp_dispatch_set_onlock_fn(p->dec_dispatch, onlock_dec_thread, p);
struct mp_stream_info *sinfo = mp_filter_find_stream_info(parent);
if (sinfo) {