This way, the decisions about which protocols are available for use in any given situations can be delegated to the caller.tags/n3.1
| @@ -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)) { | |||||
| 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 && | 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; | *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); | |||||
| 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; | 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; | ||||
| } | } | ||||
| @@ -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); | |||||
| 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; | 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); | ||||
| @@ -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 */ | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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 | ||||
| @@ -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); | ||||
| @@ -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); | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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 */ | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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 | ||||
| @@ -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; | ||||
| @@ -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 - | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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; | ||||
| @@ -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, | ||||
| @@ -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); | |||||
| } | } | ||||
| @@ -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 | ||||