MediaProcessors
tsudpsend.c
1 /*
2  * Copyright (C) 2008-2013, Lorenzo Pallara l.pallara@avalpa.com
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 
20 #define MULTICAST
21 
22 #include "tsudpsend.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #include <arpa/inet.h>
33 #include <unistd.h>
34 #include <time.h>
35 
36 #define TS_PACKET_SIZE 188
37 
38 //long long int usecDiff(struct timespec* time_stop, struct timespec* time_start)
39 static long long int usecDiff(struct timespec* time_stop, struct timespec* time_start) //RAL
40 {
41  long long int temp = 0;
42  long long int utemp = 0;
43 
44  if (time_stop && time_start) {
45  if (time_stop->tv_nsec >= time_start->tv_nsec) {
46  utemp = time_stop->tv_nsec - time_start->tv_nsec;
47  temp = time_stop->tv_sec - time_start->tv_sec;
48  } else {
49  utemp = time_stop->tv_nsec + 1000000000 - time_start->tv_nsec;
50  temp = time_stop->tv_sec - 1 - time_start->tv_sec;
51  }
52  if (temp >= 0 && utemp >= 0) {
53  temp = (temp * 1000000000) + utemp;
54  } else {
55  fprintf(stderr, "start time %ld.%ld is after stop time %ld.%ld\n", time_start->tv_sec, time_start->tv_nsec, time_stop->tv_sec, time_stop->tv_nsec);
56  temp = -1;
57  }
58  } else {
59  fprintf(stderr, "memory is garbaged?\n");
60  temp = -1;
61  }
62  return temp / 1000;
63 }
64 
65 
66 //int main (int argc, char *argv[]) {
67 int tsudpsend(int argc, char *argv[], volatile int *exit_flag) //RAL
68 {
69  int sockfd;
70  int len;
71  int sent;
72  int ret;
73  int is_multicast;
74  int transport_fd;
75  unsigned char option_ttl;
76  char start_addr[4];
77  struct sockaddr_in addr;
78  unsigned long int packet_size;
79  char* tsfile;
80  unsigned char* send_buf;
81  unsigned int bitrate;
82  unsigned long long int packet_time;
83  unsigned long long int real_time;
84  struct timespec time_start;
85  struct timespec time_stop;
86  struct timespec nano_sleep_packet;
87 
88  //printf("%s %d\n", __FILE__, __LINE__); //RAL
89 
90  memset(&addr, 0, sizeof(addr));
91  memset(&time_start, 0, sizeof(time_start));
92  memset(&time_stop, 0, sizeof(time_stop));
93  memset(&nano_sleep_packet, 0, sizeof(nano_sleep_packet));
94 
95  if(argc < 5 ) {
96  fprintf(stderr, "Usage: %s file.ts ipaddr port bitrate [ts_packet_per_ip_packet] [udp_packet_ttl]\n", argv[0]);
97  fprintf(stderr, "ts_packet_per_ip_packet default is 7\n");
98  fprintf(stderr, "bit rate refers to transport stream bit rate\n");
99  fprintf(stderr, "zero bitrate is 100.000.000 bps\n");
100  return 0;
101  } else {
102  tsfile = argv[1];
103  addr.sin_family = AF_INET;
104  addr.sin_addr.s_addr = inet_addr(argv[2]);
105  addr.sin_port = htons(atoi(argv[3]));
106  bitrate = atoi(argv[4]);
107  if (bitrate <= 0) {
108  bitrate = 100000000;
109  }
110  if (argc >= 6) {
111  packet_size = strtoul(argv[5], 0, 0) * TS_PACKET_SIZE;
112  } else {
113  packet_size = 7 * TS_PACKET_SIZE;
114  }
115  }
116 
117  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
118  if(sockfd < 0) {
119  perror("socket(): error ");
120  return 0;
121  }
122 
123  if (argc >= 7) {
124  option_ttl = atoi(argv[6]);
125  is_multicast = 0;
126  memcpy(start_addr, argv[2], 3);
127  start_addr[3] = 0;
128  is_multicast = atoi(start_addr);
129  is_multicast = (is_multicast >= 224) || (is_multicast <= 239);
130  if (is_multicast) {
131  ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &option_ttl, sizeof(option_ttl));
132  } else {
133  ret = setsockopt(sockfd, IPPROTO_IP, IP_TTL, &option_ttl, sizeof(option_ttl));
134  }
135 
136  if(ret < 0) {
137  perror("ttl configuration fail");
138  }
139 
140  }
141 
142  transport_fd = open(tsfile, O_RDONLY);
143  if(transport_fd < 0) {
144  fprintf(stderr, "can't open file %s\n", tsfile);
145  close(sockfd);
146  return 0;
147  }
148 
149  int completed = 0;
150  send_buf = malloc(packet_size);
151  packet_time = 0;
152  real_time = 0;
153 
154  nano_sleep_packet.tv_nsec = 665778; /* 1 packet at 100mbps*/
155 
156  clock_gettime(CLOCK_MONOTONIC, &time_start);
157 
158  //while (!completed) {
159  printf("starting streaming... \n"); //RAL
160  while (!completed && !(*exit_flag) ) { //RAL
161  //printf("."); // Comment-me
162 
163  clock_gettime(CLOCK_MONOTONIC, &time_stop);
164  real_time = usecDiff(&time_stop, &time_start);
165  while (real_time * bitrate > packet_time * 1000000 && !completed &&
166  !(*exit_flag)) { /* theorical bits against sent bits */
167  len = read(transport_fd, send_buf, packet_size);
168  if(len < 0) {
169  fprintf(stderr, "ts file read error \n");
170  completed = 1;
171  } else if (len == 0) {
172  fprintf(stderr, "ts sent done\n");
173  completed = 1;
174  } else {
175  sent = sendto(sockfd, send_buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
176  if(sent <= 0) {
177  perror("send(): error ");
178  completed = 1;
179  } else {
180  packet_time += packet_size * 8;
181  }
182  }
183  }
184  nanosleep(&nano_sleep_packet, 0);
185  }
186 
187  close(transport_fd);
188  close(sockfd);
189  free(send_buf);
190  return 0;
191 }
Header file for 3rd party source code "tsudpsend.c".