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