summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-02-06 19:19:15 +0100
committerwm4 <wm4@nowhere>2015-02-06 19:19:15 +0100
commit45e214d7ae7f1a8cf7af6b43968083b53b25ccb2 (patch)
tree3d27d0061df39b44a464533033639e5050937551
parente14d09c8a6aaf3a2a56898c46ec6ac817c0dd66f (diff)
downloadmpv-45e214d7ae7f1a8cf7af6b43968083b53b25ccb2.tar.bz2
mpv-45e214d7ae7f1a8cf7af6b43968083b53b25ccb2.tar.xz
stream: slightly improve reconnect behavior
Wait for a longer time between reconnects. Introdeuce and use mp_cancel_wait(), so that quitting is still immediate.
-rw-r--r--stream/stream.c46
-rw-r--r--stream/stream.h1
2 files changed, 29 insertions, 18 deletions
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 <windows.h>
+#else
+#include <poll.h>
#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);