#include "config.h" #include #include #include #include #include #include #include "osdep/io.h" #include "common/common.h" #include "common/msg.h" #include "common/global.h" #include "stream.h" #include "options/m_option.h" #include "options/path.h" #include "player/client.h" #include "libmpv/stream_cb.h" struct priv { mpv_stream_cb_info info; }; static int fill_buffer(stream_t *s, char *buffer, int max_len) { struct priv *p = s->priv; return (int)p->info.read_fn(p->info.cookie, buffer, (size_t)max_len); } static int seek(stream_t *s, int64_t newpos) { struct priv *p = s->priv; return p->info.seek_fn(p->info.cookie, newpos) >= 0; } static int control(stream_t *s, int cmd, void *arg) { struct priv *p = s->priv; switch (cmd) { case STREAM_CTRL_GET_SIZE: { if (!p->info.size_fn) break; int64_t size = p->info.size_fn(p->info.cookie); if (size >= 0) { *(int64_t *)arg = size; return 1; } break; } } return STREAM_UNSUPPORTED; } static void s_close(stream_t *s) { struct priv *p = s->priv; p->info.close_fn(p->info.cookie); } static int open_cb(stream_t *stream) { struct priv *p = talloc_ptrtype(stream, p); stream->priv = p; bstr bproto = mp_split_proto(bstr0(stream->url), NULL); char *proto = bstrto0(stream, bproto); void *user_data; mpv_stream_cb_open_ro_fn open_fn; if (!mp_streamcb_lookup(stream->global, proto, &user_data, &open_fn)) return STREAM_UNSUPPORTED; mpv_stream_cb_info info = {0}; int r = open_fn(user_data, stream->url, &info); if (r < 0) { if (r != MPV_ERROR_LOADING_FAILED) MP_WARN(stream, "unknown error from user callback\n"); return STREAM_ERROR; } if (!info.read_fn || !info.close_fn) { MP_FATAL(stream, "required read_fn or close_fn callbacks not set.\n"); return STREAM_ERROR; } p->info = info; if (p->info.seek_fn && p->info.seek_fn(p->info.cookie, 0) >= 0) { stream->seek = seek; stream->seekable = true; } stream->fast_skip = true; stream->fill_buffer = fill_buffer; stream->control = control; stream->read_chunk = 64 * 1024; stream->close = s_close; return STREAM_OK; } const stream_info_t stream_info_cb = { .name = "stream_callback", .open = open_cb, };