summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2016-02-19 18:02:45 +0100
committerAnton Khirnov <anton@khirnov.net>2016-02-22 11:45:31 +0100
commit8c0ceafb0f25da077ff23e394667119f031574fd (patch)
treec495ca2679de2d9c0bc436652cfb5764cee47905 /libavformat
parentcae448cfbf31d492cba782bc64fc4eed556ed83d (diff)
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.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/avio.c42
-rw-r--r--libavformat/aviobuf.c20
-rw-r--r--libavformat/concat.c2
-rw-r--r--libavformat/crypto.c2
-rw-r--r--libavformat/gopher.c2
-rw-r--r--libavformat/hlsproto.c2
-rw-r--r--libavformat/http.c4
-rw-r--r--libavformat/icecast.c3
-rw-r--r--libavformat/md5proto.c3
-rw-r--r--libavformat/mmsh.c4
-rw-r--r--libavformat/mmst.c2
-rw-r--r--libavformat/rtmpcrypt.c2
-rw-r--r--libavformat/rtmphttp.c2
-rw-r--r--libavformat/rtmpproto.c4
-rw-r--r--libavformat/rtpproto.c6
-rw-r--r--libavformat/rtsp.c33
-rw-r--r--libavformat/rtsp.h2
-rw-r--r--libavformat/rtspdec.c10
-rw-r--r--libavformat/sapdec.c11
-rw-r--r--libavformat/sapenc.c15
-rw-r--r--libavformat/smoothstreamingenc.c24
-rw-r--r--libavformat/srtpproto.c3
-rw-r--r--libavformat/tls.c2
-rw-r--r--libavformat/url.h16
24 files changed, 162 insertions, 54 deletions
diff --git a/libavformat/avio.c b/libavformat/avio.c
index a9a399af93..668e5eab87 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -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;
}
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 18c3945c30..20bef66029 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -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);
diff --git a/libavformat/concat.c b/libavformat/concat.c
index de48f7b55f..ecdf5dfeb7 100644
--- a/libavformat/concat.c
+++ b/libavformat/concat.c
@@ -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 */
diff --git a/libavformat/crypto.c b/libavformat/crypto.c
index e9dd474448..a364dc0af5 100644
--- a/libavformat/crypto.c
+++ b/libavformat/crypto.c
@@ -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;
}
diff --git a/libavformat/gopher.c b/libavformat/gopher.c
index fc4fbe51e4..afa2b7d68b 100644
--- a/libavformat/gopher.c
+++ b/libavformat/gopher.c
@@ -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;
diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c
index 9f46c4885d..b01cef0008 100644
--- a/libavformat/hlsproto.c
+++ b/libavformat/hlsproto.c
@@ -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;
diff --git a/libavformat/http.c b/libavformat/http.c
index 6886e151a1..48303908b5 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -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;
diff --git a/libavformat/icecast.c b/libavformat/icecast.c
index 22adbed562..78238378b7 100644
--- a/libavformat/icecast.c
+++ b/libavformat/icecast.c
@@ -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
diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c
index 42b64b2e4b..07c085a561 100644
--- a/libavformat/md5proto.c
+++ b/libavformat/md5proto.c
@@ -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);
diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c
index bdbf67820a..4c1ed05b24 100644
--- a/libavformat/mmsh.c
+++ b/libavformat/mmsh.c
@@ -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);
diff --git a/libavformat/mmst.c b/libavformat/mmst.c
index 7013389870..aeddf0fd1d 100644
--- a/libavformat/mmst.c
+++ b/libavformat/mmst.c
@@ -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;
diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c
index c35ebe9a62..75fc1283c5 100644
--- a/libavformat/rtmpcrypt.c
+++ b/libavformat/rtmpcrypt.c
@@ -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;
}
diff --git a/libavformat/rtmphttp.c b/libavformat/rtmphttp.c
index 2577df95fd..4806872493 100644
--- a/libavformat/rtmphttp.c
+++ b/libavformat/rtmphttp.c
@@ -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 */
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index f745c37606..9ed3d0f436 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -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;
}
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 5f31d97a38..50b8d249ce 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -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
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 4beb275158..1a545c78d6 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -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;
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index b9357c1b6f..0226dac0f1 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -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 -
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 8ccf147699..c6f4d521e4 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -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;
}
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index f09222df3c..9fafd6bffe 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -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;
diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c
index 89f7f99ecc..54eb0bec38 100644
--- a/libavformat/sapenc.c
+++ b/libavformat/sapenc.c
@@ -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;
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index e1b0a63949..cfb1f8f1c9 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -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;
diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c
index 4dcbad3aaa..2c64f451aa 100644
--- a/libavformat/srtpproto.c
+++ b/libavformat/srtpproto.c
@@ -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,
diff --git a/libavformat/tls.c b/libavformat/tls.c
index eee3fc3d7d..a2a1ffe36d 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -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);
}
diff --git a/libavformat/url.h b/libavformat/url.h
index 455021964e..482658b7fe 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -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