Mercurial > mplayer.hg
annotate libmpdemux/asf_mmst_streaming.c @ 13626:741649fe31cb
allow to step only one frame forward by pressing s.
author | reimar |
---|---|
date | Tue, 12 Oct 2004 22:10:56 +0000 |
parents | a0bb374553a1 |
children | dd835e8f3698 |
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> | |
7880 | 15 #include <inttypes.h> |
6092 | 16 |
17 #include "config.h" | |
18 | |
10281 | 19 #ifndef HAVE_WINSOCK2 |
20 #define closesocket close | |
21 #else | |
22 #include <winsock2.h> | |
23 #endif | |
24 | |
13600
a0bb374553a1
typo noticed by Shixin Zeng <shixinzeng at sjtu dot edu dot cn>
diego
parents:
12968
diff
changeset
|
25 #ifndef USE_SETLOCALE |
12675
7c5dee73a7dc
disable iconv in case setlocale is disabled - compile fix
alex
parents:
12674
diff
changeset
|
26 #undef USE_ICONV |
7c5dee73a7dc
disable iconv in case setlocale is disabled - compile fix
alex
parents:
12674
diff
changeset
|
27 #endif |
7c5dee73a7dc
disable iconv in case setlocale is disabled - compile fix
alex
parents:
12674
diff
changeset
|
28 |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
29 #ifdef USE_ICONV |
12674
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
30 #include <iconv.h> |
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
31 #ifdef USE_LANGINFO |
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
32 #include <langinfo.h> |
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
33 #endif |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
34 #include <locale.h> |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
35 #endif |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
36 |
6092 | 37 #include "url.h" |
38 #include "asf.h" | |
39 | |
40 #include "stream.h" | |
41 | |
42 #include "network.h" | |
43 | |
44 #define BUF_SIZE 102400 | |
45 | |
46 typedef struct | |
47 { | |
48 uint8_t buf[BUF_SIZE]; | |
49 int num_bytes; | |
50 | |
51 } command_t; | |
52 | |
7880 | 53 static int seq_num; |
54 static int num_stream_ids; | |
55 static int stream_ids[20]; | |
6092 | 56 |
57 static int get_data (int s, char *buf, size_t count); | |
58 | |
59 static void put_32 (command_t *cmd, uint32_t value) | |
60 { | |
61 cmd->buf[cmd->num_bytes ] = value % 256; | |
62 value = value >> 8; | |
63 cmd->buf[cmd->num_bytes+1] = value % 256 ; | |
64 value = value >> 8; | |
65 cmd->buf[cmd->num_bytes+2] = value % 256 ; | |
66 value = value >> 8; | |
67 cmd->buf[cmd->num_bytes+3] = value % 256 ; | |
68 | |
69 cmd->num_bytes += 4; | |
70 } | |
71 | |
72 static uint32_t get_32 (unsigned char *cmd, int offset) | |
73 { | |
74 uint32_t ret; | |
75 | |
76 ret = cmd[offset] ; | |
77 ret |= cmd[offset+1]<<8 ; | |
78 ret |= cmd[offset+2]<<16 ; | |
79 ret |= cmd[offset+3]<<24 ; | |
80 | |
81 return ret; | |
82 } | |
83 | |
84 static void send_command (int s, int command, uint32_t switches, | |
85 uint32_t extra, int length, | |
86 char *data) | |
87 { | |
88 command_t cmd; | |
89 int len8; | |
90 | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
91 len8 = (length + 7) / 8; |
6092 | 92 |
93 cmd.num_bytes = 0; | |
94 | |
95 put_32 (&cmd, 0x00000001); /* start sequence */ | |
96 put_32 (&cmd, 0xB00BFACE); /* #-)) */ | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
97 put_32 (&cmd, len8*8 + 32); |
6092 | 98 put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ |
99 put_32 (&cmd, len8 + 4); | |
100 put_32 (&cmd, seq_num); | |
101 seq_num++; | |
102 put_32 (&cmd, 0x0); /* unknown */ | |
103 put_32 (&cmd, 0x0); | |
104 put_32 (&cmd, len8+2); | |
105 put_32 (&cmd, 0x00030000 | command); /* dir | command */ | |
106 put_32 (&cmd, switches); | |
107 put_32 (&cmd, extra); | |
108 | |
109 memcpy (&cmd.buf[48], data, length); | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
110 if (length & 7) |
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
111 memset(&cmd.buf[48 + length], 0, 8 - (length & 7)); |
6092 | 112 |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
113 if (send (s, cmd.buf, len8*8+48, 0) != (len8*8+48)) { |
6092 | 114 printf ("write error\n"); |
115 } | |
116 } | |
117 | |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
118 #ifdef USE_ICONV |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
119 static iconv_t url_conv; |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
120 #endif |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
121 |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
122 static void string_utf16(char *dest, char *src, int len) { |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
123 int i; |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
124 #ifdef USE_ICONV |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
125 size_t len1, len2; |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
126 char *ip, *op; |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
127 |
11412 | 128 if (url_conv != (iconv_t)(-1)) |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
129 { |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
130 memset(dest, 0, 1000); |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
131 len1 = len; len2 = 1000; |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
132 ip = src; op = dest; |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
133 |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
134 iconv(url_conv, &ip, &len1, &op, &len2); |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
135 } |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
136 else |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
137 { |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
138 #endif |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
139 for (i=0; i<len; i++) { |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
140 dest[i*2] = src[i]; |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
141 dest[i*2+1] = 0; |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
142 } |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
143 /* trailing zeroes */ |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
144 dest[i*2] = 0; |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
145 dest[i*2+1] = 0; |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
146 #ifdef USE_ICONV |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
147 } |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
148 #endif |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
149 } |
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
150 |
6092 | 151 static void get_answer (int s) |
152 { | |
153 char data[BUF_SIZE]; | |
154 int command = 0x1b; | |
155 | |
156 while (command == 0x1b) { | |
157 int len; | |
158 | |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
10183
diff
changeset
|
159 len = recv (s, data, BUF_SIZE, 0) ; |
6092 | 160 if (!len) { |
161 printf ("\nalert! eof\n"); | |
162 return; | |
163 } | |
164 | |
165 command = get_32 (data, 36) & 0xFFFF; | |
166 | |
167 if (command == 0x1b) | |
168 send_command (s, 0x1b, 0, 0, 0, data); | |
169 } | |
170 } | |
171 | |
172 static int get_data (int s, char *buf, size_t count) | |
173 { | |
7953 | 174 ssize_t len; |
175 size_t total = 0; | |
6092 | 176 |
177 while (total < count) { | |
178 | |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
10183
diff
changeset
|
179 len = recv (s, &buf[total], count-total, 0); |
6092 | 180 |
12545 | 181 if (len<=0) { |
6092 | 182 perror ("read error:"); |
183 return 0; | |
184 } | |
185 | |
186 total += len; | |
187 | |
188 if (len != 0) { | |
189 // printf ("[%d/%d]", total, count); | |
190 fflush (stdout); | |
191 } | |
192 | |
193 } | |
194 | |
195 return 1; | |
196 | |
197 } | |
198 | |
199 static int get_header (int s, uint8_t *header, streaming_ctrl_t *streaming_ctrl) | |
200 { | |
201 unsigned char pre_header[8]; | |
7953 | 202 int header_len; |
6092 | 203 |
204 header_len = 0; | |
205 | |
206 while (1) { | |
207 if (!get_data (s, pre_header, 8)) { | |
208 printf ("pre-header read failed\n"); | |
209 return 0; | |
210 } | |
211 if (pre_header[4] == 0x02) { | |
212 | |
213 int packet_len; | |
214 | |
215 packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; | |
216 | |
217 // printf ("asf header packet detected, len=%d\n", packet_len); | |
218 | |
219 if (!get_data (s, &header[header_len], packet_len)) { | |
220 printf ("header data read failed\n"); | |
221 return 0; | |
222 } | |
223 | |
224 header_len += packet_len; | |
225 | |
226 if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) { | |
227 | |
228 | |
229 if( streaming_bufferize( streaming_ctrl, header, header_len )<0 ) { | |
230 return -1; | |
231 } | |
232 | |
233 // printf ("get header packet finished\n"); | |
234 | |
235 return (header_len); | |
236 | |
237 } | |
238 | |
239 } else { | |
240 | |
7953 | 241 int32_t packet_len; |
6092 | 242 int command; |
243 char data[BUF_SIZE]; | |
244 | |
7953 | 245 if (!get_data (s, (char*)&packet_len, 4)) { |
6092 | 246 printf ("packet_len read failed\n"); |
247 return 0; | |
248 } | |
249 | |
7953 | 250 packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; |
6092 | 251 |
252 // printf ("command packet detected, len=%d\n", packet_len); | |
253 | |
254 if (!get_data (s, data, packet_len)) { | |
255 printf ("command data read failed\n"); | |
256 return 0; | |
257 } | |
258 | |
259 command = get_32 (data, 24) & 0xFFFF; | |
260 | |
261 // printf ("command: %02x\n", command); | |
262 | |
263 if (command == 0x1b) | |
264 send_command (s, 0x1b, 0, 0, 0, data); | |
265 | |
266 } | |
267 | |
268 // printf ("get header packet succ\n"); | |
269 } | |
270 } | |
271 | |
7880 | 272 static int interp_header (uint8_t *header, int header_len) |
6092 | 273 { |
274 int i; | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7309
diff
changeset
|
275 int packet_length=-1; |
6092 | 276 |
277 /* | |
278 * parse header | |
279 */ | |
280 | |
281 i = 30; | |
282 while (i<header_len) { | |
283 | |
284 uint64_t guid_1, guid_2, length; | |
285 | |
286 guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
287 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
288 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
289 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
290 i += 8; | |
291 | |
292 guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
293 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
294 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
295 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
296 i += 8; | |
297 | |
298 // printf ("guid found: %016llx%016llx\n", guid_1, guid_2); | |
299 | |
300 length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) | |
301 | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) | |
302 | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) | |
303 | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); | |
304 | |
305 i += 8; | |
306 | |
12121 | 307 if ( (guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22630ULL) ) { |
6092 | 308 printf ("header object\n"); |
12121 | 309 } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { |
6092 | 310 printf ("data object\n"); |
12121 | 311 } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) { |
6092 | 312 |
313 packet_length = get_32(header, i+92-24); | |
314 | |
315 printf ("file object, packet length = %d (%d)\n", | |
316 packet_length, get_32(header, i+96-24)); | |
317 | |
318 | |
12121 | 319 } else if ((guid_1 == 0x6553200cc000e68eULL) && (guid_2 == 0x11cfa9b7b7dc0791ULL)) { |
6092 | 320 |
321 int stream_id = header[i+48] | header[i+49] << 8; | |
322 | |
323 printf ("stream object, stream id: %d\n", stream_id); | |
324 | |
325 stream_ids[num_stream_ids] = stream_id; | |
326 num_stream_ids++; | |
327 | |
328 } else { | |
329 printf ("unknown object\n"); | |
330 } | |
331 | |
332 // printf ("length : %lld\n", length); | |
333 | |
334 i += length-24; | |
335 | |
336 } | |
337 | |
338 return packet_length; | |
339 | |
340 } | |
341 | |
342 | |
7880 | 343 static int get_media_packet (int s, int padding, streaming_ctrl_t *stream_ctrl) { |
6092 | 344 unsigned char pre_header[8]; |
345 char data[BUF_SIZE]; | |
7880 | 346 |
347 if (!get_data (s, pre_header, 8)) { | |
348 printf ("pre-header read failed\n"); | |
349 return 0; | |
350 } | |
351 | |
352 // for (i=0; i<8; i++) | |
353 // printf ("pre_header[%d] = %02x (%d)\n", | |
354 // i, pre_header[i], pre_header[i]); | |
355 | |
356 if (pre_header[4] == 0x04) { | |
357 | |
358 int packet_len; | |
359 | |
360 packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; | |
361 | |
362 // printf ("asf media packet detected, len=%d\n", packet_len); | |
363 | |
364 if (!get_data (s, data, packet_len)) { | |
365 printf ("media data read failed\n"); | |
366 return 0; | |
367 } | |
368 | |
369 streaming_bufferize(stream_ctrl, data, padding); | |
370 | |
371 } else { | |
372 | |
7953 | 373 int32_t packet_len; |
374 int command; | |
7880 | 375 |
7953 | 376 if (!get_data (s, (char*)&packet_len, 4)) { |
7880 | 377 printf ("packet_len read failed\n"); |
378 return 0; | |
379 } | |
380 | |
7953 | 381 packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; |
7880 | 382 |
383 if (!get_data (s, data, packet_len)) { | |
384 printf ("command data read failed\n"); | |
385 return 0; | |
386 } | |
387 | |
388 if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) | |
389 || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { | |
390 | |
391 printf ("missing signature\n"); | |
392 return -1; | |
393 } | |
394 | |
395 command = get_32 (data, 24) & 0xFFFF; | |
396 | |
7977 | 397 // printf ("\ncommand packet detected, len=%d cmd=0x%X\n", packet_len, command); |
7880 | 398 |
399 if (command == 0x1b) | |
400 send_command (s, 0x1b, 0, 0, 0, data); | |
401 else if (command == 0x1e) { | |
402 printf ("everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); | |
403 return 0; | |
404 } | |
405 else if (command == 0x21 ) { | |
406 // Looks like it's new in WMS9 | |
407 // Unknown command, but ignoring it seems to work. | |
408 return 0; | |
409 } | |
410 else if (command != 0x05) { | |
411 printf ("unknown command %02x\n", command); | |
412 return -1; | |
413 } | |
414 } | |
415 | |
416 // printf ("get media packet succ\n"); | |
417 | |
418 return 1; | |
419 } | |
6092 | 420 |
421 | |
7880 | 422 static int packet_length1; |
6092 | 423 |
424 int | |
425 asf_mmst_streaming_read( int fd, char *buffer, int size, streaming_ctrl_t *stream_ctrl ) | |
426 { | |
7880 | 427 int len; |
428 | |
429 while( stream_ctrl->buffer_size==0 ) { | |
430 // buffer is empty - fill it! | |
431 int ret = get_media_packet( fd, packet_length1, stream_ctrl); | |
432 if( ret<0 ) { | |
433 printf("get_media_packet error : %s\n",strerror(errno)); | |
434 return -1; | |
12077 | 435 } else if (ret==0) //EOF? |
436 return ret; | |
7880 | 437 } |
438 | |
439 len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos; | |
440 if(len>size) len=size; | |
6092 | 441 memcpy( buffer, (stream_ctrl->buffer)+(stream_ctrl->buffer_pos), len ); |
442 stream_ctrl->buffer_pos += len; | |
443 if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) { | |
444 free( stream_ctrl->buffer ); | |
445 stream_ctrl->buffer = NULL; | |
446 stream_ctrl->buffer_size = 0; | |
447 stream_ctrl->buffer_pos = 0; | |
448 } | |
7880 | 449 return len; |
6092 | 450 |
451 } | |
452 | |
453 int | |
454 asf_mmst_streaming_seek( int fd, off_t pos, streaming_ctrl_t *streaming_ctrl ) | |
455 { | |
456 return -1; | |
7953 | 457 // Shut up gcc warning |
458 fd++; | |
459 pos++; | |
460 streaming_ctrl=NULL; | |
6092 | 461 } |
462 | |
463 int asf_mmst_streaming_start(stream_t *stream) | |
464 { | |
465 char str[1024]; | |
10183 | 466 char data[BUF_SIZE]; |
6092 | 467 uint8_t asf_header[8192]; |
468 int asf_header_len; | |
469 int len, i, packet_length; | |
12751 | 470 char *path, *unescpath; |
6092 | 471 URL_t *url1 = stream->streaming_ctrl->url; |
7953 | 472 int s = stream->fd; |
6092 | 473 |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
474 if( s>0 ) { |
10281 | 475 closesocket( stream->fd ); |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
476 stream->fd = -1; |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
477 } |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
478 |
6092 | 479 /* parse url */ |
480 path = strchr(url1->file,'/') + 1; | |
481 | |
12751 | 482 /* mmst filename are not url_escaped by MS MediaPlayer and are expected as |
483 * "plain text" by the server, so need to decode it here | |
484 */ | |
485 unescpath=malloc(strlen(path)+1); | |
486 if (!unescpath) { | |
487 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed!\n"); | |
488 return -1; | |
489 } | |
490 url_unescape_string(unescpath,path); | |
491 path=unescpath; | |
492 | |
493 | |
12968 | 494 if( url1->port==0 ) { |
495 url1->port=1755; | |
496 } | |
10625
620cc649f519
ftp support. The change on connect2Server is needed bcs we need 2
albeu
parents:
10281
diff
changeset
|
497 s = connect2Server( url1->hostname, url1->port, 1); |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
498 if( s<0 ) { |
12751 | 499 free(path); |
7250
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
500 return s; |
27a1315d6af4
Checked if the connection succeeded before writing in the socket.
bertrand
parents:
6092
diff
changeset
|
501 } |
6092 | 502 printf ("connected\n"); |
7880 | 503 |
504 seq_num=0; | |
6092 | 505 |
506 /* | |
507 * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. | |
508 * This command is sent at the very start of protocol initiation. It sends local information to the serve | |
509 * cmd 1 0x01 | |
510 * */ | |
511 | |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
512 /* prepare for the url encoding conversion */ |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
513 #ifdef USE_ICONV |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
514 setlocale(LC_CTYPE, ""); |
12674
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
515 #ifdef USE_LANGINFO |
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
516 url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET)); |
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
517 #else |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
518 url_conv = iconv_open("UTF-16LE",setlocale(LC_CTYPE, NULL)); |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
519 #endif |
12674
0392f36045f4
user nl_langinfo if langinfo support present for proper chinese support, feature requested by Shixin Zheng <shixinzheng@sjtu.edu.cn>
alex
parents:
12545
diff
changeset
|
520 #endif |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
521 |
10183 | 522 snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname); |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
523 string_utf16 (data, str, strlen(str)); |
6092 | 524 // send_command(s, commandno ....) |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
525 send_command (s, 1, 0, 0x0004000b, strlen(str)*2+2, data); |
6092 | 526 |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
10183
diff
changeset
|
527 len = recv (s, data, BUF_SIZE, 0) ; |
6092 | 528 |
529 /*This sends details of the local machine IP address to a Funnel system at the server. | |
530 * Also, the TCP or UDP transport selection is sent. | |
531 * | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
532 * here 192.168.0.1 is local ip address TCP/UDP states the tronsport we r using |
6092 | 533 * and 1037 is the local TCP or UDP socket number |
534 * cmd 2 0x02 | |
535 * */ | |
536 | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
537 string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24); |
6092 | 538 memset (data, 0, 8); |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
539 send_command (s, 2, 0, 0, 24*2+10, data); |
6092 | 540 |
10206
35e306346e59
Using recv/send instead read/write for proper MinGW support (it's a 4.2BSD standard). Patch by FloDt <flodt8@yahoo.de>
alex
parents:
10183
diff
changeset
|
541 len = recv (s, data, BUF_SIZE, 0) ; |
6092 | 542 |
543 /* This command sends file path (at server) and file name request to the server. | |
544 * 0x5 */ | |
545 | |
546 string_utf16 (&data[8], path, strlen(path)); | |
547 memset (data, 0, 8); | |
11225
48bb1fd37d2a
Fixing tons of 10ls. Patch by rgselk <rgselknospam@yahoo.com>
alex
parents:
10625
diff
changeset
|
548 send_command (s, 5, 0, 0, strlen(path)*2+10, data); |
12751 | 549 free(path); |
6092 | 550 |
551 get_answer (s); | |
552 | |
553 /* The ASF header chunk request. Includes ?session' variable for pre header value. | |
554 * After this command is sent, | |
555 * the server replies with 0x11 command and then the header chunk with header data follows. | |
556 * 0x15 */ | |
557 | |
558 memset (data, 0, 40); | |
559 data[32] = 2; | |
560 | |
561 send_command (s, 0x15, 1, 0, 40, data); | |
562 | |
563 num_stream_ids = 0; | |
564 /* get_headers(s, asf_header); */ | |
565 | |
566 asf_header_len = get_header (s, asf_header, stream->streaming_ctrl); | |
567 // printf("---------------------------------- asf_header %d\n",asf_header); | |
12545 | 568 if (asf_header_len==0) return -1; //error reading header |
6092 | 569 packet_length = interp_header (asf_header, asf_header_len); |
570 | |
571 | |
572 /* | |
573 * This command is the media stream MBR selector. Switches are always 6 bytes in length. | |
574 * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. | |
575 * Where: | |
576 * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. | |
577 * It is not yet understood what all this means. | |
578 * And the last [02] byte is probably the header ?session' value. | |
579 * | |
580 * 0x33 */ | |
581 | |
582 memset (data, 0, 40); | |
583 | |
584 for (i=1; i<num_stream_ids; i++) { | |
585 data [ (i-1) * 6 + 2 ] = 0xFF; | |
586 data [ (i-1) * 6 + 3 ] = 0xFF; | |
587 data [ (i-1) * 6 + 4 ] = stream_ids[i]; | |
588 data [ (i-1) * 6 + 5 ] = 0x00; | |
589 } | |
590 | |
591 send_command (s, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); | |
592 | |
593 get_answer (s); | |
594 | |
595 /* Start sending file from packet xx. | |
596 * This command is also used for resume downloads or requesting a lost packet. | |
597 * Also used for seeking by sending a play point value which seeks to the media time point. | |
598 * Includes ?session' value in pre header and the maximum media stream time. | |
599 * 0x07 */ | |
600 | |
601 memset (data, 0, 40); | |
602 | |
603 for (i=8; i<16; i++) | |
604 data[i] = 0xFF; | |
605 | |
606 data[20] = 0x04; | |
607 | |
608 send_command (s, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data); | |
609 | |
7880 | 610 stream->fd = s; |
611 stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read; | |
612 stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek; | |
613 stream->streaming_ctrl->buffering = 1; | |
614 stream->streaming_ctrl->status = streaming_playing_e; | |
6092 | 615 |
7880 | 616 packet_length1 = packet_length; |
617 printf("mmst packet_length = %d\n",packet_length); | |
6092 | 618 |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
619 #ifdef USE_ICONV |
11412 | 620 if (url_conv != (iconv_t)(-1)) |
11403
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
621 iconv_close(url_conv); |
86ab7e0b2a65
fallback to non-iconv dummy utf16 conversion if iconv failed
alex
parents:
11402
diff
changeset
|
622 #endif |
11350
007ec48cf146
Current mplayer (mine is mplayer-1.0-pre1cvs20031001) cannot play mms
attila
parents:
11226
diff
changeset
|
623 |
6092 | 624 return 0; |
625 } |