rtpproto.c
Go to the documentation of this file.
1 /*
2  * RTP network protocol
3  * Copyright (c) 2002 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * RTP protocol
25  */
26 
27 #include "libavutil/parseutils.h"
28 #include "libavutil/avstring.h"
29 #include "avformat.h"
30 #include "avio_internal.h"
31 #include "rtpdec.h"
32 #include "url.h"
33 
34 #include <stdarg.h>
35 #include "internal.h"
36 #include "network.h"
37 #include "os_support.h"
38 #include <fcntl.h>
39 #if HAVE_POLL_H
40 #include <sys/poll.h>
41 #endif
42 
43 typedef struct RTPContext {
46 } RTPContext;
47 
48 /**
49  * If no filename is given to av_open_input_file because you want to
50  * get the local port first, then you must call this function to set
51  * the remote server address.
52  *
53  * @param h media file context
54  * @param uri of the remote server
55  * @return zero if no error.
56  */
57 
58 int ff_rtp_set_remote_url(URLContext *h, const char *uri)
59 {
60  RTPContext *s = h->priv_data;
61  char hostname[256];
62  int port;
63 
64  char buf[1024];
65  char path[1024];
66 
67  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
68  path, sizeof(path), uri);
69 
70  ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path);
72 
73  ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port + 1, "%s", path);
75  return 0;
76 }
77 
78 
79 /**
80  * add option to url of the form:
81  * "http://host:port/path?option1=val1&option2=val2...
82  */
83 
84 static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const char *fmt, ...)
85 {
86  char buf1[1024];
87  va_list ap;
88 
89  va_start(ap, fmt);
90  if (strchr(buf, '?'))
91  av_strlcat(buf, "&", buf_size);
92  else
93  av_strlcat(buf, "?", buf_size);
94  vsnprintf(buf1, sizeof(buf1), fmt, ap);
95  av_strlcat(buf, buf1, buf_size);
96  va_end(ap);
97 }
98 
99 static void build_udp_url(char *buf, int buf_size,
100  const char *hostname, int port,
101  int local_port, int ttl,
102  int max_packet_size, int connect)
103 {
104  ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL);
105  if (local_port >= 0)
106  url_add_option(buf, buf_size, "localport=%d", local_port);
107  if (ttl >= 0)
108  url_add_option(buf, buf_size, "ttl=%d", ttl);
109  if (max_packet_size >=0)
110  url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size);
111  if (connect)
112  url_add_option(buf, buf_size, "connect=1");
113  url_add_option(buf, buf_size, "fifo_size=0");
114 }
115 
116 /**
117  * url syntax: rtp://host:port[?option=val...]
118  * option: 'ttl=n' : set the ttl value (for multicast only)
119  * 'rtcpport=n' : set the remote rtcp port to n
120  * 'localrtpport=n' : set the local rtp port to n
121  * 'localrtcpport=n' : set the local rtcp port to n
122  * 'pkt_size=n' : set max packet size
123  * 'connect=0/1' : do a connect() on the UDP socket
124  * deprecated option:
125  * 'localport=n' : set the local port to n
126  *
127  * if rtcpport isn't set the rtcp port will be the rtp port + 1
128  * if local rtp port isn't set any available port will be used for the local
129  * rtp and rtcp ports
130  * if the local rtcp port is not set it will be the local rtp port + 1
131  */
132 
133 static int rtp_open(URLContext *h, const char *uri, int flags)
134 {
135  RTPContext *s = h->priv_data;
136  int rtp_port, rtcp_port,
137  ttl, connect,
138  local_rtp_port, local_rtcp_port, max_packet_size;
139  char hostname[256];
140  char buf[1024];
141  char path[1024];
142  const char *p;
143 
144  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
145  path, sizeof(path), uri);
146  /* extract parameters */
147  ttl = -1;
148  rtcp_port = rtp_port+1;
149  local_rtp_port = -1;
150  local_rtcp_port = -1;
151  max_packet_size = -1;
152  connect = 0;
153 
154  p = strchr(uri, '?');
155  if (p) {
156  if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
157  ttl = strtol(buf, NULL, 10);
158  }
159  if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
160  rtcp_port = strtol(buf, NULL, 10);
161  }
162  if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
163  local_rtp_port = strtol(buf, NULL, 10);
164  }
165  if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) {
166  local_rtp_port = strtol(buf, NULL, 10);
167  }
168  if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) {
169  local_rtcp_port = strtol(buf, NULL, 10);
170  }
171  if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
172  max_packet_size = strtol(buf, NULL, 10);
173  }
174  if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
175  connect = strtol(buf, NULL, 10);
176  }
177  }
178 
179  build_udp_url(buf, sizeof(buf),
180  hostname, rtp_port, local_rtp_port, ttl, max_packet_size,
181  connect);
182  if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
183  goto fail;
184  if (local_rtp_port>=0 && local_rtcp_port<0)
185  local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1;
186 
187  build_udp_url(buf, sizeof(buf),
188  hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size,
189  connect);
190  if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
191  goto fail;
192 
193  /* just to ease handle access. XXX: need to suppress direct handle
194  access */
197 
199  h->is_streamed = 1;
200  return 0;
201 
202  fail:
203  if (s->rtp_hd)
204  ffurl_close(s->rtp_hd);
205  if (s->rtcp_hd)
206  ffurl_close(s->rtcp_hd);
207  return AVERROR(EIO);
208 }
209 
210 static int rtp_read(URLContext *h, uint8_t *buf, int size)
211 {
212  RTPContext *s = h->priv_data;
213  struct sockaddr_storage from;
214  socklen_t from_len;
215  int len, n;
216  struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
217 
218  for(;;) {
220  return AVERROR_EXIT;
221  /* build fdset to listen to RTP and RTCP packets */
222  n = poll(p, 2, 100);
223  if (n > 0) {
224  /* first try RTCP */
225  if (p[1].revents & POLLIN) {
226  from_len = sizeof(from);
227  len = recvfrom (s->rtcp_fd, buf, size, 0,
228  (struct sockaddr *)&from, &from_len);
229  if (len < 0) {
230  if (ff_neterrno() == AVERROR(EAGAIN) ||
231  ff_neterrno() == AVERROR(EINTR))
232  continue;
233  return AVERROR(EIO);
234  }
235  break;
236  }
237  /* then RTP */
238  if (p[0].revents & POLLIN) {
239  from_len = sizeof(from);
240  len = recvfrom (s->rtp_fd, buf, size, 0,
241  (struct sockaddr *)&from, &from_len);
242  if (len < 0) {
243  if (ff_neterrno() == AVERROR(EAGAIN) ||
244  ff_neterrno() == AVERROR(EINTR))
245  continue;
246  return AVERROR(EIO);
247  }
248  break;
249  }
250  } else if (n < 0) {
251  if (ff_neterrno() == AVERROR(EINTR))
252  continue;
253  return AVERROR(EIO);
254  }
255  }
256  return len;
257 }
258 
259 static int rtp_write(URLContext *h, const uint8_t *buf, int size)
260 {
261  RTPContext *s = h->priv_data;
262  int ret;
263  URLContext *hd;
264 
265  if (RTP_PT_IS_RTCP(buf[1])) {
266  /* RTCP payload type */
267  hd = s->rtcp_hd;
268  } else {
269  /* RTP payload type */
270  hd = s->rtp_hd;
271  }
272 
273  ret = ffurl_write(hd, buf, size);
274  return ret;
275 }
276 
277 static int rtp_close(URLContext *h)
278 {
279  RTPContext *s = h->priv_data;
280 
281  ffurl_close(s->rtp_hd);
282  ffurl_close(s->rtcp_hd);
283  return 0;
284 }
285 
286 /**
287  * Return the local rtp port used by the RTP connection
288  * @param h media file context
289  * @return the local port number
290  */
291 
293 {
294  RTPContext *s = h->priv_data;
295  return ff_udp_get_local_port(s->rtp_hd);
296 }
297 
298 /**
299  * Return the local rtcp port used by the RTP connection
300  * @param h media file context
301  * @return the local port number
302  */
303 
305 {
306  RTPContext *s = h->priv_data;
307  return ff_udp_get_local_port(s->rtcp_hd);
308 }
309 
311 {
312  RTPContext *s = h->priv_data;
313  return s->rtp_fd;
314 }
315 
316 static int rtp_get_multi_file_handle(URLContext *h, int **handles,
317  int *numhandles)
318 {
319  RTPContext *s = h->priv_data;
320  int *hs = *handles = av_malloc(sizeof(**handles) * 2);
321  if (!hs)
322  return AVERROR(ENOMEM);
323  hs[0] = s->rtp_fd;
324  hs[1] = s->rtcp_fd;
325  *numhandles = 2;
326  return 0;
327 }
328 
330  .name = "rtp",
331  .url_open = rtp_open,
332  .url_read = rtp_read,
333  .url_write = rtp_write,
334  .url_close = rtp_close,
335  .url_get_file_handle = rtp_get_file_handle,
336  .url_get_multi_file_handle = rtp_get_multi_file_handle,
337  .priv_data_size = sizeof(RTPContext),
339 };
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
const char * s
Definition: avisynth_c.h:668
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
Definition: rtpproto.c:292
int size
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:35
const char * fmt
Definition: avisynth_c.h:669
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:317
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
AVIOInterruptCB interrupt_callback
Definition: url.h:50
#define vsnprintf
Definition: snprintf.h:36
static void build_udp_url(char *buf, int buf_size, const char *hostname, int port, int local_port, int ttl, int max_packet_size, int connect)
Definition: rtpproto.c:99
URLContext * rtcp_hd
Definition: rtpproto.c:44
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...) av_printf_format(7
Assemble a URL string from components.
static int rtp_write(URLContext *h, const uint8_t *buf, int size)
Definition: rtpproto.c:259
static int rtp_close(URLContext *h)
Definition: rtpproto.c:277
miscellaneous OS support macros and functions.
int ff_udp_get_local_port(URLContext *h)
Return the local port used by the UDP connection.
Definition: udp.c:421
const char * from
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition: parseutils.c:647
URLContext * rtp_hd
Definition: rtpproto.c:44
int ff_udp_set_remote_url(URLContext *h, const char *uri)
If no filename is given to av_open_input_file because you want to get the local port first...
Definition: udp.c:382
static int rtp_read(URLContext *h, uint8_t *buf, int size)
Definition: rtpproto.c:210
ret
Definition: avfilter.c:821
#define ff_neterrno()
Definition: network.h:63
static int rtp_open(URLContext *h, const char *uri, int flags)
url syntax: rtp://host:port[?option=val...] option: &#39;ttl=n&#39; : set the ttl value (for multicast only) ...
Definition: rtpproto.c:133
int rtcp_fd
Definition: rtpproto.c:45
static int rtp_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
Definition: rtpproto.c:316
int rtp_fd
Definition: rtpproto.c:45
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:399
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
NULL
Definition: eval.c:55
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrup a blocking function associated with cb.
Definition: avio.c:428
typedef void(RENAME(mix_any_func_type))
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
static av_printf_format(3, 4)
add option to url of the form: "http://host:port/path?option1=val1&option2=val2...
Definition: rtpproto.c:84
void * priv_data
Definition: url.h:44
const uint8_t ptrdiff_t int h
Definition: hpel_template.c:97
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
misc parsing utilities
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:92
const char * name
Definition: url.h:55
#define RTP_PT_IS_RTCP(x)
Definition: rtp.h:109
static int flags
Definition: cpu.c:23
int ffurl_close(URLContext *h)
Definition: avio.c:359
Main libavformat public API header.
static int rtp_get_file_handle(URLContext *h)
Definition: rtpproto.c:310
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:247
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
Definition: rtpproto.c:304
int len
URLProtocol ff_rtp_protocol
Definition: rtpproto.c:329
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:47
unbuffered private I/O API
int ff_rtp_set_remote_url(URLContext *h, const char *uri)
If no filename is given to av_open_input_file because you want to get the local port first...
Definition: rtpproto.c:58
struct RTPContext RTPContext