From 45e214d7ae7f1a8cf7af6b43968083b53b25ccb2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 6 Feb 2015 19:19:15 +0100 Subject: stream: slightly improve reconnect behavior Wait for a longer time between reconnects. Introdeuce and use mp_cancel_wait(), so that quitting is still immediate. --- stream/stream.c | 46 ++++++++++++++++++++++++++++------------------ stream/stream.h | 1 + 2 files changed, 29 insertions(+), 18 deletions(-) (limited to 'stream') diff --git a/stream/stream.c b/stream/stream.c index 4759a01abe..e24ea69e08 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -48,6 +48,8 @@ #ifdef __MINGW32__ #include +#else +#include #endif // Includes additional padding in case sizes get rounded up by sector size. @@ -414,36 +416,27 @@ stream_t *open_output_stream(const char *filename, struct mpv_global *global) static int stream_reconnect(stream_t *s) { -#define MAX_RECONNECT_RETRIES 5 -#define RECONNECT_SLEEP_MAX_MS 500 if (!s->streaming || s->uncached_stream) return 0; if (!s->seekable) return 0; - if (mp_cancel_test(s->cancel)) + if (mp_cancel_test(s->cancel) || !s->cancel) return 0; int64_t pos = s->pos; - int sleep_ms = 5; - for (int retry = 0; retry < MAX_RECONNECT_RETRIES; retry++) { + double sleep_secs = 0; + for (int retry = 0; retry < 6; retry++) { MP_WARN(s, "Connection lost! Attempting to reconnect (%d)...\n", retry + 1); - if (retry) { - mp_sleep_us(sleep_ms * 1000); - sleep_ms = MPMIN(sleep_ms * 2, RECONNECT_SLEEP_MAX_MS); - } - - if (mp_cancel_test(s->cancel)) - return 0; + if (mp_cancel_wait(s->cancel, sleep_secs)) + break; - s->eof = 1; + sleep_secs = MPMAX(sleep_secs, 0.1); + sleep_secs = MPMIN(sleep_secs * 4, 10.0); int r = stream_control(s, STREAM_CTRL_RECONNECT, NULL); if (r == STREAM_UNSUPPORTED) - return 0; - if (r != STREAM_OK) - continue; - - if (stream_seek_unbuffered(s, pos) < 0 && s->pos == pos) + break; + if (r == STREAM_OK && stream_seek_unbuffered(s, pos) < 0 && s->pos == pos) return 1; } return 0; @@ -1059,6 +1052,23 @@ bool mp_cancel_test(struct mp_cancel *c) return c ? atomic_load(&c->triggered) : false; } +// Wait until the even is signaled. If the timeout (in seconds) expires, return +// false. timeout==0 polls, timeout<0 waits forever. +#ifdef __MINGW32__ +bool mp_cancel_wait(struct mp_cancel *c, double timeout) +{ + return WaitForSingleObject(c->event, timeout < 0 ? INFINITE : timeout * 1000) + == WAIT_OBJECT_0; +} +#else +bool mp_cancel_wait(struct mp_cancel *c, double timeout) +{ + struct pollfd fd = { .fd = c->wakeup_pipe[0], .events = POLLIN }; + poll(&fd, 1, timeout * 1000); + return fd.revents & POLLIN; +} +#endif + #ifdef __MINGW32__ void *mp_cancel_get_event(struct mp_cancel *c) { diff --git a/stream/stream.h b/stream/stream.h index ef900bf16f..ef9f402c72 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -277,6 +277,7 @@ 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); +bool mp_cancel_wait(struct mp_cancel *c, double timeout); void mp_cancel_reset(struct mp_cancel *c); void *mp_cancel_get_event(struct mp_cancel *c); // win32 HANDLE int mp_cancel_get_fd(struct mp_cancel *c); -- cgit v1.2.3