Mercurial > libavformat.hg
comparison mmst.c @ 6367:c58f5d360b4e libavformat
Extract fields that are to be shared between MMST/MMSH into a common struct,
MMSContext. The other MMST-specific members go into MMSTContext.
Patch by Zhentan Feng <spyfeng gmail com>.
author | rbultje |
---|---|
date | Wed, 11 Aug 2010 22:43:54 +0000 |
parents | d4691e73420f |
children | 1423af8f47f7 |
comparison
equal
deleted
inserted
replaced
6366:d4691e73420f | 6367:c58f5d360b4e |
---|---|
86 typedef struct { | 86 typedef struct { |
87 int id; | 87 int id; |
88 }MMSStream; | 88 }MMSStream; |
89 | 89 |
90 typedef struct { | 90 typedef struct { |
91 int outgoing_packet_seq; ///< Outgoing packet sequence number. | |
92 char path[256]; ///< Path of the resource being asked for. | |
93 char host[128]; ///< Host of the resources. | |
94 | |
95 URLContext *mms_hd; ///< TCP connection handle | 91 URLContext *mms_hd; ///< TCP connection handle |
96 MMSStream streams[MAX_STREAMS]; | 92 MMSStream streams[MAX_STREAMS]; |
97 | 93 |
98 /** Buffer for outgoing packets. */ | 94 /** Buffer for outgoing packets. */ |
99 /*@{*/ | 95 /*@{*/ |
106 uint8_t in_buffer[8192]; ///< Buffer for incoming packets. | 102 uint8_t in_buffer[8192]; ///< Buffer for incoming packets. |
107 uint8_t *read_in_ptr; ///< Pointer for reading from incoming buffer. | 103 uint8_t *read_in_ptr; ///< Pointer for reading from incoming buffer. |
108 int remaining_in_len; ///< Reading length from incoming buffer. | 104 int remaining_in_len; ///< Reading length from incoming buffer. |
109 /*@}*/ | 105 /*@}*/ |
110 | 106 |
111 int incoming_packet_seq; ///< Incoming packet sequence number. | |
112 int incoming_flags; ///< Incoming packet flags. | |
113 | |
114 int packet_id; ///< Identifier for packets in the current stream. | |
115 unsigned int header_packet_id; ///< default is 2. | |
116 | 107 |
117 /** Internal handling of the ASF header */ | 108 /** Internal handling of the ASF header */ |
118 /*@{*/ | 109 /*@{*/ |
119 uint8_t *asf_header; ///< Stored ASF header. | 110 uint8_t *asf_header; ///< Stored ASF header. |
120 int asf_header_size; ///< Size of stored ASF header. | 111 int asf_header_size; ///< Size of stored ASF header. |
124 /*@}*/ | 115 /*@}*/ |
125 | 116 |
126 int stream_num; ///< stream numbers. | 117 int stream_num; ///< stream numbers. |
127 } MMSContext; | 118 } MMSContext; |
128 | 119 |
120 typedef struct { | |
121 MMSContext mms; | |
122 int outgoing_packet_seq; ///< Outgoing packet sequence number. | |
123 char path[256]; ///< Path of the resource being asked for. | |
124 char host[128]; ///< Host of the resources. | |
125 int incoming_packet_seq; ///< Incoming packet sequence number. | |
126 int incoming_flags; ///< Incoming packet flags. | |
127 int packet_id; ///< Identifier for packets in the current stream. | |
128 unsigned int header_packet_id; ///< default is 2. | |
129 } MMSTContext; | |
130 | |
129 /** Create MMST command packet header */ | 131 /** Create MMST command packet header */ |
130 static void start_command_packet(MMSContext *mms, MMSCSPacketType packet_type) | 132 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type) |
131 { | 133 { |
134 MMSContext *mms = &mmst->mms; | |
132 mms->write_out_ptr = mms->out_buffer; | 135 mms->write_out_ptr = mms->out_buffer; |
133 | 136 |
134 bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence | 137 bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence |
135 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface); | 138 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface); |
136 bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes | 139 bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes |
137 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); | 140 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); |
138 bytestream_put_le32(&mms->write_out_ptr, 0); | 141 bytestream_put_le32(&mms->write_out_ptr, 0); |
139 bytestream_put_le32(&mms->write_out_ptr, mms->outgoing_packet_seq++); | 142 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++); |
140 bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp | 143 bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp |
141 bytestream_put_le32(&mms->write_out_ptr, 0); | 144 bytestream_put_le32(&mms->write_out_ptr, 0); |
142 bytestream_put_le16(&mms->write_out_ptr, packet_type); | 145 bytestream_put_le16(&mms->write_out_ptr, packet_type); |
143 bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server | 146 bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server |
144 } | 147 } |
150 bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix | 153 bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix |
151 bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix | 154 bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix |
152 } | 155 } |
153 | 156 |
154 /** Send a prepared MMST command packet. */ | 157 /** Send a prepared MMST command packet. */ |
155 static int send_command_packet(MMSContext *mms) | 158 static int send_command_packet(MMSTContext *mmst) |
156 { | 159 { |
160 MMSContext *mms = &mmst->mms; | |
157 int len= mms->write_out_ptr - mms->out_buffer; | 161 int len= mms->write_out_ptr - mms->out_buffer; |
158 int exact_length = FFALIGN(len, 8); | 162 int exact_length = FFALIGN(len, 8); |
159 int first_length= exact_length - 16; | 163 int first_length= exact_length - 16; |
160 int len8= first_length/8; | 164 int len8= first_length/8; |
161 int write_result; | 165 int write_result; |
190 | 194 |
191 len = ff_put_str16_nolen(&bic, src); | 195 len = ff_put_str16_nolen(&bic, src); |
192 mms->write_out_ptr += len; | 196 mms->write_out_ptr += len; |
193 } | 197 } |
194 | 198 |
195 static int send_time_test_data(MMSContext *mms) | 199 static int send_time_test_data(MMSTContext *mmst) |
196 { | 200 { |
197 start_command_packet(mms, CS_PKT_TIMING_DATA_REQUEST); | 201 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST); |
198 insert_command_prefixes(mms, 0xf0f0f0f1, 0x0004000b); | 202 insert_command_prefixes(&mmst->mms, 0xf0f0f0f1, 0x0004000b); |
199 return send_command_packet(mms); | 203 return send_command_packet(mmst); |
200 } | 204 } |
201 | 205 |
202 static int send_protocol_select(MMSContext *mms) | 206 static int send_protocol_select(MMSTContext *mmst) |
203 { | 207 { |
204 char data_string[256]; | 208 char data_string[256]; |
205 | 209 MMSContext *mms = &mmst->mms; |
206 start_command_packet(mms, CS_PKT_PROTOCOL_SELECT); | 210 |
211 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT); | |
207 insert_command_prefixes(mms, 0, 0xffffffff); | 212 insert_command_prefixes(mms, 0, 0xffffffff); |
208 bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes | 213 bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes |
209 bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate | 214 bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate |
210 bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode | 215 bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode |
211 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d", | 216 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d", |
215 LOCAL_ADDRESS&0xff, | 220 LOCAL_ADDRESS&0xff, |
216 "TCP", // or UDP | 221 "TCP", // or UDP |
217 LOCAL_PORT); | 222 LOCAL_PORT); |
218 | 223 |
219 mms_put_utf16(mms, data_string); | 224 mms_put_utf16(mms, data_string); |
220 return send_command_packet(mms); | 225 return send_command_packet(mmst); |
221 } | 226 } |
222 | 227 |
223 static int send_media_file_request(MMSContext *mms) | 228 static int send_media_file_request(MMSTContext *mmst) |
224 { | 229 { |
225 start_command_packet(mms, CS_PKT_MEDIA_FILE_REQUEST); | 230 MMSContext *mms = &mmst->mms; |
231 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST); | |
226 insert_command_prefixes(mms, 1, 0xffffffff); | 232 insert_command_prefixes(mms, 1, 0xffffffff); |
227 bytestream_put_le32(&mms->write_out_ptr, 0); | 233 bytestream_put_le32(&mms->write_out_ptr, 0); |
228 bytestream_put_le32(&mms->write_out_ptr, 0); | 234 bytestream_put_le32(&mms->write_out_ptr, 0); |
229 mms_put_utf16(mms, mms->path + 1); // +1 for skip "/" | 235 mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/" |
230 | 236 |
231 return send_command_packet(mms); | 237 return send_command_packet(mmst); |
232 } | 238 } |
233 | 239 |
234 static void handle_packet_stream_changing_type(MMSContext *mms) | 240 static void handle_packet_stream_changing_type(MMSTContext *mmst) |
235 { | 241 { |
242 MMSContext *mms = &mmst->mms; | |
236 dprintf(NULL, "Stream changing!\n"); | 243 dprintf(NULL, "Stream changing!\n"); |
237 | 244 |
238 // 40 is the packet header size, 7 is the prefix size. | 245 // 40 is the packet header size, 7 is the prefix size. |
239 mms->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); | 246 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); |
240 dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id); | 247 dprintf(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id); |
241 } | 248 } |
242 | 249 |
243 static int send_keepalive_packet(MMSContext *mms) | 250 static int send_keepalive_packet(MMSTContext *mmst) |
244 { | 251 { |
245 // respond to a keepalive with a keepalive... | 252 // respond to a keepalive with a keepalive... |
246 start_command_packet(mms, CS_PKT_KEEPALIVE); | 253 start_command_packet(mmst, CS_PKT_KEEPALIVE); |
247 insert_command_prefixes(mms, 1, 0x100FFFF); | 254 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF); |
248 return send_command_packet(mms); | 255 return send_command_packet(mmst); |
249 } | 256 } |
250 | 257 |
251 /** Pad media packets smaller than max_packet_size and/or adjust read position | 258 /** Pad media packets smaller than max_packet_size and/or adjust read position |
252 * after a seek. */ | 259 * after a seek. */ |
253 static void pad_media_packet(MMSContext *mms) | 260 static void pad_media_packet(MMSContext *mms) |
258 mms->remaining_in_len += padding_size; | 265 mms->remaining_in_len += padding_size; |
259 } | 266 } |
260 } | 267 } |
261 | 268 |
262 /** Read incoming MMST media, header or command packet. */ | 269 /** Read incoming MMST media, header or command packet. */ |
263 static MMSSCPacketType get_tcp_server_response(MMSContext *mms) | 270 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) |
264 { | 271 { |
265 int read_result; | 272 int read_result; |
266 MMSSCPacketType packet_type= -1; | 273 MMSSCPacketType packet_type= -1; |
267 | 274 MMSContext *mms = &mmst->mms; |
268 for(;;) { | 275 for(;;) { |
269 read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); | 276 read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); |
270 if (read_result != 8) { | 277 if (read_result != 8) { |
271 if(read_result < 0) { | 278 if(read_result < 0) { |
272 av_log(NULL, AV_LOG_ERROR, | 279 av_log(NULL, AV_LOG_ERROR, |
283 | 290 |
284 // handle command packet. | 291 // handle command packet. |
285 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { | 292 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { |
286 int length_remaining, hr; | 293 int length_remaining, hr; |
287 | 294 |
288 mms->incoming_flags= mms->in_buffer[3]; | 295 mmst->incoming_flags= mms->in_buffer[3]; |
289 read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); | 296 read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); |
290 if(read_result != 4) { | 297 if(read_result != 4) { |
291 av_log(NULL, AV_LOG_ERROR, | 298 av_log(NULL, AV_LOG_ERROR, |
292 "Reading command packet length failed: %d (%s)\n", | 299 "Reading command packet length failed: %d (%s)\n", |
293 read_result, | 300 read_result, |
330 | 337 |
331 // note we cache the first 8 bytes, | 338 // note we cache the first 8 bytes, |
332 // then fill up the buffer with the others | 339 // then fill up the buffer with the others |
333 tmp = AV_RL16(mms->in_buffer + 6); | 340 tmp = AV_RL16(mms->in_buffer + 6); |
334 length_remaining = (tmp - 8) & 0xffff; | 341 length_remaining = (tmp - 8) & 0xffff; |
335 mms->incoming_packet_seq = AV_RL32(mms->in_buffer); | 342 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); |
336 packet_id_type = mms->in_buffer[4]; | 343 packet_id_type = mms->in_buffer[4]; |
337 mms->incoming_flags = mms->in_buffer[5]; | 344 mmst->incoming_flags = mms->in_buffer[5]; |
338 | 345 |
339 if (length_remaining < 0 | 346 if (length_remaining < 0 |
340 || length_remaining > sizeof(mms->in_buffer) - 8) { | 347 || length_remaining > sizeof(mms->in_buffer) - 8) { |
341 av_log(NULL, AV_LOG_ERROR, | 348 av_log(NULL, AV_LOG_ERROR, |
342 "Data length %d is invalid or too large (max=%zu)\n", | 349 "Data length %d is invalid or too large (max=%zu)\n", |
354 "The server closed the connection"); | 361 "The server closed the connection"); |
355 return read_result < 0 ? read_result : AVERROR_IO; | 362 return read_result < 0 ? read_result : AVERROR_IO; |
356 } | 363 } |
357 | 364 |
358 // if we successfully read everything. | 365 // if we successfully read everything. |
359 if(packet_id_type == mms->header_packet_id) { | 366 if(packet_id_type == mmst->header_packet_id) { |
360 packet_type = SC_PKT_ASF_HEADER; | 367 packet_type = SC_PKT_ASF_HEADER; |
361 // Store the asf header | 368 // Store the asf header |
362 if(!mms->header_parsed) { | 369 if(!mms->header_parsed) { |
363 void *p = av_realloc(mms->asf_header, | 370 void *p = av_realloc(mms->asf_header, |
364 mms->asf_header_size + mms->remaining_in_len); | 371 mms->asf_header_size + mms->remaining_in_len); |
370 memcpy(mms->asf_header + mms->asf_header_size, | 377 memcpy(mms->asf_header + mms->asf_header_size, |
371 mms->read_in_ptr, mms->remaining_in_len); | 378 mms->read_in_ptr, mms->remaining_in_len); |
372 mms->asf_header_size += mms->remaining_in_len; | 379 mms->asf_header_size += mms->remaining_in_len; |
373 } | 380 } |
374 // 0x04 means asf header is sent in multiple packets. | 381 // 0x04 means asf header is sent in multiple packets. |
375 if (mms->incoming_flags == 0x04) | 382 if (mmst->incoming_flags == 0x04) |
376 continue; | 383 continue; |
377 } else if(packet_id_type == mms->packet_id) { | 384 } else if(packet_id_type == mmst->packet_id) { |
378 packet_type = SC_PKT_ASF_MEDIA; | 385 packet_type = SC_PKT_ASF_MEDIA; |
379 } else { | 386 } else { |
380 dprintf(NULL, "packet id type %d is old.", packet_id_type); | 387 dprintf(NULL, "packet id type %d is old.", packet_id_type); |
381 continue; | 388 continue; |
382 } | 389 } |
383 } | 390 } |
384 | 391 |
385 // preprocess some packet type | 392 // preprocess some packet type |
386 if(packet_type == SC_PKT_KEEPALIVE) { | 393 if(packet_type == SC_PKT_KEEPALIVE) { |
387 send_keepalive_packet(mms); | 394 send_keepalive_packet(mmst); |
388 continue; | 395 continue; |
389 } else if(packet_type == SC_PKT_STREAM_CHANGING) { | 396 } else if(packet_type == SC_PKT_STREAM_CHANGING) { |
390 handle_packet_stream_changing_type(mms); | 397 handle_packet_stream_changing_type(mmst); |
391 } else if(packet_type == SC_PKT_ASF_MEDIA) { | 398 } else if(packet_type == SC_PKT_ASF_MEDIA) { |
392 pad_media_packet(mms); | 399 pad_media_packet(mms); |
393 } | 400 } |
394 return packet_type; | 401 return packet_type; |
395 } | 402 } |
396 } | 403 } |
397 | 404 |
398 static int mms_safe_send_recv(MMSContext *mms, | 405 static int mms_safe_send_recv(MMSTContext *mmst, |
399 int (*send_fun)(MMSContext *mms), | 406 int (*send_fun)(MMSTContext *mmst), |
400 const MMSSCPacketType expect_type) | 407 const MMSSCPacketType expect_type) |
401 { | 408 { |
402 MMSSCPacketType type; | 409 MMSSCPacketType type; |
403 if(send_fun) { | 410 if(send_fun) { |
404 int ret = send_fun(mms); | 411 int ret = send_fun(mmst); |
405 if (ret < 0) { | 412 if (ret < 0) { |
406 dprintf(NULL, "Send Packet error before expecting recv packet %d\n", expect_type); | 413 dprintf(NULL, "Send Packet error before expecting recv packet %d\n", expect_type); |
407 return ret; | 414 return ret; |
408 } | 415 } |
409 } | 416 } |
410 | 417 |
411 if ((type = get_tcp_server_response(mms)) != expect_type) { | 418 if ((type = get_tcp_server_response(mmst)) != expect_type) { |
412 av_log(NULL, AV_LOG_ERROR, | 419 av_log(NULL, AV_LOG_ERROR, |
413 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", | 420 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", |
414 type, expect_type); | 421 type, expect_type); |
415 return AVERROR_INVALIDDATA; | 422 return AVERROR_INVALIDDATA; |
416 } else { | 423 } else { |
417 return 0; | 424 return 0; |
418 } | 425 } |
419 } | 426 } |
420 | 427 |
421 static int send_media_header_request(MMSContext *mms) | 428 static int send_media_header_request(MMSTContext *mmst) |
422 { | 429 { |
423 start_command_packet(mms, CS_PKT_MEDIA_HEADER_REQUEST); | 430 MMSContext *mms = &mmst->mms; |
431 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST); | |
424 insert_command_prefixes(mms, 1, 0); | 432 insert_command_prefixes(mms, 1, 0); |
425 bytestream_put_le32(&mms->write_out_ptr, 0); | 433 bytestream_put_le32(&mms->write_out_ptr, 0); |
426 bytestream_put_le32(&mms->write_out_ptr, 0x00800000); | 434 bytestream_put_le32(&mms->write_out_ptr, 0x00800000); |
427 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); | 435 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); |
428 bytestream_put_le32(&mms->write_out_ptr, 0); | 436 bytestream_put_le32(&mms->write_out_ptr, 0); |
433 bytestream_put_le32(&mms->write_out_ptr, 0); | 441 bytestream_put_le32(&mms->write_out_ptr, 0); |
434 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000); | 442 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000); |
435 bytestream_put_le32(&mms->write_out_ptr, 2); | 443 bytestream_put_le32(&mms->write_out_ptr, 2); |
436 bytestream_put_le32(&mms->write_out_ptr, 0); | 444 bytestream_put_le32(&mms->write_out_ptr, 0); |
437 | 445 |
438 return send_command_packet(mms); | 446 return send_command_packet(mmst); |
439 } | 447 } |
440 | 448 |
441 /** Send the initial handshake. */ | 449 /** Send the initial handshake. */ |
442 static int send_startup_packet(MMSContext *mms) | 450 static int send_startup_packet(MMSTContext *mmst) |
443 { | 451 { |
444 char data_string[256]; | 452 char data_string[256]; |
453 MMSContext *mms = &mmst->mms; | |
445 // SubscriberName is defined in MS specification linked below. | 454 // SubscriberName is defined in MS specification linked below. |
446 // The guid value can be any valid value. | 455 // The guid value can be any valid value. |
447 // http://download.microsoft.com/ | 456 // http://download.microsoft.com/ |
448 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf | 457 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf |
449 snprintf(data_string, sizeof(data_string), | 458 snprintf(data_string, sizeof(data_string), |
450 "NSPlayer/7.0.0.1956; {%s}; Host: %s", | 459 "NSPlayer/7.0.0.1956; {%s}; Host: %s", |
451 "7E667F5D-A661-495E-A512-F55686DDA178", mms->host); | 460 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host); |
452 | 461 |
453 start_command_packet(mms, CS_PKT_INITIAL); | 462 start_command_packet(mmst, CS_PKT_INITIAL); |
454 insert_command_prefixes(mms, 0, 0x0004000b); | 463 insert_command_prefixes(mms, 0, 0x0004000b); |
455 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); | 464 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); |
456 mms_put_utf16(mms, data_string); | 465 mms_put_utf16(mms, data_string); |
457 return send_command_packet(mms); | 466 return send_command_packet(mmst); |
458 } | 467 } |
459 | 468 |
460 static int asf_header_parser(MMSContext *mms) | 469 static int asf_header_parser(MMSContext *mms) |
461 { | 470 { |
462 uint8_t *p = mms->asf_header; | 471 uint8_t *p = mms->asf_header; |
517 | 526 |
518 return 0; | 527 return 0; |
519 } | 528 } |
520 | 529 |
521 /** Send MMST stream selection command based on the AVStream->discard values. */ | 530 /** Send MMST stream selection command based on the AVStream->discard values. */ |
522 static int send_stream_selection_request(MMSContext *mms) | 531 static int send_stream_selection_request(MMSTContext *mmst) |
523 { | 532 { |
524 int i; | 533 int i; |
525 | 534 MMSContext *mms = &mmst->mms; |
526 // send the streams we want back... | 535 // send the streams we want back... |
527 start_command_packet(mms, CS_PKT_STREAM_ID_REQUEST); | 536 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST); |
528 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums | 537 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums |
529 for(i= 0; i<mms->stream_num; i++) { | 538 for(i= 0; i<mms->stream_num; i++) { |
530 bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags | 539 bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags |
531 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id | 540 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id |
532 bytestream_put_le16(&mms->write_out_ptr, 0); // selection | 541 bytestream_put_le16(&mms->write_out_ptr, 0); // selection |
533 } | 542 } |
534 return send_command_packet(mms); | 543 return send_command_packet(mmst); |
535 } | 544 } |
536 | 545 |
537 static int read_data(MMSContext *mms, uint8_t *buf, const int buf_size) | 546 static int read_data(MMSContext *mms, uint8_t *buf, const int buf_size) |
538 { | 547 { |
539 int read_size; | 548 int read_size; |
542 mms->remaining_in_len -= read_size; | 551 mms->remaining_in_len -= read_size; |
543 mms->read_in_ptr += read_size; | 552 mms->read_in_ptr += read_size; |
544 return read_size; | 553 return read_size; |
545 } | 554 } |
546 | 555 |
547 static int send_close_packet(MMSContext *mms) | 556 static int send_close_packet(MMSTContext *mmst) |
548 { | 557 { |
549 start_command_packet(mms, CS_PKT_STREAM_CLOSE); | 558 start_command_packet(mmst, CS_PKT_STREAM_CLOSE); |
550 insert_command_prefixes(mms, 1, 1); | 559 insert_command_prefixes(&mmst->mms, 1, 1); |
551 | 560 |
552 return send_command_packet(mms); | 561 return send_command_packet(mmst); |
553 } | 562 } |
554 | 563 |
555 /** Close the MMSH/MMST connection */ | 564 /** Close the MMSH/MMST connection */ |
556 static int mms_close(URLContext *h) | 565 static int mms_close(URLContext *h) |
557 { | 566 { |
558 MMSContext *mms = (MMSContext *)h->priv_data; | 567 MMSTContext *mmst = (MMSTContext *)h->priv_data; |
559 | 568 MMSContext *mms = &mmst->mms; |
560 if(mms->mms_hd) { | 569 if(mms->mms_hd) { |
561 send_close_packet(mms); | 570 send_close_packet(mmst); |
562 url_close(mms->mms_hd); | 571 url_close(mms->mms_hd); |
563 } | 572 } |
564 | 573 |
565 /* free all separately allocated pointers in mms */ | 574 /* free all separately allocated pointers in mms */ |
566 av_free(mms->asf_header); | 575 av_free(mms->asf_header); |
567 av_freep(&h->priv_data); | 576 av_freep(&h->priv_data); |
568 | 577 |
569 return 0; | 578 return 0; |
570 } | 579 } |
571 | 580 |
572 static int send_media_packet_request(MMSContext *mms) | 581 static int send_media_packet_request(MMSTContext *mmst) |
573 { | 582 { |
574 start_command_packet(mms, CS_PKT_START_FROM_PKT_ID); | 583 MMSContext *mms = &mmst->mms; |
584 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID); | |
575 insert_command_prefixes(mms, 1, 0x0001FFFF); | 585 insert_command_prefixes(mms, 1, 0x0001FFFF); |
576 bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp | 586 bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp |
577 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown | 587 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown |
578 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset | 588 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset |
579 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit | 589 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit |
580 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit | 590 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit |
581 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit | 591 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit |
582 bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag | 592 bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag |
583 | 593 |
584 mms->packet_id++; // new packet_id | 594 mmst->packet_id++; // new packet_id |
585 bytestream_put_le32(&mms->write_out_ptr, mms->packet_id); | 595 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id); |
586 return send_command_packet(mms); | 596 return send_command_packet(mmst); |
587 } | 597 } |
588 | 598 |
589 | 599 |
590 static void clear_stream_buffers(MMSContext *mms) | 600 static void clear_stream_buffers(MMSContext *mms) |
591 { | 601 { |
593 mms->read_in_ptr = mms->in_buffer; | 603 mms->read_in_ptr = mms->in_buffer; |
594 } | 604 } |
595 | 605 |
596 static int mms_open(URLContext *h, const char *uri, int flags) | 606 static int mms_open(URLContext *h, const char *uri, int flags) |
597 { | 607 { |
608 MMSTContext *mmst; | |
598 MMSContext *mms; | 609 MMSContext *mms; |
599 int port, err; | 610 int port, err; |
600 char tcpname[256]; | 611 char tcpname[256]; |
601 | 612 |
602 h->is_streamed = 1; | 613 h->is_streamed = 1; |
603 mms = h->priv_data = av_mallocz(sizeof(MMSContext)); | 614 mmst = h->priv_data = av_mallocz(sizeof(MMSTContext)); |
604 if (!h->priv_data) | 615 if (!h->priv_data) |
605 return AVERROR(ENOMEM); | 616 return AVERROR(ENOMEM); |
617 mms = &mmst->mms; | |
606 | 618 |
607 // only for MMS over TCP, so set proto = NULL | 619 // only for MMS over TCP, so set proto = NULL |
608 av_url_split(NULL, 0, NULL, 0, | 620 av_url_split(NULL, 0, NULL, 0, |
609 mms->host, sizeof(mms->host), &port, mms->path, | 621 mmst->host, sizeof(mmst->host), &port, mmst->path, |
610 sizeof(mms->path), uri); | 622 sizeof(mmst->path), uri); |
611 | 623 |
612 if(port<0) | 624 if(port<0) |
613 port = 1755; // defaut mms protocol port | 625 port = 1755; // defaut mms protocol port |
614 | 626 |
615 // establish tcp connection. | 627 // establish tcp connection. |
616 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mms->host, port, NULL); | 628 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); |
617 err = url_open(&mms->mms_hd, tcpname, URL_RDWR); | 629 err = url_open(&mms->mms_hd, tcpname, URL_RDWR); |
618 if (err) | 630 if (err) |
619 goto fail; | 631 goto fail; |
620 | 632 |
621 mms->packet_id = 3; // default, initial value. | 633 mmst->packet_id = 3; // default, initial value. |
622 mms->header_packet_id = 2; // default, initial value. | 634 mmst->header_packet_id = 2; // default, initial value. |
623 err = mms_safe_send_recv(mms, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); | 635 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); |
624 if (err) | 636 if (err) |
625 goto fail; | 637 goto fail; |
626 err = mms_safe_send_recv(mms, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); | 638 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); |
627 if (err) | 639 if (err) |
628 goto fail; | 640 goto fail; |
629 err = mms_safe_send_recv(mms, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); | 641 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); |
630 if (err) | 642 if (err) |
631 goto fail; | 643 goto fail; |
632 err = mms_safe_send_recv(mms, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); | 644 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); |
633 if (err) | 645 if (err) |
634 goto fail; | 646 goto fail; |
635 err = mms_safe_send_recv(mms, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); | 647 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); |
636 if (err) | 648 if (err) |
637 goto fail; | 649 goto fail; |
638 err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_HEADER); | 650 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER); |
639 if (err) | 651 if (err) |
640 goto fail; | 652 goto fail; |
641 if((mms->incoming_flags != 0X08) && (mms->incoming_flags != 0X0C)) | 653 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) |
642 goto fail; | 654 goto fail; |
643 err = asf_header_parser(mms); | 655 err = asf_header_parser(mms); |
644 if (err) { | 656 if (err) { |
645 dprintf(NULL, "asf header parsed failed!\n"); | 657 dprintf(NULL, "asf header parsed failed!\n"); |
646 goto fail; | 658 goto fail; |
649 | 661 |
650 if (!mms->asf_packet_len || !mms->stream_num) | 662 if (!mms->asf_packet_len || !mms->stream_num) |
651 goto fail; | 663 goto fail; |
652 | 664 |
653 clear_stream_buffers(mms); | 665 clear_stream_buffers(mms); |
654 err = mms_safe_send_recv(mms, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); | 666 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); |
655 if (err) | 667 if (err) |
656 goto fail; | 668 goto fail; |
657 // send media packet request | 669 // send media packet request |
658 err = mms_safe_send_recv(mms, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); | 670 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); |
659 if (err) { | 671 if (err) { |
660 goto fail; | 672 goto fail; |
661 } | 673 } |
662 dprintf(NULL, "Leaving open (success)\n"); | 674 dprintf(NULL, "Leaving open (success)\n"); |
663 return 0; | 675 return 0; |
669 | 681 |
670 /** Read ASF data through the protocol. */ | 682 /** Read ASF data through the protocol. */ |
671 static int mms_read(URLContext *h, uint8_t *buf, int size) | 683 static int mms_read(URLContext *h, uint8_t *buf, int size) |
672 { | 684 { |
673 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ | 685 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ |
674 MMSContext *mms = h->priv_data; | 686 MMSTContext *mmst = h->priv_data; |
687 MMSContext *mms = &mmst->mms; | |
675 int result = 0; | 688 int result = 0; |
676 int size_to_copy; | 689 int size_to_copy; |
677 | 690 |
678 do { | 691 do { |
679 if(mms->asf_header_read_size < mms->asf_header_size) { | 692 if(mms->asf_header_read_size < mms->asf_header_size) { |
692 /* Read remaining packet data to buffer. | 705 /* Read remaining packet data to buffer. |
693 * the result can not be zero because remaining_in_len is positive.*/ | 706 * the result can not be zero because remaining_in_len is positive.*/ |
694 result = read_data(mms, buf, size); | 707 result = read_data(mms, buf, size); |
695 } else { | 708 } else { |
696 /* Read from network */ | 709 /* Read from network */ |
697 int err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_MEDIA); | 710 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA); |
698 if (err == 0) { | 711 if (err == 0) { |
699 if(mms->remaining_in_len>mms->asf_packet_len) { | 712 if(mms->remaining_in_len>mms->asf_packet_len) { |
700 av_log(NULL, AV_LOG_ERROR, | 713 av_log(NULL, AV_LOG_ERROR, |
701 "Incoming pktlen %d is larger than ASF pktsize %d\n", | 714 "Incoming pktlen %d is larger than ASF pktsize %d\n", |
702 mms->remaining_in_len, mms->asf_packet_len); | 715 mms->remaining_in_len, mms->asf_packet_len); |