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.

124 lines
3.2KB

  1. /*
  2. * UDP prototype streaming system
  3. * Copyright (c) 2000 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <arpa/inet.h>
  27. #include <netdb.h>
  28. #include "mpegenc.h"
  29. #define UDP_TX_BUF_SIZE 32768
  30. /* put it in UDP context */
  31. static struct sockaddr_in dest_addr;
  32. /* return non zero if error */
  33. int udp_tx_open(UDPContext *s,
  34. const char *uri,
  35. int local_port)
  36. {
  37. struct sockaddr_in my_addr;
  38. const char *p, *q;
  39. char hostname[1024];
  40. int port, udp_socket, tmp;
  41. struct hostent *hp;
  42. /* fill the dest addr */
  43. p = uri;
  44. if (!strstart(p, "udp:", &p))
  45. return -1;
  46. q = strchr(p, ':');
  47. if (!q)
  48. return -1;
  49. memcpy(hostname, p, q - p);
  50. hostname[q - p] = '\0';
  51. port = strtol(q+1, NULL, 10);
  52. if (port <= 0)
  53. return -1;
  54. dest_addr.sin_family = AF_INET;
  55. dest_addr.sin_port = htons(port);
  56. if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) {
  57. hp = gethostbyname(hostname);
  58. if (!hp)
  59. return -1;
  60. memcpy ((char *) &dest_addr.sin_addr, hp->h_addr, hp->h_length);
  61. }
  62. udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
  63. if (udp_socket < 0)
  64. return -1;
  65. my_addr.sin_family = AF_INET;
  66. my_addr.sin_port = htons(local_port);
  67. my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  68. /* the bind is needed to give a port to the socket now */
  69. if (bind(udp_socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
  70. goto fail;
  71. /* limit the tx buf size to limit latency */
  72. tmp = UDP_TX_BUF_SIZE;
  73. if (setsockopt(udp_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
  74. perror("setsockopt sndbuf");
  75. goto fail;
  76. }
  77. s->udp_socket = udp_socket;
  78. s->max_payload_size = 1024;
  79. return 0;
  80. fail:
  81. return -1;
  82. }
  83. void udp_tx_close(UDPContext *s)
  84. {
  85. close(s->udp_socket);
  86. }
  87. extern int data_out_size;
  88. void udp_write_data(void *opaque, UINT8 *buf, int size)
  89. {
  90. UDPContext *s = opaque;
  91. int ret, len;
  92. /* primitive way to avoid big packets */
  93. data_out_size += size;
  94. while (size > 0) {
  95. len = size;
  96. if (len > s->max_payload_size)
  97. len = s->max_payload_size;
  98. ret = sendto (s->udp_socket, buf, len, 0,
  99. (struct sockaddr *) &dest_addr,
  100. sizeof (dest_addr));
  101. if (ret < 0)
  102. perror("sendto");
  103. buf += len;
  104. size -= len;
  105. }
  106. }