Mercurial > mplayer.hg
annotate libmpdemux/asf_streaming.c @ 2315:c3c73ba53f0e
streaming fixed
author | arpi |
---|---|
date | Sat, 20 Oct 2001 20:35:12 +0000 |
parents | 9e059416eea6 |
children | 0ecc1b4f7cf8 |
rev | line source |
---|---|
871 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
833 | 3 #include <string.h> |
1430 | 4 #include <unistd.h> |
833 | 5 |
871 | 6 #include "url.h" |
7 #include "http.h" | |
1001 | 8 #include "asf.h" |
905 | 9 #include "network.h" |
871 | 10 |
1001 | 11 #include "stream.h" |
1340
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
12 //#include "demuxer.h" |
871 | 13 |
1340
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
14 //extern demuxer_t *demuxer; |
833 | 15 |
905 | 16 static ASF_StreamType_e streaming_type = ASF_Unknown_e; |
871 | 17 |
1001 | 18 int |
19 asf_http_streaming_read( streaming_ctrl_t *streaming_ctrl ) { | |
20 char *buffer; | |
21 int drop_packet; | |
22 int ret; | |
23 printf("asf_streaming_read\n"); | |
24 ret = asf_streaming( streaming_ctrl->buffer->buffer, streaming_ctrl->buffer->length, &drop_packet ); | |
25 printf("ret: %d\n", ret); | |
26 if( ret<0 ) return -1; | |
27 if( ret>streaming_ctrl->buffer->length ) return 0; | |
28 buffer = (char*)malloc(ret); | |
29 if( buffer==NULL ) { | |
30 printf("Memory allocation failed\n"); | |
31 return -1; | |
32 } | |
33 printf("buffer length: %d\n", streaming_ctrl->buffer->length ); | |
34 net_fifo_pop( streaming_ctrl->buffer, buffer, ret ); | |
35 printf(" pop: 0x%02X\n", *((unsigned int*)buffer) ); | |
36 printf("buffer length: %d\n", streaming_ctrl->buffer->length ); | |
37 printf("0x%02X\n", *((unsigned int*)(buffer+sizeof(ASF_stream_chunck_t))) ); | |
38 if( !drop_packet ) { | |
39 write( streaming_ctrl->fd_pipe_in, buffer+sizeof(ASF_stream_chunck_t), ret-sizeof(ASF_stream_chunck_t) ); | |
40 } | |
41 free( buffer ); | |
42 return ret; | |
43 } | |
44 | |
45 int | |
46 asf_streaming(char *data, int length, int *drop_packet ) { | |
833 | 47 ASF_stream_chunck_t *stream_chunck=(ASF_stream_chunck_t*)data; |
871 | 48 printf("ASF stream chunck size=%d\n", stream_chunck->size); |
1001 | 49 printf("length: %d\n", length ); |
50 printf("0x%02X\n", stream_chunck->type ); | |
51 | |
52 if( drop_packet!=NULL ) *drop_packet = 0; | |
53 if( data==NULL || length<=0 ) return -1; | |
871 | 54 |
55 if( stream_chunck->size<8 ) { | |
56 printf("Ahhhh, stream_chunck size is too small: %d\n", stream_chunck->size); | |
1001 | 57 return -1; |
871 | 58 } |
59 if( stream_chunck->size!=stream_chunck->size_confirm ) { | |
60 printf("size_confirm mismatch!: %d %d\n", stream_chunck->size, stream_chunck->size_confirm); | |
1001 | 61 return -1; |
871 | 62 } |
833 | 63 |
1001 | 64 printf(" type: 0x%02X\n", stream_chunck->type ); |
65 printf(" size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size ); | |
66 printf(" sequence_number: 0x%04X\n", stream_chunck->sequence_number ); | |
67 printf(" unknown: 0x%02X\n", stream_chunck->unknown ); | |
68 printf(" size_confirm: 0x%02X\n", stream_chunck->size_confirm ); | |
69 | |
70 | |
833 | 71 switch(stream_chunck->type) { |
72 case 0x4324: // Clear ASF configuration | |
871 | 73 printf("=====> Clearing ASF stream configuration!\n"); |
1001 | 74 if( drop_packet!=NULL ) *drop_packet = 1; |
75 return stream_chunck->size; | |
833 | 76 break; |
77 case 0x4424: // Data follows | |
871 | 78 printf("=====> Data follows\n"); |
833 | 79 break; |
80 case 0x4524: // Transfer complete | |
871 | 81 printf("=====> Transfer complete\n"); |
1001 | 82 if( drop_packet!=NULL ) *drop_packet = 1; |
83 return stream_chunck->size; | |
833 | 84 break; |
85 case 0x4824: // ASF header chunk follows | |
871 | 86 printf("=====> ASF header chunk follows\n"); |
833 | 87 break; |
88 default: | |
871 | 89 printf("=====> Unknown stream type 0x%x\n", stream_chunck->type ); |
833 | 90 } |
1001 | 91 return stream_chunck->size+4; |
833 | 92 } |
93 | |
905 | 94 int |
95 asf_http_streaming_type(char *content_type, char *features) { | |
96 if( content_type==NULL ) return ASF_Unknown_e; | |
833 | 97 if( !strcasecmp(content_type, "application/octet-stream") ) { |
905 | 98 if( features==NULL ) { |
1001 | 99 printf("=====> ASF Prerecorded\n"); |
905 | 100 return ASF_Prerecorded_e; |
101 } else if( strstr(features, "broadcast")) { | |
1001 | 102 printf("=====> ASF Live stream\n"); |
905 | 103 return ASF_Live_e; |
833 | 104 } else { |
1001 | 105 printf("=====> ASF Prerecorded\n"); |
905 | 106 return ASF_Prerecorded_e; |
833 | 107 } |
108 } else { | |
871 | 109 if( (!strcasecmp(content_type, "audio/x-ms-wax")) || |
833 | 110 (!strcasecmp(content_type, "audio/x-ms-wma")) || |
111 (!strcasecmp(content_type, "video/x-ms-asf")) || | |
112 (!strcasecmp(content_type, "video/x-ms-afs")) || | |
113 (!strcasecmp(content_type, "video/x-ms-wvx")) || | |
114 (!strcasecmp(content_type, "video/x-ms-wmv")) || | |
115 (!strcasecmp(content_type, "video/x-ms-wma")) ) { | |
1001 | 116 printf("=====> ASF Redirector\n"); |
905 | 117 return ASF_Redirector_e; |
833 | 118 } else { |
1001 | 119 printf("=====> ASF unknown content-type: %s\n", content_type ); |
905 | 120 return ASF_Unknown_e; |
833 | 121 } |
122 } | |
905 | 123 return ASF_Unknown_e; |
833 | 124 } |
871 | 125 |
905 | 126 HTTP_header_t * |
871 | 127 asf_http_request(URL_t *url) { |
128 HTTP_header_t *http_hdr; | |
129 char str[250]; | |
1001 | 130 char *ptr; |
871 | 131 char *request; |
1001 | 132 int i; |
871 | 133 |
134 int offset_hi=0, offset_lo=0, req_nb=1, length=0; | |
1001 | 135 int asf_nb_stream; |
871 | 136 |
137 // Common header for all requests. | |
138 http_hdr = http_new_header(); | |
139 http_set_uri( http_hdr, url->file ); | |
140 http_set_field( http_hdr, "Accept: */*" ); | |
141 http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" ); | |
142 sprintf( str, "Host: %s:%d", url->hostname, url->port ); | |
143 http_set_field( http_hdr, str ); | |
144 http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" ); | |
145 sprintf(str, | |
146 "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u", | |
147 offset_hi, offset_lo, req_nb, length ); | |
148 http_set_field( http_hdr, str ); | |
149 | |
905 | 150 switch( streaming_type ) { |
871 | 151 case ASF_Live_e: |
152 case ASF_Prerecorded_e: | |
153 http_set_field( http_hdr, "Pragma: xPlayStrm=1" ); | |
1001 | 154 ptr = str; |
155 ptr += sprintf( ptr, "Pragma: stream-switch-entry="); | |
1340
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
156 |
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
157 // FIXME: why do you need demuxer here? if you really need it, pass it as |
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
158 // parameter. -- A'rpi |
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
159 |
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
160 #if 0 |
1001 | 161 for( i=0, asf_nb_stream=0 ; i<256 ; i++ ) { |
162 // FIXME START | |
163 if( demuxer==NULL ) { | |
164 ptr += sprintf( ptr, " ffff:1:0" ); | |
165 asf_nb_stream = 1; | |
166 break; | |
167 } | |
168 // FIXME END | |
169 if( demuxer->a_streams[i] ) { | |
170 ptr += sprintf( ptr, " ffff:%d:0", i ); | |
171 asf_nb_stream++; | |
172 } | |
173 if( demuxer->v_streams[i] ) { | |
174 ptr += sprintf( ptr, " ffff:%d:0", i ); | |
175 asf_nb_stream++; | |
176 } | |
177 } | |
1340
d4f1e8d0e591
demuxer struct access code temporary disabled - FIXME
arpi
parents:
1001
diff
changeset
|
178 #endif |
1001 | 179 http_set_field( http_hdr, str ); |
871 | 180 sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream ); |
181 http_set_field( http_hdr, str ); | |
182 break; | |
183 case ASF_Redirector_e: | |
184 break; | |
185 case ASF_Unknown_e: | |
186 // First request goes here. | |
187 break; | |
188 default: | |
189 printf("Unknown asf stream type\n"); | |
190 } | |
191 | |
192 http_set_field( http_hdr, "Connection: Close" ); | |
905 | 193 http_build_request( http_hdr ); |
871 | 194 |
905 | 195 return http_hdr; |
871 | 196 } |
197 | |
198 int | |
905 | 199 asf_http_parse_response( HTTP_header_t *http_hdr ) { |
871 | 200 char *content_type, *pragma; |
201 char features[64] = "\0"; | |
202 int len; | |
905 | 203 if( http_response_parse(http_hdr)<0 ) { |
204 printf("Failed to parse HTTP response\n"); | |
205 return -1; | |
206 } | |
871 | 207 if( http_hdr->status_code!=200 ) { |
208 printf("Server return %d:%s\n", http_hdr->status_code, http_hdr->reason_phrase); | |
209 return -1; | |
210 } | |
211 | |
212 content_type = http_get_field( http_hdr, "Content-Type"); | |
213 | |
214 pragma = http_get_field( http_hdr, "Pragma"); | |
905 | 215 while( pragma!=NULL ) { |
871 | 216 char *comma_ptr=NULL; |
217 char *end; | |
218 // The pragma line can get severals attributes | |
219 // separeted with a comma ','. | |
220 do { | |
221 if( !strncasecmp( pragma, "features=", 9) ) { | |
222 pragma += 9; | |
223 end = strstr( pragma, "," ); | |
224 if( end==NULL ) { | |
225 len = strlen(pragma); | |
226 } | |
227 len = MIN(end-pragma,sizeof(features)); | |
228 strncpy( features, pragma, len ); | |
229 features[len]='\0'; | |
230 break; | |
231 } | |
232 comma_ptr = strstr( pragma, "," ); | |
233 if( comma_ptr!=NULL ) { | |
234 pragma = comma_ptr+1; | |
235 if( pragma[0]==' ' ) pragma++; | |
236 } | |
237 } while( comma_ptr!=NULL ); | |
238 pragma = http_get_next_field( http_hdr ); | |
905 | 239 } |
240 | |
241 streaming_type = asf_http_streaming_type( content_type, features ); | |
871 | 242 |
905 | 243 if( http_hdr->body_size>0 ) { |
1001 | 244 asf_streaming( http_hdr->body, http_hdr->body_size, NULL); |
905 | 245 } |
871 | 246 |
247 return 0; | |
248 } | |
249 | |
905 | 250 URL_t * |
251 asf_http_ASX_redirect( HTTP_header_t *http_hdr ) { | |
252 URL_t *url_redirect=NULL; | |
253 printf("=========>> ASX parser not yet implemented <<==========\n"); | |
254 | |
255 printf("ASX=[%s]\n", http_hdr->body ); | |
256 | |
257 return url_redirect; | |
871 | 258 } |
905 | 259 |
260 int | |
1001 | 261 asf_http_streaming_start( streaming_ctrl_t *streaming_ctrl ) { |
905 | 262 HTTP_header_t *http_hdr=NULL; |
263 URL_t *url_next=NULL; | |
1001 | 264 URL_t *url = *(streaming_ctrl->url); |
905 | 265 char buffer[BUFFER_SIZE]; |
266 int i; | |
1001 | 267 int fd = streaming_ctrl->fd_net; |
905 | 268 int done=1; |
1001 | 269 |
270 streaming_type = ASF_Live_e; | |
905 | 271 do { |
272 if( fd>0 ) close( fd ); | |
1001 | 273 |
905 | 274 fd = connect2Server( url->hostname, url->port ); |
275 if( fd<0 ) return -1; | |
276 | |
277 http_hdr = asf_http_request( url ); | |
1001 | 278 printf("[%s]\n", http_hdr->buffer ); |
905 | 279 write( fd, http_hdr->buffer, http_hdr->buffer_size ); |
1001 | 280 // http_free( http_hdr ); |
905 | 281 |
282 http_hdr = http_new_header(); | |
283 do { | |
1001 | 284 i = readFromServer( fd, buffer, BUFFER_SIZE ); |
905 | 285 printf("read: %d\n", i ); |
1001 | 286 if( i<0 ) { |
287 perror("read"); | |
288 http_free( http_hdr ); | |
289 return -1; | |
290 } | |
905 | 291 http_response_append( http_hdr, buffer, i ); |
292 } while( !http_is_header_entired( http_hdr ) ); | |
293 //http_hdr->buffer[http_hdr->buffer_len]='\0'; | |
294 //printf("[%s]\n", http_hdr->buffer ); | |
295 if( asf_http_parse_response(http_hdr)<0 ) { | |
296 printf("Failed to parse header\n"); | |
1001 | 297 http_free( http_hdr ); |
905 | 298 return -1; |
299 } | |
1001 | 300 switch( streaming_type ) { |
905 | 301 case ASF_Live_e: |
302 case ASF_Prerecorded_e: | |
1001 | 303 if( http_hdr->body_size>0 ) { |
304 printf("--- 0x%02X\n", streaming_ctrl->buffer ); | |
305 net_fifo_push( streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size ); | |
306 } else { | |
307 ASF_stream_chunck_t *ptr; | |
308 int ret; | |
309 i = readFromServer( fd, buffer, sizeof(ASF_stream_chunck_t) ); | |
905 | 310 printf("read: %d\n", i ); |
1001 | 311 ret = asf_streaming( buffer, i, NULL ); |
312 net_fifo_push( streaming_ctrl->buffer, buffer, i ); | |
313 ptr = (ASF_stream_chunck_t*)buffer; | |
314 if( ret==ptr->size ) { | |
315 } | |
905 | 316 } |
1001 | 317 // done = 0; |
905 | 318 break; |
319 case ASF_Redirector_e: | |
320 url_next = asf_http_ASX_redirect( http_hdr ); | |
321 if( url_next==NULL ) { | |
322 printf("Failed to parse ASX file\n"); | |
323 close(fd); | |
1001 | 324 http_free( http_hdr ); |
905 | 325 return -1; |
326 } | |
327 if( url_next->port==0 ) url_next->port=80; | |
328 url_free( url ); | |
329 url = url_next; | |
1001 | 330 *(streaming_ctrl->url) = url_next; |
905 | 331 url_next = NULL; |
332 break; | |
333 case ASF_Unknown_e: | |
334 default: | |
335 printf("Unknown ASF streaming type\n"); | |
336 close(fd); | |
1001 | 337 http_free( http_hdr ); |
905 | 338 return -1; |
339 } | |
340 | |
341 // Check if we got a redirect. | |
342 } while(!done); | |
343 | |
1001 | 344 streaming_ctrl->fd_net = fd; |
345 streaming_ctrl->streaming_read = asf_http_streaming_read; | |
346 streaming_ctrl->prebuffer_size = 10000; | |
347 streaming_ctrl->buffering = 1; | |
348 streaming_ctrl->status = streaming_playing_e; | |
349 | |
350 http_free( http_hdr ); | |
905 | 351 return fd; |
352 } | |
353 |