00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "avformat.h"
00032 #include "mms.h"
00033 #include "internal.h"
00034 #include "libavutil/intreadwrite.h"
00035 #include "libavcodec/bytestream.h"
00036 #include "network.h"
00037 #include "asf.h"
00038
00039 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
00040 #define LOCAL_PORT 1037 // as above.
00041
00042 typedef enum {
00043 CS_PKT_INITIAL = 0x01,
00044 CS_PKT_PROTOCOL_SELECT = 0x02,
00045 CS_PKT_MEDIA_FILE_REQUEST = 0x05,
00046 CS_PKT_START_FROM_PKT_ID = 0x07,
00047 CS_PKT_STREAM_PAUSE = 0x09,
00048 CS_PKT_STREAM_CLOSE = 0x0d,
00049 CS_PKT_MEDIA_HEADER_REQUEST = 0x15,
00050 CS_PKT_TIMING_DATA_REQUEST = 0x18,
00051 CS_PKT_USER_PASSWORD = 0x1a,
00052 CS_PKT_KEEPALIVE = 0x1b,
00053 CS_PKT_STREAM_ID_REQUEST = 0x33,
00054 } MMSCSPacketType;
00055
00057 typedef enum {
00060 SC_PKT_CLIENT_ACCEPTED = 0x01,
00061 SC_PKT_PROTOCOL_ACCEPTED = 0x02,
00062 SC_PKT_PROTOCOL_FAILED = 0x03,
00063 SC_PKT_MEDIA_PKT_FOLLOWS = 0x05,
00064 SC_PKT_MEDIA_FILE_DETAILS = 0x06,
00065 SC_PKT_HEADER_REQUEST_ACCEPTED = 0x11,
00066 SC_PKT_TIMING_TEST_REPLY = 0x15,
00067 SC_PKT_PASSWORD_REQUIRED = 0x1a,
00068 SC_PKT_KEEPALIVE = 0x1b,
00069 SC_PKT_STREAM_STOPPED = 0x1e,
00070 SC_PKT_STREAM_CHANGING = 0x20,
00071 SC_PKT_STREAM_ID_ACCEPTED = 0x21,
00076 SC_PKT_CANCEL = -1,
00077 SC_PKT_NO_DATA = -2,
00082 SC_PKT_ASF_HEADER = 0x010000,
00083 SC_PKT_ASF_MEDIA = 0x010001,
00085 } MMSSCPacketType;
00086
00087 typedef struct {
00088 MMSContext mms;
00089 int outgoing_packet_seq;
00090 char path[256];
00091 char host[128];
00092 int incoming_packet_seq;
00093 int incoming_flags;
00094 int packet_id;
00095 unsigned int header_packet_id;
00096 } MMSTContext;
00097
00099 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
00100 {
00101 MMSContext *mms = &mmst->mms;
00102 mms->write_out_ptr = mms->out_buffer;
00103
00104 bytestream_put_le32(&mms->write_out_ptr, 1);
00105 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
00106 bytestream_put_le32(&mms->write_out_ptr, 0);
00107 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
00108 bytestream_put_le32(&mms->write_out_ptr, 0);
00109 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++);
00110 bytestream_put_le64(&mms->write_out_ptr, 0);
00111 bytestream_put_le32(&mms->write_out_ptr, 0);
00112 bytestream_put_le16(&mms->write_out_ptr, packet_type);
00113 bytestream_put_le16(&mms->write_out_ptr, 3);
00114 }
00115
00117 static void insert_command_prefixes(MMSContext *mms,
00118 uint32_t prefix1, uint32_t prefix2)
00119 {
00120 bytestream_put_le32(&mms->write_out_ptr, prefix1);
00121 bytestream_put_le32(&mms->write_out_ptr, prefix2);
00122 }
00123
00125 static int send_command_packet(MMSTContext *mmst)
00126 {
00127 MMSContext *mms = &mmst->mms;
00128 int len= mms->write_out_ptr - mms->out_buffer;
00129 int exact_length = FFALIGN(len, 8);
00130 int first_length= exact_length - 16;
00131 int len8= first_length/8;
00132 int write_result;
00133
00134
00135 AV_WL32(mms->out_buffer + 8, first_length);
00136 AV_WL32(mms->out_buffer + 16, len8);
00137 AV_WL32(mms->out_buffer + 32, len8-2);
00138 memset(mms->write_out_ptr, 0, exact_length - len);
00139
00140
00141 write_result= url_write(mms->mms_hd, mms->out_buffer, exact_length);
00142 if(write_result != exact_length) {
00143 av_log(NULL, AV_LOG_ERROR,
00144 "Failed to write data of length %d: %d (%s)\n",
00145 exact_length, write_result,
00146 write_result < 0 ? strerror(write_result) :
00147 "The server closed the connection");
00148 return AVERROR_IO;
00149 }
00150
00151 return 0;
00152 }
00153
00154 static void mms_put_utf16(MMSContext *mms, uint8_t *src)
00155 {
00156 ByteIOContext bic;
00157 int size = mms->write_out_ptr - mms->out_buffer;
00158 int len;
00159 init_put_byte(&bic, mms->write_out_ptr,
00160 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
00161
00162 len = ff_put_str16_nolen(&bic, src);
00163 mms->write_out_ptr += len;
00164 }
00165
00166 static int send_time_test_data(MMSTContext *mmst)
00167 {
00168 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST);
00169 insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
00170 return send_command_packet(mmst);
00171 }
00172
00173 static int send_protocol_select(MMSTContext *mmst)
00174 {
00175 char data_string[256];
00176 MMSContext *mms = &mmst->mms;
00177
00178 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT);
00179 insert_command_prefixes(mms, 0, 0xffffffff);
00180 bytestream_put_le32(&mms->write_out_ptr, 0);
00181 bytestream_put_le32(&mms->write_out_ptr, 0x00989680);
00182 bytestream_put_le32(&mms->write_out_ptr, 2);
00183 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
00184 (LOCAL_ADDRESS>>24)&0xff,
00185 (LOCAL_ADDRESS>>16)&0xff,
00186 (LOCAL_ADDRESS>>8)&0xff,
00187 LOCAL_ADDRESS&0xff,
00188 "TCP",
00189 LOCAL_PORT);
00190
00191 mms_put_utf16(mms, data_string);
00192 return send_command_packet(mmst);
00193 }
00194
00195 static int send_media_file_request(MMSTContext *mmst)
00196 {
00197 MMSContext *mms = &mmst->mms;
00198 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST);
00199 insert_command_prefixes(mms, 1, 0xffffffff);
00200 bytestream_put_le32(&mms->write_out_ptr, 0);
00201 bytestream_put_le32(&mms->write_out_ptr, 0);
00202 mms_put_utf16(mms, mmst->path + 1);
00203
00204 return send_command_packet(mmst);
00205 }
00206
00207 static void handle_packet_stream_changing_type(MMSTContext *mmst)
00208 {
00209 MMSContext *mms = &mmst->mms;
00210 dprintf(NULL, "Stream changing!\n");
00211
00212
00213 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
00214 dprintf(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id);
00215 }
00216
00217 static int send_keepalive_packet(MMSTContext *mmst)
00218 {
00219
00220 start_command_packet(mmst, CS_PKT_KEEPALIVE);
00221 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
00222 return send_command_packet(mmst);
00223 }
00224
00227 static void pad_media_packet(MMSContext *mms)
00228 {
00229 if(mms->remaining_in_len<mms->asf_packet_len) {
00230 int padding_size = mms->asf_packet_len - mms->remaining_in_len;
00231 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
00232 mms->remaining_in_len += padding_size;
00233 }
00234 }
00235
00237 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
00238 {
00239 int read_result;
00240 MMSSCPacketType packet_type= -1;
00241 MMSContext *mms = &mmst->mms;
00242 for(;;) {
00243 read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8);
00244 if (read_result != 8) {
00245 if(read_result < 0) {
00246 av_log(NULL, AV_LOG_ERROR,
00247 "Error reading packet header: %d (%s)\n",
00248 read_result, strerror(read_result));
00249 packet_type = SC_PKT_CANCEL;
00250 } else {
00251 av_log(NULL, AV_LOG_ERROR,
00252 "The server closed the connection\n");
00253 packet_type = SC_PKT_NO_DATA;
00254 }
00255 return packet_type;
00256 }
00257
00258
00259 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
00260 int length_remaining, hr;
00261
00262 mmst->incoming_flags= mms->in_buffer[3];
00263 read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
00264 if(read_result != 4) {
00265 av_log(NULL, AV_LOG_ERROR,
00266 "Reading command packet length failed: %d (%s)\n",
00267 read_result,
00268 read_result < 0 ? strerror(read_result) :
00269 "The server closed the connection");
00270 return read_result < 0 ? read_result : AVERROR_IO;
00271 }
00272
00273 length_remaining= AV_RL32(mms->in_buffer+8) + 4;
00274 dprintf(NULL, "Length remaining is %d\n", length_remaining);
00275
00276 if (length_remaining < 0
00277 || length_remaining > sizeof(mms->in_buffer) - 12) {
00278 av_log(NULL, AV_LOG_ERROR,
00279 "Incoming packet length %d exceeds bufsize %zu\n",
00280 length_remaining, sizeof(mms->in_buffer) - 12);
00281 return AVERROR_INVALIDDATA;
00282 }
00283 read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12,
00284 length_remaining) ;
00285 if (read_result != length_remaining) {
00286 av_log(NULL, AV_LOG_ERROR,
00287 "Reading pkt data (length=%d) failed: %d (%s)\n",
00288 length_remaining, read_result,
00289 read_result < 0 ? strerror(read_result) :
00290 "The server closed the connection");
00291 return read_result < 0 ? read_result : AVERROR_IO;
00292 }
00293 packet_type= AV_RL16(mms->in_buffer+36);
00294 hr = AV_RL32(mms->in_buffer + 40);
00295 if (hr) {
00296 av_log(NULL, AV_LOG_ERROR,
00297 "Server sent an error status code: 0x%08x\n", hr);
00298 return AVERROR_UNKNOWN;
00299 }
00300 } else {
00301 int length_remaining;
00302 int packet_id_type;
00303 int tmp;
00304
00305
00306
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= url_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_IO;
00330 }
00331
00332
00333 if(packet_id_type == mmst->header_packet_id) {
00334 packet_type = SC_PKT_ASF_HEADER;
00335
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
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 dprintf(NULL, "packet id type %d is old.", packet_id_type);
00355 continue;
00356 }
00357 }
00358
00359
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 dprintf(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
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
00422
00423
00424
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
00442 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST);
00443 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num);
00444 for(i= 0; i<mms->stream_num; i++) {
00445 bytestream_put_le16(&mms->write_out_ptr, 0xffff);
00446 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id);
00447 bytestream_put_le16(&mms->write_out_ptr, 0);
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 url_close(mms->mms_hd);
00468 }
00469
00470
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);
00484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00485 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00486 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00487 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00488 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00489 bytestream_put_byte(&mms->write_out_ptr, 0x00);
00490
00491 mmst->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
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;
00523
00524
00525 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
00526 err = url_open(&mms->mms_hd, tcpname, URL_RDWR);
00527 if (err)
00528 goto fail;
00529
00530 mmst->packet_id = 3;
00531 mmst->header_packet_id = 2;
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_NOFMT;
00554 goto fail;
00555 }
00556 err = ff_mms_asf_header_parser(mms);
00557 if (err) {
00558 dprintf(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
00571 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
00572 if (err) {
00573 goto fail;
00574 }
00575 dprintf(NULL, "Leaving open (success)\n");
00576 return 0;
00577 fail:
00578 mms_close(h);
00579 dprintf(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
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
00594 result = ff_mms_read_header(mms, buf, size);
00595 } else if(mms->remaining_in_len) {
00596
00597
00598 result = ff_mms_read_data(mms, buf, size);
00599 } else {
00600
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_IO;
00608 } else {
00609
00610 result = ff_mms_read_data(mms, buf, size);
00611 if (result == 0) {
00612 dprintf(NULL, "read asf media paket size is zero!\n");
00613 break;
00614 }
00615 }
00616 } else {
00617 dprintf(NULL, "read packet error!\n");
00618 break;
00619 }
00620 }
00621 } while(!result);
00622 return result;
00623 }
00624
00625 URLProtocol mmst_protocol = {
00626 "mmst",
00627 mms_open,
00628 mms_read,
00629 NULL,
00630 NULL,
00631 mms_close,
00632 };