diff options
author | wm4 <wm4@nowhere> | 2014-09-13 14:23:08 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-09-13 16:09:51 +0200 |
commit | 2e91d44e2031c299de0d879e2656024d701c27da (patch) | |
tree | fdbe4903705bff3d6a21c42f08eb7e4b31e5cf07 /stream/stream.h | |
parent | 2dd819705dcbeb4a20c0d6123082f9662cfa2ae4 (diff) | |
download | mpv-2e91d44e2031c299de0d879e2656024d701c27da.tar.bz2 mpv-2e91d44e2031c299de0d879e2656024d701c27da.tar.xz |
stream: redo playback abort handling
This mechanism originates from MPlayer's way of dealing with blocking
network, but it's still useful. On opening and closing, mpv waits for
network synchronously, and also some obscure commands and use-cases can
lead to such blocking. In these situations, the stream is asynchronously
forced to stop by "interrupting" it.
The old design interrupting I/O was a bit broken: polling with a
callback, instead of actively interrupting it. Change the direction of
this. There is no callback anymore, and the player calls
mp_cancel_trigger() to force the stream to return.
libavformat (via stream_lavf.c) has the old broken design, and fixing it
would require fixing libavformat, which won't happen so quickly. So we
have to keep that part. But everything above the stream layer is
prepared for a better design, and more sophisticated methods than
mp_cancel_test() could be easily introduced.
There's still one problem: commands are still run in the central
playback loop, which we assume can block on I/O in the worst case.
That's not a problem yet, because we simply mark some commands as being
able to stop playback of the current file ("quit" etc.), so input.c
could abort playback as soon as such a command is queued. But there are
also commands abort playback only conditionally, and the logic for that
is in the playback core and thus "unreachable". For example,
"playlist_next" aborts playback only if there's a next file. We don't
want it to always abort playback.
As a quite ugly hack, abort playback only if at least 2 abort commands
are queued - this pretty much happens only if the core is frozen and
doesn't react to input.
Diffstat (limited to 'stream/stream.h')
-rw-r--r-- | stream/stream.h | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/stream/stream.h b/stream/stream.h index 20c2e03e6a..0f028e330d 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -189,6 +189,8 @@ typedef struct stream { struct MPOpts *opts; struct mpv_global *global; + struct mp_cancel *cancel; // cancellation notification + FILE *capture_file; char *capture_filename; @@ -248,16 +250,20 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, int max_size); int stream_control(stream_t *s, int cmd, void *arg); void free_stream(stream_t *s); -struct stream *stream_create(const char *url, int flags, struct mpv_global *global); +struct stream *stream_create(const char *url, int flags, + struct mp_cancel *c, struct mpv_global *global); struct stream *stream_open(const char *filename, struct mpv_global *global); stream_t *open_output_stream(const char *filename, struct mpv_global *global); stream_t *open_memory_stream(void *data, int len); -bool stream_check_interrupt(struct stream *s); - void mp_url_unescape_inplace(char *buf); char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok); +struct mp_cancel *mp_cancel_new(void *talloc_ctx); +void mp_cancel_trigger(struct mp_cancel *c); +bool mp_cancel_test(struct mp_cancel *c); +void mp_cancel_reset(struct mp_cancel *c); + // stream_file.c char *mp_file_url_to_filename(void *talloc_ctx, bstr url); |