Mercurial > mplayer.hg
annotate libmpdemux/rtp.c @ 15733:e678e306068e
support lenght-quoting of strings in subopt parser.
author | reimar |
---|---|
date | Thu, 16 Jun 2005 09:03:11 +0000 |
parents | 281d155fb37f |
children | 5dcc5524cb68 |
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); | |
79 return -1; | |
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"); | |
106 closesocket(socket_server_fd); | |
107 return -1; | |
108 } | |
109 } | |
110 | |
111 #ifdef HAVE_WINSOCK2 | |
112 if (isalpha(url->hostname[0])) { | |
113 hp =(struct hostent*)gethostbyname( url->hostname ); | |
114 if( hp==NULL ) { | |
115 mp_msg(MSGT_NETWORK,MSGL_ERR,"Counldn't resolve name: %s\n", url->hostname); | |
116 return -1; | |
117 } | |
118 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); | |
119 } else { | |
120 unsigned int addr = inet_addr(url->hostname); | |
121 memcpy( (void*)&server_address.sin_addr, (void*)&addr, sizeof(addr) ); | |
122 } | |
123 #endif | |
124 | |
125 // Increase the socket rx buffer size to maximum -- this is UDP | |
126 rxsockbufsz = 240 * 1024; | |
127 if( setsockopt( socket_server_fd, SOL_SOCKET, SO_RCVBUF, &rxsockbufsz, sizeof(rxsockbufsz))) { | |
128 mp_msg(MSGT_NETWORK,MSGL_ERR,"Couldn't set receive socket buffer size\n"); | |
129 } | |
130 | |
131 if((ntohl(server_address.sin_addr.s_addr) >> 28) == 0xe) { | |
132 mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr; | |
133 //mcast.imr_interface.s_addr = inet_addr("10.1.1.2"); | |
134 mcast.imr_interface.s_addr = 0; | |
135 if( setsockopt( socket_server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))) { | |
136 mp_msg(MSGT_NETWORK,MSGL_ERR,"IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n"); | |
137 return -1; | |
138 } | |
139 } | |
140 | |
141 tv.tv_sec = 0; | |
142 tv.tv_usec = (1 * 1000000); // 1 second timeout | |
143 FD_ZERO( &set ); | |
144 FD_SET( socket_server_fd, &set ); | |
145 if( select(socket_server_fd+1, &set, NULL, NULL, &tv)>0 ) { | |
146 //if( select(socket_server_fd+1, &set, NULL, NULL, NULL)>0 ) { | |
147 err_len = sizeof( err ); | |
148 getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); | |
149 if( err ) { | |
150 mp_msg(MSGT_NETWORK,MSGL_ERR,"Timeout! No data from host %s\n", url->hostname ); | |
151 mp_msg(MSGT_NETWORK,MSGL_DBG2,"Socket error: %d\n", err ); | |
152 closesocket(socket_server_fd); | |
153 return -1; | |
154 } | |
155 } | |
156 return socket_server_fd; | |
157 } | |
158 | |
159 static int rtp_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *streaming_ctrl ) { | |
160 return read_rtp_from_server( fd, buffer, size ); | |
161 } | |
162 | |
163 static int rtp_streaming_start( stream_t *stream, int raw_udp ) { | |
164 streaming_ctrl_t *streaming_ctrl; | |
165 int fd; | |
166 | |
167 if( stream==NULL ) return -1; | |
168 streaming_ctrl = stream->streaming_ctrl; | |
169 fd = stream->fd; | |
170 | |
171 if( fd<0 ) { | |
172 fd = rtp_open_socket( (streaming_ctrl->url) ); | |
173 if( fd<0 ) return -1; | |
174 stream->fd = fd; | |
175 } | |
176 | |
177 if(raw_udp) | |
178 streaming_ctrl->streaming_read = nop_streaming_read; | |
179 else | |
180 streaming_ctrl->streaming_read = rtp_streaming_read; | |
181 streaming_ctrl->streaming_seek = nop_streaming_seek; | |
182 streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes | |
183 streaming_ctrl->buffering = 0; | |
184 streaming_ctrl->status = streaming_playing_e; | |
185 return 0; | |
186 } | |
187 | |
3686 | 188 |
189 int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { | |
190 static char buf[1600]; | |
191 unsigned int intP; | |
192 char* charP = (char*) &intP; | |
193 int headerSize; | |
194 int lengthPacket; | |
195 lengthPacket=recv(fd,buf,1590,0); | |
196 if (lengthPacket==0) | |
197 exit(1); | |
198 if (lengthPacket<0) { | |
199 fprintf(stderr,"socket read error\n"); | |
200 exit(2); | |
201 } | |
202 if (lengthPacket<12) { | |
203 fprintf(stderr,"packet too small (%d) to be an rtp frame (>12bytes)\n", lengthPacket); | |
204 exit(3); | |
205 } | |
206 rh->b.v = (unsigned int) ((buf[0]>>6)&0x03); | |
207 rh->b.p = (unsigned int) ((buf[0]>>5)&0x01); | |
208 rh->b.x = (unsigned int) ((buf[0]>>4)&0x01); | |
209 rh->b.cc = (unsigned int) ((buf[0]>>0)&0x0f); | |
210 rh->b.m = (unsigned int) ((buf[1]>>7)&0x01); | |
211 rh->b.pt = (unsigned int) ((buf[1]>>0)&0x7f); | |
212 intP = 0; | |
213 memcpy(charP+2,&buf[2],2); | |
214 rh->b.sequence = ntohl(intP); | |
215 intP = 0; | |
216 memcpy(charP,&buf[4],4); | |
217 rh->timestamp = ntohl(intP); | |
218 | |
219 headerSize = 12 + 4*rh->b.cc; /* in bytes */ | |
220 | |
221 *lengthData = lengthPacket - headerSize; | |
222 *data = (char*) buf + headerSize; | |
223 | |
224 // 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); | |
225 | |
226 return(0); | |
227 } | |
228 | |
229 | |
15585 | 230 static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { |
231 URL_t *url; | |
232 int udp = 0; | |
233 | |
234 mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_RTP, URL: %s\n", stream->url); | |
235 stream->streaming_ctrl = streaming_ctrl_new(); | |
236 if( stream->streaming_ctrl==NULL ) { | |
237 return STREAM_ERROR; | |
238 } | |
239 stream->streaming_ctrl->bandwidth = network_bandwidth; | |
240 url = url_new(stream->url); | |
241 stream->streaming_ctrl->url = check4proxies(url); | |
242 | |
243 if( url->port==0 ) { | |
244 mp_msg(MSGT_NETWORK,MSGL_ERR,"You must enter a port number for RTP and UDP streams!\n"); | |
245 goto fail; | |
246 } | |
247 if(!strncmp(stream->url, "udp", 3)) | |
248 udp = 1; | |
249 | |
250 if(rtp_streaming_start(stream, udp) < 0) { | |
251 mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp_streaming_start(rtp) failed\n"); | |
252 goto fail; | |
253 } | |
254 | |
255 stream->type = STREAMTYPE_STREAM; | |
256 fixup_network_stream_cache(stream); | |
257 return STREAM_OK; | |
258 | |
259 fail: | |
260 streaming_ctrl_free( stream->streaming_ctrl ); | |
261 stream->streaming_ctrl = NULL; | |
262 return STREAM_UNSUPORTED; | |
263 } | |
264 | |
265 | |
266 stream_info_t stream_info_rtp_udp = { | |
267 "mpeg rtp and upd streaming", | |
268 "rtp and udp", | |
269 "Dave Chapman", | |
270 "native rtp support", | |
271 open_s, | |
272 {"rtp", "udp", NULL}, | |
273 NULL, | |
274 0 // Urls are an option string | |
275 }; | |
276 | |
277 |