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