summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c129
-rw-r--r--stream/stream.h9
2 files changed, 83 insertions, 55 deletions
diff --git a/stream/stream.c b/stream/stream.c
index e1b8efee83..474e46d96a 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -76,7 +76,7 @@ extern const stream_info_t stream_info_ifo;
extern const stream_info_t stream_info_dvd;
extern const stream_info_t stream_info_bluray;
-static const stream_info_t *const auto_open_streams[] = {
+static const stream_info_t *const stream_list[] = {
#ifdef CONFIG_VCD
&stream_info_vcd,
#endif
@@ -210,15 +210,48 @@ static stream_t *new_stream(void)
return s;
}
-static stream_t *open_stream_plugin(const stream_info_t *sinfo,
- const char *url, const char *path, int mode,
- struct MPOpts *options, int *ret)
+static const char *match_proto(const char *url, const char *proto)
+{
+ int l = strlen(proto);
+ if (l > 0) {
+ if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
+ return url + l + 3;
+ } else {
+ // pure filenames (including "/path" and "./path")
+ if (url[0] == '/' || url[0] == '.' || !strstr(url, "://"))
+ return url;
+ }
+ return NULL;
+}
+
+static int open_internal(const stream_info_t *sinfo, struct stream *underlying,
+ const char *url, int flags, struct MPOpts *options,
+ struct stream **ret)
{
+ if (sinfo->stream_filter != !!underlying)
+ return STREAM_NO_MATCH;
+ if (sinfo->stream_filter && (flags & STREAM_NO_FILTERS))
+ return STREAM_NO_MATCH;
+
+ const char *path = NULL;
+ // Stream filters use the original URL, with no protocol matching at all.
+ if (!sinfo->stream_filter) {
+ for (int n = 0; sinfo->protocols && sinfo->protocols[n]; n++) {
+ path = match_proto(url, sinfo->protocols[n]);
+ if (path)
+ break;
+ }
+
+ if (!path)
+ return STREAM_NO_MATCH;
+ }
+
stream_t *s = new_stream();
s->info = sinfo;
s->opts = options;
s->url = talloc_strdup(s, url);
s->path = talloc_strdup(s, path);
+ s->source = underlying;
// Parse options
if (sinfo->priv_size) {
@@ -232,17 +265,16 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
if (s->info->url_options && !parse_url(s, config)) {
mp_tmsg(MSGT_OPEN, MSGL_ERR, "URL parsing failed on url %s\n", url);
talloc_free(s);
- *ret = STREAM_ERROR;
- return NULL;
+ return STREAM_ERROR;
}
}
s->flags = 0;
- s->mode = mode;
- *ret = sinfo->open(s, mode);
- if ((*ret) != STREAM_OK) {
+ s->mode = flags & (STREAM_READ | STREAM_WRITE);
+ int r = sinfo->open(s, s->mode);
+ if (r != STREAM_OK) {
talloc_free(s);
- return NULL;
+ return r;
}
if (!s->read_chunk)
@@ -256,8 +288,6 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
if (s->flags & MP_STREAM_FAST_SKIPPING)
s->flags |= MP_STREAM_SEEK_FW;
- s->mode = mode;
-
s->uncached_type = s->type;
mp_msg(MSGT_OPEN, MSGL_V, "[stream] [%s] %s\n", sinfo->name, url);
@@ -265,67 +295,57 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
if (s->mime_type)
mp_msg(MSGT_OPEN, MSGL_V, "Mime-type: '%s'\n", s->mime_type);
- return s;
+ *ret = s;
+ return STREAM_OK;
}
-static const char *match_proto(const char *url, const char *proto)
+struct stream *stream_create(const char *url, int flags, struct MPOpts *options)
{
- int l = strlen(proto);
- if (l > 0) {
- if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
- return url + l + 3;
- } else {
- // pure filenames
- if (!strstr(url, "://"))
- return url;
- }
- return NULL;
-}
-
-static stream_t *open_stream_full(const char *url, int mode,
- struct MPOpts *options)
-{
- int i, j, r;
- const stream_info_t *sinfo;
- stream_t *s;
-
+ struct stream *s = NULL;
assert(url);
- for (i = 0; auto_open_streams[i]; i++) {
- sinfo = auto_open_streams[i];
- if (!sinfo->protocols) {
- mp_msg(MSGT_OPEN, MSGL_WARN,
- "Stream type %s has protocols == NULL, it's a bug\n",
- sinfo->name);
+ // Open stream proper
+ for (int i = 0; stream_list[i]; i++) {
+ int r = open_internal(stream_list[i], NULL, url, flags, options, &s);
+ if (r == STREAM_OK)
+ break;
+ if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
continue;
+ if (r != STREAM_OK) {
+ mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s.\n", url);
+ return NULL;
}
- for (j = 0; sinfo->protocols[j]; j++) {
- const char *path = match_proto(url, sinfo->protocols[j]);
- if (path) {
- s = open_stream_plugin(sinfo, url, path, mode, options, &r);
- if (s)
- return s;
- if (r != STREAM_UNSUPPORTED) {
- mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s.\n", url);
- return NULL;
- }
+ }
+
+ if (!s) {
+ mp_tmsg(MSGT_OPEN, MSGL_ERR, "No stream found to handle url %s\n", url);
+ return NULL;
+ }
+
+ // Open stream filters
+ for (;;) {
+ struct stream *new = NULL;
+ for (int i = 0; stream_list[i]; i++) {
+ int r = open_internal(stream_list[i], s, s->url, flags, options, &new);
+ if (r == STREAM_OK)
break;
- }
}
+ if (!new)
+ break;
+ s = new;
}
- mp_tmsg(MSGT_OPEN, MSGL_ERR, "No stream found to handle url %s\n", url);
- return NULL;
+ return s;
}
struct stream *stream_open(const char *filename, struct MPOpts *options)
{
- return open_stream_full(filename, STREAM_READ, options);
+ return stream_create(filename, STREAM_READ, options);
}
stream_t *open_output_stream(const char *filename, struct MPOpts *options)
{
- return open_stream_full(filename, STREAM_WRITE, options);
+ return stream_create(filename, STREAM_WRITE, options);
}
static int stream_reconnect(stream_t *s)
@@ -673,6 +693,7 @@ void free_stream(stream_t *s)
if (s->close)
s->close(s);
free_stream(s->uncached_stream);
+ free_stream(s->source);
talloc_free(s);
}
diff --git a/stream/stream.h b/stream/stream.h
index 1009a2a7b0..6f389ceb04 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -57,12 +57,16 @@ enum streamtype {
#define STREAM_READ 0
#define STREAM_WRITE 1
+// flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE)
+#define STREAM_NO_FILTERS 2
+
// stream->flags
#define MP_STREAM_FAST_SKIPPING 1 // allow forward seeks by skipping
#define MP_STREAM_SEEK_BW 2
#define MP_STREAM_SEEK_FW 4
#define MP_STREAM_SEEK (MP_STREAM_SEEK_BW | MP_STREAM_SEEK_FW)
+#define STREAM_NO_MATCH -2
#define STREAM_UNSUPPORTED -1
#define STREAM_ERROR 0
#define STREAM_OK 1
@@ -116,6 +120,7 @@ typedef struct stream_info_st {
const void *priv_defaults;
const struct m_option *options;
const char **url_options;
+ bool stream_filter;
} stream_info_t;
typedef struct stream {
@@ -156,7 +161,8 @@ typedef struct stream {
FILE *capture_file;
char *capture_filename;
- struct stream *uncached_stream;
+ struct stream *uncached_stream; // underlying stream for cache wrapper
+ struct stream *source;
// Includes additional padding in case sizes get rounded up by sector size.
unsigned char buffer[];
@@ -234,6 +240,7 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx,
int stream_control(stream_t *s, int cmd, void *arg);
void stream_update_size(stream_t *s);
void free_stream(stream_t *s);
+struct stream *stream_create(const char *url, int flags, struct MPOpts *options);
struct stream *stream_open(const char *filename, struct MPOpts *options);
stream_t *open_output_stream(const char *filename, struct MPOpts *options);
stream_t *open_memory_stream(void *data, int len);