Mercurial > mplayer.hg
annotate libmpdemux/rtp.c @ 17267:123b780115e7
for roff: add missing linebreak in uspp description
author | wanderer |
---|---|
date | Fri, 30 Dec 2005 05:08:37 +0000 |
parents | 5dcc5524cb68 |
children | 028e4c7a749e |
rev | line source |
---|---|
15178
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
1 /* Imported from the dvbstream-0.2 project |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
2 * |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
3 * Modified for use with MPlayer, for details see the CVS changelog at |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
4 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
5 * $Id$ |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
6 */ |
8dd7a656eaf8
Mark modified imported files as such to comply more closely with GPL ¡ø2a.
diego
parents:
12799
diff
changeset
|
7 |
3686 | 8 #include <stdlib.h> |
9 #include <string.h> | |
3716 | 10 #include <unistd.h> |
3686 | 11 #include <stdlib.h> |
12 #include <stdio.h> | |
13 #include <sys/types.h> | |
15585 | 14 #include <ctype.h> |
10281 | 15 #include "config.h" |
16 #ifndef HAVE_WINSOCK2 | |
17 #include <netinet/in.h> | |
3686 | 18 #include <sys/socket.h> |
19 #include <arpa/inet.h> | |
15585 | 20 #define closesocket close |
10281 | 21 #else |
22 #include <winsock2.h> | |
23 #include <ws2tcpip.h> | |
24 #endif | |
15585 | 25 #include <errno.h> |
26 #include "stream.h" | |
3686 | 27 |
28 /* MPEG-2 TS RTP stack */ | |
29 | |
30 #define DEBUG 1 | |
31 #include "rtp.h" | |
32 | |
15585 | 33 extern int network_bandwidth; |
34 | |
35 int read_rtp_from_server(int fd, char *buffer, int length) { | |
36 struct rtpheader rh; | |
37 char *data; | |
38 int len; | |
39 static int got_first = 0; | |
40 static unsigned short sequence; | |
41 | |
42 if( buffer==NULL || length<0 ) return -1; | |
43 | |
44 getrtp2(fd, &rh, &data, &len); | |
45 if( got_first && rh.b.sequence != (unsigned short)(sequence+1) ) | |
46 mp_msg(MSGT_NETWORK,MSGL_ERR,"RTP packet sequence error! Expected: %d, received: %d\n", | |
47 sequence+1, rh.b.sequence); | |
48 got_first = 1; | |
49 sequence = rh.b.sequence; | |
50 memcpy(buffer, data, len); | |
51 return(len); | |
52 } | |
53 | |
54 | |
55 // Start listening on a UDP port. If multicast, join the group. | |
56 static int rtp_open_socket( URL_t *url ) { | |
57 int socket_server_fd, rxsockbufsz; | |
58 int err, err_len; | |
59 fd_set set; | |
60 struct sockaddr_in server_address; | |
61 struct ip_mreq mcast; | |
62 struct timeval tv; | |
63 struct hostent *hp; | |
64 | |
65 mp_msg(MSGT_NETWORK,MSGL_V,"Listening for traffic on %s:%d ...\n", url->hostname, url->port ); | |
66 | |
67 socket_server_fd = socket(AF_INET, SOCK_DGRAM, 0); | |
68 // fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); | |
69 if( socket_server_fd==-1 ) { | |
70 mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create socket\n"); | |
71 return -1; | |
72 } | |
73 | |
74 if( isalpha(url->hostname[0]) ) { | |
75 #ifndef HAVE_WINSOCK2 | |
76 hp =(struct hostent*)gethostbyname( url->hostname ); | |
77 if( hp==NULL ) { | |
78 mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
79 goto err_out; |
15585 | 80 } |
81 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); | |
82 #else | |
83 server_address.sin_addr.s_addr = htonl(INADDR_ANY); | |
84 #endif | |
85 } else { | |
86 #ifndef HAVE_WINSOCK2 | |
87 #ifdef USE_ATON | |
88 inet_aton(url->hostname, &server_address.sin_addr); | |
89 #else | |
90 inet_pton(AF_INET, url->hostname, &server_address.sin_addr); | |
91 #endif | |
92 #else | |
93 server_address.sin_addr.s_addr = htonl(INADDR_ANY); | |
94 #endif | |
95 } | |
96 server_address.sin_family=AF_INET; | |
97 server_address.sin_port=htons(url->port); | |
98 | |
99 if( bind( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { | |
100 #ifndef HAVE_WINSOCK2 | |
101 if( errno!=EINPROGRESS ) { | |
102 #else | |
103 if( WSAGetLastError() != WSAEINPROGRESS ) { | |
104 #endif | |
105 mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to connect to server\n"); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
106 goto err_out; |
15585 | 107 } |
108 } | |
109 | |
110 #ifdef HAVE_WINSOCK2 | |
111 if (isalpha(url->hostname[0])) { | |
112 hp =(struct hostent*)gethostbyname( url->hostname ); | |
113 if( hp==NULL ) { | |
114 mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
115 goto err_out; |
15585 | 116 } |
117 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); | |
118 } else { | |
119 unsigned int addr = inet_addr(url->hostname); | |
120 memcpy( (void*)&server_address.sin_addr, (void*)&addr, sizeof(addr) ); | |
121 } | |
122 #endif | |
123 | |
124 // Increase the socket rx buffer size to maximum -- this is UDP | |
125 rxsockbufsz = 240 * 1024; | |
126 if( setsockopt( socket_server_fd, SOL_SOCKET, SO_RCVBUF, &rxsockbufsz, sizeof(rxsockbufsz))) { | |
127 mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't set receive socket buffer size\n"); | |
128 } | |
129 | |
130 if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) { | |
131 mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr; | |
132 //mcast.imr_interface.s_addr = inet_addr("10.1.1.2"); | |
133 mcast.imr_interface.s_addr = 0; | |
134 if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) { | |
135 mp_msg(MSGT_NETWORK,MSGL_ERR,"IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n"); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
136 goto err_out; |
15585 | 137 } |
138 } | |
139 | |
140 tv.tv_sec = 0; | |
141 tv.tv_usec = (1 * 1000000); // 1 second timeout | |
142 FD_ZERO( &set ); | |
143 FD_SET( socket_server_fd, &set ); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
144 err = select(socket_server_fd+1, &set, NULL, NULL, &tv); |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
145 if (err < 0) { |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
146 mp_msg(MSGT_NETWORK, MSGL_FATAL, "Select failed: %s\n", strerror(errno)); |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
147 goto err_out; |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
148 } |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
149 if (err == 0) { |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
150 mp_msg(MSGT_NETWORK,MSGL_ERR,"Timeout! No data from host %s\n", url->hostname ); |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
151 goto err_out; |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
152 } |
15585 | 153 err_len = sizeof( err ); |
154 getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); | |
155 if( err ) { | |
156 mp_msg(MSGT_NETWORK,MSGL_DBG2,"Socket error: %d\n", err ); | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
157 goto err_out; |
15585 | 158 } |
159 return socket_server_fd; | |
15760
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
160 |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
161 err_out: |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
162 closesocket(socket_server_fd); |
5dcc5524cb68
fix wrong usage of select() (based on patch by Selwyn Tang selwyn hectrix com),
reimar
parents:
15585
diff
changeset
|
163 return -1; |
15585 | 164 } |
165 | |
166 static int rtp_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) { | |
167 return read_rtp_from_server( fd, buffer, size ); | |
168 } | |
169 | |
170 static int rtp_streaming_start( stream_t *stream, int raw_udp ) { | |
171 streaming_ctrl_t *streaming_ctrl; | |
172 int fd; | |
173 | |
174 if( stream==NULL ) return -1; | |
175 streaming_ctrl = stream->streaming_ctrl; | |
176 fd = stream->fd; | |
177 | |
178 if( fd<0 ) { | |
179 fd = rtp_open_socket( (streaming_ctrl->url) ); | |
180 if( fd<0 ) return -1; | |
181 stream->fd = fd; | |
182 } | |
183 | |
184 if(raw_udp) | |
185 streaming_ctrl->streaming_read = nop_streaming_read; | |
186 else | |
187 streaming_ctrl->streaming_read = rtp_streaming_read; | |
188 streaming_ctrl->streaming_seek = nop_streaming_seek; | |
189 streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes | |
190 streaming_ctrl->buffering = 0; | |
191 streaming_ctrl->status = streaming_playing_e; | |
192 return 0; | |
193 } | |
194 | |
3686 | 195 |
196 int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { | |
197 static char buf[1600]; | |
198 unsigned int intP; | |
199 char* charP = (char*) &intP; | |
200 int headerSize; | |
201 int lengthPacket; | |
202 lengthPacket=recv(fd,buf,1590,0); | |
203 if (lengthPacket==0) | |
204 exit(1); | |
205 if (lengthPacket<0) { | |
206 fprintf(stderr,"socket read error\n"); | |
207 exit(2); | |
208 } | |
209 if (lengthPacket<12) { | |
210 fprintf(stderr,"packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket); | |
211 exit(3); | |
212 } | |
213 rh->b.v = (unsigned int) ((buf[0]>>6)&0x03); | |
214 rh->b.p = (unsigned int) ((buf[0]>>5)&0x01); | |
215 rh->b.x = (unsigned int) ((buf[0]>>4)&0x01); | |
216 rh->b.cc = (unsigned int) ((buf[0]>>0)&0x0f); | |
217 rh->b.m = (unsigned int) ((buf[1]>>7)&0x01); | |
218 rh->b.pt = (unsigned int) ((buf[1]>>0)&0x7f); | |
219 intP = 0; | |
220 memcpy(charP+2,&buf[2],2); | |
221 rh->b.sequence = ntohl(intP); | |
222 intP = 0; | |
223 memcpy(charP,&buf[4],4); | |
224 rh->timestamp = ntohl(intP); | |
225 | |
226 headerSize = 12 + 4*rh->b.cc; /* in bytes */ | |
227 | |
228 *lengthData = lengthPacket - headerSize; | |
229 *data = (char*) buf + headerSize; | |
230 | |
231 // fprintf(stderr,"Reading rtp: v=%x p=%x x=%x cc=%x m=%x pt=%x seq=%x ts=%x lgth=%d\n",rh->b.v,rh->b.p,rh->b.x,rh->b.cc,rh->b.m,rh->b.pt,rh->b.sequence,rh->timestamp,lengthPacket); | |
232 | |
233 return(0); | |
234 } | |
235 | |
236 | |
15585 | 237 static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { |
238 URL_t *url; | |
239 int udp = 0; | |
240 | |
241 mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_RTP, URL: %s\n", stream->url); | |
242 stream->streaming_ctrl = streaming_ctrl_new(); | |
243 if( stream->streaming_ctrl==NULL ) { | |
244 return STREAM_ERROR; | |
245 } | |
246 stream->streaming_ctrl->bandwidth = network_bandwidth; | |
247 url = url_new(stream->url); | |
248 stream->streaming_ctrl->url = check4proxies(url); | |
249 | |
250 if( url->port==0 ) { | |
251 mp_msg(MSGT_NETWORK,MSGL_ERR,"You must enter a port number for RTP and UDP streams!\n"); | |
252 goto fail; | |
253 } | |
254 if(!strncmp(stream->url, "udp", 3)) | |
255 udp = 1; | |
256 | |
257 if(rtp_streaming_start(stream, udp) < 0) { | |
258 mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp_streaming_start(rtp) failed\n"); | |
259 goto fail; | |
260 } | |
261 | |
262 stream->type = STREAMTYPE_STREAM; | |
263 fixup_network_stream_cache(stream); | |
264 return STREAM_OK; | |
265 | |
266 fail: | |
267 streaming_ctrl_free( stream->streaming_ctrl ); | |
268 stream->streaming_ctrl = NULL; | |
269 return STREAM_UNSUPORTED; | |
270 } | |
271 | |
272 | |
273 stream_info_t stream_info_rtp_udp = { | |
274 "mpeg rtp and upd streaming", | |
275 "rtp and udp", | |
276 "Dave Chapman", | |
277 "native rtp support", | |
278 open_s, | |
279 {"rtp", "udp", NULL}, | |
280 NULL, | |
281 0 // Urls are an option string | |
282 }; | |
283 | |
284 |