Mercurial > mplayer.hg
comparison network.c @ 999:92833c9472e8
Continue implementation of the network streaming part.
author | bertrand |
---|---|
date | Mon, 04 Jun 2001 17:52:33 +0000 |
parents | 7f6641b1b0df |
children | a710b2a06564 |
comparison
equal
deleted
inserted
replaced
998:8c83e3ff26cc | 999:92833c9472e8 |
---|---|
2 * Network layer for MPlayer | 2 * Network layer for MPlayer |
3 * by Bertrand BAUDET <bertrand_baudet@yahoo.com> | 3 * by Bertrand BAUDET <bertrand_baudet@yahoo.com> |
4 * (C) 2001, MPlayer team. | 4 * (C) 2001, MPlayer team. |
5 */ | 5 */ |
6 | 6 |
7 #define DUMP2FILE | |
8 | |
7 #include <unistd.h> | 9 #include <unistd.h> |
10 #include <fcntl.h> | |
11 #include <netdb.h> | |
8 #include <netinet/in.h> | 12 #include <netinet/in.h> |
9 #include <netdb.h> | 13 #include <sys/time.h> |
10 #include <sys/types.h> | 14 #include <sys/types.h> |
11 #include <sys/socket.h> | 15 #include <sys/socket.h> |
12 #include <arpa/inet.h> | 16 #include <arpa/inet.h> |
13 | 17 |
18 #include <pthread.h> | |
19 | |
20 #include <errno.h> | |
14 #include <ctype.h> | 21 #include <ctype.h> |
15 #include <string.h> | 22 #include <string.h> |
16 #include <stdlib.h> | 23 #include <stdlib.h> |
17 #include <stdio.h> | 24 #include <stdio.h> |
18 | 25 |
26 #include "stream.h" | |
27 #include "demuxer.h" | |
28 | |
19 #include "network.h" | 29 #include "network.h" |
20 #include "http.h" | 30 #include "http.h" |
21 #include "url.h" | 31 #include "url.h" |
22 #include "asf.h" | 32 #include "asf.h" |
23 | 33 |
34 streaming_ctrl_t *streaming_ctrl; | |
35 | |
36 static ASF_StreamType_e streaming_type = ASF_Unknown_e; | |
37 | |
38 Net_Fifo * | |
39 net_fifo_new() { | |
40 Net_Fifo *net_fifo; | |
41 net_fifo = (Net_Fifo*)malloc(sizeof(Net_Fifo)); | |
42 if( net_fifo==NULL ) { | |
43 printf("Memory allocation failed\n"); | |
44 return NULL; | |
45 } | |
46 memset( net_fifo, 0, sizeof(Net_Fifo) ); | |
47 return net_fifo; | |
48 } | |
49 | |
50 void | |
51 net_fifo_free( Net_Fifo *net_fifo ) { | |
52 if( net_fifo->buffer!=NULL ) free( net_fifo->buffer ); | |
53 free( net_fifo ); | |
54 } | |
55 | |
56 int | |
57 net_fifo_push(Net_Fifo *net_fifo, char *buffer, int length ) { | |
58 char *ptr; | |
59 if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; | |
60 | |
61 ptr = (char*)malloc(length+net_fifo->length); | |
62 if( ptr==NULL ) { | |
63 printf("Memory allocation failed\n"); | |
64 return -1; | |
65 } | |
66 if( net_fifo->buffer!=NULL ) { | |
67 memcpy( ptr, net_fifo->buffer, net_fifo->length ); | |
68 free( net_fifo->buffer ); | |
69 } | |
70 memcpy( ptr+net_fifo->length, buffer, length ); | |
71 net_fifo->buffer = ptr; | |
72 net_fifo->length += length; | |
73 return net_fifo->length; | |
74 } | |
75 | |
76 int | |
77 net_fifo_pop(Net_Fifo *net_fifo, char *buffer, int length ) { | |
78 char *ptr; | |
79 int len; | |
80 if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; | |
81 if( net_fifo->buffer==NULL || net_fifo->length==0 ) return -1; | |
82 | |
83 len = MIN(net_fifo->length, length); | |
84 | |
85 ptr = (char*)malloc(net_fifo->length-len); | |
86 if( ptr==NULL ) { | |
87 printf("Memory allocation failed\n"); | |
88 return -1; | |
89 } | |
90 memcpy( buffer, net_fifo->buffer, len ); | |
91 if( net_fifo->length-len!=0 ) { | |
92 memcpy( ptr, net_fifo->buffer+len, net_fifo->length-len ); | |
93 free( net_fifo->buffer ); | |
94 net_fifo->buffer = ptr; | |
95 net_fifo->length -= len; | |
96 } else { | |
97 free( net_fifo->buffer ); | |
98 net_fifo->buffer = NULL; | |
99 net_fifo->length = 0; | |
100 } | |
101 return len; | |
102 } | |
103 | |
104 streaming_ctrl_t * | |
105 streaming_ctrl_new( ) { | |
106 streaming_ctrl_t *streaming_ctrl; | |
107 streaming_ctrl = (streaming_ctrl_t*)malloc(sizeof(streaming_ctrl_t)); | |
108 if( streaming_ctrl==NULL ) { | |
109 printf("Failed to allocate memory\n"); | |
110 return NULL; | |
111 } | |
112 memset( streaming_ctrl, 0, sizeof(streaming_ctrl_t) ); | |
113 streaming_ctrl->buffer = net_fifo_new(); | |
114 return streaming_ctrl; | |
115 } | |
116 | |
117 void | |
118 streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) { | |
119 if( streaming_ctrl==NULL ) return; | |
120 if( streaming_ctrl->buffer!=NULL ) net_fifo_free( streaming_ctrl->buffer ); | |
121 free( streaming_ctrl ); | |
122 } | |
123 | |
124 int | |
125 readFromServer(int fd, char *buffer, int length) { | |
126 int ret; | |
127 int done=0; | |
128 fd_set set; | |
129 struct timeval tv; | |
130 if( buffer==NULL || length<0 ) return -1; | |
131 | |
132 | |
133 // fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK ); | |
134 return read( fd, buffer, length ); | |
135 | |
136 do { | |
137 tv.tv_sec = 0; | |
138 tv.tv_usec = 10000; // 10 milli-seconds timeout | |
139 FD_ZERO( &set ); | |
140 FD_SET( fd, &set ); | |
141 ret = select( fd+1, &set, NULL, NULL, &tv ); | |
142 if( ret<0 ) { | |
143 perror("select"); | |
144 } else if( ret==0 ) { | |
145 printf("timeout\n"); | |
146 } | |
147 if( FD_ISSET(fd, &set) ) { | |
148 ret = read( fd, buffer, length ); | |
149 if( ret<0 ) { | |
150 if( errno!=EINPROGRESS ) { | |
151 } | |
152 } else { | |
153 done = 1; | |
154 } | |
155 } else { | |
156 return -1; | |
157 } | |
158 } while( !done ); | |
159 | |
160 return ret; | |
161 } | |
162 | |
24 // Connect to a server using a TCP connection | 163 // Connect to a server using a TCP connection |
25 int | 164 int |
26 connect2Server(char *host, int port) { | 165 connect2Server(char *host, int port) { |
27 int socket_server_fd; | 166 int socket_server_fd; |
167 int err, err_len; | |
168 fd_set set; | |
169 struct timeval tv; | |
28 struct sockaddr_in server_address; | 170 struct sockaddr_in server_address; |
171 | |
29 printf("Connecting to server %s:%d ...\n", host, port ); | 172 printf("Connecting to server %s:%d ...\n", host, port ); |
173 | |
30 socket_server_fd = socket(AF_INET, SOCK_STREAM, 0); | 174 socket_server_fd = socket(AF_INET, SOCK_STREAM, 0); |
175 // fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); | |
31 if( socket_server_fd==-1 ) { | 176 if( socket_server_fd==-1 ) { |
32 perror("Failed to create socket"); | 177 perror("Failed to create socket"); |
33 return -1; | 178 return -1; |
34 } | 179 } |
35 | 180 |
36 if( isalpha(host[0]) ) { | 181 if( isalpha(host[0]) ) { |
37 struct hostent *hp =(struct hostent*)gethostbyname( host ); | 182 struct hostent *hp =(struct hostent*)gethostbyname( host ); |
38 if( hp==NULL ) { | 183 if( hp==NULL ) { |
39 printf("Unknown host: %s\n", host); | 184 printf("Counldn't resolve name: %s\n", host); |
40 return -1; | 185 return -1; |
41 } | 186 } |
42 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); | 187 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); |
43 } else { | 188 } else { |
44 inet_pton(AF_INET, host, &server_address.sin_addr); | 189 inet_pton(AF_INET, host, &server_address.sin_addr); |
45 } | 190 } |
46 server_address.sin_family=AF_INET; | 191 server_address.sin_family=AF_INET; |
47 server_address.sin_port=htons(port); | 192 server_address.sin_port=htons(port); |
48 | 193 |
49 if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { | 194 if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { |
50 perror("Failed to connect to server"); | 195 if( errno!=EINPROGRESS ) { |
51 close(socket_server_fd); | 196 perror("Failed to connect to server"); |
52 return -1; | 197 close(socket_server_fd); |
198 return -1; | |
199 } | |
200 } | |
201 | |
202 tv.tv_sec = 0; | |
203 tv.tv_usec = 10000; // 10 milli-seconds timeout | |
204 FD_ZERO( &set ); | |
205 FD_SET( socket_server_fd, &set ); | |
206 if( select(socket_server_fd+1, NULL, &set, NULL, &tv)>0 ) { | |
207 err_len = sizeof( err ); | |
208 getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); | |
209 if( err ) { | |
210 printf("Couldn't connect to host %s\n", host ); | |
211 printf("Socket error: %d\n", err ); | |
212 close(socket_server_fd); | |
213 return -1; | |
214 } | |
53 } | 215 } |
54 return socket_server_fd; | 216 return socket_server_fd; |
217 } | |
218 | |
219 int | |
220 http_send_request( URL_t *url ) { | |
221 HTTP_header_t *http_hdr; | |
222 int fd; | |
223 http_hdr = http_new_header(); | |
224 http_set_uri( http_hdr, url->file ); | |
225 http_set_field( http_hdr, "User-Agent: MPlayer"); | |
226 http_set_field( http_hdr, "Connection: closed"); | |
227 if( http_build_request( http_hdr )==NULL ) { | |
228 return -1; | |
229 } | |
230 | |
231 fd = connect2Server( url->hostname, url->port ); | |
232 if( fd<0 ) { | |
233 return -1; | |
234 } | |
235 write( fd, http_hdr->buffer, http_hdr->buffer_size ); | |
236 http_free( http_hdr ); | |
237 | |
238 return fd; | |
239 } | |
240 | |
241 HTTP_header_t * | |
242 http_read_response( int fd ) { | |
243 HTTP_header_t *http_hdr; | |
244 char response[BUFFER_SIZE]; | |
245 int i; | |
246 | |
247 http_hdr = http_new_header(); | |
248 if( http_hdr==NULL ) { | |
249 return NULL; | |
250 } | |
251 | |
252 do { | |
253 i = readFromServer( fd, response, BUFFER_SIZE ); | |
254 if( i<0 ) { | |
255 printf("Read failed\n"); | |
256 } | |
257 http_response_append( http_hdr, response, i ); | |
258 } while( !http_is_header_entired( http_hdr ) ); | |
259 http_response_parse( http_hdr ); | |
260 return http_hdr; | |
55 } | 261 } |
56 | 262 |
57 // By using the protocol, the extension of the file or the content-type | 263 // By using the protocol, the extension of the file or the content-type |
58 // we might be able to guess the streaming type. | 264 // we might be able to guess the streaming type. |
59 int | 265 int |
60 autodetectProtocol(URL_t *url, int *fd_out) { | 266 autodetectProtocol(URL_t *url, int *fd_out) { |
61 HTTP_header_t *http_hdr; | 267 HTTP_header_t *http_hdr; |
62 int fd=-1; | 268 int fd=-1; |
63 int i; | 269 int i; |
270 int redirect; | |
64 char *extension; | 271 char *extension; |
65 char *content_type; | 272 char *content_type; |
66 char *next_url; | 273 char *next_url; |
67 char response[1024]; | 274 char response[1024]; |
68 | 275 |
69 redo_request: | 276 do { |
70 *fd_out=-1; | 277 *fd_out=-1; |
71 next_url = NULL; | 278 next_url = NULL; |
72 extension = NULL; | 279 extension = NULL; |
73 content_type = NULL; | 280 content_type = NULL; |
74 | 281 redirect = 0; |
75 if( url==NULL ) return STREAMING_TYPE_UNKNOWN; | 282 |
76 | 283 if( url==NULL ) return DEMUXER_TYPE_UNKNOWN; |
77 // Get the extension of the file if present | 284 |
78 if( url->file!=NULL ) { | 285 // Get the extension of the file if present |
79 for( i=strlen(url->file) ; i>0 ; i-- ) { | 286 if( url->file!=NULL ) { |
80 if( url->file[i]=='.' ) { | 287 for( i=strlen(url->file) ; i>0 ; i-- ) { |
81 extension=(url->file)+i+1; | 288 if( url->file[i]=='.' ) { |
82 break; | 289 extension=(url->file)+i+1; |
83 } | 290 break; |
84 } | 291 } |
85 } | 292 } |
86 | 293 } |
87 if( extension!=NULL ) { | 294 // extension=NULL; |
88 printf("Extension: %s\n", extension ); | 295 if( extension!=NULL ) { |
89 if( !strcasecmp(extension, "asf") || | 296 printf("Extension: %s\n", extension ); |
90 !strcasecmp(extension, "wmv") || | 297 if( !strcasecmp(extension, "asf") || |
91 !strcasecmp(extension, "asx") ) { | 298 !strcasecmp(extension, "wmv") || |
299 !strcasecmp(extension, "asx") ) { | |
300 if( url->port==0 ) url->port = 80; | |
301 return DEMUXER_TYPE_ASF; | |
302 } | |
303 if( !strcasecmp(extension, "mpg") || | |
304 !strcasecmp(extension, "mpeg") ) { | |
305 if( url->port==0 ) url->port = 80; | |
306 return DEMUXER_TYPE_MPEG_PS; | |
307 } | |
308 if( !strcasecmp(extension, "avi") ) { | |
309 if( url->port==0 ) url->port = 80; | |
310 return DEMUXER_TYPE_AVI; | |
311 } | |
312 } | |
313 | |
314 // Checking for RTSP | |
315 if( !strcasecmp(url->protocol, "rtsp") ) { | |
316 printf("RTSP protocol not yet implemented!\n"); | |
317 return DEMUXER_TYPE_UNKNOWN; | |
318 } | |
319 | |
320 // Checking for ASF | |
321 if( !strcasecmp(url->protocol, "mms") ) { | |
92 if( url->port==0 ) url->port = 80; | 322 if( url->port==0 ) url->port = 80; |
93 return STREAMING_TYPE_ASF; | 323 return DEMUXER_TYPE_ASF; |
94 } | 324 } |
95 } | 325 |
96 | 326 // HTTP based protocol |
97 // Checking for RTSP | 327 if( !strcasecmp(url->protocol, "http") ) { |
98 if( !strcasecmp(url->protocol, "rtsp") ) { | 328 if( url->port==0 ) url->port = 80; |
99 printf("RTSP protocol not yet implemented!\n"); | 329 |
100 return STREAMING_TYPE_UNKNOWN; | 330 fd = http_send_request( url ); |
101 } | 331 if( fd<0 ) { |
102 | 332 *fd_out=-1; |
103 // Checking for ASF | 333 return DEMUXER_TYPE_UNKNOWN; |
104 if( !strcasecmp(url->protocol, "mms") ) { | 334 } |
105 if( url->port==0 ) url->port = 80; | 335 |
106 return STREAMING_TYPE_ASF; | 336 http_hdr = http_read_response( fd ); |
107 } | 337 if( http_hdr==NULL ) { |
108 | 338 close( fd ); |
109 // HTTP based protocol | 339 *fd_out=-1; |
110 if( !strcasecmp(url->protocol, "http") ) { | 340 return DEMUXER_TYPE_UNKNOWN; |
111 if( url->port==0 ) url->port = 80; | 341 } |
112 | 342 |
113 http_hdr = http_new_header(); | 343 *fd_out=fd; |
114 http_set_uri( http_hdr, url->file ); | 344 //http_debug_hdr( http_hdr ); |
115 http_set_field( http_hdr, "User-Agent: MPlayer"); | 345 |
116 http_set_field( http_hdr, "Connection: closed"); | 346 // Check if the response is an ICY status_code reason_phrase |
117 if( http_build_request( http_hdr )==NULL ) { | 347 if( !strcasecmp(http_hdr->protocol, "ICY") ) { |
118 return STREAMING_TYPE_UNKNOWN; | 348 // Ok, we have detected an mp3 streaming |
119 } | 349 return DEMUXER_TYPE_MPEG_PS; |
120 | 350 } |
121 fd = connect2Server( url->hostname, url->port ); | 351 |
122 if( fd<0 ) { | 352 switch( http_hdr->status_code ) { |
123 *fd_out=-1; | 353 case 200: // OK |
124 return STREAMING_TYPE_UNKNOWN; | 354 // Look if we can use the Content-Type |
125 } | 355 content_type = http_get_field( http_hdr, "Content-Type" ); |
126 write( fd, http_hdr->buffer, http_hdr->buffer_size ); | 356 if( content_type!=NULL ) { |
127 // http_free( http_hdr ); | 357 printf("Content-Type: [%s]\n", content_type ); |
128 | 358 printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); |
129 http_hdr = http_new_header(); | 359 // Check for ASF |
130 if( http_hdr==NULL ) { | 360 if( asf_http_streaming_type(content_type, NULL)!=ASF_Unknown_e ) { |
131 close( fd ); | 361 return DEMUXER_TYPE_ASF; |
132 *fd_out=-1; | 362 } |
133 return STREAMING_TYPE_UNKNOWN; | 363 // Check for MP3 streaming |
134 } | 364 // Some MP3 streaming server answer with audio/mpeg |
135 | 365 if( !strcasecmp(content_type, "audio/mpeg") ) { |
136 do { | 366 return DEMUXER_TYPE_MPEG_PS; |
137 i = read( fd, response, 1024 ); | 367 } |
138 http_response_append( http_hdr, response, i ); | 368 // Check for MPEG streaming |
139 } while( !http_is_header_entired( http_hdr ) ); | 369 if( !strcasecmp(content_type, "video/mpeg") ) { |
140 http_response_parse( http_hdr ); | 370 return DEMUXER_TYPE_MPEG_PS; |
141 | 371 } |
142 *fd_out=fd; | 372 // AVI ??? => video/x-msvideo |
143 //http_debug_hdr( http_hdr ); | 373 if( !strcasecmp(content_type, "video/x-msvideo") ) { |
144 | 374 return DEMUXER_TYPE_AVI; |
145 // Check if the response is an ICY status_code reason_phrase | 375 } |
146 if( !strcasecmp(http_hdr->protocol, "ICY") ) { | 376 } |
147 // Ok, we have detected an mp3 streaming | 377 break; |
148 return STREAMING_TYPE_MP3; | 378 // Redirect |
149 } | 379 case 301: // Permanently |
380 case 302: // Temporarily | |
381 // TODO: RFC 2616, recommand to detect infinite redirection loops | |
382 next_url = http_get_field( http_hdr, "Location" ); | |
383 if( next_url!=NULL ) { | |
384 close( fd ); | |
385 url_free( url ); | |
386 url = url_new( next_url ); | |
387 redirect = 1; | |
388 } | |
389 break; | |
390 default: | |
391 printf("Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); | |
392 close( fd ); | |
393 *fd_out=-1; | |
394 return DEMUXER_TYPE_UNKNOWN; | |
395 } | |
396 } | |
397 } while( redirect ); | |
398 | |
399 return DEMUXER_TYPE_UNKNOWN; | |
400 } | |
401 | |
402 int | |
403 nop_streaming_read( streaming_ctrl_t *streaming_ctrl ) { | |
404 char *buffer; | |
405 int len; | |
406 if( streaming_ctrl==NULL ) return -1; | |
407 len = streaming_ctrl->buffer->length; | |
408 if( len==0 ) return 0; | |
150 | 409 |
410 buffer = (char*)malloc( len ); | |
411 if( buffer==NULL ) { | |
412 printf("Memory allocation failed\n"); | |
413 return -1; | |
414 } | |
415 net_fifo_pop( streaming_ctrl->buffer, buffer, len ); | |
416 write( streaming_ctrl->fd_pipe_in, buffer, len ); | |
417 free( buffer ); | |
418 return len; | |
419 } | |
420 | |
421 int | |
422 nop_streaming_start( streaming_ctrl_t *streaming_ctrl ) { | |
423 HTTP_header_t *http_hdr; | |
424 int fd; | |
425 if( streaming_ctrl==NULL ) return -1; | |
426 | |
427 fd = streaming_ctrl->fd_net; | |
428 if( fd<0 ) { | |
429 fd = http_send_request( *(streaming_ctrl->url) ); | |
430 if( fd<0 ) return -1; | |
431 http_hdr = http_read_response( fd ); | |
432 if( http_hdr==NULL ) return -1; | |
433 | |
151 switch( http_hdr->status_code ) { | 434 switch( http_hdr->status_code ) { |
152 case 200: // OK | 435 case 200: // OK |
153 // Look if we can use the Content-Type | 436 printf("Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") ); |
154 content_type = http_get_field( http_hdr, "Content-Type" ); | 437 printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); |
155 if( content_type!=NULL ) { | 438 if( http_hdr->body_size>0 ) { |
156 printf("Content-Type: %s\n", content_type ); | 439 write( streaming_ctrl->fd_pipe_in, http_hdr->body, http_hdr->body_size ); |
157 // Check for ASF | 440 } |
158 if( asf_http_streaming_type(content_type, NULL)!=ASF_Unknown_e ) { | 441 break; |
159 return STREAMING_TYPE_ASF; | 442 default: |
160 } | 443 printf("Server return %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); |
161 // Check for MP3 streaming | 444 close( fd ); |
162 // Some MP3 streaming server answer with audio/mpeg | 445 fd = -1; |
163 if( !strcasecmp(content_type, "audio/mpeg") ) { | 446 } |
164 return STREAMING_TYPE_MP3; | 447 streaming_ctrl->fd_net = fd; |
448 } | |
449 | |
450 http_free( http_hdr ); | |
451 | |
452 streaming_ctrl->streaming_read = nop_streaming_read; | |
453 streaming_ctrl->prebuffer_size = 180000; | |
454 // streaming_ctrl->prebuffer_size = 0; | |
455 streaming_ctrl->buffering = 1; | |
456 // streaming_ctrl->buffering = 0; | |
457 streaming_ctrl->status = streaming_playing_e; | |
458 return fd; | |
459 } | |
460 | |
461 void | |
462 network_streaming(void *arg) { | |
463 char buffer[BUFFER_SIZE]; | |
464 fd_set fd_net_in; | |
465 int ret; | |
466 | |
467 arg = arg; | |
468 | |
469 do { | |
470 FD_ZERO( &fd_net_in ); | |
471 FD_SET( streaming_ctrl->fd_net, &fd_net_in ); | |
472 | |
473 ret = select( streaming_ctrl->fd_net+1, &fd_net_in, NULL, NULL, NULL ); | |
474 if( ret<0 ) { | |
475 perror("select"); | |
476 exit(1); | |
477 } | |
478 if( FD_ISSET( streaming_ctrl->fd_net, &fd_net_in ) ) { | |
479 ret = readFromServer( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); | |
480 if( ret<=0 ) { | |
481 streaming_ctrl->status=streaming_stopped_e; | |
482 } else { | |
483 //printf(" push: 0x%02X\n", *((unsigned int*)buffer) ); | |
484 net_fifo_push( streaming_ctrl->buffer, buffer, ret ); | |
485 if( !streaming_ctrl->buffering ) { | |
486 do { | |
487 ret = streaming_ctrl->streaming_read( streaming_ctrl ); | |
488 if( ret<0 && streaming_ctrl->buffer->length<streaming_ctrl->prebuffer_size ) { | |
489 // Need buffering | |
490 streaming_ctrl->buffering = 1; | |
491 } | |
492 } while( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ); | |
493 } else { | |
494 if( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ) { | |
495 streaming_ctrl->buffering = 0; | |
496 printf("\n"); | |
497 } else { | |
498 printf(" Buffering: %d \%\r", (int)((float)(((float)streaming_ctrl->buffer->length)/((float)streaming_ctrl->prebuffer_size))*100) ); | |
499 fflush(stdout); | |
165 } | 500 } |
166 } | 501 } |
167 break; | 502 } |
168 // Redirect | 503 } else { |
169 case 301: // Permanently | 504 printf("Network fd not set\n"); |
170 case 302: // Temporarily | 505 } |
171 // RFC 2616, recommand to detect infinite redirection loops | 506 } while( streaming_ctrl->status==streaming_playing_e ); |
172 next_url = http_get_field( http_hdr, "Location" ); | 507 |
173 if( next_url!=NULL ) { | 508 // Flush the buffer |
174 close( fd ); | 509 while( streaming_ctrl->buffer->length>0 ) { |
175 url_free( url ); | 510 ret = streaming_ctrl->streaming_read( streaming_ctrl ); |
176 url_new( next_url ); | 511 if( ret<0 ) break; |
177 goto redo_request; | 512 } |
178 } | 513 |
179 //break; | 514 printf("Network thread done\n"); |
180 default: | 515 |
181 printf("Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); | 516 // Close to the pipe to stop mplayer. |
182 close( fd ); | 517 close( streaming_ctrl->fd_pipe_in ); |
183 *fd_out=-1; | 518 |
184 return STREAMING_TYPE_UNKNOWN; | |
185 } | |
186 } | |
187 return STREAMING_TYPE_UNKNOWN; | |
188 } | |
189 | |
190 | |
191 void | |
192 network_streaming() { | |
193 int ret; | |
194 /* | |
195 do { | |
196 ret = select( ); | |
197 | |
198 } while( ); | |
199 */ | |
200 } | 519 } |
201 | 520 |
202 int | 521 int |
203 streaming_start(URL_t **url, int fd, int streaming_type) { | 522 streaming_start(URL_t **url, int fd, int streaming_type) { |
523 int fd_pipe[2]; | |
524 // Open the pipe | |
525 if( pipe(fd_pipe)<0 ) { | |
526 printf("Pipe creation failed\n"); | |
527 return -1; | |
528 } | |
529 | |
530 streaming_ctrl = streaming_ctrl_new( ); | |
531 if( streaming_ctrl==NULL ) { | |
532 return -1; | |
533 } | |
534 streaming_ctrl->url = url; | |
535 streaming_ctrl->fd_pipe_in = fd_pipe[1]; | |
536 streaming_ctrl->fd_net = fd; | |
537 | |
538 #ifdef DUMP2FILE | |
539 { | |
540 int fd_file; | |
541 fd_file = open("dump.stream", O_WRONLY | O_CREAT ); | |
542 if( fd_file<0 ) { | |
543 perror("open"); | |
544 } | |
545 streaming_ctrl->fd_pipe_in = fd_file; | |
546 } | |
547 #endif | |
548 | |
204 switch( streaming_type ) { | 549 switch( streaming_type ) { |
205 case STREAMING_TYPE_ASF: | 550 case DEMUXER_TYPE_ASF: |
206 // Send a the appropriate HTTP request | 551 // Send the appropriate HTTP request |
207 if( fd>0 ) close( fd ); | 552 fd = asf_http_streaming_start( streaming_ctrl ); |
208 fd = asf_http_streaming_start( url ); | |
209 break; | 553 break; |
210 case STREAMING_TYPE_MP3: | 554 case DEMUXER_TYPE_AVI: |
211 // Nothing else to do the server is already feeding the pipe. | 555 case DEMUXER_TYPE_MPEG_ES: |
556 case DEMUXER_TYPE_MPEG_PS: | |
557 fd = nop_streaming_start( streaming_ctrl ); | |
212 break; | 558 break; |
213 case STREAMING_TYPE_UNKNOWN: | 559 case DEMUXER_TYPE_UNKNOWN: |
214 default: | 560 default: |
215 printf("Unable to detect the streaming type\n"); | 561 printf("Unable to detect the streaming type\n"); |
216 close( fd ); | 562 close( fd ); |
563 free( streaming_ctrl ); | |
217 return -1; | 564 return -1; |
218 } | 565 } |
219 | 566 |
220 return fd; | 567 if( fd<0 ) { |
568 free( streaming_ctrl ); | |
569 return -1; | |
570 } | |
571 | |
572 // Start the network thread | |
573 if( pthread_create( &(streaming_ctrl->thread_id), NULL , (void*)network_streaming, (void*)NULL)<0 ) { | |
574 printf("Unable to start the network thread.\n"); | |
575 close( fd ); | |
576 free( streaming_ctrl ); | |
577 return -1; | |
578 } | |
579 printf("Network thread created with id: %d\n", streaming_ctrl->thread_id ); | |
580 | |
581 // streaming_ctrl->status = streaming_stopped_e; | |
582 | |
583 // return fd; | |
584 return fd_pipe[0]; | |
221 } | 585 } |
222 | 586 |
223 int | 587 int |
224 streaming_stop( ) { | 588 streaming_stop( ) { |
225 | 589 streaming_ctrl->status = streaming_stopped_e; |
226 } | 590 return 0; |
591 } |