FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 "libavutil/opt.h"
30 #include "avformat.h"
31 #include "avio_internal.h"
32 #include "rtp.h"
33 #include "rtpproto.h"
34 #include "url.h"
35 
36 #include <stdarg.h>
37 #include "internal.h"
38 #include "network.h"
39 #include "os_support.h"
40 #include <fcntl.h>
41 #if HAVE_POLL_H
42 #include <sys/poll.h>
43 #endif
44 
45 typedef struct RTPContext {
46  const AVClass *class;
51  struct sockaddr_storage last_rtp_source, last_rtcp_source;
53  int ttl;
56  int connect;
57  int pkt_size;
58  int dscp;
59  char *sources;
60  char *block;
62 } RTPContext;
63 
64 #define OFFSET(x) offsetof(RTPContext, x)
65 #define D AV_OPT_FLAG_DECODING_PARAM
66 #define E AV_OPT_FLAG_ENCODING_PARAM
67 static const AVOption options[] = {
68  { "ttl", "Time to live (in milliseconds, multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
69  { "buffer_size", "Send/Receive buffer size (in bytes)", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
70  { "rtcp_port", "Custom rtcp port", OFFSET(rtcp_port), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
71  { "local_rtpport", "Local rtp port", OFFSET(local_rtpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
72  { "local_rtcpport", "Local rtcp port", OFFSET(local_rtcpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
73  { "connect", "Connect socket", OFFSET(connect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E },
74  { "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E },
75  { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
76  { "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
77  { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
78  { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
79  { "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E },
80  { NULL }
81 };
82 
83 static const AVClass rtp_class = {
84  .class_name = "rtp",
85  .item_name = av_default_item_name,
86  .option = options,
87  .version = LIBAVUTIL_VERSION_INT,
88 };
89 
90 /**
91  * If no filename is given to av_open_input_file because you want to
92  * get the local port first, then you must call this function to set
93  * the remote server address.
94  *
95  * @param h media file context
96  * @param uri of the remote server
97  * @return zero if no error.
98  */
99 
100 int ff_rtp_set_remote_url(URLContext *h, const char *uri)
101 {
102  RTPContext *s = h->priv_data;
103  char hostname[256];
104  int port, rtcp_port;
105  const char *p;
106 
107  char buf[1024];
108  char path[1024];
109 
110  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
111  path, sizeof(path), uri);
112  rtcp_port = port + 1;
113 
114  p = strchr(uri, '?');
115  if (p) {
116  if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
117  rtcp_port = strtol(buf, NULL, 10);
118  }
119  }
120 
121  ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path);
122  ff_udp_set_remote_url(s->rtp_hd, buf);
123 
124  ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, rtcp_port, "%s", path);
126  return 0;
127 }
128 
129 static struct addrinfo* rtp_resolve_host(const char *hostname, int port,
130  int type, int family, int flags)
131 {
132  struct addrinfo hints = { 0 }, *res = 0;
133  int error;
134  char service[16];
135 
136  snprintf(service, sizeof(service), "%d", port);
137  hints.ai_socktype = type;
138  hints.ai_family = family;
139  hints.ai_flags = flags;
140  if ((error = getaddrinfo(hostname, service, &hints, &res))) {
141  res = NULL;
142  av_log(NULL, AV_LOG_ERROR, "rtp_resolve_host: %s\n", gai_strerror(error));
143  }
144 
145  return res;
146 }
147 
148 static int compare_addr(const struct sockaddr_storage *a,
149  const struct sockaddr_storage *b)
150 {
151  if (a->ss_family != b->ss_family)
152  return 1;
153  if (a->ss_family == AF_INET) {
154  return (((const struct sockaddr_in *)a)->sin_addr.s_addr !=
155  ((const struct sockaddr_in *)b)->sin_addr.s_addr);
156  }
157 
158 #if HAVE_STRUCT_SOCKADDR_IN6
159  if (a->ss_family == AF_INET6) {
160  const uint8_t *s6_addr_a = ((const struct sockaddr_in6 *)a)->sin6_addr.s6_addr;
161  const uint8_t *s6_addr_b = ((const struct sockaddr_in6 *)b)->sin6_addr.s6_addr;
162  return memcmp(s6_addr_a, s6_addr_b, 16);
163  }
164 #endif
165  return 1;
166 }
167 
168 static int get_port(const struct sockaddr_storage *ss)
169 {
170  if (ss->ss_family == AF_INET)
171  return ntohs(((const struct sockaddr_in *)ss)->sin_port);
172 #if HAVE_STRUCT_SOCKADDR_IN6
173  if (ss->ss_family == AF_INET6)
174  return ntohs(((const struct sockaddr_in6 *)ss)->sin6_port);
175 #endif
176  return 0;
177 }
178 
179 static void set_port(struct sockaddr_storage *ss, int port)
180 {
181  if (ss->ss_family == AF_INET)
182  ((struct sockaddr_in *)ss)->sin_port = htons(port);
183 #if HAVE_STRUCT_SOCKADDR_IN6
184  else if (ss->ss_family == AF_INET6)
185  ((struct sockaddr_in6 *)ss)->sin6_port = htons(port);
186 #endif
187 }
188 
189 static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr)
190 {
191  int i;
192  if (s->nb_ssm_exclude_addrs) {
193  for (i = 0; i < s->nb_ssm_exclude_addrs; i++) {
194  if (!compare_addr(source_addr_ptr, s->ssm_exclude_addrs[i]))
195  return 1;
196  }
197  }
198  if (s->nb_ssm_include_addrs) {
199  for (i = 0; i < s->nb_ssm_include_addrs; i++) {
200  if (!compare_addr(source_addr_ptr, s->ssm_include_addrs[i]))
201  return 0;
202  }
203  return 1;
204  }
205  return 0;
206 }
207 
208 /**
209  * add option to url of the form:
210  * "http://host:port/path?option1=val1&option2=val2...
211  */
212 
213 static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const char *fmt, ...)
214 {
215  char buf1[1024];
216  va_list ap;
217 
218  va_start(ap, fmt);
219  if (strchr(buf, '?'))
220  av_strlcat(buf, "&", buf_size);
221  else
222  av_strlcat(buf, "?", buf_size);
223  vsnprintf(buf1, sizeof(buf1), fmt, ap);
224  av_strlcat(buf, buf1, buf_size);
225  va_end(ap);
226 }
227 
229  char *buf, int buf_size,
230  const char *hostname,
231  int port, int local_port,
232  const char *include_sources,
233  const char *exclude_sources)
234 {
235  ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL);
236  if (local_port >= 0)
237  url_add_option(buf, buf_size, "localport=%d", local_port);
238  if (s->ttl >= 0)
239  url_add_option(buf, buf_size, "ttl=%d", s->ttl);
240  if (s->buffer_size >= 0)
241  url_add_option(buf, buf_size, "buffer_size=%d", s->buffer_size);
242  if (s->pkt_size >= 0)
243  url_add_option(buf, buf_size, "pkt_size=%d", s->pkt_size);
244  if (s->connect)
245  url_add_option(buf, buf_size, "connect=1");
246  if (s->dscp >= 0)
247  url_add_option(buf, buf_size, "dscp=%d", s->dscp);
248  url_add_option(buf, buf_size, "fifo_size=0");
249  if (include_sources && include_sources[0])
250  url_add_option(buf, buf_size, "sources=%s", include_sources);
251  if (exclude_sources && exclude_sources[0])
252  url_add_option(buf, buf_size, "block=%s", exclude_sources);
253 }
254 
255 static void rtp_parse_addr_list(URLContext *h, char *buf,
256  struct sockaddr_storage ***address_list_ptr,
257  int *address_list_size_ptr)
258 {
259  struct addrinfo *ai = NULL;
260  struct sockaddr_storage *source_addr;
261  char tmp = '\0', *p = buf, *next;
262 
263  /* Resolve all of the IPs */
264 
265  while (p && p[0]) {
266  next = strchr(p, ',');
267 
268  if (next) {
269  tmp = *next;
270  *next = '\0';
271  }
272 
273  ai = rtp_resolve_host(p, 0, SOCK_DGRAM, AF_UNSPEC, 0);
274  if (ai) {
275  source_addr = av_mallocz(sizeof(struct sockaddr_storage));
276  if (!source_addr) {
277  freeaddrinfo(ai);
278  break;
279  }
280 
281  memcpy(source_addr, ai->ai_addr, ai->ai_addrlen);
282  freeaddrinfo(ai);
283  dynarray_add(address_list_ptr, address_list_size_ptr, source_addr);
284  } else {
285  av_log(h, AV_LOG_WARNING, "Unable to resolve %s\n", p);
286  }
287 
288  if (next) {
289  *next = tmp;
290  p = next + 1;
291  } else {
292  p = NULL;
293  }
294  }
295 }
296 
297 /**
298  * url syntax: rtp://host:port[?option=val...]
299  * option: 'ttl=n' : set the ttl value (for multicast only)
300  * 'rtcpport=n' : set the remote rtcp port to n
301  * 'localrtpport=n' : set the local rtp port to n
302  * 'localrtcpport=n' : set the local rtcp port to n
303  * 'pkt_size=n' : set max packet size
304  * 'connect=0/1' : do a connect() on the UDP socket
305  * 'sources=ip[,ip]' : list allowed source IP addresses
306  * 'block=ip[,ip]' : list disallowed source IP addresses
307  * 'write_to_source=0/1' : send packets to the source address of the latest received packet
308  * 'dscp=n' : set DSCP value to n (QoS)
309  * deprecated option:
310  * 'localport=n' : set the local port to n
311  *
312  * if rtcpport isn't set the rtcp port will be the rtp port + 1
313  * if local rtp port isn't set any available port will be used for the local
314  * rtp and rtcp ports
315  * if the local rtcp port is not set it will be the local rtp port + 1
316  */
317 
318 static int rtp_open(URLContext *h, const char *uri, int flags)
319 {
320  RTPContext *s = h->priv_data;
321  AVDictionary *fec_opts = NULL;
322  int rtp_port;
323  char hostname[256], include_sources[1024] = "", exclude_sources[1024] = "";
324  char *sources = include_sources, *block = exclude_sources;
325  char *fec_protocol = NULL;
326  char buf[1024];
327  char path[1024];
328  const char *p;
329  int i, max_retry_count = 3;
330  int rtcpflags;
331 
332  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
333  path, sizeof(path), uri);
334  /* extract parameters */
335  if (s->rtcp_port < 0)
336  s->rtcp_port = rtp_port + 1;
337 
338  p = strchr(uri, '?');
339  if (p) {
340  if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
341  s->ttl = strtol(buf, NULL, 10);
342  }
343  if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
344  s->rtcp_port = strtol(buf, NULL, 10);
345  }
346  if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
347  s->local_rtpport = strtol(buf, NULL, 10);
348  }
349  if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) {
350  s->local_rtpport = strtol(buf, NULL, 10);
351  }
352  if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) {
353  s->local_rtcpport = strtol(buf, NULL, 10);
354  }
355  if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
356  s->pkt_size = strtol(buf, NULL, 10);
357  }
358  if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
359  s->connect = strtol(buf, NULL, 10);
360  }
361  if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) {
362  s->write_to_source = strtol(buf, NULL, 10);
363  }
364  if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
365  s->dscp = strtol(buf, NULL, 10);
366  }
367  if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
368  av_strlcpy(include_sources, buf, sizeof(include_sources));
369 
371  } else {
373  sources = s->sources;
374  }
375  if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
376  av_strlcpy(exclude_sources, buf, sizeof(exclude_sources));
378  } else {
380  block = s->block;
381  }
382  }
383 
384  if (s->fec_options_str) {
385  p = s->fec_options_str;
386 
387  if (!(fec_protocol = av_get_token(&p, "="))) {
388  av_log(h, AV_LOG_ERROR, "Failed to parse the FEC protocol value\n");
389  goto fail;
390  }
391  if (strcmp(fec_protocol, "prompeg")) {
392  av_log(h, AV_LOG_ERROR, "Unsupported FEC protocol %s\n", fec_protocol);
393  goto fail;
394  }
395 
396  p = s->fec_options_str + strlen(fec_protocol);
397  while (*p && *p == '=') p++;
398 
399  if (av_dict_parse_string(&fec_opts, p, "=", ":", 0) < 0) {
400  av_log(h, AV_LOG_ERROR, "Failed to parse the FEC options\n");
401  goto fail;
402  }
403  if (s->ttl > 0) {
404  snprintf(buf, sizeof (buf), "%d", s->ttl);
405  av_dict_set(&fec_opts, "ttl", buf, 0);
406  }
407  }
408 
409  for (i = 0; i < max_retry_count; i++) {
410  build_udp_url(s, buf, sizeof(buf),
411  hostname, rtp_port, s->local_rtpport,
412  sources, block);
413  if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
415  goto fail;
417  if(s->local_rtpport == 65535) {
418  s->local_rtpport = -1;
419  continue;
420  }
421  rtcpflags = flags | AVIO_FLAG_WRITE;
422  if (s->local_rtcpport < 0) {
423  s->local_rtcpport = s->local_rtpport + 1;
424  build_udp_url(s, buf, sizeof(buf),
425  hostname, s->rtcp_port, s->local_rtcpport,
426  sources, block);
427  if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
429  h->protocol_whitelist, h->protocol_blacklist, h) < 0) {
430  s->local_rtpport = s->local_rtcpport = -1;
431  continue;
432  }
433  break;
434  }
435  build_udp_url(s, buf, sizeof(buf),
436  hostname, s->rtcp_port, s->local_rtcpport,
437  sources, block);
438  if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
440  goto fail;
441  break;
442  }
443 
444  s->fec_hd = NULL;
445  if (fec_protocol) {
446  ff_url_join(buf, sizeof(buf), fec_protocol, NULL, hostname, rtp_port, NULL);
447  if (ffurl_open_whitelist(&s->fec_hd, buf, flags, &h->interrupt_callback,
448  &fec_opts, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
449  goto fail;
450  }
451 
452  /* just to ease handle access. XXX: need to suppress direct handle
453  access */
456 
458  h->is_streamed = 1;
459 
460  av_free(fec_protocol);
461  av_dict_free(&fec_opts);
462 
463  return 0;
464 
465  fail:
466  if (s->rtp_hd)
467  ffurl_close(s->rtp_hd);
468  if (s->rtcp_hd)
469  ffurl_close(s->rtcp_hd);
470  ffurl_closep(&s->fec_hd);
471  av_free(fec_protocol);
472  av_dict_free(&fec_opts);
473  return AVERROR(EIO);
474 }
475 
476 static int rtp_read(URLContext *h, uint8_t *buf, int size)
477 {
478  RTPContext *s = h->priv_data;
479  int len, n, i;
480  struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
481  int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100;
482  struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source };
483  socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len };
484 
485  for(;;) {
487  return AVERROR_EXIT;
488  n = poll(p, 2, poll_delay);
489  if (n > 0) {
490  /* first try RTCP, then RTP */
491  for (i = 1; i >= 0; i--) {
492  if (!(p[i].revents & POLLIN))
493  continue;
494  *addr_lens[i] = sizeof(*addrs[i]);
495  len = recvfrom(p[i].fd, buf, size, 0,
496  (struct sockaddr *)addrs[i], addr_lens[i]);
497  if (len < 0) {
498  if (ff_neterrno() == AVERROR(EAGAIN) ||
499  ff_neterrno() == AVERROR(EINTR))
500  continue;
501  return AVERROR(EIO);
502  }
503  if (rtp_check_source_lists(s, addrs[i]))
504  continue;
505  return len;
506  }
507  } else if (n < 0) {
508  if (ff_neterrno() == AVERROR(EINTR))
509  continue;
510  return AVERROR(EIO);
511  }
512  if (h->flags & AVIO_FLAG_NONBLOCK)
513  return AVERROR(EAGAIN);
514  }
515  return len;
516 }
517 
518 static int rtp_write(URLContext *h, const uint8_t *buf, int size)
519 {
520  RTPContext *s = h->priv_data;
521  int ret, ret_fec;
522  URLContext *hd;
523 
524  if (size < 2)
525  return AVERROR(EINVAL);
526 
527  if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
528  av_log(h, AV_LOG_WARNING, "Data doesn't look like RTP packets, "
529  "make sure the RTP muxer is used\n");
530 
531  if (s->write_to_source) {
532  int fd;
533  struct sockaddr_storage *source, temp_source;
534  socklen_t *source_len, temp_len;
535  if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) {
536  av_log(h, AV_LOG_ERROR,
537  "Unable to send packet to source, no packets received yet\n");
538  // Intentionally not returning an error here
539  return size;
540  }
541 
542  if (RTP_PT_IS_RTCP(buf[1])) {
543  fd = s->rtcp_fd;
544  source = &s->last_rtcp_source;
545  source_len = &s->last_rtcp_source_len;
546  } else {
547  fd = s->rtp_fd;
548  source = &s->last_rtp_source;
549  source_len = &s->last_rtp_source_len;
550  }
551  if (!source->ss_family) {
552  source = &temp_source;
553  source_len = &temp_len;
554  if (RTP_PT_IS_RTCP(buf[1])) {
555  temp_source = s->last_rtp_source;
556  temp_len = s->last_rtp_source_len;
557  set_port(source, get_port(source) + 1);
558  av_log(h, AV_LOG_INFO,
559  "Not received any RTCP packets yet, inferring peer port "
560  "from the RTP port\n");
561  } else {
562  temp_source = s->last_rtcp_source;
563  temp_len = s->last_rtcp_source_len;
564  set_port(source, get_port(source) - 1);
565  av_log(h, AV_LOG_INFO,
566  "Not received any RTP packets yet, inferring peer port "
567  "from the RTCP port\n");
568  }
569  }
570 
571  if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
572  ret = ff_network_wait_fd(fd, 1);
573  if (ret < 0)
574  return ret;
575  }
576  ret = sendto(fd, buf, size, 0, (struct sockaddr *) source,
577  *source_len);
578 
579  return ret < 0 ? ff_neterrno() : ret;
580  }
581 
582  if (RTP_PT_IS_RTCP(buf[1])) {
583  /* RTCP payload type */
584  hd = s->rtcp_hd;
585  } else {
586  /* RTP payload type */
587  hd = s->rtp_hd;
588  }
589 
590  if ((ret = ffurl_write(hd, buf, size)) < 0) {
591  return ret;
592  }
593 
594  if (s->fec_hd && !RTP_PT_IS_RTCP(buf[1])) {
595  if ((ret_fec = ffurl_write(s->fec_hd, buf, size)) < 0) {
596  av_log(h, AV_LOG_ERROR, "Failed to send FEC\n");
597  return ret_fec;
598  }
599  }
600 
601  return ret;
602 }
603 
604 static int rtp_close(URLContext *h)
605 {
606  RTPContext *s = h->priv_data;
607  int i;
608 
609  for (i = 0; i < s->nb_ssm_include_addrs; i++)
610  av_freep(&s->ssm_include_addrs[i]);
612  for (i = 0; i < s->nb_ssm_exclude_addrs; i++)
613  av_freep(&s->ssm_exclude_addrs[i]);
615 
616  ffurl_close(s->rtp_hd);
617  ffurl_close(s->rtcp_hd);
618  ffurl_closep(&s->fec_hd);
619  return 0;
620 }
621 
622 /**
623  * Return the local rtp port used by the RTP connection
624  * @param h media file context
625  * @return the local port number
626  */
627 
629 {
630  RTPContext *s = h->priv_data;
631  return ff_udp_get_local_port(s->rtp_hd);
632 }
633 
634 /**
635  * Return the local rtcp port used by the RTP connection
636  * @param h media file context
637  * @return the local port number
638  */
639 
641 {
642  RTPContext *s = h->priv_data;
643  return ff_udp_get_local_port(s->rtcp_hd);
644 }
645 
647 {
648  RTPContext *s = h->priv_data;
649  return s->rtp_fd;
650 }
651 
652 static int rtp_get_multi_file_handle(URLContext *h, int **handles,
653  int *numhandles)
654 {
655  RTPContext *s = h->priv_data;
656  int *hs = *handles = av_malloc(sizeof(**handles) * 2);
657  if (!hs)
658  return AVERROR(ENOMEM);
659  hs[0] = s->rtp_fd;
660  hs[1] = s->rtcp_fd;
661  *numhandles = 2;
662  return 0;
663 }
664 
666  .name = "rtp",
667  .url_open = rtp_open,
668  .url_read = rtp_read,
669  .url_write = rtp_write,
670  .url_close = rtp_close,
671  .url_get_file_handle = rtp_get_file_handle,
672  .url_get_multi_file_handle = rtp_get_multi_file_handle,
673  .priv_data_size = sizeof(RTPContext),
675  .priv_data_class = &rtp_class,
676 };
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.
Definition: utils.c:4461
#define NULL
Definition: coverity.c:32
int rtcp_port
Definition: rtpproto.c:55
int buffer_size
Definition: rtpproto.c:54
const char * s
Definition: avisynth_c.h:768
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
Definition: rtpproto.c:628
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:309
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
AVOption.
Definition: opt.h:246
const char * fmt
Definition: avisynth_c.h:769
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
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:421
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
AVIOInterruptCB interrupt_callback
Definition: url.h:47
#define RTP_VERSION
Definition: rtp.h:78
#define vsnprintf
Definition: snprintf.h:36
static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr)
Definition: rtpproto.c:189
const char * b
Definition: vf_curves.c:113
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:607
static void rtp_parse_addr_list(URLContext *h, char *buf, struct sockaddr_storage ***address_list_ptr, int *address_list_size_ptr)
Definition: rtpproto.c:255
char * block
Definition: rtpproto.c:60
int flags
Definition: url.h:43
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:252
#define freeaddrinfo
Definition: network.h:208
const URLProtocol ff_rtp_protocol
Definition: rtpproto.c:665
URLContext * rtcp_hd
Definition: rtpproto.c:47
static int compare_addr(const struct sockaddr_storage *a, const struct sockaddr_storage *b)
Definition: rtpproto.c:148
static int16_t block[64]
Definition: dct.c:113
static int rtp_write(URLContext *h, const uint8_t *buf, int size)
Definition: rtpproto.c:518
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
static int rtp_close(URLContext *h)
Definition: rtpproto.c:604
uint8_t
#define av_malloc(s)
AVOptions.
#define D
Definition: rtpproto.c:65
miscellaneous OS support macros and functions.
socklen_t last_rtp_source_len
Definition: rtpproto.c:52
static int get_port(const struct sockaddr_storage *ss)
Definition: rtpproto.c:168
int ff_udp_get_local_port(URLContext *h)
Return the local port used by the UDP connection.
Definition: udp.c:481
uint16_t ss_family
Definition: network.h:106
int pkt_size
Definition: rtpproto.c:57
static int flags
Definition: log.c:57
struct sockaddr_storage ** ssm_include_addrs
Definition: rtpproto.c:49
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:705
ptrdiff_t size
Definition: opengl_enc.c:101
#define av_log(a,...)
URLContext * rtp_hd
Definition: rtpproto.c:47
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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:442
const char * protocol_whitelist
Definition: url.h:49
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
static int rtp_read(URLContext *h, uint8_t *buf, int size)
Definition: rtpproto.c:476
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
static void error(const char *err)
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
#define fail()
Definition: checkasm.h:84
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:149
int ai_addrlen
Definition: network.h:132
#define dynarray_add(tab, nb_ptr, elem)
Definition: internal.h:183
char * fec_options_str
Definition: rtpproto.c:61
static const AVClass rtp_class
Definition: rtpproto.c:83
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
struct sockaddr_storage last_rtp_source last_rtcp_source
Definition: rtpproto.c:51
#define ff_neterrno()
Definition: network.h:64
static int rtp_open(URLContext *h, const char *uri, int flags)
url syntax: rtp://host:port[?option=val...] option: 'ttl=n' : set the ttl value (for multicast only) ...
Definition: rtpproto.c:318
static const AVOption options[]
Definition: rtpproto.c:67
int n
Definition: avisynth_c.h:684
int rtcp_fd
Definition: rtpproto.c:48
static int rtp_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
Definition: rtpproto.c:652
int rtp_fd
Definition: rtpproto.c:48
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:626
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:444
int local_rtcpport
Definition: rtpproto.c:55
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
const char * protocol_blacklist
Definition: url.h:50
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:655
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:625
#define ss
socklen_t last_rtcp_source_len
Definition: rtpproto.c:52
void * buf
Definition: avisynth_c.h:690
Definition: url.h:38
GLint GLenum type
Definition: opengl_enc.c:105
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
Describe the class of an AVClass context structure.
Definition: log.h:67
static av_printf_format(3, 4)
add option to url of the form: "http://host:port/path?option1=val1&option2=val2...
Definition: rtpproto.c:213
void * priv_data
Definition: url.h:41
#define gai_strerror
Definition: network.h:215
#define snprintf
Definition: snprintf.h:34
misc parsing utilities
URLContext * fec_hd
Definition: rtpproto.c:47
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:93
const char * name
Definition: url.h:54
int ai_socktype
Definition: network.h:130
#define RTP_PT_IS_RTCP(x)
Definition: rtp.h:110
static void set_port(struct sockaddr_storage *ss, int port)
Definition: rtpproto.c:179
int dscp
Definition: rtpproto.c:58
int ffurl_close(URLContext *h)
Definition: avio.c:467
char * sources
Definition: rtpproto.c:59
static struct addrinfo * rtp_resolve_host(const char *hostname, int port, int type, int family, int flags)
Definition: rtpproto.c:129
int nb_ssm_include_addrs
Definition: rtpproto.c:48
#define getaddrinfo
Definition: network.h:207
Main libavformat public API header.
struct sockaddr_storage ** ssm_exclude_addrs
Definition: rtpproto.c:49
static int rtp_get_file_handle(URLContext *h)
Definition: rtpproto.c:646
static void build_udp_url(RTPContext *s, char *buf, int buf_size, const char *hostname, int port, int local_port, const char *include_sources, const char *exclude_sources)
Definition: rtpproto.c:228
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
Definition: rtpproto.c:640
int write_to_source
Definition: rtpproto.c:50
#define av_free(p)
int len
int nb_ssm_exclude_addrs
Definition: rtpproto.c:48
int local_rtpport
Definition: rtpproto.c:55
static uint8_t tmp[8]
Definition: des.c:38
int ttl
Definition: rtpproto.c:53
#define OFFSET(x)
Definition: rtpproto.c:64
int ai_flags
Definition: network.h:128
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:44
#define av_freep(p)
int ff_network_wait_fd(int fd, int write)
Definition: network.c:73
unbuffered private I/O API
struct sockaddr * ai_addr
Definition: network.h:133
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:100
int connect
Definition: rtpproto.c:56
#define E
Definition: rtpproto.c:66
int ai_family
Definition: network.h:129