You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

670 lines
23KB

  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. * @file
  23. * RTP protocol
  24. */
  25. #include "libavutil/parseutils.h"
  26. #include "libavutil/avstring.h"
  27. #include "libavutil/opt.h"
  28. #include "avformat.h"
  29. #include "avio_internal.h"
  30. #include "rtp.h"
  31. #include "rtpproto.h"
  32. #include "url.h"
  33. #include <stdarg.h>
  34. #include "internal.h"
  35. #include "network.h"
  36. #include "os_support.h"
  37. #include <fcntl.h>
  38. #if HAVE_POLL_H
  39. #include <sys/poll.h>
  40. #endif
  41. typedef struct RTPContext {
  42. const AVClass *class;
  43. URLContext *rtp_hd, *rtcp_hd, *fec_hd;
  44. int rtp_fd, rtcp_fd, nb_ssm_include_addrs, nb_ssm_exclude_addrs;
  45. struct sockaddr_storage **ssm_include_addrs, **ssm_exclude_addrs;
  46. int write_to_source;
  47. struct sockaddr_storage last_rtp_source, last_rtcp_source;
  48. socklen_t last_rtp_source_len, last_rtcp_source_len;
  49. int ttl;
  50. int buffer_size;
  51. int rtcp_port, local_rtpport, local_rtcpport;
  52. int connect;
  53. int pkt_size;
  54. int dscp;
  55. char *sources;
  56. char *block;
  57. char *fec_options_str;
  58. } RTPContext;
  59. #define OFFSET(x) offsetof(RTPContext, x)
  60. #define D AV_OPT_FLAG_DECODING_PARAM
  61. #define E AV_OPT_FLAG_ENCODING_PARAM
  62. static const AVOption options[] = {
  63. { "ttl", "Time to live (in milliseconds, multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  64. { "buffer_size", "Send/Receive buffer size (in bytes)", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  65. { "rtcp_port", "Custom rtcp port", OFFSET(rtcp_port), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  66. { "local_rtpport", "Local rtp port", OFFSET(local_rtpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  67. { "local_rtcpport", "Local rtcp port", OFFSET(local_rtcpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  68. { "connect", "Connect socket", OFFSET(connect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E },
  69. { "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 },
  70. { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  71. { "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
  72. { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
  73. { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
  74. { "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E },
  75. { NULL }
  76. };
  77. static const AVClass rtp_class = {
  78. .class_name = "rtp",
  79. .item_name = av_default_item_name,
  80. .option = options,
  81. .version = LIBAVUTIL_VERSION_INT,
  82. };
  83. /**
  84. * If no filename is given to av_open_input_file because you want to
  85. * get the local port first, then you must call this function to set
  86. * the remote server address.
  87. *
  88. * @param h media file context
  89. * @param uri of the remote server
  90. * @return zero if no error.
  91. */
  92. int ff_rtp_set_remote_url(URLContext *h, const char *uri)
  93. {
  94. RTPContext *s = h->priv_data;
  95. char hostname[256];
  96. int port, rtcp_port;
  97. const char *p;
  98. char buf[1024];
  99. char path[1024];
  100. av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
  101. path, sizeof(path), uri);
  102. rtcp_port = port + 1;
  103. p = strchr(uri, '?');
  104. if (p) {
  105. if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
  106. rtcp_port = strtol(buf, NULL, 10);
  107. }
  108. }
  109. ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path);
  110. ff_udp_set_remote_url(s->rtp_hd, buf);
  111. ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, rtcp_port, "%s", path);
  112. ff_udp_set_remote_url(s->rtcp_hd, buf);
  113. return 0;
  114. }
  115. static struct addrinfo* rtp_resolve_host(const char *hostname, int port,
  116. int type, int family, int flags)
  117. {
  118. struct addrinfo hints = { 0 }, *res = 0;
  119. int error;
  120. char service[16];
  121. snprintf(service, sizeof(service), "%d", port);
  122. hints.ai_socktype = type;
  123. hints.ai_family = family;
  124. hints.ai_flags = flags;
  125. if ((error = getaddrinfo(hostname, service, &hints, &res))) {
  126. res = NULL;
  127. av_log(NULL, AV_LOG_ERROR, "rtp_resolve_host: %s\n", gai_strerror(error));
  128. }
  129. return res;
  130. }
  131. static int compare_addr(const struct sockaddr_storage *a,
  132. const struct sockaddr_storage *b)
  133. {
  134. if (a->ss_family != b->ss_family)
  135. return 1;
  136. if (a->ss_family == AF_INET) {
  137. return (((const struct sockaddr_in *)a)->sin_addr.s_addr !=
  138. ((const struct sockaddr_in *)b)->sin_addr.s_addr);
  139. }
  140. #if HAVE_STRUCT_SOCKADDR_IN6
  141. if (a->ss_family == AF_INET6) {
  142. const uint8_t *s6_addr_a = ((const struct sockaddr_in6 *)a)->sin6_addr.s6_addr;
  143. const uint8_t *s6_addr_b = ((const struct sockaddr_in6 *)b)->sin6_addr.s6_addr;
  144. return memcmp(s6_addr_a, s6_addr_b, 16);
  145. }
  146. #endif
  147. return 1;
  148. }
  149. static int get_port(const struct sockaddr_storage *ss)
  150. {
  151. if (ss->ss_family == AF_INET)
  152. return ntohs(((const struct sockaddr_in *)ss)->sin_port);
  153. #if HAVE_STRUCT_SOCKADDR_IN6
  154. if (ss->ss_family == AF_INET6)
  155. return ntohs(((const struct sockaddr_in6 *)ss)->sin6_port);
  156. #endif
  157. return 0;
  158. }
  159. static void set_port(struct sockaddr_storage *ss, int port)
  160. {
  161. if (ss->ss_family == AF_INET)
  162. ((struct sockaddr_in *)ss)->sin_port = htons(port);
  163. #if HAVE_STRUCT_SOCKADDR_IN6
  164. else if (ss->ss_family == AF_INET6)
  165. ((struct sockaddr_in6 *)ss)->sin6_port = htons(port);
  166. #endif
  167. }
  168. static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr)
  169. {
  170. int i;
  171. if (s->nb_ssm_exclude_addrs) {
  172. for (i = 0; i < s->nb_ssm_exclude_addrs; i++) {
  173. if (!compare_addr(source_addr_ptr, s->ssm_exclude_addrs[i]))
  174. return 1;
  175. }
  176. }
  177. if (s->nb_ssm_include_addrs) {
  178. for (i = 0; i < s->nb_ssm_include_addrs; i++) {
  179. if (!compare_addr(source_addr_ptr, s->ssm_include_addrs[i]))
  180. return 0;
  181. }
  182. return 1;
  183. }
  184. return 0;
  185. }
  186. /**
  187. * add option to url of the form:
  188. * "http://host:port/path?option1=val1&option2=val2...
  189. */
  190. static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const char *fmt, ...)
  191. {
  192. char buf1[1024];
  193. va_list ap;
  194. va_start(ap, fmt);
  195. if (strchr(buf, '?'))
  196. av_strlcat(buf, "&", buf_size);
  197. else
  198. av_strlcat(buf, "?", buf_size);
  199. vsnprintf(buf1, sizeof(buf1), fmt, ap);
  200. av_strlcat(buf, buf1, buf_size);
  201. va_end(ap);
  202. }
  203. static void build_udp_url(RTPContext *s,
  204. char *buf, int buf_size,
  205. const char *hostname,
  206. int port, int local_port,
  207. const char *include_sources,
  208. const char *exclude_sources)
  209. {
  210. ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL);
  211. if (local_port >= 0)
  212. url_add_option(buf, buf_size, "localport=%d", local_port);
  213. if (s->ttl >= 0)
  214. url_add_option(buf, buf_size, "ttl=%d", s->ttl);
  215. if (s->buffer_size >= 0)
  216. url_add_option(buf, buf_size, "buffer_size=%d", s->buffer_size);
  217. if (s->pkt_size >= 0)
  218. url_add_option(buf, buf_size, "pkt_size=%d", s->pkt_size);
  219. if (s->connect)
  220. url_add_option(buf, buf_size, "connect=1");
  221. if (s->dscp >= 0)
  222. url_add_option(buf, buf_size, "dscp=%d", s->dscp);
  223. url_add_option(buf, buf_size, "fifo_size=0");
  224. if (include_sources && include_sources[0])
  225. url_add_option(buf, buf_size, "sources=%s", include_sources);
  226. if (exclude_sources && exclude_sources[0])
  227. url_add_option(buf, buf_size, "block=%s", exclude_sources);
  228. }
  229. static void rtp_parse_addr_list(URLContext *h, char *buf,
  230. struct sockaddr_storage ***address_list_ptr,
  231. int *address_list_size_ptr)
  232. {
  233. struct addrinfo *ai = NULL;
  234. struct sockaddr_storage *source_addr;
  235. char tmp = '\0', *p = buf, *next;
  236. /* Resolve all of the IPs */
  237. while (p && p[0]) {
  238. next = strchr(p, ',');
  239. if (next) {
  240. tmp = *next;
  241. *next = '\0';
  242. }
  243. ai = rtp_resolve_host(p, 0, SOCK_DGRAM, AF_UNSPEC, 0);
  244. if (ai) {
  245. source_addr = av_mallocz(sizeof(struct sockaddr_storage));
  246. if (!source_addr) {
  247. freeaddrinfo(ai);
  248. break;
  249. }
  250. memcpy(source_addr, ai->ai_addr, ai->ai_addrlen);
  251. freeaddrinfo(ai);
  252. dynarray_add(address_list_ptr, address_list_size_ptr, source_addr);
  253. } else {
  254. av_log(h, AV_LOG_WARNING, "Unable to resolve %s\n", p);
  255. }
  256. if (next) {
  257. *next = tmp;
  258. p = next + 1;
  259. } else {
  260. p = NULL;
  261. }
  262. }
  263. }
  264. /**
  265. * url syntax: rtp://host:port[?option=val...]
  266. * option: 'ttl=n' : set the ttl value (for multicast only)
  267. * 'rtcpport=n' : set the remote rtcp port to n
  268. * 'localrtpport=n' : set the local rtp port to n
  269. * 'localrtcpport=n' : set the local rtcp port to n
  270. * 'pkt_size=n' : set max packet size
  271. * 'connect=0/1' : do a connect() on the UDP socket
  272. * 'sources=ip[,ip]' : list allowed source IP addresses
  273. * 'block=ip[,ip]' : list disallowed source IP addresses
  274. * 'write_to_source=0/1' : send packets to the source address of the latest received packet
  275. * 'dscp=n' : set DSCP value to n (QoS)
  276. * deprecated option:
  277. * 'localport=n' : set the local port to n
  278. *
  279. * if rtcpport isn't set the rtcp port will be the rtp port + 1
  280. * if local rtp port isn't set any available port will be used for the local
  281. * rtp and rtcp ports
  282. * if the local rtcp port is not set it will be the local rtp port + 1
  283. */
  284. static int rtp_open(URLContext *h, const char *uri, int flags)
  285. {
  286. RTPContext *s = h->priv_data;
  287. AVDictionary *fec_opts = NULL;
  288. int rtp_port;
  289. char hostname[256], include_sources[1024] = "", exclude_sources[1024] = "";
  290. char *sources = include_sources, *block = exclude_sources;
  291. char *fec_protocol = NULL;
  292. char buf[1024];
  293. char path[1024];
  294. const char *p;
  295. int i, max_retry_count = 3;
  296. int rtcpflags;
  297. av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
  298. path, sizeof(path), uri);
  299. /* extract parameters */
  300. if (s->rtcp_port < 0)
  301. s->rtcp_port = rtp_port + 1;
  302. p = strchr(uri, '?');
  303. if (p) {
  304. if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
  305. s->ttl = strtol(buf, NULL, 10);
  306. }
  307. if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
  308. s->rtcp_port = strtol(buf, NULL, 10);
  309. }
  310. if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
  311. s->local_rtpport = strtol(buf, NULL, 10);
  312. }
  313. if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) {
  314. s->local_rtpport = strtol(buf, NULL, 10);
  315. }
  316. if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) {
  317. s->local_rtcpport = strtol(buf, NULL, 10);
  318. }
  319. if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
  320. s->pkt_size = strtol(buf, NULL, 10);
  321. }
  322. if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
  323. s->connect = strtol(buf, NULL, 10);
  324. }
  325. if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) {
  326. s->write_to_source = strtol(buf, NULL, 10);
  327. }
  328. if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
  329. s->dscp = strtol(buf, NULL, 10);
  330. }
  331. if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
  332. av_strlcpy(include_sources, buf, sizeof(include_sources));
  333. rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs);
  334. } else {
  335. rtp_parse_addr_list(h, s->sources, &s->ssm_include_addrs, &s->nb_ssm_include_addrs);
  336. sources = s->sources;
  337. }
  338. if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
  339. av_strlcpy(exclude_sources, buf, sizeof(exclude_sources));
  340. rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs);
  341. } else {
  342. rtp_parse_addr_list(h, s->block, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs);
  343. block = s->block;
  344. }
  345. }
  346. if (s->fec_options_str) {
  347. p = s->fec_options_str;
  348. if (!(fec_protocol = av_get_token(&p, "="))) {
  349. av_log(h, AV_LOG_ERROR, "Failed to parse the FEC protocol value\n");
  350. goto fail;
  351. }
  352. if (strcmp(fec_protocol, "prompeg")) {
  353. av_log(h, AV_LOG_ERROR, "Unsupported FEC protocol %s\n", fec_protocol);
  354. goto fail;
  355. }
  356. p = s->fec_options_str + strlen(fec_protocol);
  357. while (*p && *p == '=') p++;
  358. if (av_dict_parse_string(&fec_opts, p, "=", ":", 0) < 0) {
  359. av_log(h, AV_LOG_ERROR, "Failed to parse the FEC options\n");
  360. goto fail;
  361. }
  362. if (s->ttl > 0) {
  363. snprintf(buf, sizeof (buf), "%d", s->ttl);
  364. av_dict_set(&fec_opts, "ttl", buf, 0);
  365. }
  366. }
  367. for (i = 0; i < max_retry_count; i++) {
  368. build_udp_url(s, buf, sizeof(buf),
  369. hostname, rtp_port, s->local_rtpport,
  370. sources, block);
  371. if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
  372. NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
  373. goto fail;
  374. s->local_rtpport = ff_udp_get_local_port(s->rtp_hd);
  375. if(s->local_rtpport == 65535) {
  376. s->local_rtpport = -1;
  377. continue;
  378. }
  379. rtcpflags = flags | AVIO_FLAG_WRITE;
  380. if (s->local_rtcpport < 0) {
  381. s->local_rtcpport = s->local_rtpport + 1;
  382. build_udp_url(s, buf, sizeof(buf),
  383. hostname, s->rtcp_port, s->local_rtcpport,
  384. sources, block);
  385. if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
  386. &h->interrupt_callback, NULL,
  387. h->protocol_whitelist, h->protocol_blacklist, h) < 0) {
  388. s->local_rtpport = s->local_rtcpport = -1;
  389. continue;
  390. }
  391. break;
  392. }
  393. build_udp_url(s, buf, sizeof(buf),
  394. hostname, s->rtcp_port, s->local_rtcpport,
  395. sources, block);
  396. if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
  397. NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
  398. goto fail;
  399. break;
  400. }
  401. s->fec_hd = NULL;
  402. if (fec_protocol) {
  403. ff_url_join(buf, sizeof(buf), fec_protocol, NULL, hostname, rtp_port, NULL);
  404. if (ffurl_open_whitelist(&s->fec_hd, buf, flags, &h->interrupt_callback,
  405. &fec_opts, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
  406. goto fail;
  407. }
  408. /* just to ease handle access. XXX: need to suppress direct handle
  409. access */
  410. s->rtp_fd = ffurl_get_file_handle(s->rtp_hd);
  411. s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd);
  412. h->max_packet_size = s->rtp_hd->max_packet_size;
  413. h->is_streamed = 1;
  414. av_free(fec_protocol);
  415. av_dict_free(&fec_opts);
  416. return 0;
  417. fail:
  418. if (s->rtp_hd)
  419. ffurl_close(s->rtp_hd);
  420. if (s->rtcp_hd)
  421. ffurl_close(s->rtcp_hd);
  422. ffurl_closep(&s->fec_hd);
  423. av_free(fec_protocol);
  424. av_dict_free(&fec_opts);
  425. return AVERROR(EIO);
  426. }
  427. static int rtp_read(URLContext *h, uint8_t *buf, int size)
  428. {
  429. RTPContext *s = h->priv_data;
  430. int len, n, i;
  431. struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
  432. int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100;
  433. struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source };
  434. socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len };
  435. for(;;) {
  436. if (ff_check_interrupt(&h->interrupt_callback))
  437. return AVERROR_EXIT;
  438. n = poll(p, 2, poll_delay);
  439. if (n > 0) {
  440. /* first try RTCP, then RTP */
  441. for (i = 1; i >= 0; i--) {
  442. if (!(p[i].revents & POLLIN))
  443. continue;
  444. *addr_lens[i] = sizeof(*addrs[i]);
  445. len = recvfrom(p[i].fd, buf, size, 0,
  446. (struct sockaddr *)addrs[i], addr_lens[i]);
  447. if (len < 0) {
  448. if (ff_neterrno() == AVERROR(EAGAIN) ||
  449. ff_neterrno() == AVERROR(EINTR))
  450. continue;
  451. return AVERROR(EIO);
  452. }
  453. if (rtp_check_source_lists(s, addrs[i]))
  454. continue;
  455. return len;
  456. }
  457. } else if (n < 0) {
  458. if (ff_neterrno() == AVERROR(EINTR))
  459. continue;
  460. return AVERROR(EIO);
  461. }
  462. if (h->flags & AVIO_FLAG_NONBLOCK)
  463. return AVERROR(EAGAIN);
  464. }
  465. }
  466. static int rtp_write(URLContext *h, const uint8_t *buf, int size)
  467. {
  468. RTPContext *s = h->priv_data;
  469. int ret, ret_fec;
  470. URLContext *hd;
  471. if (size < 2)
  472. return AVERROR(EINVAL);
  473. if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
  474. av_log(h, AV_LOG_WARNING, "Data doesn't look like RTP packets, "
  475. "make sure the RTP muxer is used\n");
  476. if (s->write_to_source) {
  477. int fd;
  478. struct sockaddr_storage *source, temp_source;
  479. socklen_t *source_len, temp_len;
  480. if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) {
  481. av_log(h, AV_LOG_ERROR,
  482. "Unable to send packet to source, no packets received yet\n");
  483. // Intentionally not returning an error here
  484. return size;
  485. }
  486. if (RTP_PT_IS_RTCP(buf[1])) {
  487. fd = s->rtcp_fd;
  488. source = &s->last_rtcp_source;
  489. source_len = &s->last_rtcp_source_len;
  490. } else {
  491. fd = s->rtp_fd;
  492. source = &s->last_rtp_source;
  493. source_len = &s->last_rtp_source_len;
  494. }
  495. if (!source->ss_family) {
  496. source = &temp_source;
  497. source_len = &temp_len;
  498. if (RTP_PT_IS_RTCP(buf[1])) {
  499. temp_source = s->last_rtp_source;
  500. temp_len = s->last_rtp_source_len;
  501. set_port(source, get_port(source) + 1);
  502. av_log(h, AV_LOG_INFO,
  503. "Not received any RTCP packets yet, inferring peer port "
  504. "from the RTP port\n");
  505. } else {
  506. temp_source = s->last_rtcp_source;
  507. temp_len = s->last_rtcp_source_len;
  508. set_port(source, get_port(source) - 1);
  509. av_log(h, AV_LOG_INFO,
  510. "Not received any RTP packets yet, inferring peer port "
  511. "from the RTCP port\n");
  512. }
  513. }
  514. if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
  515. ret = ff_network_wait_fd(fd, 1);
  516. if (ret < 0)
  517. return ret;
  518. }
  519. ret = sendto(fd, buf, size, 0, (struct sockaddr *) source,
  520. *source_len);
  521. return ret < 0 ? ff_neterrno() : ret;
  522. }
  523. if (RTP_PT_IS_RTCP(buf[1])) {
  524. /* RTCP payload type */
  525. hd = s->rtcp_hd;
  526. } else {
  527. /* RTP payload type */
  528. hd = s->rtp_hd;
  529. }
  530. if ((ret = ffurl_write(hd, buf, size)) < 0) {
  531. return ret;
  532. }
  533. if (s->fec_hd && !RTP_PT_IS_RTCP(buf[1])) {
  534. if ((ret_fec = ffurl_write(s->fec_hd, buf, size)) < 0) {
  535. av_log(h, AV_LOG_ERROR, "Failed to send FEC\n");
  536. return ret_fec;
  537. }
  538. }
  539. return ret;
  540. }
  541. static int rtp_close(URLContext *h)
  542. {
  543. RTPContext *s = h->priv_data;
  544. int i;
  545. for (i = 0; i < s->nb_ssm_include_addrs; i++)
  546. av_freep(&s->ssm_include_addrs[i]);
  547. av_freep(&s->ssm_include_addrs);
  548. for (i = 0; i < s->nb_ssm_exclude_addrs; i++)
  549. av_freep(&s->ssm_exclude_addrs[i]);
  550. av_freep(&s->ssm_exclude_addrs);
  551. ffurl_close(s->rtp_hd);
  552. ffurl_close(s->rtcp_hd);
  553. ffurl_closep(&s->fec_hd);
  554. return 0;
  555. }
  556. /**
  557. * Return the local rtp port used by the RTP connection
  558. * @param h media file context
  559. * @return the local port number
  560. */
  561. int ff_rtp_get_local_rtp_port(URLContext *h)
  562. {
  563. RTPContext *s = h->priv_data;
  564. return ff_udp_get_local_port(s->rtp_hd);
  565. }
  566. /**
  567. * Return the local rtcp port used by the RTP connection
  568. * @param h media file context
  569. * @return the local port number
  570. */
  571. static int rtp_get_file_handle(URLContext *h)
  572. {
  573. RTPContext *s = h->priv_data;
  574. return s->rtp_fd;
  575. }
  576. static int rtp_get_multi_file_handle(URLContext *h, int **handles,
  577. int *numhandles)
  578. {
  579. RTPContext *s = h->priv_data;
  580. int *hs = *handles = av_malloc(sizeof(**handles) * 2);
  581. if (!hs)
  582. return AVERROR(ENOMEM);
  583. hs[0] = s->rtp_fd;
  584. hs[1] = s->rtcp_fd;
  585. *numhandles = 2;
  586. return 0;
  587. }
  588. const URLProtocol ff_rtp_protocol = {
  589. .name = "rtp",
  590. .url_open = rtp_open,
  591. .url_read = rtp_read,
  592. .url_write = rtp_write,
  593. .url_close = rtp_close,
  594. .url_get_file_handle = rtp_get_file_handle,
  595. .url_get_multi_file_handle = rtp_get_multi_file_handle,
  596. .priv_data_size = sizeof(RTPContext),
  597. .flags = URL_PROTOCOL_FLAG_NETWORK,
  598. .priv_data_class = &rtp_class,
  599. };