Mercurial > mplayer.hg
annotate libmpdemux/asf_mmst_streaming.c @ 7834:830f10ad97ac
add a forgotten shutdown test
author | henry |
---|---|
date | Tue, 22 Oct 2002 07:29:09 +0000 |
parents | c4434bdf6e51 |
children | 5bb4d8801a2c |
rev | line source |
---|---|
6092 | 1 // mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/) |
2 // | |
3 // ported to mplayer by Abhijeet Phatak <abhijeetphatak@yahoo.com> | |
4 // date : 16 April 2002 | |
5 // | |
6 // information about the mms protocol can be find at http://get.to/sdp | |
7 // | |
8 | |
9 | |
10 #include <stdio.h> | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 #include <unistd.h> | |
14 #include <errno.h> | |
15 | |
16 #include "config.h" | |
17 | |
18 #include "url.h" | |
19 #include "asf.h" | |
20 | |
21 #include "stream.h" | |
22 | |
23 #include "network.h" | |
24 | |
25 int data_length = 0; | |
26 int packet_length1; | |
27 int media_padding; | |
28 int to_skip = 0; | |
29 | |
30 #include <inttypes.h> | |
31 | |
32 #define BUF_SIZE 102400 | |
33 int checknum =1; | |
34 | |
35 typedef struct | |
36 { | |
37 uint8_t buf[BUF_SIZE]; | |
38 int num_bytes; | |
39 | |
40 } command_t; | |
41 | |
42 int seq_num; | |
43 int num_stream_ids; | |
44 int stream_ids[20]; | |
45 int output_fh; | |
46 | |
47 static int get_data (int s, char *buf, size_t count); | |
48 int store_data(int s, int size, char *buffer) | |
49 { | |
50 // printf("data_length %d, media_padding %d, size %d \n", data_length, media_padding, size ); | |
51 if(data_length >= size) | |
52 { | |
53 if (!get_data (s, buffer, size)) | |
54 { | |
55 printf ("media data read failed\n"); | |
56 return 0; | |
57 } | |
58 data_length -= size; | |
59 return size; | |
60 } | |
61 else | |
62 { | |
63 int temp_size, media_temp_padding; | |
64 if(data_length) | |
65 { | |
66 if (!get_data (s, buffer, data_length)) | |
67 { | |
68 printf ("media data read failed\n"); | |
69 return 0; | |
70 } | |
71 } | |
72 if(media_padding) | |
73 { | |
74 if(media_padding > size - data_length) | |
75 { | |
76 memset(buffer+data_length,0,(size - data_length)); | |
77 media_padding -= (size - data_length); | |
78 data_length = 0; | |
79 return size; | |
80 } | |
81 else | |
82 { | |
83 memset(buffer+data_length,0,media_padding); | |
84 media_temp_padding = media_padding; | |
85 media_padding = 0; | |
86 temp_size =data_length; | |
87 data_length = 0; | |
88 return (temp_size + media_temp_padding); | |
89 } | |
90 } | |
91 temp_size = data_length; | |
92 data_length = 0; | |
93 return temp_size; | |
94 } | |
95 } | |
96 | |
97 static void put_32 (command_t *cmd, uint32_t value) | |
98 { | |
99 cmd->buf[cmd->num_bytes ] = value % 256; | |
100 value = value >> 8; | |
101 cmd->buf[cmd->num_bytes+1] = value % 256 ; | |
102 value = value >> 8; | |
103 cmd->buf[cmd->num_bytes+2] = value % 256 ; | |
104 value = value >> 8; | |
105 cmd->buf[cmd->num_bytes+3] = value % 256 ; | |
106 | |
107 cmd->num_bytes += 4; | |
108 } | |
109 | |
110 static uint32_t get_32 (unsigned char *cmd, int offset) | |
111 { | |
112 uint32_t ret; | |
113 | |
114 ret = cmd[offset] ; | |
115 ret |= cmd[offset+1]<<8 ; | |
116 ret |= cmd[offset+2]<<16 ; | |
117 ret |= cmd[offset+3]<<24 ; | |
118 | |
119 return ret; | |
120 } | |
121 | |
122 static void send_command (int s, int command, uint32_t switches, | |
123 uint32_t extra, int length, | |
124 char *data) | |
125 { | |
126 command_t cmd; | |
127 int len8; | |
128 | |
129 len8 = (length + (length%8)) / 8; | |
130 | |
131 cmd.num_bytes = 0; | |
132 | |
133 put_32 (&cmd, 0x00000001); /* start sequence */ | |
134 put_32 (&cmd, 0xB00BFACE); /* #-)) */ | |
135 put_32 (&cmd, length + 32); | |
136 put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ | |
137 put_32 (&cmd, len8 + 4); | |
138 put_32 (&cmd, seq_num); | |
139 seq_num++; | |
140 put_32 (&cmd, 0x0); /* unknown */ | |
141 put_32 (&cmd, 0x0); | |
142 put_32 (&cmd, len8+2); | |
143 put_32 (&cmd, 0x00030000 | command); /* dir | command */ | |
144 put_32 (&cmd, switches); | |
145 put_32 (&cmd, extra); | |
146 | |
147 memcpy (&cmd.buf[48], data, length); | |
148 | |
149 if (write (s, cmd.buf, length+48) != (length+48)) { | |
150 printf ("write error\n"); | |
151 } | |
152 } | |
153 | |
154 static void string_utf16(char *dest, char *src, int len) | |
155 { | |
156 int i; | |
157 | |
158 memset (dest, 0, 1000); | |
159 | |
160 for (i=0; i<len; i++) { | |
161 dest[i*2] = src[i]; | |
162 dest[i*2+1] = 0; | |
163 } | |
164 | |
165 dest[i*2] = 0; | |
166 dest[i*2+1] = 0; | |
167 } | |
168 | |
169 static void get_answer (int s) | |
170 { | |
171 char data[BUF_SIZE]; | |
172 int command = 0x1b; | |
173 | |
174 while (command == 0x1b) { | |
175 int len; | |
176 | |
177 len = read (s, data, BUF_SIZE) ; | |
178 if (!len) { | |
179 printf ("\nalert! eof\n"); | |
180 return; | |
181 } | |
182 | |
183 command = get_32 (data, 36) & 0xFFFF; | |
184 | |
185 if (command == 0x1b) | |
186 send_command (s, 0x1b, 0, 0, 0, data); | |
187 } | |
188 } | |
189 | |
190 static int get_data (int s, char *buf, size_t count) | |
191 { | |
192 ssize_t len, total; | |
193 total = 0; | |
194 | |
195 while (total < count) { | |
196 | |
197 len = read (s, &buf[total], count-total); | |
198 | |
199 if (len<0) { | |
200 perror ("read error:"); | |
201 return 0; | |
202 } | |
203 | |
204 total += len; | |
205 | |
206 if (len != 0) { | |
207 // printf ("[%d/%d]", total, count); | |
208 fflush (stdout); | |
209 } | |
210 | |
211 } | |
212 | |
213 return 1; | |
214 | |
215 } | |
216 | |
217 static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) | |
218 { | |
219 unsigned char pre_header[8]; | |
220 int header_len,i ; | |
221 | |
222 header_len = 0; | |
223 | |
224 while (1) { | |
225 if (!get_data (s, pre_header, 8)) { | |
226 printf ("pre-header read failed\n"); | |
227 return 0; | |
228 } | |
229 if (pre_header[4] == 0x02) { | |
230 | |
231 int packet_len; | |
232 | |
233 packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; | |
234 | |
235 // printf ("asf header packet detected, len=%d\n", packet_len); | |
236 | |
237 if (!get_data (s, &header[header_len], packet_len)) { | |
238 printf ("header data read failed\n"); | |
239 return 0; | |
240 } | |
241 | |
242 header_len += packet_len; | |
243 | |
244 if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) { | |
245 | |
246 | |
247 if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) { | |
248 return -1; | |
249 } | |
250 | |
251 // printf ("get header packet finished\n"); | |
252 | |
253 return (header_len); | |
254 | |
255 } | |
256 | |
257 } else { | |
258 | |
259 char packet_len; | |
260 int command; | |
261 char data[BUF_SIZE]; | |
262 | |
263 if (!get_data (s, &packet_len, 4)) { | |
264 printf ("packet_len read failed\n"); | |
265 return 0; | |
266 } | |
267 | |
268 packet_len = get_32 (&packet_len, 0) + 4; | |
269 | |
270 // printf ("command packet detected, len=%d\n", packet_len); | |
271 | |
272 if (!get_data (s, data, packet_len)) { | |
273 printf ("command data read failed\n"); | |
274 return 0; | |
275 } | |
276 | |
277 command = get_32 (data, 24) & 0xFFFF; | |
278 | |
279 // printf ("command: %02x\n", command); | |
280 | |
281 if (command == 0x1b) | |
282 send_command (s, 0x1b, 0, 0, 0, data); | |
283 | |
284 } | |
285 | |
286 // printf ("get header packet succ\n"); | |
287 } | |
288 } | |
289 | |
290 int interp_header (uint8_t *header, int header_len) | |
291 { | |
292 int i; | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7309
diff
changeset
|
293 int packet_length=-1; |
6092 | 294 |
295 /* | |
296 * parse header | |
297 */ | |
298 | |
299 i = 30; | |
300 while (i<header_len) { | |
301 | |
302 uint64_t guid_1, guid_2, length; | |
303 | |
304 guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
305 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
306 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
307 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
308 i += 8; | |
309 | |
310 guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
311 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
312 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
313 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
314 i += 8; | |
315 | |
316 // printf ("guid found: %016llx%016llx\n", guid_1, guid_2); | |
317 | |
318 length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
319 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
320 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
321 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
322 | |
323 i += 8; | |
324 | |
325 if ( (guid_1 == 0x6cce6200aa00d9a6) && (guid_2 == 0x11cf668e75b22630) ) { | |
326 printf ("header object\n"); | |
327 } else if ((guid_1 == 0x6cce6200aa00d9a6) && (guid_2 == 0x11cf668e75b22636)) { | |
328 printf ("data object\n"); | |
329 } else if ((guid_1 == 0x6553200cc000e48e) && (guid_2 == 0x11cfa9478cabdca1)) { | |
330 | |
331 packet_length = get_32(header, i+92-24); | |
332 | |
333 printf ("file object, packet length = %d (%d)\n", | |
334 packet_length, get_32(header, i+96-24)); | |
335 | |
336 | |
337 } else if ((guid_1 == 0x6553200cc000e68e) && (guid_2 == 0x11cfa9b7b7dc0791)) { | |
338 | |
339 int stream_id = header[i+48] | header[i+49] << 8; | |
340 | |
341 printf ("stream object, stream id: %d\n", stream_id); | |
342 | |
343 stream_ids[num_stream_ids] = stream_id; | |
344 num_stream_ids++; | |
345 | |
346 } else { | |
347 printf ("unknown object\n"); | |
348 } | |
349 | |
350 // printf ("length : %lld\n", length); | |
351 | |
352 i += length-24; | |
353 | |
354 } | |
355 | |
356 return packet_length; | |
357 | |
358 } | |
359 | |
360 | |
361 static int get_media_packet (int s, int padding, char *buffer, int size) | |
362 { | |
363 unsigned char pre_header[8]; | |
364 char data[BUF_SIZE]; | |
365 int CheckInnerData = 1; | |
366 int CheckOuterData = 1; | |
367 | |
368 | |
369 while(CheckOuterData) | |
370 { | |
371 int a; | |
372 if(media_padding ==0 && data_length == 0) | |
373 { | |
374 while(CheckInnerData) | |
375 { | |
376 if (!get_data (s, pre_header, 8)) { | |
377 printf ("pre-header read failed\n"); | |
378 return 0; | |
379 } | |
380 | |
381 if (pre_header[4] == 0x04) | |
382 { | |
383 data_length = (pre_header[7] << 8 | pre_header[6]) - 8; | |
384 media_padding = packet_length1 - data_length; | |
385 if(to_skip) | |
386 { | |
387 a = store_data(s, size - to_skip, buffer + to_skip); | |
388 to_skip = 0; | |
389 } | |
390 else | |
391 { | |
392 a = store_data(s, size, buffer); | |
393 } | |
394 // printf("a inner %d \n", size); | |
395 return size; | |
396 } | |
397 else | |
398 { | |
399 int command; | |
400 char packet_len; | |
401 if (!get_data (s, &packet_len, 4)) | |
402 { | |
403 printf ("packet_len read failed\n"); | |
404 return 0; | |
405 } | |
406 packet_len = get_32 (&packet_len, 0) + 4; | |
407 | |
408 if (!get_data (s, data, packet_len)) | |
409 { | |
410 printf ("command data read failed\n"); | |
411 return 0; | |
412 } | |
413 if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) | |
414 { | |
415 printf ("missing signature\n"); | |
7309
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
416 return -1; |
6092 | 417 } |
418 command = get_32 (data, 24) & 0xFFFF; | |
419 | |
420 if (command == 0x1b) | |
421 { | |
422 send_command (s, 0x1b, 0, 0, 0, data); | |
423 } | |
424 else if (command == 0x1e) | |
425 { | |
426 printf ("everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); | |
427 return 0; | |
428 } | |
7309
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
429 else if (command == 0x21 ) |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
430 { |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
431 // Looks like it's new in WMS9 |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
432 // Unknown command, but ignoring it seems to work. |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
433 return 0; |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
434 } |
6092 | 435 else if (command != 0x05) |
436 { | |
437 printf ("unknown command %02x\n", command); | |
7309
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
438 return -1; |
6092 | 439 } |
440 } | |
441 } | |
442 } | |
443 if(to_skip) | |
444 { | |
445 a = store_data(s, size - to_skip, buffer+to_skip ); | |
446 to_skip = 0; | |
447 } | |
448 else | |
449 { | |
450 a = store_data(s, size, buffer); | |
451 } | |
452 | |
453 if(a == size) | |
454 { | |
455 // printf("a outer %d", a ); | |
456 return a; | |
457 } | |
458 else | |
459 to_skip = a; | |
460 | |
461 } | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7309
diff
changeset
|
462 return 0; // is this ok? |
6092 | 463 } |
464 | |
465 int | |
466 asf_mmst_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) | |
467 { | |
468 int len = 0; | |
469 if( stream_ctrl->buffer_size!=0 ) { | |
470 int buffer_len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos; | |
471 len = (size<buffer_len)?size:buffer_len; | |
472 memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len ); | |
473 stream_ctrl->buffer_pos += len; | |
474 if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) { | |
475 free( stream_ctrl->buffer ); | |
476 stream_ctrl->buffer = NULL; | |
477 stream_ctrl->buffer_size = 0; | |
478 stream_ctrl->buffer_pos = 0; | |
479 } | |
480 | |
481 } | |
482 | |
483 if( len<size ) { | |
484 | |
485 int ret; | |
486 | |
487 ret = get_media_packet( fd, size - len, buffer+len, size-len ); | |
488 | |
489 if( ret<0 ) { | |
490 | |
7309
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
491 printf("get_media_packet error : %s\n",strerror(errno)); |
10f629e33ee6
Fixed an unknown command. Looks like it's a new command from WMS9.
bertrand
parents:
7250
diff
changeset
|
492 return -1; |
6092 | 493 |
494 } | |
495 | |
496 len += ret; | |
497 | |
498 //printf("read %d bytes from network\n", len ); | |
499 | |
500 } | |
501 | |
502 return len; | |
503 } | |
504 | |
505 int | |
506 asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) | |
507 { | |
508 return -1; | |
509 } | |
510 | |
511 int asf_mmst_streaming_start(stream_t *stream) | |
512 { | |
513 char str[1024]; | |
514 char data[1024]; | |
515 uint8_t asf_header[8192]; | |
516 int asf_header_len; | |
517 int len, i, packet_length; | |
518 char host[256]; | |
519 char *path; | |
520 URL_t *url1 = stream->streaming_ctrl->url; | |
521 int s = stream->fd; | |
522 | |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
523 if( s>0 ) { |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
524 close( stream->fd ); |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
525 stream->fd = -1; |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
526 } |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
527 |
6092 | 528 /* parse url */ |
529 path = strchr(url1->file,'/') + 1; | |
530 | |
531 url1->port=1755; | |
532 s = connect2Server( url1->hostname, url1->port ); | |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
533 if( s<0 ) { |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
534 return s; |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
535 } |
6092 | 536 printf ("connected\n"); |
537 | |
538 /* | |
539 * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. | |
540 * This command is sent at the very start of protocol initiation. It sends local information to the serve | |
541 * cmd 1 0x01 | |
542 * */ | |
543 | |
544 sprintf (str, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", host); | |
545 string_utf16 (data, str, strlen(str)+2); | |
546 // send_command(s, commandno ....) | |
547 send_command (s, 1, 0, 0x0004000b, strlen(str) * 2+8, data); | |
548 | |
549 len = read (s, data, BUF_SIZE) ; | |
550 | |
551 /*This sends details of the local machine IP address to a Funnel system at the server. | |
552 * Also, the TCP or UDP transport selection is sent. | |
553 * | |
554 * here 192.168.0.129 is local ip address TCP/UDP states the tronsport we r using | |
555 * and 1037 is the local TCP or UDP socket number | |
556 * cmd 2 0x02 | |
557 * */ | |
558 | |
559 string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037\0000", | |
560 28); | |
561 memset (data, 0, 8); | |
562 send_command (s, 2, 0, 0, 28*2+8, data); | |
563 | |
564 len = read (s, data, BUF_SIZE) ; | |
565 | |
566 /* This command sends file path (at server) and file name request to the server. | |
567 * 0x5 */ | |
568 | |
569 string_utf16 (&data[8], path, strlen(path)); | |
570 memset (data, 0, 8); | |
571 send_command (s, 5, 0, 0, strlen(path)*2+12, data); | |
572 | |
573 get_answer (s); | |
574 | |
575 /* The ASF header chunk request. Includes ?session' variable for pre header value. | |
576 * After this command is sent, | |
577 * the server replies with 0x11 command and then the header chunk with header data follows. | |
578 * 0x15 */ | |
579 | |
580 memset (data, 0, 40); | |
581 data[32] = 2; | |
582 | |
583 send_command (s, 0x15, 1, 0, 40, data); | |
584 | |
585 num_stream_ids = 0; | |
586 /* get_headers(s, asf_header); */ | |
587 | |
588 asf_header_len = get_header (s, asf_header, stream->streaming_ctrl); | |
589 // printf("---------------------------------- asf_header %d\n",asf_header); | |
590 packet_length = interp_header (asf_header, asf_header_len); | |
591 | |
592 | |
593 /* | |
594 * This command is the media stream MBR selector. Switches are always 6 bytes in length. | |
595 * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. | |
596 * Where: | |
597 * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. | |
598 * It is not yet understood what all this means. | |
599 * And the last [02] byte is probably the header ?session' value. | |
600 * | |
601 * 0x33 */ | |
602 | |
603 memset (data, 0, 40); | |
604 | |
605 for (i=1; i<num_stream_ids; i++) { | |
606 data [ (i-1) * 6 + 2 ] = 0xFF; | |
607 data [ (i-1) * 6 + 3 ] = 0xFF; | |
608 data [ (i-1) * 6 + 4 ] = stream_ids[i]; | |
609 data [ (i-1) * 6 + 5 ] = 0x00; | |
610 } | |
611 | |
612 send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); | |
613 | |
614 get_answer (s); | |
615 | |
616 /* Start sending file from packet xx. | |
617 * This command is also used for resume downloads or requesting a lost packet. | |
618 * Also used for seeking by sending a play point value which seeks to the media time point. | |
619 * Includes ?session' value in pre header and the maximum media stream time. | |
620 * 0x07 */ | |
621 | |
622 memset (data, 0, 40); | |
623 | |
624 for (i=8; i<16; i++) | |
625 data[i] = 0xFF; | |
626 | |
627 data[20] = 0x04; | |
628 | |
629 send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data); | |
630 | |
631 | |
632 stream->fd = s; | |
633 stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read; | |
634 stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek; | |
635 stream->streaming_ctrl->buffering = 1; | |
636 | |
637 stream->streaming_ctrl->status = streaming_playing_e; | |
638 stream->streaming_ctrl->buffering = 1; | |
639 | |
640 packet_length1 = packet_length; | |
641 | |
642 return 0; | |
643 } |