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.

338 lines
8.8KB

  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 libavformat/rtpproto.c
  23. * RTP protocol
  24. */
  25. #include "libavutil/avstring.h"
  26. #include "avformat.h"
  27. #include "rtpdec.h"
  28. #include <unistd.h>
  29. #include <stdarg.h>
  30. #include "network.h"
  31. #include "os_support.h"
  32. #include <fcntl.h>
  33. #if HAVE_SYS_SELECT_H
  34. #include <sys/select.h>
  35. #endif
  36. #define RTP_TX_BUF_SIZE (64 * 1024)
  37. #define RTP_RX_BUF_SIZE (128 * 1024)
  38. typedef struct RTPContext {
  39. URLContext *rtp_hd, *rtcp_hd;
  40. int rtp_fd, rtcp_fd;
  41. } RTPContext;
  42. /**
  43. * If no filename is given to av_open_input_file because you want to
  44. * get the local port first, then you must call this function to set
  45. * the remote server address.
  46. *
  47. * @param s1 media file context
  48. * @param uri of the remote server
  49. * @return zero if no error.
  50. */
  51. int rtp_set_remote_url(URLContext *h, const char *uri)
  52. {
  53. RTPContext *s = h->priv_data;
  54. char hostname[256];
  55. int port;
  56. char buf[1024];
  57. char path[1024];
  58. ff_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
  59. path, sizeof(path), uri);
  60. ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path);
  61. udp_set_remote_url(s->rtp_hd, buf);
  62. ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port + 1, "%s", path);
  63. udp_set_remote_url(s->rtcp_hd, buf);
  64. return 0;
  65. }
  66. /**
  67. * add option to url of the form:
  68. * "http://host:port/path?option1=val1&option2=val2...
  69. */
  70. static void url_add_option(char *buf, int buf_size, const char *fmt, ...)
  71. {
  72. char buf1[1024];
  73. va_list ap;
  74. va_start(ap, fmt);
  75. if (strchr(buf, '?'))
  76. av_strlcat(buf, "&", buf_size);
  77. else
  78. av_strlcat(buf, "?", buf_size);
  79. vsnprintf(buf1, sizeof(buf1), fmt, ap);
  80. av_strlcat(buf, buf1, buf_size);
  81. va_end(ap);
  82. }
  83. static void build_udp_url(char *buf, int buf_size,
  84. const char *hostname, int port,
  85. int local_port, int ttl,
  86. int max_packet_size)
  87. {
  88. ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL);
  89. if (local_port >= 0)
  90. url_add_option(buf, buf_size, "localport=%d", local_port);
  91. if (ttl >= 0)
  92. url_add_option(buf, buf_size, "ttl=%d", ttl);
  93. if (max_packet_size >=0)
  94. url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size);
  95. }
  96. /**
  97. * url syntax: rtp://host:port[?option=val...]
  98. * option: 'ttl=n' : set the ttl value (for multicast only)
  99. * 'localport=n' : set the local port to n
  100. * 'pkt_size=n' : set max packet size
  101. *
  102. */
  103. static int rtp_open(URLContext *h, const char *uri, int flags)
  104. {
  105. RTPContext *s;
  106. int port, is_output, ttl, local_port, max_packet_size;
  107. char hostname[256];
  108. char buf[1024];
  109. char path[1024];
  110. const char *p;
  111. is_output = (flags & URL_WRONLY);
  112. s = av_mallocz(sizeof(RTPContext));
  113. if (!s)
  114. return AVERROR(ENOMEM);
  115. h->priv_data = s;
  116. ff_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
  117. path, sizeof(path), uri);
  118. /* extract parameters */
  119. ttl = -1;
  120. local_port = -1;
  121. max_packet_size = -1;
  122. p = strchr(uri, '?');
  123. if (p) {
  124. if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
  125. ttl = strtol(buf, NULL, 10);
  126. }
  127. if (find_info_tag(buf, sizeof(buf), "localport", p)) {
  128. local_port = strtol(buf, NULL, 10);
  129. }
  130. if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
  131. max_packet_size = strtol(buf, NULL, 10);
  132. }
  133. }
  134. build_udp_url(buf, sizeof(buf),
  135. hostname, port, local_port, ttl, max_packet_size);
  136. if (url_open(&s->rtp_hd, buf, flags) < 0)
  137. goto fail;
  138. local_port = udp_get_local_port(s->rtp_hd);
  139. /* XXX: need to open another connection if the port is not even */
  140. /* well, should suppress localport in path */
  141. build_udp_url(buf, sizeof(buf),
  142. hostname, port + 1, local_port + 1, ttl, max_packet_size);
  143. if (url_open(&s->rtcp_hd, buf, flags) < 0)
  144. goto fail;
  145. /* just to ease handle access. XXX: need to suppress direct handle
  146. access */
  147. s->rtp_fd = url_get_file_handle(s->rtp_hd);
  148. s->rtcp_fd = url_get_file_handle(s->rtcp_hd);
  149. h->max_packet_size = url_get_max_packet_size(s->rtp_hd);
  150. h->is_streamed = 1;
  151. return 0;
  152. fail:
  153. if (s->rtp_hd)
  154. url_close(s->rtp_hd);
  155. if (s->rtcp_hd)
  156. url_close(s->rtcp_hd);
  157. av_free(s);
  158. return AVERROR(EIO);
  159. }
  160. static int rtp_read(URLContext *h, uint8_t *buf, int size)
  161. {
  162. RTPContext *s = h->priv_data;
  163. struct sockaddr_in from;
  164. socklen_t from_len;
  165. int len, fd_max, n;
  166. fd_set rfds;
  167. struct timeval tv;
  168. #if 0
  169. for(;;) {
  170. from_len = sizeof(from);
  171. len = recvfrom (s->rtp_fd, buf, size, 0,
  172. (struct sockaddr *)&from, &from_len);
  173. if (len < 0) {
  174. if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
  175. ff_neterrno() == FF_NETERROR(EINTR))
  176. continue;
  177. return AVERROR(EIO);
  178. }
  179. break;
  180. }
  181. #else
  182. for(;;) {
  183. if (url_interrupt_cb())
  184. return AVERROR(EINTR);
  185. /* build fdset to listen to RTP and RTCP packets */
  186. FD_ZERO(&rfds);
  187. fd_max = s->rtp_fd;
  188. FD_SET(s->rtp_fd, &rfds);
  189. if (s->rtcp_fd > fd_max)
  190. fd_max = s->rtcp_fd;
  191. FD_SET(s->rtcp_fd, &rfds);
  192. tv.tv_sec = 0;
  193. tv.tv_usec = 100 * 1000;
  194. n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
  195. if (n > 0) {
  196. /* first try RTCP */
  197. if (FD_ISSET(s->rtcp_fd, &rfds)) {
  198. from_len = sizeof(from);
  199. len = recvfrom (s->rtcp_fd, buf, size, 0,
  200. (struct sockaddr *)&from, &from_len);
  201. if (len < 0) {
  202. if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
  203. ff_neterrno() == FF_NETERROR(EINTR))
  204. continue;
  205. return AVERROR(EIO);
  206. }
  207. break;
  208. }
  209. /* then RTP */
  210. if (FD_ISSET(s->rtp_fd, &rfds)) {
  211. from_len = sizeof(from);
  212. len = recvfrom (s->rtp_fd, buf, size, 0,
  213. (struct sockaddr *)&from, &from_len);
  214. if (len < 0) {
  215. if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
  216. ff_neterrno() == FF_NETERROR(EINTR))
  217. continue;
  218. return AVERROR(EIO);
  219. }
  220. break;
  221. }
  222. } else if (n < 0) {
  223. return AVERROR(EIO);
  224. }
  225. }
  226. #endif
  227. return len;
  228. }
  229. static int rtp_write(URLContext *h, uint8_t *buf, int size)
  230. {
  231. RTPContext *s = h->priv_data;
  232. int ret;
  233. URLContext *hd;
  234. if (buf[1] >= 200 && buf[1] <= 204) {
  235. /* RTCP payload type */
  236. hd = s->rtcp_hd;
  237. } else {
  238. /* RTP payload type */
  239. hd = s->rtp_hd;
  240. }
  241. ret = url_write(hd, buf, size);
  242. #if 0
  243. {
  244. struct timespec ts;
  245. ts.tv_sec = 0;
  246. ts.tv_nsec = 10 * 1000000;
  247. nanosleep(&ts, NULL);
  248. }
  249. #endif
  250. return ret;
  251. }
  252. static int rtp_close(URLContext *h)
  253. {
  254. RTPContext *s = h->priv_data;
  255. url_close(s->rtp_hd);
  256. url_close(s->rtcp_hd);
  257. av_free(s);
  258. return 0;
  259. }
  260. /**
  261. * Return the local port used by the RTP connection
  262. * @param s1 media file context
  263. * @return the local port number
  264. */
  265. int rtp_get_local_port(URLContext *h)
  266. {
  267. RTPContext *s = h->priv_data;
  268. return udp_get_local_port(s->rtp_hd);
  269. }
  270. #if (LIBAVFORMAT_VERSION_MAJOR <= 52)
  271. /**
  272. * Return the rtp and rtcp file handles for select() usage to wait for
  273. * several RTP streams at the same time.
  274. * @param h media file context
  275. */
  276. void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd)
  277. {
  278. RTPContext *s = h->priv_data;
  279. *prtp_fd = s->rtp_fd;
  280. *prtcp_fd = s->rtcp_fd;
  281. }
  282. #endif
  283. static int rtp_get_file_handle(URLContext *h)
  284. {
  285. RTPContext *s = h->priv_data;
  286. return s->rtp_fd;
  287. }
  288. URLProtocol rtp_protocol = {
  289. "rtp",
  290. rtp_open,
  291. rtp_read,
  292. rtp_write,
  293. NULL, /* seek */
  294. rtp_close,
  295. .url_get_file_handle = rtp_get_file_handle,
  296. };