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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -181,7 +181,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
if (!s->hd) { if (!s->hd) {
err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, options); &h->interrupt_callback, options, h->protocols);
if (err < 0) if (err < 0)
return err; return err;
} }
@ -1079,7 +1079,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
NULL); NULL);
redo: redo:
ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL); &h->interrupt_callback, NULL, h->protocols);
if (ret < 0) if (ret < 0)
return ret; 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 // Build new URI for passing to http protocol
ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path); ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
// Finally open http proto handler // 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: cleanup:
// Free variables // Free variables

View File

@ -70,7 +70,8 @@ static int md5_close(URLContext *h)
if (*filename) { if (*filename) {
err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, err = ffurl_open(&out, filename, AVIO_FLAG_WRITE,
&h->interrupt_callback, NULL); &h->interrupt_callback, NULL,
h->protocols);
if (err) if (err)
return err; return err;
err = ffurl_write(out, buf, i*2+1); 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); ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path);
if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
&h->interrupt_callback) < 0) { &h->interrupt_callback, h->protocols) < 0) {
return AVERROR(EIO); return AVERROR(EIO);
} }
@ -259,7 +259,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
ffurl_close(mms->mms_hd); ffurl_close(mms->mms_hd);
memset(headers, 0, sizeof(headers)); memset(headers, 0, sizeof(headers));
if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
&h->interrupt_callback)) < 0) { &h->interrupt_callback, h->protocols)) < 0) {
goto fail; goto fail;
} }
stream_selection = av_mallocz(mms->stream_num * 19 + 1); 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. // establish tcp connection.
ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE, err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
&h->interrupt_callback, NULL); &h->interrupt_callback, NULL, h->protocols);
if (err) if (err)
goto fail; 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 */ /* open the tcp or ffrtmphttp connection */
if ((ret = ffurl_open(&rt->stream, url, AVIO_FLAG_READ_WRITE, 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); rtmpe_close(h);
return ret; return ret;
} }

View File

@ -208,7 +208,7 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags)
} }
/* alloc the http context */ /* 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; goto fail;
/* set options */ /* set options */

View File

@ -1119,7 +1119,7 @@ static int rtmp_calc_swfhash(URLContext *s)
/* Get the SWF player file. */ /* Get the SWF player file. */
if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ, 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); av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
goto fail; goto fail;
} }
@ -2641,7 +2641,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
reconnect: reconnect:
if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE, 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); av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
goto fail; 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), build_udp_url(s, buf, sizeof(buf),
hostname, rtp_port, s->local_rtpport, sources, block); 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; goto fail;
if (s->local_rtpport >= 0 && s->local_rtcpport < 0) if (s->local_rtpport >= 0 && s->local_rtcpport < 0)
s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1; s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1;
build_udp_url(s, buf, sizeof(buf), build_udp_url(s, buf, sizeof(buf),
hostname, s->rtcp_port, s->local_rtcpport, sources, block); 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; goto fail;
/* just to ease handle access. XXX: need to suppress direct handle /* 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) if (CONFIG_RTPDEC && rt->ts)
ff_mpegts_parse_close(rt->ts); ff_mpegts_parse_close(rt->ts);
av_freep(&rt->protocols);
av_free(rt->p); av_free(rt->p);
av_free(rt->recvbuf); 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) */ /* we will use two ports per rtp stream (rtp and rtcp) */
j += 2; j += 2;
err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, 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); 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, ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
port, "%s", optbuf); port, "%s", optbuf);
if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, 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; err = AVERROR_INVALIDDATA;
goto fail; goto fail;
} }
@ -1666,6 +1667,12 @@ int ff_rtsp_connect(AVFormatContext *s)
if (!ff_network_init()) if (!ff_network_init())
return AVERROR(EIO); 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 */ if (s->max_delay < 0) /* Not set by the caller */
s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0; s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0;
@ -1729,7 +1736,7 @@ redirect:
/* GET requests */ /* GET requests */
if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ, if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ,
&s->interrupt_callback) < 0) { &s->interrupt_callback, rt->protocols) < 0) {
err = AVERROR(EIO); err = AVERROR(EIO);
goto fail; goto fail;
} }
@ -1751,7 +1758,7 @@ redirect:
/* POST requests */ /* POST requests */
if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE, if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE,
&s->interrupt_callback) < 0 ) { &s->interrupt_callback, rt->protocols) < 0 ) {
err = AVERROR(EIO); err = AVERROR(EIO);
goto fail; goto fail;
} }
@ -1796,7 +1803,7 @@ redirect:
ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL, ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL,
host, port, NULL); host, port, NULL);
if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, 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); err = AVERROR(EIO);
goto fail; goto fail;
} }
@ -2244,6 +2251,12 @@ static int sdp_read_header(AVFormatContext *s)
if (!ff_network_init()) if (!ff_network_init())
return AVERROR(EIO); 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 */ if (s->max_delay < 0) /* Not set by the caller */
s->max_delay = DEFAULT_REORDERING_DELAY; s->max_delay = DEFAULT_REORDERING_DELAY;
if (rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO) 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->nb_exclude_source_addrs,
rtsp_st->exclude_source_addrs); rtsp_st->exclude_source_addrs);
err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, 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); av_dict_free(&opts);
@ -2365,8 +2378,14 @@ static int rtp_read_header(AVFormatContext *s)
if (!ff_network_init()) if (!ff_network_init())
return AVERROR(EIO); 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, ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
&s->interrupt_callback, NULL); &s->interrupt_callback, NULL, rt->protocols);
if (ret) if (ret)
goto fail; goto fail;

View File

@ -398,6 +398,8 @@ typedef struct RTSPState {
char default_lang[4]; char default_lang[4];
int buffer_size; int buffer_size;
const URLProtocol **protocols;
} RTSPState; } RTSPState;
#define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - #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); ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL);
av_log(s, AV_LOG_TRACE, "Opening: %s", url); av_log(s, AV_LOG_TRACE, "Opening: %s", url);
ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, 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); av_dict_free(&opts);
if (ret) if (ret)
localport += 2; localport += 2;
@ -639,6 +639,12 @@ static int rtsp_listen(AVFormatContext *s)
int ret; int ret;
enum RTSPMethod methodcode; enum RTSPMethod methodcode;
if (!rt->protocols) {
rt->protocols = ffurl_get_protocols(NULL, NULL);
if (!rt->protocols)
return AVERROR(ENOMEM);
}
/* extract hostname and port */ /* extract hostname and port */
av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host),
&port, path, sizeof(path), s->filename); &port, path, sizeof(path), s->filename);
@ -660,7 +666,7 @@ static int rtsp_listen(AVFormatContext *s)
"?listen&listen_timeout=%d", rt->initial_timeout * 1000); "?listen&listen_timeout=%d", rt->initial_timeout * 1000);
if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, 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"); av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
return ret; return ret;
} }

View File

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

View File

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

View File

@ -64,6 +64,8 @@ typedef struct OutputStream {
char *private_str; char *private_str;
int packet_size; int packet_size;
int audio_tag; int audio_tag;
const URLProtocol **protocols;
} OutputStream; } OutputStream;
typedef struct SmoothStreamingContext { typedef struct SmoothStreamingContext {
@ -76,6 +78,8 @@ typedef struct SmoothStreamingContext {
OutputStream *streams; OutputStream *streams;
int has_video, has_audio; int has_video, has_audio;
int nb_fragments; int nb_fragments;
const URLProtocol **protocols;
} SmoothStreamingContext; } SmoothStreamingContext;
static int ism_write(void *opaque, uint8_t *buf, int buf_size) 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; AVDictionary *opts = NULL;
os->tail_out = os->out; os->tail_out = os->out;
av_dict_set(&opts, "truncate", "0", 0); 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); av_dict_free(&opts);
if (ret < 0) { if (ret < 0) {
os->out = os->tail_out; os->out = os->tail_out;
@ -129,7 +134,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
return ret; return ret;
} }
av_dict_set(&opts, "truncate", "0", 0); 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); av_dict_free(&opts);
ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET); ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
if (os->out2) if (os->out2)
@ -168,6 +174,9 @@ static void ism_free(AVFormatContext *s)
{ {
SmoothStreamingContext *c = s->priv_data; SmoothStreamingContext *c = s->priv_data;
int i, j; int i, j;
av_freep(&c->protocols);
if (!c->streams) if (!c->streams)
return; return;
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
@ -303,6 +312,12 @@ static int ism_write_header(AVFormatContext *s)
goto fail; 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); c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
if (!c->streams) { if (!c->streams) {
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
@ -327,6 +342,8 @@ static int ism_write_header(AVFormatContext *s)
goto fail; goto fail;
} }
os->protocols = c->protocols;
ctx = avformat_alloc_context(); ctx = avformat_alloc_context();
if (!ctx) { if (!ctx) {
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
@ -523,7 +540,8 @@ static int ism_flush(AVFormatContext *s, int final)
continue; continue;
snprintf(filename, sizeof(filename), "%s/temp", os->dirname); 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) if (ret < 0)
break; break;
os->cur_start_pos = os->tail_pos; 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, av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
path, sizeof(path), uri); path, sizeof(path), uri);
ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path); 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; goto fail;
h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size, 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, 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 { typedef struct URLContext {
const AVClass *av_class; /**< information for av_log(). Set by url_open(). */ const AVClass *av_class; /**< information for av_log(). Set by url_open(). */
const struct URLProtocol *prot; const struct URLProtocol *prot;
/**
* A NULL-terminated list of protocols usable by the child contexts.
*/
const struct URLProtocol **protocols;
void *priv_data; void *priv_data;
char *filename; /**< specified URL */ char *filename; /**< specified URL */
int flags; int flags;
@ -96,11 +100,15 @@ typedef struct URLProtocol {
* is to be opened * is to be opened
* @param int_cb interrupt callback to use for the URLContext, may be * @param int_cb interrupt callback to use for the URLContext, may be
* NULL * 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 * @return 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure * AVERROR code in case of failure
*/ */
int ffurl_alloc(URLContext **puc, const char *filename, int flags, 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 * 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 * @param options A dictionary filled with protocol-private options. On return
* this parameter will be destroyed and replaced with a dict containing options * this parameter will be destroyed and replaced with a dict containing options
* that were not found. May be NULL. * 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 * @return 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure * AVERROR code in case of failure
*/ */
int ffurl_open(URLContext **puc, const char *filename, int flags, 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 * Read up to size bytes from the resource accessed by h, and store