mirror of
https://github.com/mpv-player/mpv
synced 2025-03-19 09:57:34 +00:00
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.
This commit is contained in:
parent
12375f67b4
commit
c5eb2f2ac4
@ -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
|
||||
|
@ -1141,6 +1141,13 @@ static void wakeup_dec_thread(void *ptr)
|
||||
mp_dispatch_interrupt(p->dec_dispatch);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user