X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtpproto.c;h=46511bab604ef6e1b9e4e0d0206086b575fc4033;hb=9d3fdf2031403301f25d7f5b4f5c323ba95139ee;hp=99fae3a9a0e1ac91aca40334537f2e13bf8d9363;hpb=245976da2a7f9a4a03dfb6903e9437b7cf2967f4;p=ffmpeg diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 99fae3a9a0e..46511bab604 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -1,6 +1,6 @@ /* * RTP network protocol - * Copyright (c) 2002 Fabrice Bellard. + * Copyright (c) 2002 Fabrice Bellard * * This file is part of FFmpeg. * @@ -20,18 +20,24 @@ */ /** - * @file rtpproto.c + * @file * RTP protocol */ #include "libavutil/avstring.h" #include "avformat.h" +#include "rtpdec.h" #include #include +#include "internal.h" #include "network.h" #include "os_support.h" #include +#if HAVE_SYS_SELECT_H +#include +#endif +#include #define RTP_TX_BUF_SIZE (64 * 1024) #define RTP_RX_BUF_SIZE (128 * 1024) @@ -46,7 +52,7 @@ typedef struct RTPContext { * get the local port first, then you must call this function to set * the remote server address. * - * @param s1 media file context + * @param h media file context * @param uri of the remote server * @return zero if no error. */ @@ -60,13 +66,13 @@ int rtp_set_remote_url(URLContext *h, const char *uri) char buf[1024]; char path[1024]; - url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, - path, sizeof(path), uri); + av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, + path, sizeof(path), uri); - snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path); + ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path); udp_set_remote_url(s->rtp_hd, buf); - snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port + 1, path); + ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port + 1, "%s", path); udp_set_remote_url(s->rtcp_hd, buf); return 0; } @@ -97,7 +103,7 @@ static void build_udp_url(char *buf, int buf_size, int local_port, int ttl, int max_packet_size) { - snprintf(buf, buf_size, "udp://%s:%d", hostname, port); + ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL); if (local_port >= 0) url_add_option(buf, buf_size, "localport=%d", local_port); if (ttl >= 0) @@ -108,16 +114,26 @@ static void build_udp_url(char *buf, int buf_size, /** * url syntax: rtp://host:port[?option=val...] - * option: 'ttl=n' : set the ttl value (for multicast only) - * 'localport=n' : set the local port to n - * 'pkt_size=n' : set max packet size + * option: 'ttl=n' : set the ttl value (for multicast only) + * 'rtcpport=n' : set the remote rtcp port to n + * 'localrtpport=n' : set the local rtp port to n + * 'localrtcpport=n' : set the local rtcp port to n + * 'pkt_size=n' : set max packet size + * deprecated option: + * 'localport=n' : set the local port to n * + * if rtcpport isn't set the rtcp port will be the rtp port + 1 + * if local rtp port isn't set any available port will be used for the local + * rtp and rtcp ports + * if the local rtcp port is not set it will be the local rtp port + 1 */ static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s; - int port, is_output, ttl, local_port, max_packet_size; + int rtp_port, rtcp_port, + is_output, ttl, + local_rtp_port, local_rtcp_port, max_packet_size; char hostname[256]; char buf[1024]; char path[1024]; @@ -130,11 +146,13 @@ static int rtp_open(URLContext *h, const char *uri, int flags) return AVERROR(ENOMEM); h->priv_data = s; - url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, - path, sizeof(path), uri); + av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, + path, sizeof(path), uri); /* extract parameters */ ttl = -1; - local_port = -1; + rtcp_port = rtp_port+1; + local_rtp_port = -1; + local_rtcp_port = -1; max_packet_size = -1; p = strchr(uri, '?'); @@ -142,8 +160,17 @@ static int rtp_open(URLContext *h, const char *uri, int flags) if (find_info_tag(buf, sizeof(buf), "ttl", p)) { ttl = strtol(buf, NULL, 10); } + if (find_info_tag(buf, sizeof(buf), "rtcpport", p)) { + rtcp_port = strtol(buf, NULL, 10); + } if (find_info_tag(buf, sizeof(buf), "localport", p)) { - local_port = strtol(buf, NULL, 10); + local_rtp_port = strtol(buf, NULL, 10); + } + if (find_info_tag(buf, sizeof(buf), "localrtpport", p)) { + local_rtp_port = strtol(buf, NULL, 10); + } + if (find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { + local_rtcp_port = strtol(buf, NULL, 10); } if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) { max_packet_size = strtol(buf, NULL, 10); @@ -151,23 +178,21 @@ static int rtp_open(URLContext *h, const char *uri, int flags) } build_udp_url(buf, sizeof(buf), - hostname, port, local_port, ttl, max_packet_size); + hostname, rtp_port, local_rtp_port, ttl, max_packet_size); if (url_open(&s->rtp_hd, buf, flags) < 0) goto fail; - local_port = udp_get_local_port(s->rtp_hd); - /* XXX: need to open another connection if the port is not even */ - - /* well, should suppress localport in path */ + if (local_rtp_port>=0 && local_rtcp_port<0) + local_rtcp_port = udp_get_local_port(s->rtp_hd) + 1; build_udp_url(buf, sizeof(buf), - hostname, port + 1, local_port + 1, ttl, max_packet_size); + hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size); if (url_open(&s->rtcp_hd, buf, flags) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle access */ - s->rtp_fd = udp_get_file_handle(s->rtp_hd); - s->rtcp_fd = udp_get_file_handle(s->rtcp_hd); + s->rtp_fd = url_get_file_handle(s->rtp_hd); + s->rtcp_fd = url_get_file_handle(s->rtcp_hd); h->max_packet_size = url_get_max_packet_size(s->rtp_hd); h->is_streamed = 1; @@ -189,6 +214,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) socklen_t from_len; int len, fd_max, n; fd_set rfds; + struct timeval tv; #if 0 for(;;) { from_len = sizeof(from); @@ -204,6 +230,8 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) } #else for(;;) { + if (url_interrupt_cb()) + return AVERROR(EINTR); /* build fdset to listen to RTP and RTCP packets */ FD_ZERO(&rfds); fd_max = s->rtp_fd; @@ -211,7 +239,9 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) if (s->rtcp_fd > fd_max) fd_max = s->rtcp_fd; FD_SET(s->rtcp_fd, &rfds); - n = select(fd_max + 1, &rfds, NULL, NULL, NULL); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + n = select(fd_max + 1, &rfds, NULL, NULL, &tv); if (n > 0) { /* first try RTCP */ if (FD_ISSET(s->rtcp_fd, &rfds)) { @@ -239,13 +269,17 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) } break; } + } else if (n < 0) { + if (ff_neterrno() == FF_NETERROR(EINTR)) + continue; + return AVERROR(EIO); } } #endif return len; } -static int rtp_write(URLContext *h, uint8_t *buf, int size) +static int rtp_write(URLContext *h, const uint8_t *buf, int size) { RTPContext *s = h->priv_data; int ret; @@ -282,8 +316,20 @@ static int rtp_close(URLContext *h) } /** - * Return the local port used by the RTP connection - * @param s1 media file context + * Return the local rtp port used by the RTP connection + * @param h media file context + * @return the local port number + */ + +int rtp_get_local_rtp_port(URLContext *h) +{ + RTPContext *s = h->priv_data; + return udp_get_local_port(s->rtp_hd); +} + +/** + * Return the local rtp port used by the RTP connection + * @param h media file context * @return the local port number */ @@ -293,6 +339,19 @@ int rtp_get_local_port(URLContext *h) return udp_get_local_port(s->rtp_hd); } +/** + * Return the local rtcp port used by the RTP connection + * @param h media file context + * @return the local port number + */ + +int rtp_get_local_rtcp_port(URLContext *h) +{ + RTPContext *s = h->priv_data; + return udp_get_local_port(s->rtcp_hd); +} + +#if (LIBAVFORMAT_VERSION_MAJOR <= 52) /** * Return the rtp and rtcp file handles for select() usage to wait for * several RTP streams at the same time. @@ -306,6 +365,13 @@ void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd) *prtp_fd = s->rtp_fd; *prtcp_fd = s->rtcp_fd; } +#endif + +static int rtp_get_file_handle(URLContext *h) +{ + RTPContext *s = h->priv_data; + return s->rtp_fd; +} URLProtocol rtp_protocol = { "rtp", @@ -314,4 +380,5 @@ URLProtocol rtp_protocol = { rtp_write, NULL, /* seek */ rtp_close, + .url_get_file_handle = rtp_get_file_handle, };