summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-06-19 16:48:46 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:05 +0200
commite40885d963f8b60d83aa5ea8104985dd20af262f (patch)
tree82c2fd8284e9a81a211dc7755f5e40e97926cd6e /stream
parentde3ecc60cb5ac39e727d8bd1fe4f9e3499f8e672 (diff)
downloadmpv-e40885d963f8b60d83aa5ea8104985dd20af262f.tar.bz2
mpv-e40885d963f8b60d83aa5ea8104985dd20af262f.tar.xz
stream: create memory streams in more straightforward way
Instead of having to rely on the protocol matching, make a function that creates a stream from a stream_info_t directly. Instead of going through a weird indirection with STREAM_CTRL, add a direct argument for non-text arguments to the open callback. Instead of creating a weird dummy mpv_global, just pass an existing one from all callers. (The latter one is just an artifact from the past, where mpv_global wasn't available everywhere.) Actually I just wanted a function that creates a stream without any of that bullshit. This goal was slightly missed, since you still need this heavy "constructor" just to setup a shitty struct with some shitty callbacks.
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c53
-rw-r--r--stream/stream.h13
-rw-r--r--stream/stream_memory.c31
3 files changed, 57 insertions, 40 deletions
diff --git a/stream/stream.c b/stream/stream.c
index b99e7419ae..61dbf8ce6c 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -213,10 +213,12 @@ static void stream_resize_buffer(struct stream *s, int new)
}
}
-static int open_internal(const stream_info_t *sinfo, const char *url, int flags,
- struct mp_cancel *c, struct mpv_global *global,
- struct stream **ret)
+int stream_create_instance(const stream_info_t *sinfo, const char *url, int flags,
+ struct mp_cancel *c, struct mpv_global *global,
+ void *arg, struct stream **ret)
{
+ *ret = NULL;
+
if (!sinfo->is_safe && (flags & STREAM_SAFE_ONLY))
return STREAM_UNSAFE;
if (!sinfo->is_network && (flags & STREAM_NETWORK_ONLY))
@@ -233,7 +235,11 @@ static int open_internal(const stream_info_t *sinfo, const char *url, int flags,
return STREAM_NO_MATCH;
stream_t *s = talloc_zero(NULL, stream_t);
- s->log = mp_log_new(s, global->log, sinfo->name);
+ if (flags & STREAM_SILENT) {
+ s->log = mp_null_log;
+ } else {
+ s->log = mp_log_new(s, global->log, sinfo->name);
+ }
s->info = sinfo;
s->cancel = c;
s->global = global;
@@ -242,21 +248,30 @@ static int open_internal(const stream_info_t *sinfo, const char *url, int flags,
s->is_network = sinfo->is_network;
s->mode = flags & (STREAM_READ | STREAM_WRITE);
- if (global->config) {
- int opt;
- mp_read_option_raw(global, "access-references", &m_option_type_flag, &opt);
- s->access_references = opt;
- }
+ int opt;
+ mp_read_option_raw(global, "access-references", &m_option_type_flag, &opt);
+ s->access_references = opt;
MP_VERBOSE(s, "Opening %s\n", url);
+ if (strlen(url) > INT_MAX / 8) {
+ MP_ERR(s, "URL too large.\n");
+ talloc_free(s);
+ return STREAM_ERROR;
+ }
+
if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
MP_DBG(s, "No write access implemented.\n");
talloc_free(s);
return STREAM_NO_MATCH;
}
- int r = (sinfo->open)(s);
+ int r = STREAM_UNSUPPORTED;
+ if (sinfo->open2) {
+ r = sinfo->open2(s, arg);
+ } else if (!arg) {
+ r = (sinfo->open)(s);
+ }
if (r != STREAM_OK) {
talloc_free(s);
return r;
@@ -286,13 +301,11 @@ struct stream *stream_create(const char *url, int flags,
struct stream *s = NULL;
assert(url);
- if (strlen(url) > INT_MAX / 8)
- goto done;
-
// Open stream proper
bool unsafe = false;
for (int i = 0; stream_list[i]; i++) {
- int r = open_internal(stream_list[i], url, flags, c, global, &s);
+ int r = stream_create_instance(stream_list[i], url, flags, c, global,
+ NULL, &s);
if (r == STREAM_OK)
break;
if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
@@ -617,18 +630,6 @@ void free_stream(stream_t *s)
talloc_free(s);
}
-stream_t *open_memory_stream(void *data, int len)
-{
- assert(len >= 0);
- struct mpv_global *dummy = talloc_zero(NULL, struct mpv_global);
- dummy->log = mp_null_log;
- stream_t *s = stream_open("memory://", dummy);
- MP_HANDLE_OOM(s);
- talloc_steal(s, dummy);
- stream_control(s, STREAM_CTRL_SET_CONTENTS, &(bstr){data, len});
- return s;
-}
-
static uint16_t stream_read_word_endian(stream_t *s, bool big_endian)
{
unsigned int y = stream_read_char(s);
diff --git a/stream/stream.h b/stream/stream.h
index 8bd8ecfc01..4bd6a7b713 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -37,6 +37,7 @@
// flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE)
#define STREAM_SAFE_ONLY 4
#define STREAM_NETWORK_ONLY 8
+#define STREAM_SILENT 16
#define STREAM_UNSAFE -3
#define STREAM_NO_MATCH -2
@@ -47,9 +48,6 @@
enum stream_ctrl {
STREAM_CTRL_GET_SIZE = 1,
- // stream_memory.c
- STREAM_CTRL_SET_CONTENTS,
-
// Certain network protocols
STREAM_CTRL_AVSEEK,
STREAM_CTRL_HAS_AVSEEK,
@@ -72,6 +70,8 @@ typedef struct stream_info_st {
const char *name;
// opts is set from ->opts
int (*open)(struct stream *st);
+ // Alternative to open(). Only either open() or open2() can be set.
+ int (*open2)(struct stream *st, void *arg);
const char *const *protocols;
bool can_write; // correctly checks for READ/WRITE modes
bool is_safe; // opening is no security issue, even with remote provided URLs
@@ -165,15 +165,20 @@ struct bstr stream_read_file(const char *filename, void *talloc_ctx,
struct mpv_global *global, int max_size);
int stream_control(stream_t *s, int cmd, void *arg);
void free_stream(stream_t *s);
+int stream_create_instance(const stream_info_t *sinfo, const char *url, int flags,
+ struct mp_cancel *c, struct mpv_global *global,
+ void *arg, struct stream **ret);
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);
void mp_url_unescape_inplace(char *buf);
char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok);
+// stream_memory.c
+struct stream *stream_memory_open(struct mpv_global *global, void *data, int len);
+
// stream_file.c
char *mp_file_url_to_filename(void *talloc_ctx, bstr url);
char *mp_file_get_path(void *talloc_ctx, bstr url);
diff --git a/stream/stream_memory.c b/stream/stream_memory.c
index 8df043201e..107fa80d19 100644
--- a/stream/stream_memory.c
+++ b/stream/stream_memory.c
@@ -17,6 +17,7 @@
#include <libavutil/common.h>
+#include "common/common.h"
#include "stream.h"
struct priv {
@@ -42,20 +43,14 @@ static int seek(stream_t *s, int64_t newpos)
static int control(stream_t *s, int cmd, void *arg)
{
struct priv *p = s->priv;
- switch(cmd) {
- case STREAM_CTRL_GET_SIZE:
+ if (cmd == STREAM_CTRL_GET_SIZE) {
*(int64_t *)arg = p->data.len;
return 1;
- case STREAM_CTRL_SET_CONTENTS: ;
- bstr *data = (bstr *)arg;
- talloc_free(p->data.start);
- p->data = bstrdup(s, *data);
- return 1;
}
return STREAM_UNSUPPORTED;
}
-static int open_f(stream_t *stream)
+static int open2(stream_t *stream, void *arg)
{
stream->fill_buffer = fill_buffer;
stream->seek = seek;
@@ -71,7 +66,11 @@ static int open_f(stream_t *stream)
bool use_hex = bstr_eatstart0(&data, "hex://");
if (!use_hex)
bstr_eatstart0(&data, "memory://");
- stream_control(stream, STREAM_CTRL_SET_CONTENTS, &data);
+
+ if (arg)
+ data = *(bstr *)arg;
+
+ p->data = bstrdup(stream, data);
if (use_hex && !bstr_decode_hex(stream, p->data, &p->data)) {
MP_FATAL(stream, "Invalid data.\n");
@@ -83,6 +82,18 @@ static int open_f(stream_t *stream)
const stream_info_t stream_info_memory = {
.name = "memory",
- .open = open_f,
+ .open2 = open2,
.protocols = (const char*const[]){ "memory", "hex", NULL },
};
+
+struct stream *stream_memory_open(struct mpv_global *global, void *data, int len)
+{
+ assert(len >= 0);
+
+ struct stream *s = NULL;
+ stream_create_instance(&stream_info_memory, "memory://",
+ STREAM_READ | STREAM_SILENT, NULL, global,
+ &(bstr){data, len}, &s);
+ MP_HANDLE_OOM(s);
+ return s;
+}