lavf: reorganize URLProtocols

Instead of a linked list constructed at av_register_all(), store them
in a constant array of pointers.

Since no registration is necessary now, this removes some global state
from lavf. This will also allow the urlprotocol layer caller to limit
the available protocols in a simple and flexible way in the following
commits.
This commit is contained in:
Anton Khirnov 2016-02-19 10:39:29 +01:00
parent 225e84e745
commit 2758cdedfb
28 changed files with 227 additions and 121 deletions

10
configure vendored
View File

@ -2522,9 +2522,17 @@ MUXER_LIST=$(find_things muxer _MUX libavformat/allformats.c)
DEMUXER_LIST=$(find_things demuxer DEMUX libavformat/allformats.c)
OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c)
INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c)
PROTOCOL_LIST=$(find_things protocol PROTOCOL libavformat/allformats.c)
FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c)
find_things_extern(){
thing=$1
pattern=$2
file=$source_path/$3
sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file"
}
PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c)
ALL_COMPONENTS="
$BSF_LIST
$DECODER_LIST

View File

@ -17,6 +17,7 @@ OBJS = allformats.o \
mux.o \
options.o \
os_support.o \
protocols.o \
riff.o \
sdp.o \
url.o \

View File

@ -41,13 +41,6 @@
#define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
#define REGISTER_PROTOCOL(X, x) \
{ \
extern URLProtocol ff_##x##_protocol; \
if (CONFIG_##X##_PROTOCOL) \
ffurl_register_protocol(&ff_##x##_protocol); \
}
void av_register_all(void)
{
static int initialized;
@ -264,42 +257,4 @@ void av_register_all(void)
REGISTER_DEMUXER (XWMA, xwma);
REGISTER_DEMUXER (YOP, yop);
REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe);
/* protocols */
REGISTER_PROTOCOL(CONCAT, concat);
REGISTER_PROTOCOL(CRYPTO, crypto);
REGISTER_PROTOCOL(FFRTMPCRYPT, ffrtmpcrypt);
REGISTER_PROTOCOL(FFRTMPHTTP, ffrtmphttp);
REGISTER_PROTOCOL(FILE, file);
REGISTER_PROTOCOL(GOPHER, gopher);
REGISTER_PROTOCOL(HLS, hls);
REGISTER_PROTOCOL(HTTP, http);
REGISTER_PROTOCOL(HTTPPROXY, httpproxy);
REGISTER_PROTOCOL(HTTPS, https);
REGISTER_PROTOCOL(ICECAST, icecast);
REGISTER_PROTOCOL(MMSH, mmsh);
REGISTER_PROTOCOL(MMST, mmst);
REGISTER_PROTOCOL(MD5, md5);
REGISTER_PROTOCOL(PIPE, pipe);
REGISTER_PROTOCOL(RTMP, rtmp);
REGISTER_PROTOCOL(RTMPE, rtmpe);
REGISTER_PROTOCOL(RTMPS, rtmps);
REGISTER_PROTOCOL(RTMPT, rtmpt);
REGISTER_PROTOCOL(RTMPTE, rtmpte);
REGISTER_PROTOCOL(RTMPTS, rtmpts);
REGISTER_PROTOCOL(RTP, rtp);
REGISTER_PROTOCOL(SCTP, sctp);
REGISTER_PROTOCOL(SRTP, srtp);
REGISTER_PROTOCOL(TCP, tcp);
REGISTER_PROTOCOL(TLS_GNUTLS, tls_gnutls);
REGISTER_PROTOCOL(TLS_OPENSSL, tls_openssl);
REGISTER_PROTOCOL(UDP, udp);
REGISTER_PROTOCOL(UNIX, unix);
/* external libraries */
REGISTER_PROTOCOL(LIBRTMP, librtmp);
REGISTER_PROTOCOL(LIBRTMPE, librtmpe);
REGISTER_PROTOCOL(LIBRTMPS, librtmps);
REGISTER_PROTOCOL(LIBRTMPT, librtmpt);
REGISTER_PROTOCOL(LIBRTMPTE, librtmpte);
}

View File

@ -30,13 +30,6 @@
#endif
#include "url.h"
static URLProtocol *first_protocol = NULL;
URLProtocol *ffurl_protocol_next(const URLProtocol *prev)
{
return prev ? prev->next : first_protocol;
}
/** @name Logging context. */
/*@{*/
static const char *urlcontext_to_name(void *ptr)
@ -58,17 +51,20 @@ static void *urlcontext_child_next(void *obj, void *prev)
static const AVClass *urlcontext_child_class_next(const AVClass *prev)
{
URLProtocol *p = NULL;
int i;
/* find the protocol that corresponds to prev */
while (prev && (p = ffurl_protocol_next(p)))
if (p->priv_data_class == prev)
for (i = 0; ff_url_protocols[i]; i++) {
if (ff_url_protocols[i]->priv_data_class == prev) {
i++;
break;
}
}
/* find next protocol with priv options */
while (p = ffurl_protocol_next(p))
if (p->priv_data_class)
return p->priv_data_class;
for (; ff_url_protocols[i]; i++)
if (ff_url_protocols[i]->priv_data_class)
return ff_url_protocols[i]->priv_data_class;
return NULL;
}
@ -85,27 +81,20 @@ const AVClass ffurl_context_class = {
const char *avio_enum_protocols(void **opaque, int output)
{
URLProtocol *p;
*opaque = ffurl_protocol_next(*opaque);
if (!(p = *opaque))
const URLProtocol **p = *opaque;
p = p ? p + 1 : ff_url_protocols;
*opaque = p;
if (!*p) {
*opaque = NULL;
return NULL;
if ((output && p->url_write) || (!output && p->url_read))
return p->name;
}
if ((output && (*p)->url_write) || (!output && (*p)->url_read))
return (*p)->name;
return avio_enum_protocols(opaque, output);
}
int ffurl_register_protocol(URLProtocol *protocol)
{
URLProtocol **p;
p = &first_protocol;
while (*p)
p = &(*p)->next;
*p = protocol;
protocol->next = NULL;
return 0;
}
static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up,
static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
@ -183,9 +172,9 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
int ffurl_alloc(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
URLProtocol *up = NULL;
char proto_str[128], proto_nested[128], *ptr;
size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
int i;
if (filename[proto_len] != ':' || is_dos_path(filename))
strcpy(proto_str, "file");
@ -197,7 +186,8 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
if ((ptr = strchr(proto_nested, '+')))
*ptr = '\0';
while (up = ffurl_protocol_next(up)) {
for (i = 0; ff_url_protocols[i]; i++) {
const URLProtocol *up = ff_url_protocols[i];
if (!strcmp(proto_str, up->name))
return url_alloc_for_protocol(puc, up, filename, flags, int_cb);
if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&

View File

@ -181,7 +181,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
return result;
}
URLProtocol ff_concat_protocol = {
const URLProtocol ff_concat_protocol = {
.name = "concat",
.url_open = concat_open,
.url_read = concat_read,

View File

@ -159,7 +159,7 @@ static int crypto_close(URLContext *h)
return 0;
}
URLProtocol ff_crypto_protocol = {
const URLProtocol ff_crypto_protocol = {
.name = "crypto",
.url_open = crypto_open,
.url_read = crypto_read,

View File

@ -144,7 +144,7 @@ static int file_close(URLContext *h)
return close(c->fd);
}
URLProtocol ff_file_protocol = {
const URLProtocol ff_file_protocol = {
.name = "file",
.url_open = file_open,
.url_read = file_read,
@ -184,7 +184,7 @@ static int pipe_open(URLContext *h, const char *filename, int flags)
return 0;
}
URLProtocol ff_pipe_protocol = {
const URLProtocol ff_pipe_protocol = {
.name = "pipe",
.url_open = pipe_open,
.url_read = file_read,

View File

@ -114,7 +114,7 @@ static int gopher_read(URLContext *h, uint8_t *buf, int size)
}
URLProtocol ff_gopher_protocol = {
const URLProtocol ff_gopher_protocol = {
.name = "gopher",
.url_open = gopher_open,
.url_read = gopher_read,

View File

@ -315,7 +315,7 @@ retry:
goto start;
}
URLProtocol ff_hls_protocol = {
const URLProtocol ff_hls_protocol = {
.name = "hls",
.url_open = hls_open,
.url_read = hls_read,

View File

@ -1013,7 +1013,7 @@ static const AVClass flavor ## _context_class = { \
#if CONFIG_HTTP_PROTOCOL
HTTP_CLASS(http);
URLProtocol ff_http_protocol = {
const URLProtocol ff_http_protocol = {
.name = "http",
.url_open2 = http_open,
.url_read = http_read,
@ -1031,7 +1031,7 @@ URLProtocol ff_http_protocol = {
#if CONFIG_HTTPS_PROTOCOL
HTTP_CLASS(https);
URLProtocol ff_https_protocol = {
const URLProtocol ff_https_protocol = {
.name = "https",
.url_open2 = http_open,
.url_read = http_read,
@ -1142,7 +1142,7 @@ static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
return ffurl_write(s->hd, buf, size);
}
URLProtocol ff_httpproxy_protocol = {
const URLProtocol ff_httpproxy_protocol = {
.name = "httpproxy",
.url_open = http_proxy_open,
.url_read = http_buf_read,

View File

@ -221,7 +221,7 @@ static const AVClass icecast_context_class = {
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ff_icecast_protocol = {
const URLProtocol ff_icecast_protocol = {
.name = "icecast",
.url_open = icecast_open,
.url_write = icecast_write,

View File

@ -320,7 +320,7 @@ static const AVClass lib ## flavor ## _class = {\
};
RTMP_CLASS(rtmp)
URLProtocol ff_librtmp_protocol = {
const URLProtocol ff_librtmp_protocol = {
.name = "rtmp",
.url_open = rtmp_open,
.url_read = rtmp_read,
@ -335,7 +335,7 @@ URLProtocol ff_librtmp_protocol = {
};
RTMP_CLASS(rtmpt)
URLProtocol ff_librtmpt_protocol = {
const URLProtocol ff_librtmpt_protocol = {
.name = "rtmpt",
.url_open = rtmp_open,
.url_read = rtmp_read,
@ -350,7 +350,7 @@ URLProtocol ff_librtmpt_protocol = {
};
RTMP_CLASS(rtmpe)
URLProtocol ff_librtmpe_protocol = {
const URLProtocol ff_librtmpe_protocol = {
.name = "rtmpe",
.url_open = rtmp_open,
.url_read = rtmp_read,
@ -365,7 +365,7 @@ URLProtocol ff_librtmpe_protocol = {
};
RTMP_CLASS(rtmpte)
URLProtocol ff_librtmpte_protocol = {
const URLProtocol ff_librtmpte_protocol = {
.name = "rtmpte",
.url_open = rtmp_open,
.url_read = rtmp_read,
@ -380,7 +380,7 @@ URLProtocol ff_librtmpte_protocol = {
};
RTMP_CLASS(rtmps)
URLProtocol ff_librtmps_protocol = {
const URLProtocol ff_librtmps_protocol = {
.name = "rtmps",
.url_open = rtmp_open,
.url_read = rtmp_read,

View File

@ -86,7 +86,7 @@ static int md5_close(URLContext *h)
}
URLProtocol ff_md5_protocol = {
const URLProtocol ff_md5_protocol = {
.name = "md5",
.url_open = md5_open,
.url_write = md5_write,

View File

@ -358,7 +358,7 @@ static int mmsh_read(URLContext *h, uint8_t *buf, int size)
return res;
}
URLProtocol ff_mmsh_protocol = {
const URLProtocol ff_mmsh_protocol = {
.name = "mmsh",
.url_open = mmsh_open,
.url_read = mmsh_read,

View File

@ -619,7 +619,7 @@ static int mms_read(URLContext *h, uint8_t *buf, int size)
return result;
}
URLProtocol ff_mmst_protocol = {
const URLProtocol ff_mmst_protocol = {
.name = "mmst",
.url_open = mms_open,
.url_read = mms_read,

164
libavformat/protocols.c Normal file
View File

@ -0,0 +1,164 @@
/*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "url.h"
extern const URLProtocol ff_concat_protocol;
extern const URLProtocol ff_crypto_protocol;
extern const URLProtocol ff_ffrtmpcrypt_protocol;
extern const URLProtocol ff_ffrtmphttp_protocol;
extern const URLProtocol ff_file_protocol;
extern const URLProtocol ff_gopher_protocol;
extern const URLProtocol ff_hls_protocol;
extern const URLProtocol ff_http_protocol;
extern const URLProtocol ff_httpproxy_protocol;
extern const URLProtocol ff_https_protocol;
extern const URLProtocol ff_icecast_protocol;
extern const URLProtocol ff_mmsh_protocol;
extern const URLProtocol ff_mmst_protocol;
extern const URLProtocol ff_md5_protocol;
extern const URLProtocol ff_pipe_protocol;
extern const URLProtocol ff_rtmp_protocol;
extern const URLProtocol ff_rtmpe_protocol;
extern const URLProtocol ff_rtmps_protocol;
extern const URLProtocol ff_rtmpt_protocol;
extern const URLProtocol ff_rtmpte_protocol;
extern const URLProtocol ff_rtmpts_protocol;
extern const URLProtocol ff_rtp_protocol;
extern const URLProtocol ff_sctp_protocol;
extern const URLProtocol ff_srtp_protocol;
extern const URLProtocol ff_tcp_protocol;
extern const URLProtocol ff_tls_gnutls_protocol;
extern const URLProtocol ff_tls_openssl_protocol;
extern const URLProtocol ff_udp_protocol;
extern const URLProtocol ff_unix_protocol;
extern const URLProtocol ff_librtmp_protocol;
extern const URLProtocol ff_librtmpe_protocol;
extern const URLProtocol ff_librtmps_protocol;
extern const URLProtocol ff_librtmpt_protocol;
extern const URLProtocol ff_librtmpte_protocol;
const URLProtocol *ff_url_protocols[] = {
#if CONFIG_CONCAT_PROTOCOL
&ff_concat_protocol,
#endif
#if CONFIG_CRYPTO_PROTOCOL
&ff_crypto_protocol,
#endif
#if CONFIG_FFRTMPCRYPT_PROTOCOL
&ff_ffrtmpcrypt_protocol,
#endif
#if CONFIG_FFRTMPHTTP_PROTOCOL
&ff_ffrtmphttp_protocol,
#endif
#if CONFIG_FILE_PROTOCOL
&ff_file_protocol,
#endif
#if CONFIG_GOPHER_PROTOCOL
&ff_gopher_protocol,
#endif
#if CONFIG_HLS_PROTOCOL
&ff_hls_protocol,
#endif
#if CONFIG_HTTP_PROTOCOL
&ff_http_protocol,
#endif
#if CONFIG_HTTPPROXY_PROTOCOL
&ff_httpproxy_protocol,
#endif
#if CONFIG_HTTPS_PROTOCOL
&ff_https_protocol,
#endif
#if CONFIG_ICECAST_PROTOCOL
&ff_icecast_protocol,
#endif
#if CONFIG_MMSH_PROTOCOL
&ff_mmsh_protocol,
#endif
#if CONFIG_MMST_PROTOCOL
&ff_mmst_protocol,
#endif
#if CONFIG_MD5_PROTOCOL
&ff_md5_protocol,
#endif
#if CONFIG_PIPE_PROTOCOL
&ff_pipe_protocol,
#endif
#if CONFIG_RTMP_PROTOCOL
&ff_rtmp_protocol,
#endif
#if CONFIG_RTMPE_PROTOCOL
&ff_rtmpe_protocol,
#endif
#if CONFIG_RTMPS_PROTOCOL
&ff_rtmps_protocol,
#endif
#if CONFIG_RTMPT_PROTOCOL
&ff_rtmpt_protocol,
#endif
#if CONFIG_RTMPTE_PROTOCOL
&ff_rtmpte_protocol,
#endif
#if CONFIG_RTMPTS_PROTOCOL
&ff_rtmpts_protocol,
#endif
#if CONFIG_RTP_PROTOCOL
&ff_rtp_protocol,
#endif
#if CONFIG_SCTP_PROTOCOL
&ff_sctp_protocol,
#endif
#if CONFIG_SRTP_PROTOCOL
&ff_srtp_protocol,
#endif
#if CONFIG_TCP_PROTOCOL
&ff_tcp_protocol,
#endif
#if CONFIG_TLS_GNUTLS_PROTOCOL
&ff_tls_gnutls_protocol,
#endif
#if CONFIG_TLS_OPENSSL_PROTOCOL
&ff_tls_openssl_protocol,
#endif
#if CONFIG_UDP_PROTOCOL
&ff_udp_protocol,
#endif
#if CONFIG_UNIX_PROTOCOL
&ff_unix_protocol,
#endif
/* external libraries */
#if CONFIG_LIBRTMP_PROTOCOL
&ff_librtmp_protocol,
#endif
#if CONFIG_LIBRTMPE_PROTOCOL
&ff_librtmpe_protocol,
#endif
#if CONFIG_LIBRTMPS_PROTOCOL
&ff_librtmps_protocol,
#endif
#if CONFIG_LIBRTMPT_PROTOCOL
&ff_librtmpt_protocol,
#endif
#if CONFIG_LIBRTMPTE_PROTOCOL
&ff_librtmpte_protocol,
#endif
NULL,
};

View File

@ -324,7 +324,7 @@ static const AVClass ffrtmpcrypt_class = {
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ff_ffrtmpcrypt_protocol = {
const URLProtocol ff_ffrtmpcrypt_protocol = {
.name = "ffrtmpcrypt",
.url_open = rtmpe_open,
.url_read = rtmpe_read,

View File

@ -265,7 +265,7 @@ static const AVClass ffrtmphttp_class = {
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ff_ffrtmphttp_protocol = {
const URLProtocol ff_ffrtmphttp_protocol = {
.name = "ffrtmphttp",
.url_open = rtmp_http_open,
.url_read = rtmp_http_read,

View File

@ -3087,7 +3087,7 @@ static const AVClass flavor##_class = { \
.version = LIBAVUTIL_VERSION_INT, \
}; \
\
URLProtocol ff_##flavor##_protocol = { \
const URLProtocol ff_##flavor##_protocol = { \
.name = #flavor, \
.url_open = rtmp_open, \
.url_read = rtmp_read, \

View File

@ -573,7 +573,7 @@ static int rtp_get_multi_file_handle(URLContext *h, int **handles,
return 0;
}
URLProtocol ff_rtp_protocol = {
const URLProtocol ff_rtp_protocol = {
.name = "rtp",
.url_open = rtp_open,
.url_read = rtp_read,

View File

@ -357,7 +357,7 @@ static int sctp_get_file_handle(URLContext *h)
return s->fd;
}
URLProtocol ff_sctp_protocol = {
const URLProtocol ff_sctp_protocol = {
.name = "sctp",
.url_open = sctp_open,
.url_read = sctp_read,

View File

@ -131,7 +131,7 @@ static int srtp_get_multi_file_handle(URLContext *h, int **handles,
return ffurl_get_multi_file_handle(s->rtp_hd, handles, numhandles);
}
URLProtocol ff_srtp_protocol = {
const URLProtocol ff_srtp_protocol = {
.name = "srtp",
.url_open = srtp_open,
.url_read = srtp_read,

View File

@ -208,7 +208,7 @@ static int tcp_get_file_handle(URLContext *h)
return s->fd;
}
URLProtocol ff_tcp_protocol = {
const URLProtocol ff_tcp_protocol = {
.name = "tcp",
.url_open = tcp_open,
.url_read = tcp_read,

View File

@ -243,7 +243,7 @@ static const AVClass tls_class = {
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ff_tls_gnutls_protocol = {
const URLProtocol ff_tls_gnutls_protocol = {
.name = "tls",
.url_open2 = tls_open,
.url_read = tls_read,

View File

@ -285,7 +285,7 @@ static const AVClass tls_class = {
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ff_tls_openssl_protocol = {
const URLProtocol ff_tls_openssl_protocol = {
.name = "tls",
.url_open2 = tls_open,
.url_read = tls_read,

View File

@ -685,7 +685,7 @@ static int udp_close(URLContext *h)
return 0;
}
URLProtocol ff_udp_protocol = {
const URLProtocol ff_udp_protocol = {
.name = "udp",
.url_open = udp_open,
.url_read = udp_read,

View File

@ -141,7 +141,7 @@ static int unix_get_file_handle(URLContext *h)
return s->fd;
}
URLProtocol ff_unix_protocol = {
const URLProtocol ff_unix_protocol = {
.name = "unix",
.url_open = unix_open,
.url_read = unix_read,

View File

@ -37,7 +37,7 @@ extern const AVClass ffurl_context_class;
typedef struct URLContext {
const AVClass *av_class; /**< information for av_log(). Set by url_open(). */
struct URLProtocol *prot;
const struct URLProtocol *prot;
void *priv_data;
char *filename; /**< specified URL */
int flags;
@ -73,7 +73,6 @@ typedef struct URLProtocol {
int (*url_write)(URLContext *h, const unsigned char *buf, int size);
int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);
int (*url_close)(URLContext *h);
struct URLProtocol *next;
int (*url_read_pause)(URLContext *h, int pause);
int64_t (*url_read_seek)(URLContext *h, int stream_index,
int64_t timestamp, int flags);
@ -219,24 +218,12 @@ int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles);
*/
int ffurl_shutdown(URLContext *h, int flags);
/**
* Register the URLProtocol protocol.
*/
int ffurl_register_protocol(URLProtocol *protocol);
/**
* Check if the user has requested to interrup a blocking function
* associated with cb.
*/
int ff_check_interrupt(AVIOInterruptCB *cb);
/**
* Iterate over all available protocols.
*
* @param prev result of the previous call to this functions or NULL.
*/
URLProtocol *ffurl_protocol_next(const URLProtocol *prev);
/* udp.c */
int ff_udp_set_remote_url(URLContext *h, const char *uri);
int ff_udp_get_local_port(URLContext *h);
@ -277,5 +264,6 @@ int ff_url_join(char *str, int size, const char *proto,
void ff_make_absolute_url(char *buf, int size, const char *base,
const char *rel);
extern const URLProtocol *ff_url_protocols[];
#endif /* AVFORMAT_URL_H */