urlprotocol: receive a list of protocols from the caller

This way, the decisions about which protocols are available for use in
any given situations can be delegated to the caller.
This commit is contained in:
Anton Khirnov 2016-02-19 18:02:45 +01:00
parent cae448cfbf
commit 8c0ceafb0f
24 changed files with 162 additions and 54 deletions

View File

@ -62,7 +62,8 @@ const AVClass ffurl_context_class = {
static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
const char *filename, int flags,
const AVIOInterruptCB *int_cb)
const AVIOInterruptCB *int_cb,
const URLProtocol **protocols)
{
URLContext *uc;
int err;
@ -83,6 +84,7 @@ static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
uc->flags = flags;
uc->is_streamed = 0; /* default = not streamed */
uc->max_packet_size = 0; /* default: stream file */
uc->protocols = protocols;
if (up->priv_data_size) {
uc->priv_data = av_mallocz(up->priv_data_size);
if (!uc->priv_data) {
@ -136,9 +138,9 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
"0123456789+-."
int ffurl_alloc(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb)
const AVIOInterruptCB *int_cb,
const URLProtocol **protocols)
{
const URLProtocol **protocols;
char proto_str[128], proto_nested[128], *ptr;
size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
int i;
@ -153,27 +155,25 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
if ((ptr = strchr(proto_nested, '+')))
*ptr = '\0';
protocols = ffurl_get_protocols(NULL, NULL);
for (i = 0; protocols[i]; i++) {
const URLProtocol *up = protocols[i];
if (!strcmp(proto_str, up->name)) {
av_freep(&protocols);
return url_alloc_for_protocol(puc, up, filename, flags, int_cb);
}
if (!strcmp(proto_str, up->name))
return url_alloc_for_protocol(puc, up, filename, flags, int_cb,
protocols);
if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
!strcmp(proto_nested, up->name)) {
av_freep(&protocols);
return url_alloc_for_protocol(puc, up, filename, flags, int_cb);
}
!strcmp(proto_nested, up->name))
return url_alloc_for_protocol(puc, up, filename, flags, int_cb,
protocols);
}
*puc = NULL;
return AVERROR_PROTOCOL_NOT_FOUND;
}
int ffurl_open(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options)
const AVIOInterruptCB *int_cb, AVDictionary **options,
const URLProtocol **protocols)
{
int ret = ffurl_alloc(puc, filename, flags, int_cb);
int ret = ffurl_alloc(puc, filename, flags, int_cb, protocols);
if (ret)
return ret;
if (options && (*puc)->prot->priv_data_class &&
@ -281,10 +281,19 @@ int ffurl_close(URLContext *h)
int avio_check(const char *url, int flags)
{
const URLProtocol **protocols;
URLContext *h;
int ret = ffurl_alloc(&h, url, flags, NULL);
if (ret)
int ret;
protocols = ffurl_get_protocols(NULL, NULL);
if (!protocols)
return AVERROR(ENOMEM);
ret = ffurl_alloc(&h, url, flags, NULL, protocols);
if (ret) {
av_freep(&protocols);
return ret;
}
if (h->prot->url_check) {
ret = h->prot->url_check(h, flags);
@ -295,6 +304,7 @@ int avio_check(const char *url, int flags)
}
ffurl_close(h);
av_freep(&protocols);
return ret;
}

View File

@ -42,6 +42,7 @@
typedef struct AVIOInternal {
URLContext *h;
const URLProtocol **protocols;
} AVIOInternal;
static void *ff_avio_child_next(void *obj, void *prev)
@ -846,17 +847,31 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
int avio_open2(AVIOContext **s, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options)
{
AVIOInternal *internal;
const URLProtocol **protocols;
URLContext *h;
int err;
err = ffurl_open(&h, filename, flags, int_cb, options);
if (err < 0)
protocols = ffurl_get_protocols(NULL, NULL);
if (!protocols)
return AVERROR(ENOMEM);
err = ffurl_open(&h, filename, flags, int_cb, options, protocols);
if (err < 0) {
av_freep(&protocols);
return err;
}
err = ffio_fdopen(s, h);
if (err < 0) {
ffurl_close(h);
av_freep(&protocols);
return err;
}
internal = (*s)->opaque;
internal->protocols = protocols;
return 0;
}
@ -872,6 +887,7 @@ int avio_close(AVIOContext *s)
internal = s->opaque;
h = internal->h;
av_freep(&internal->protocols);
av_freep(&s->opaque);
av_freep(&s->buffer);
av_free(s);

View File

@ -95,7 +95,7 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
/* creating URLContext */
if ((err = ffurl_open(&uc, node_uri, flags,
&h->interrupt_callback, NULL)) < 0)
&h->interrupt_callback, NULL, h->protocols)) < 0)
break;
/* creating size */

View File

@ -83,7 +83,7 @@ static int crypto_open(URLContext *h, const char *uri, int flags)
goto err;
}
if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ,
&h->interrupt_callback, NULL)) < 0) {
&h->interrupt_callback, NULL, h->protocols)) < 0) {
av_log(h, AV_LOG_ERROR, "Unable to open input\n");
goto err;
}

View File

@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
s->hd = NULL;
err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL);
&h->interrupt_callback, NULL, h->protocols);
if (err < 0)
goto fail;

View File

@ -304,7 +304,7 @@ retry:
url = s->segments[s->cur_seq_no - s->start_seq_no]->url,
av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ,
&h->interrupt_callback, NULL);
&h->interrupt_callback, NULL, h->protocols);
if (ret < 0) {
if (ff_check_interrupt(&h->interrupt_callback))
return AVERROR_EXIT;

View File

@ -181,7 +181,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
if (!s->hd) {
err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, options);
&h->interrupt_callback, options, h->protocols);
if (err < 0)
return err;
}
@ -1079,7 +1079,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
NULL);
redo:
ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL);
&h->interrupt_callback, NULL, h->protocols);
if (ret < 0)
return ret;

View File

@ -176,7 +176,8 @@ static int icecast_open(URLContext *h, const char *uri, int flags)
// Build new URI for passing to http protocol
ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
// Finally open http proto handler
ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict);
ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict,
h->protocols);
cleanup:
// Free variables

View File

@ -70,7 +70,8 @@ static int md5_close(URLContext *h)
if (*filename) {
err = ffurl_open(&out, filename, AVIO_FLAG_WRITE,
&h->interrupt_callback, NULL);
&h->interrupt_callback, NULL,
h->protocols);
if (err)
return err;
err = ffurl_write(out, buf, i*2+1);

View File

@ -230,7 +230,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path);
if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
&h->interrupt_callback) < 0) {
&h->interrupt_callback, h->protocols) < 0) {
return AVERROR(EIO);
}
@ -259,7 +259,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
ffurl_close(mms->mms_hd);
memset(headers, 0, sizeof(headers));
if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
&h->interrupt_callback)) < 0) {
&h->interrupt_callback, h->protocols)) < 0) {
goto fail;
}
stream_selection = av_mallocz(mms->stream_num * 19 + 1);

View File

@ -520,7 +520,7 @@ static int mms_open(URLContext *h, const char *uri, int flags)
// establish tcp connection.
ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL);
&h->interrupt_callback, NULL, h->protocols);
if (err)
goto fail;

View File

@ -265,7 +265,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags)
/* open the tcp or ffrtmphttp connection */
if ((ret = ffurl_open(&rt->stream, url, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL)) < 0) {
&h->interrupt_callback, NULL, h->protocols)) < 0) {
rtmpe_close(h);
return ret;
}

View File

@ -208,7 +208,7 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags)
}
/* alloc the http context */
if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL)) < 0)
if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL, h->protocols)) < 0)
goto fail;
/* set options */

View File

@ -1119,7 +1119,7 @@ static int rtmp_calc_swfhash(URLContext *s)
/* Get the SWF player file. */
if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
&s->interrupt_callback, NULL)) < 0) {
&s->interrupt_callback, NULL, s->protocols)) < 0) {
av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
goto fail;
}
@ -2641,7 +2641,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
reconnect:
if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, &opts)) < 0) {
&s->interrupt_callback, &opts, s->protocols)) < 0) {
av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
goto fail;
}

View File

@ -368,14 +368,16 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
build_udp_url(s, buf, sizeof(buf),
hostname, rtp_port, s->local_rtpport, sources, block);
if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL,
h->protocols) < 0)
goto fail;
if (s->local_rtpport >= 0 && s->local_rtcpport < 0)
s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1;
build_udp_url(s, buf, sizeof(buf),
hostname, s->rtcp_port, s->local_rtcpport, sources, block);
if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL,
h->protocols) < 0)
goto fail;
/* just to ease handle access. XXX: need to suppress direct handle

View File

@ -777,6 +777,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
}
if (CONFIG_RTPDEC && rt->ts)
ff_mpegts_parse_close(rt->ts);
av_freep(&rt->protocols);
av_free(rt->p);
av_free(rt->recvbuf);
}
@ -1465,7 +1466,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
/* we will use two ports per rtp stream (rtp and rtcp) */
j += 2;
err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, &opts);
&s->interrupt_callback, &opts, rt->protocols);
av_dict_free(&opts);
@ -1609,7 +1610,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
port, "%s", optbuf);
if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, NULL) < 0) {
&s->interrupt_callback, NULL, rt->protocols) < 0) {
err = AVERROR_INVALIDDATA;
goto fail;
}
@ -1666,6 +1667,12 @@ int ff_rtsp_connect(AVFormatContext *s)
if (!ff_network_init())
return AVERROR(EIO);
if (!rt->protocols) {
rt->protocols = ffurl_get_protocols(NULL, NULL);
if (!rt->protocols)
return AVERROR(ENOMEM);
}
if (s->max_delay < 0) /* Not set by the caller */
s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0;
@ -1729,7 +1736,7 @@ redirect:
/* GET requests */
if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ,
&s->interrupt_callback) < 0) {
&s->interrupt_callback, rt->protocols) < 0) {
err = AVERROR(EIO);
goto fail;
}
@ -1751,7 +1758,7 @@ redirect:
/* POST requests */
if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE,
&s->interrupt_callback) < 0 ) {
&s->interrupt_callback, rt->protocols) < 0 ) {
err = AVERROR(EIO);
goto fail;
}
@ -1796,7 +1803,7 @@ redirect:
ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
host, port, NULL);
if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, NULL) < 0) {
&s->interrupt_callback, NULL, rt->protocols) < 0) {
err = AVERROR(EIO);
goto fail;
}
@ -2244,6 +2251,12 @@ static int sdp_read_header(AVFormatContext *s)
if (!ff_network_init())
return AVERROR(EIO);
if (!rt->protocols) {
rt->protocols = ffurl_get_protocols(NULL, NULL);
if (!rt->protocols)
return AVERROR(ENOMEM);
}
if (s->max_delay < 0) /* Not set by the caller */
s->max_delay = DEFAULT_REORDERING_DELAY;
if (rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)
@ -2296,7 +2309,7 @@ static int sdp_read_header(AVFormatContext *s)
rtsp_st->nb_exclude_source_addrs,
rtsp_st->exclude_source_addrs);
err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, &opts);
&s->interrupt_callback, &opts, rt->protocols);
av_dict_free(&opts);
@ -2365,8 +2378,14 @@ static int rtp_read_header(AVFormatContext *s)
if (!ff_network_init())
return AVERROR(EIO);
if (!rt->protocols) {
rt->protocols = ffurl_get_protocols(NULL, NULL);
if (!rt->protocols)
return AVERROR(ENOMEM);
}
ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
&s->interrupt_callback, NULL);
&s->interrupt_callback, NULL, rt->protocols);
if (ret)
goto fail;

View File

@ -398,6 +398,8 @@ typedef struct RTSPState {
char default_lang[4];
int buffer_size;
const URLProtocol **protocols;
} RTSPState;
#define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets -

View File

@ -295,7 +295,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL);
av_log(s, AV_LOG_TRACE, "Opening: %s", url);
ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, &opts);
&s->interrupt_callback, &opts, rt->protocols);
av_dict_free(&opts);
if (ret)
localport += 2;
@ -639,6 +639,12 @@ static int rtsp_listen(AVFormatContext *s)
int ret;
enum RTSPMethod methodcode;
if (!rt->protocols) {
rt->protocols = ffurl_get_protocols(NULL, NULL);
if (!rt->protocols)
return AVERROR(ENOMEM);
}
/* extract hostname and port */
av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host),
&port, path, sizeof(path), s->filename);
@ -660,7 +666,7 @@ static int rtsp_listen(AVFormatContext *s)
"?listen&listen_timeout=%d", rt->initial_timeout * 1000);
if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
&s->interrupt_callback, NULL)) {
&s->interrupt_callback, NULL, rt->protocols)) {
av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
return ret;
}

View File

@ -39,6 +39,8 @@ struct SAPState {
uint16_t hash;
char *sdp;
int eof;
const URLProtocol **protocols;
};
static int sap_probe(AVProbeData *p)
@ -55,6 +57,7 @@ static int sap_read_close(AVFormatContext *s)
avformat_close_input(&sap->sdp_ctx);
if (sap->ann_fd)
ffurl_close(sap->ann_fd);
av_freep(&sap->protocols);
av_freep(&sap->sdp);
ff_network_close();
return 0;
@ -82,10 +85,16 @@ static int sap_read_header(AVFormatContext *s)
av_strlcpy(host, "224.2.127.254", sizeof(host));
}
sap->protocols = ffurl_get_protocols(NULL, NULL);
if (!sap->protocols) {
ret = AVERROR(ENOMEM);
goto fail;
}
ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d",
port);
ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ,
&s->interrupt_callback, NULL);
&s->interrupt_callback, NULL, sap->protocols);
if (ret)
goto fail;

View File

@ -37,6 +37,8 @@ struct SAPState {
int ann_size;
URLContext *ann_fd;
int64_t last_time;
const URLProtocol **protocols;
};
static int sap_write_close(AVFormatContext *s)
@ -59,6 +61,8 @@ static int sap_write_close(AVFormatContext *s)
ffurl_write(sap->ann_fd, sap->ann, sap->ann_size);
}
av_freep(&sap->protocols);
av_freep(&sap->ann);
if (sap->ann_fd)
ffurl_close(sap->ann_fd);
@ -134,6 +138,12 @@ static int sap_write_header(AVFormatContext *s)
freeaddrinfo(ai);
}
sap->protocols = ffurl_get_protocols(NULL, NULL);
if (!sap->protocols) {
ret = AVERROR(ENOMEM);
goto fail;
}
contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams);
if (!contexts) {
ret = AVERROR(ENOMEM);
@ -148,7 +158,8 @@ static int sap_write_header(AVFormatContext *s)
"?ttl=%d", ttl);
if (!same_port)
base_port += 2;
ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL,
sap->protocols);
if (ret) {
ret = AVERROR(EIO);
goto fail;
@ -167,7 +178,7 @@ static int sap_write_header(AVFormatContext *s)
ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port,
"?ttl=%d&connect=1", ttl);
ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL);
&s->interrupt_callback, NULL, sap->protocols);
if (ret) {
ret = AVERROR(EIO);
goto fail;

View File

@ -64,6 +64,8 @@ typedef struct OutputStream {
char *private_str;
int packet_size;
int audio_tag;
const URLProtocol **protocols;
} OutputStream;
typedef struct SmoothStreamingContext {
@ -76,6 +78,8 @@ typedef struct SmoothStreamingContext {
OutputStream *streams;
int has_video, has_audio;
int nb_fragments;
const URLProtocol **protocols;
} SmoothStreamingContext;
static int ism_write(void *opaque, uint8_t *buf, int buf_size)
@ -121,7 +125,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
AVDictionary *opts = NULL;
os->tail_out = os->out;
av_dict_set(&opts, "truncate", "0", 0);
ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts);
ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts,
os->protocols);
av_dict_free(&opts);
if (ret < 0) {
os->out = os->tail_out;
@ -129,7 +134,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
return ret;
}
av_dict_set(&opts, "truncate", "0", 0);
ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts);
ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts,
os->protocols);
av_dict_free(&opts);
ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
if (os->out2)
@ -168,6 +174,9 @@ static void ism_free(AVFormatContext *s)
{
SmoothStreamingContext *c = s->priv_data;
int i, j;
av_freep(&c->protocols);
if (!c->streams)
return;
for (i = 0; i < s->nb_streams; i++) {
@ -303,6 +312,12 @@ static int ism_write_header(AVFormatContext *s)
goto fail;
}
c->protocols = ffurl_get_protocols(NULL, NULL);
if (!c->protocols) {
ret = AVERROR(ENOMEM);
goto fail;
}
c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
if (!c->streams) {
ret = AVERROR(ENOMEM);
@ -327,6 +342,8 @@ static int ism_write_header(AVFormatContext *s)
goto fail;
}
os->protocols = c->protocols;
ctx = avformat_alloc_context();
if (!ctx) {
ret = AVERROR(ENOMEM);
@ -523,7 +540,8 @@ static int ism_flush(AVFormatContext *s, int final)
continue;
snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL,
c->protocols);
if (ret < 0)
break;
os->cur_start_pos = os->tail_pos;

View File

@ -80,7 +80,8 @@ static int srtp_open(URLContext *h, const char *uri, int flags)
av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
path, sizeof(path), uri);
ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path);
if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL)) < 0)
if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL,
h->protocols)) < 0)
goto fail;
h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size,

View File

@ -76,5 +76,5 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
}
return ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
&parent->interrupt_callback, options);
&parent->interrupt_callback, options, parent->protocols);
}

View File

@ -38,6 +38,10 @@ extern const AVClass ffurl_context_class;
typedef struct URLContext {
const AVClass *av_class; /**< information for av_log(). Set by url_open(). */
const struct URLProtocol *prot;
/**
* A NULL-terminated list of protocols usable by the child contexts.
*/
const struct URLProtocol **protocols;
void *priv_data;
char *filename; /**< specified URL */
int flags;
@ -96,11 +100,15 @@ typedef struct URLProtocol {
* is to be opened
* @param int_cb interrupt callback to use for the URLContext, may be
* NULL
* @param protocols a NULL-terminate list of protocols available for use by
* this context and its children. The caller must ensure this
* list remains valid until the context is closed.
* @return 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int ffurl_alloc(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb);
const AVIOInterruptCB *int_cb,
const URLProtocol **protocols);
/**
* Connect an URLContext that has been allocated by ffurl_alloc
@ -125,11 +133,15 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
* @param options A dictionary filled with protocol-private options. On return
* this parameter will be destroyed and replaced with a dict containing options
* that were not found. May be NULL.
* @param protocols a NULL-terminate list of protocols available for use by
* this context and its children. The caller must ensure this
* list remains valid until the context is closed.
* @return 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int ffurl_open(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options);
const AVIOInterruptCB *int_cb, AVDictionary **options,
const URLProtocol **protocols);
/**
* Read up to size bytes from the resource accessed by h, and store