diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/cache.c | 26 | ||||
-rw-r--r-- | stream/stream.c | 84 | ||||
-rw-r--r-- | stream/stream_cdda.c | 2 | ||||
-rw-r--r-- | stream/stream_memory.c | 37 |
4 files changed, 100 insertions, 49 deletions
diff --git a/stream/cache.c b/stream/cache.c index f8304df8b9..4765ddb23a 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -159,11 +159,11 @@ static void cache_drop_contents(struct priv *s) static void update_speed(struct priv *s) { int64_t now = mp_time_us(); - s->speed = 0; - if (s->speed_start && s->speed_start < now) + if (s->speed_start + 1000000 <= now) { s->speed = s->speed_amount * 1e6 / (now - s->speed_start); - s->speed_amount = 0; - s->speed_start = now; + s->speed_amount = 0; + s->speed_start = now; + } } // Copy at most dst_size from the cache at the given absolute file position pos. @@ -232,11 +232,6 @@ static void cache_fill(struct priv *s) if (mp_cancel_test(s->cache->cancel)) goto done; - if (!s->speed_start) { - s->speed_start = mp_time_us(); - s->speed_amount = 0; - } - // number of buffer bytes which should be preserved in backwards direction int64_t back = MPCLAMP(read - s->min_filepos, 0, s->back_size); @@ -300,20 +295,12 @@ done: ; s->eof = len <= 0; if (!prev_eof && s->eof) { s->eof_pos = stream_tell(s->stream); - s->speed_start = 0; MP_VERBOSE(s, "EOF reached.\n"); } s->idle = s->eof || !read_attempted; s->reads++; - if (s->idle) { - update_speed(s); - s->speed_start = 0; - } - - int64_t now = mp_time_us(); - if (s->speed_start && s->speed_start + 1000000 <= now) - update_speed(s); + update_speed(s); pthread_cond_signal(&s->wakeup); } @@ -366,7 +353,6 @@ static int resize_cache(struct priv *s, int64_t size) s->buffer_size = buffer_size; s->buffer = buffer; s->idle = false; - s->speed_start = 0; s->eof = false; //make sure that we won't wait from cache_fill @@ -661,6 +647,8 @@ int stream_cache_init(stream_t *cache, stream_t *stream, cache_drop_contents(s); + s->speed_start = mp_time_us(); + s->seek_limit = opts->seek_min * 1024ULL; s->back_size = opts->back_buffer * 1024ULL; diff --git a/stream/stream.c b/stream/stream.c index 1048a8006d..846765f326 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -952,20 +952,15 @@ struct bstr stream_read_file(const char *filename, void *talloc_ctx, return res; } +#ifndef __MINGW32__ struct mp_cancel { atomic_bool triggered; -#ifdef __MINGW32__ - HANDLE event; -#endif int wakeup_pipe[2]; }; static void cancel_destroy(void *p) { struct mp_cancel *c = p; -#ifdef __MINGW32__ - CloseHandle(c->event); -#endif close(c->wakeup_pipe[0]); close(c->wakeup_pipe[1]); } @@ -975,9 +970,6 @@ struct mp_cancel *mp_cancel_new(void *talloc_ctx) struct mp_cancel *c = talloc_ptrtype(talloc_ctx, c); talloc_set_destructor(c, cancel_destroy); *c = (struct mp_cancel){.triggered = ATOMIC_VAR_INIT(false)}; -#ifdef __MINGW32__ - c->event = CreateEventW(NULL, TRUE, FALSE, NULL); -#endif mp_make_wakeup_pipe(c->wakeup_pipe); return c; } @@ -986,19 +978,13 @@ struct mp_cancel *mp_cancel_new(void *talloc_ctx) void mp_cancel_trigger(struct mp_cancel *c) { atomic_store(&c->triggered, true); -#ifdef __MINGW32__ - SetEvent(c->event); -#endif - write(c->wakeup_pipe[1], &(char){0}, 1); + (void)write(c->wakeup_pipe[1], &(char){0}, 1); } // Restore original state. (Allows reusing a mp_cancel.) void mp_cancel_reset(struct mp_cancel *c) { atomic_store(&c->triggered, false); -#ifdef __MINGW32__ - ResetEvent(c->event); -#endif // Flush it fully. while (1) { int r = read(c->wakeup_pipe[0], &(char[256]){0}, 256); @@ -1018,35 +1004,77 @@ bool mp_cancel_test(struct mp_cancel *c) // 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; + struct pollfd fd = { .fd = c->wakeup_pipe[0], .events = POLLIN }; + poll(&fd, 1, timeout * 1000); + return fd.revents & POLLIN; } + +// The FD becomes readable if mp_cancel_test() would return true. +// Don't actually read from it, just use it for poll(). +int mp_cancel_get_fd(struct mp_cancel *c) +{ + return c->wakeup_pipe[0]; +} + #else + +struct mp_cancel { + atomic_bool triggered; + HANDLE event; +}; + +static void cancel_destroy(void *p) +{ + struct mp_cancel *c = p; + CloseHandle(c->event); +} + +struct mp_cancel *mp_cancel_new(void *talloc_ctx) +{ + struct mp_cancel *c = talloc_ptrtype(talloc_ctx, c); + talloc_set_destructor(c, cancel_destroy); + *c = (struct mp_cancel){.triggered = ATOMIC_VAR_INIT(false)}; + c->event = CreateEventW(NULL, TRUE, FALSE, NULL); + return c; +} + +void mp_cancel_trigger(struct mp_cancel *c) +{ + atomic_store(&c->triggered, true); + SetEvent(c->event); +} + +void mp_cancel_reset(struct mp_cancel *c) +{ + atomic_store(&c->triggered, false); + ResetEvent(c->event); +} + +bool mp_cancel_test(struct mp_cancel *c) +{ + return c ? atomic_load_explicit(&c->triggered, memory_order_relaxed) : false; +} + 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; + return WaitForSingleObject(c->event, timeout < 0 ? INFINITE : timeout * 1000) + == WAIT_OBJECT_0; } -#endif -#ifdef __MINGW32__ void *mp_cancel_get_event(struct mp_cancel *c) { return c->event; } -#endif -// The FD becomes readable if mp_cancel_test() would return true. -// Don't actually read from it, just use it for poll(). int mp_cancel_get_fd(struct mp_cancel *c) { - return c->wakeup_pipe[0]; + return -1; } +#endif + char **stream_get_proto_list(void) { char **list = NULL; diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c index 8fadf3452a..1d96ea6029 100644 --- a/stream/stream_cdda.c +++ b/stream/stream_cdda.c @@ -384,6 +384,8 @@ static int open_cdda(stream_t *st) st->control = control; st->close = close_cdda; + st->streaming = true; + st->type = STREAMTYPE_CDDA; st->demuxer = "+disc"; diff --git a/stream/stream_memory.c b/stream/stream_memory.c index 4bcb860c49..84947b5aeb 100644 --- a/stream/stream_memory.c +++ b/stream/stream_memory.c @@ -55,6 +55,32 @@ static int control(stream_t *s, int cmd, void *arg) return STREAM_UNSUPPORTED; } +static int h_to_i(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static bool bstr_to_hex_inplace(bstr *h) +{ + if (h->len % 2) + return false; + for (int n = 0; n < h->len / 2; n++) { + int hi = h_to_i(h->start[n * 2 + 0]); + int lo = h_to_i(h->start[n * 2 + 1]); + if (hi < 0 || lo < 0) + return false; + h->start[n] = (hi << 4) | lo; + } + h->len /= 2; + return true; +} + static int open_f(stream_t *stream) { stream->fill_buffer = fill_buffer; @@ -68,14 +94,21 @@ static int open_f(stream_t *stream) // Initial data bstr data = bstr0(stream->url); - bstr_eatstart0(&data, "memory://"); + bool use_hex = bstr_eatstart0(&data, "hex://"); + if (!use_hex) + bstr_eatstart0(&data, "memory://"); stream_control(stream, STREAM_CTRL_SET_CONTENTS, &data); + if (use_hex && !bstr_to_hex_inplace(&p->data)) { + MP_FATAL(stream, "Invalid data.\n"); + return STREAM_ERROR; + } + return STREAM_OK; } const stream_info_t stream_info_memory = { .name = "memory", .open = open_f, - .protocols = (const char*const[]){ "memory", NULL }, + .protocols = (const char*const[]){ "memory", "hex", NULL }, }; |