Libav 0.7.1
|
00001 /* 00002 * MMS protocol over TCP 00003 * Copyright (c) 2006,2007 Ryan Martell 00004 * Copyright (c) 2007 Björn Axelsson 00005 * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com> 00006 * 00007 * This file is part of Libav. 00008 * 00009 * Libav is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * Libav is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with Libav; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 */ 00023 00024 /* References 00025 * MMS protocol specification: 00026 * [1]http://msdn.microsoft.com/en-us/library/cc234711(PROT.10).aspx 00027 * ASF specification. Revision 01.20.03. 00028 * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx 00029 */ 00030 00031 #include "avformat.h" 00032 #include "mms.h" 00033 #include "internal.h" 00034 #include "avio_internal.h" 00035 #include "libavutil/intreadwrite.h" 00036 #include "libavcodec/bytestream.h" 00037 #include "network.h" 00038 #include "url.h" 00039 00040 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address. 00041 #define LOCAL_PORT 1037 // as above. 00042 00043 typedef enum { 00044 CS_PKT_INITIAL = 0x01, 00045 CS_PKT_PROTOCOL_SELECT = 0x02, 00046 CS_PKT_MEDIA_FILE_REQUEST = 0x05, 00047 CS_PKT_START_FROM_PKT_ID = 0x07, 00048 CS_PKT_STREAM_PAUSE = 0x09, 00049 CS_PKT_STREAM_CLOSE = 0x0d, 00050 CS_PKT_MEDIA_HEADER_REQUEST = 0x15, 00051 CS_PKT_TIMING_DATA_REQUEST = 0x18, 00052 CS_PKT_USER_PASSWORD = 0x1a, 00053 CS_PKT_KEEPALIVE = 0x1b, 00054 CS_PKT_STREAM_ID_REQUEST = 0x33, 00055 } MMSCSPacketType; 00056 00058 typedef enum { 00061 SC_PKT_CLIENT_ACCEPTED = 0x01, 00062 SC_PKT_PROTOCOL_ACCEPTED = 0x02, 00063 SC_PKT_PROTOCOL_FAILED = 0x03, 00064 SC_PKT_MEDIA_PKT_FOLLOWS = 0x05, 00065 SC_PKT_MEDIA_FILE_DETAILS = 0x06, 00066 SC_PKT_HEADER_REQUEST_ACCEPTED = 0x11, 00067 SC_PKT_TIMING_TEST_REPLY = 0x15, 00068 SC_PKT_PASSWORD_REQUIRED = 0x1a, 00069 SC_PKT_KEEPALIVE = 0x1b, 00070 SC_PKT_STREAM_STOPPED = 0x1e, 00071 SC_PKT_STREAM_CHANGING = 0x20, 00072 SC_PKT_STREAM_ID_ACCEPTED = 0x21, 00077 SC_PKT_CANCEL = -1, 00078 SC_PKT_NO_DATA = -2, 00083 SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in case of 00084 SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets. 00086 } MMSSCPacketType; 00087 00088 typedef struct { 00089 MMSContext mms; 00090 int outgoing_packet_seq; 00091 char path[256]; 00092 char host[128]; 00093 int incoming_packet_seq; 00094 int incoming_flags; 00095 int packet_id; 00096 unsigned int header_packet_id; 00097 } MMSTContext; 00098 00100 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type) 00101 { 00102 MMSContext *mms = &mmst->mms; 00103 mms->write_out_ptr = mms->out_buffer; 00104 00105 bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence 00106 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface); 00107 bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes 00108 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); 00109 bytestream_put_le32(&mms->write_out_ptr, 0); 00110 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++); 00111 bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp 00112 bytestream_put_le32(&mms->write_out_ptr, 0); 00113 bytestream_put_le16(&mms->write_out_ptr, packet_type); 00114 bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server 00115 } 00116 00118 static void insert_command_prefixes(MMSContext *mms, 00119 uint32_t prefix1, uint32_t prefix2) 00120 { 00121 bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix 00122 bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix 00123 } 00124 00126 static int send_command_packet(MMSTContext *mmst) 00127 { 00128 MMSContext *mms = &mmst->mms; 00129 int len= mms->write_out_ptr - mms->out_buffer; 00130 int exact_length = FFALIGN(len, 8); 00131 int first_length= exact_length - 16; 00132 int len8= first_length/8; 00133 int write_result; 00134 00135 // update packet length fields. 00136 AV_WL32(mms->out_buffer + 8, first_length); 00137 AV_WL32(mms->out_buffer + 16, len8); 00138 AV_WL32(mms->out_buffer + 32, len8-2); 00139 memset(mms->write_out_ptr, 0, exact_length - len); 00140 00141 // write it out. 00142 write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length); 00143 if(write_result != exact_length) { 00144 av_log(NULL, AV_LOG_ERROR, 00145 "Failed to write data of length %d: %d (%s)\n", 00146 exact_length, write_result, 00147 write_result < 0 ? strerror(write_result) : 00148 "The server closed the connection"); 00149 return AVERROR(EIO); 00150 } 00151 00152 return 0; 00153 } 00154 00155 static void mms_put_utf16(MMSContext *mms, uint8_t *src) 00156 { 00157 AVIOContext bic; 00158 int size = mms->write_out_ptr - mms->out_buffer; 00159 int len; 00160 ffio_init_context(&bic, mms->write_out_ptr, 00161 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL); 00162 00163 len = avio_put_str16le(&bic, src); 00164 mms->write_out_ptr += len; 00165 } 00166 00167 static int send_time_test_data(MMSTContext *mmst) 00168 { 00169 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST); 00170 insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b); 00171 return send_command_packet(mmst); 00172 } 00173 00174 static int send_protocol_select(MMSTContext *mmst) 00175 { 00176 char data_string[256]; 00177 MMSContext *mms = &mmst->mms; 00178 00179 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT); 00180 insert_command_prefixes(mms, 0, 0xffffffff); 00181 bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes 00182 bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate 00183 bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode 00184 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d", 00185 (LOCAL_ADDRESS>>24)&0xff, 00186 (LOCAL_ADDRESS>>16)&0xff, 00187 (LOCAL_ADDRESS>>8)&0xff, 00188 LOCAL_ADDRESS&0xff, 00189 "TCP", // or UDP 00190 LOCAL_PORT); 00191 00192 mms_put_utf16(mms, data_string); 00193 return send_command_packet(mmst); 00194 } 00195 00196 static int send_media_file_request(MMSTContext *mmst) 00197 { 00198 MMSContext *mms = &mmst->mms; 00199 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST); 00200 insert_command_prefixes(mms, 1, 0xffffffff); 00201 bytestream_put_le32(&mms->write_out_ptr, 0); 00202 bytestream_put_le32(&mms->write_out_ptr, 0); 00203 mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/" 00204 00205 return send_command_packet(mmst); 00206 } 00207 00208 static void handle_packet_stream_changing_type(MMSTContext *mmst) 00209 { 00210 MMSContext *mms = &mmst->mms; 00211 av_dlog(NULL, "Stream changing!\n"); 00212 00213 // 40 is the packet header size, 7 is the prefix size. 00214 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); 00215 av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id); 00216 } 00217 00218 static int send_keepalive_packet(MMSTContext *mmst) 00219 { 00220 // respond to a keepalive with a keepalive... 00221 start_command_packet(mmst, CS_PKT_KEEPALIVE); 00222 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF); 00223 return send_command_packet(mmst); 00224 } 00225 00228 static void pad_media_packet(MMSContext *mms) 00229 { 00230 if(mms->remaining_in_len<mms->asf_packet_len) { 00231 int padding_size = mms->asf_packet_len - mms->remaining_in_len; 00232 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size); 00233 mms->remaining_in_len += padding_size; 00234 } 00235 } 00236 00238 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) 00239 { 00240 int read_result; 00241 MMSSCPacketType packet_type= -1; 00242 MMSContext *mms = &mmst->mms; 00243 for(;;) { 00244 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8); 00245 if (read_result != 8) { 00246 if(read_result < 0) { 00247 av_log(NULL, AV_LOG_ERROR, 00248 "Error reading packet header: %d (%s)\n", 00249 read_result, strerror(read_result)); 00250 packet_type = SC_PKT_CANCEL; 00251 } else { 00252 av_log(NULL, AV_LOG_ERROR, 00253 "The server closed the connection\n"); 00254 packet_type = SC_PKT_NO_DATA; 00255 } 00256 return packet_type; 00257 } 00258 00259 // handle command packet. 00260 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { 00261 int length_remaining, hr; 00262 00263 mmst->incoming_flags= mms->in_buffer[3]; 00264 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4); 00265 if(read_result != 4) { 00266 av_log(NULL, AV_LOG_ERROR, 00267 "Reading command packet length failed: %d (%s)\n", 00268 read_result, 00269 read_result < 0 ? strerror(read_result) : 00270 "The server closed the connection"); 00271 return read_result < 0 ? read_result : AVERROR(EIO); 00272 } 00273 00274 length_remaining= AV_RL32(mms->in_buffer+8) + 4; 00275 av_dlog(NULL, "Length remaining is %d\n", length_remaining); 00276 // read the rest of the packet. 00277 if (length_remaining < 0 00278 || length_remaining > sizeof(mms->in_buffer) - 12) { 00279 av_log(NULL, AV_LOG_ERROR, 00280 "Incoming packet length %d exceeds bufsize %zu\n", 00281 length_remaining, sizeof(mms->in_buffer) - 12); 00282 return AVERROR_INVALIDDATA; 00283 } 00284 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12, 00285 length_remaining) ; 00286 if (read_result != length_remaining) { 00287 av_log(NULL, AV_LOG_ERROR, 00288 "Reading pkt data (length=%d) failed: %d (%s)\n", 00289 length_remaining, read_result, 00290 read_result < 0 ? strerror(read_result) : 00291 "The server closed the connection"); 00292 return read_result < 0 ? read_result : AVERROR(EIO); 00293 } 00294 packet_type= AV_RL16(mms->in_buffer+36); 00295 if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) { 00296 av_log(NULL, AV_LOG_ERROR, 00297 "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr); 00298 return AVERROR(EINVAL); 00299 } 00300 } else { 00301 int length_remaining; 00302 int packet_id_type; 00303 int tmp; 00304 00305 // note we cache the first 8 bytes, 00306 // then fill up the buffer with the others 00307 tmp = AV_RL16(mms->in_buffer + 6); 00308 length_remaining = (tmp - 8) & 0xffff; 00309 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); 00310 packet_id_type = mms->in_buffer[4]; 00311 mmst->incoming_flags = mms->in_buffer[5]; 00312 00313 if (length_remaining < 0 00314 || length_remaining > sizeof(mms->in_buffer) - 8) { 00315 av_log(NULL, AV_LOG_ERROR, 00316 "Data length %d is invalid or too large (max=%zu)\n", 00317 length_remaining, sizeof(mms->in_buffer)); 00318 return AVERROR_INVALIDDATA; 00319 } 00320 mms->remaining_in_len = length_remaining; 00321 mms->read_in_ptr = mms->in_buffer; 00322 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); 00323 if(read_result != length_remaining) { 00324 av_log(NULL, AV_LOG_ERROR, 00325 "Failed to read packet data of size %d: %d (%s)\n", 00326 length_remaining, read_result, 00327 read_result < 0 ? strerror(read_result) : 00328 "The server closed the connection"); 00329 return read_result < 0 ? read_result : AVERROR(EIO); 00330 } 00331 00332 // if we successfully read everything. 00333 if(packet_id_type == mmst->header_packet_id) { 00334 packet_type = SC_PKT_ASF_HEADER; 00335 // Store the asf header 00336 if(!mms->header_parsed) { 00337 void *p = av_realloc(mms->asf_header, 00338 mms->asf_header_size + mms->remaining_in_len); 00339 if (!p) { 00340 av_freep(&mms->asf_header); 00341 return AVERROR(ENOMEM); 00342 } 00343 mms->asf_header = p; 00344 memcpy(mms->asf_header + mms->asf_header_size, 00345 mms->read_in_ptr, mms->remaining_in_len); 00346 mms->asf_header_size += mms->remaining_in_len; 00347 } 00348 // 0x04 means asf header is sent in multiple packets. 00349 if (mmst->incoming_flags == 0x04) 00350 continue; 00351 } else if(packet_id_type == mmst->packet_id) { 00352 packet_type = SC_PKT_ASF_MEDIA; 00353 } else { 00354 av_dlog(NULL, "packet id type %d is old.", packet_id_type); 00355 continue; 00356 } 00357 } 00358 00359 // preprocess some packet type 00360 if(packet_type == SC_PKT_KEEPALIVE) { 00361 send_keepalive_packet(mmst); 00362 continue; 00363 } else if(packet_type == SC_PKT_STREAM_CHANGING) { 00364 handle_packet_stream_changing_type(mmst); 00365 } else if(packet_type == SC_PKT_ASF_MEDIA) { 00366 pad_media_packet(mms); 00367 } 00368 return packet_type; 00369 } 00370 } 00371 00372 static int mms_safe_send_recv(MMSTContext *mmst, 00373 int (*send_fun)(MMSTContext *mmst), 00374 const MMSSCPacketType expect_type) 00375 { 00376 MMSSCPacketType type; 00377 if(send_fun) { 00378 int ret = send_fun(mmst); 00379 if (ret < 0) { 00380 av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type); 00381 return ret; 00382 } 00383 } 00384 00385 if ((type = get_tcp_server_response(mmst)) != expect_type) { 00386 av_log(NULL, AV_LOG_ERROR, 00387 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", 00388 type, expect_type); 00389 return AVERROR_INVALIDDATA; 00390 } else { 00391 return 0; 00392 } 00393 } 00394 00395 static int send_media_header_request(MMSTContext *mmst) 00396 { 00397 MMSContext *mms = &mmst->mms; 00398 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST); 00399 insert_command_prefixes(mms, 1, 0); 00400 bytestream_put_le32(&mms->write_out_ptr, 0); 00401 bytestream_put_le32(&mms->write_out_ptr, 0x00800000); 00402 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); 00403 bytestream_put_le32(&mms->write_out_ptr, 0); 00404 bytestream_put_le32(&mms->write_out_ptr, 0); 00405 bytestream_put_le32(&mms->write_out_ptr, 0); 00406 00407 // the media preroll value in milliseconds? 00408 bytestream_put_le32(&mms->write_out_ptr, 0); 00409 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000); 00410 bytestream_put_le32(&mms->write_out_ptr, 2); 00411 bytestream_put_le32(&mms->write_out_ptr, 0); 00412 00413 return send_command_packet(mmst); 00414 } 00415 00417 static int send_startup_packet(MMSTContext *mmst) 00418 { 00419 char data_string[256]; 00420 MMSContext *mms = &mmst->mms; 00421 // SubscriberName is defined in MS specification linked below. 00422 // The guid value can be any valid value. 00423 // http://download.microsoft.com/ 00424 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf 00425 snprintf(data_string, sizeof(data_string), 00426 "NSPlayer/7.0.0.1956; {%s}; Host: %s", 00427 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host); 00428 00429 start_command_packet(mmst, CS_PKT_INITIAL); 00430 insert_command_prefixes(mms, 0, 0x0004000b); 00431 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); 00432 mms_put_utf16(mms, data_string); 00433 return send_command_packet(mmst); 00434 } 00435 00437 static int send_stream_selection_request(MMSTContext *mmst) 00438 { 00439 int i; 00440 MMSContext *mms = &mmst->mms; 00441 // send the streams we want back... 00442 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST); 00443 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums 00444 for(i= 0; i<mms->stream_num; i++) { 00445 bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags 00446 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id 00447 bytestream_put_le16(&mms->write_out_ptr, 0); // selection 00448 } 00449 return send_command_packet(mmst); 00450 } 00451 00452 static int send_close_packet(MMSTContext *mmst) 00453 { 00454 start_command_packet(mmst, CS_PKT_STREAM_CLOSE); 00455 insert_command_prefixes(&mmst->mms, 1, 1); 00456 00457 return send_command_packet(mmst); 00458 } 00459 00461 static int mms_close(URLContext *h) 00462 { 00463 MMSTContext *mmst = (MMSTContext *)h->priv_data; 00464 MMSContext *mms = &mmst->mms; 00465 if(mms->mms_hd) { 00466 send_close_packet(mmst); 00467 ffurl_close(mms->mms_hd); 00468 } 00469 00470 /* free all separately allocated pointers in mms */ 00471 av_free(mms->streams); 00472 av_free(mms->asf_header); 00473 av_freep(&h->priv_data); 00474 00475 return 0; 00476 } 00477 00478 static int send_media_packet_request(MMSTContext *mmst) 00479 { 00480 MMSContext *mms = &mmst->mms; 00481 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID); 00482 insert_command_prefixes(mms, 1, 0x0001FFFF); 00483 bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp 00484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown 00485 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset 00486 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit 00487 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit 00488 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit 00489 bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag 00490 00491 mmst->packet_id++; // new packet_id 00492 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id); 00493 return send_command_packet(mmst); 00494 } 00495 00496 00497 static void clear_stream_buffers(MMSContext *mms) 00498 { 00499 mms->remaining_in_len = 0; 00500 mms->read_in_ptr = mms->in_buffer; 00501 } 00502 00503 static int mms_open(URLContext *h, const char *uri, int flags) 00504 { 00505 MMSTContext *mmst; 00506 MMSContext *mms; 00507 int port, err; 00508 char tcpname[256]; 00509 00510 h->is_streamed = 1; 00511 mmst = h->priv_data = av_mallocz(sizeof(MMSTContext)); 00512 if (!h->priv_data) 00513 return AVERROR(ENOMEM); 00514 mms = &mmst->mms; 00515 00516 // only for MMS over TCP, so set proto = NULL 00517 av_url_split(NULL, 0, NULL, 0, 00518 mmst->host, sizeof(mmst->host), &port, mmst->path, 00519 sizeof(mmst->path), uri); 00520 00521 if(port<0) 00522 port = 1755; // defaut mms protocol port 00523 00524 // establish tcp connection. 00525 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); 00526 err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE); 00527 if (err) 00528 goto fail; 00529 00530 mmst->packet_id = 3; // default, initial value. 00531 mmst->header_packet_id = 2; // default, initial value. 00532 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); 00533 if (err) 00534 goto fail; 00535 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); 00536 if (err) 00537 goto fail; 00538 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); 00539 if (err) 00540 goto fail; 00541 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); 00542 if (err) 00543 goto fail; 00544 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); 00545 if (err) 00546 goto fail; 00547 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER); 00548 if (err) 00549 goto fail; 00550 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) { 00551 av_log(NULL, AV_LOG_ERROR, 00552 "The server does not support MMST (try MMSH or RTSP)\n"); 00553 err = AVERROR(EINVAL); 00554 goto fail; 00555 } 00556 err = ff_mms_asf_header_parser(mms); 00557 if (err) { 00558 av_dlog(NULL, "asf header parsed failed!\n"); 00559 goto fail; 00560 } 00561 mms->header_parsed = 1; 00562 00563 if (!mms->asf_packet_len || !mms->stream_num) 00564 goto fail; 00565 00566 clear_stream_buffers(mms); 00567 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); 00568 if (err) 00569 goto fail; 00570 // send media packet request 00571 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); 00572 if (err) { 00573 goto fail; 00574 } 00575 av_dlog(NULL, "Leaving open (success)\n"); 00576 return 0; 00577 fail: 00578 mms_close(h); 00579 av_dlog(NULL, "Leaving open (failure: %d)\n", err); 00580 return err; 00581 } 00582 00584 static int mms_read(URLContext *h, uint8_t *buf, int size) 00585 { 00586 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ 00587 MMSTContext *mmst = h->priv_data; 00588 MMSContext *mms = &mmst->mms; 00589 int result = 0; 00590 00591 do { 00592 if(mms->asf_header_read_size < mms->asf_header_size) { 00593 /* Read from ASF header buffer */ 00594 result = ff_mms_read_header(mms, buf, size); 00595 } else if(mms->remaining_in_len) { 00596 /* Read remaining packet data to buffer. 00597 * the result can not be zero because remaining_in_len is positive.*/ 00598 result = ff_mms_read_data(mms, buf, size); 00599 } else { 00600 /* Read from network */ 00601 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA); 00602 if (err == 0) { 00603 if(mms->remaining_in_len>mms->asf_packet_len) { 00604 av_log(NULL, AV_LOG_ERROR, 00605 "Incoming pktlen %d is larger than ASF pktsize %d\n", 00606 mms->remaining_in_len, mms->asf_packet_len); 00607 result= AVERROR(EIO); 00608 } else { 00609 // copy the data to the packet buffer. 00610 result = ff_mms_read_data(mms, buf, size); 00611 if (result == 0) { 00612 av_dlog(NULL, "read asf media paket size is zero!\n"); 00613 break; 00614 } 00615 } 00616 } else { 00617 av_dlog(NULL, "read packet error!\n"); 00618 break; 00619 } 00620 } 00621 } while(!result); // only return one packet. 00622 return result; 00623 } 00624 00625 URLProtocol ff_mmst_protocol = { 00626 .name = "mmst", 00627 .url_open = mms_open, 00628 .url_read = mms_read, 00629 .url_close = mms_close, 00630 };