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 "avio_internal.h"
00035 #include "libavutil/intreadwrite.h"
00036 #include "libavcodec/bytestream.h"
00037 #include "network.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 AVIOContext bic;
00157 int size = mms->write_out_ptr - mms->out_buffer;
00158 int len;
00159 ffio_init_context(&bic, mms->write_out_ptr,
00160 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
00161
00162 len = avio_put_str16le(&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 av_dlog(NULL, "Stream changing!\n");
00211
00212
00213 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
00214 av_dlog(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 av_dlog(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 if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
00295 av_log(NULL, AV_LOG_ERROR,
00296 "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
00297 return AVERROR_UNKNOWN;
00298 }
00299 } else {
00300 int length_remaining;
00301 int packet_id_type;
00302 int tmp;
00303
00304
00305
00306 tmp = AV_RL16(mms->in_buffer + 6);
00307 length_remaining = (tmp - 8) & 0xffff;
00308 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
00309 packet_id_type = mms->in_buffer[4];
00310 mmst->incoming_flags = mms->in_buffer[5];
00311
00312 if (length_remaining < 0
00313 || length_remaining > sizeof(mms->in_buffer) - 8) {
00314 av_log(NULL, AV_LOG_ERROR,
00315 "Data length %d is invalid or too large (max=%zu)\n",
00316 length_remaining, sizeof(mms->in_buffer));
00317 return AVERROR_INVALIDDATA;
00318 }
00319 mms->remaining_in_len = length_remaining;
00320 mms->read_in_ptr = mms->in_buffer;
00321 read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
00322 if(read_result != length_remaining) {
00323 av_log(NULL, AV_LOG_ERROR,
00324 "Failed to read packet data of size %d: %d (%s)\n",
00325 length_remaining, read_result,
00326 read_result < 0 ? strerror(read_result) :
00327 "The server closed the connection");
00328 return read_result < 0 ? read_result : AVERROR_IO;
00329 }
00330
00331
00332 if(packet_id_type == mmst->header_packet_id) {
00333 packet_type = SC_PKT_ASF_HEADER;
00334
00335 if(!mms->header_parsed) {
00336 void *p = av_realloc(mms->asf_header,
00337 mms->asf_header_size + mms->remaining_in_len);
00338 if (!p) {
00339 av_freep(&mms->asf_header);
00340 return AVERROR(ENOMEM);
00341 }
00342 mms->asf_header = p;
00343 memcpy(mms->asf_header + mms->asf_header_size,
00344 mms->read_in_ptr, mms->remaining_in_len);
00345 mms->asf_header_size += mms->remaining_in_len;
00346 }
00347
00348 if (mmst->incoming_flags == 0x04)
00349 continue;
00350 } else if(packet_id_type == mmst->packet_id) {
00351 packet_type = SC_PKT_ASF_MEDIA;
00352 } else {
00353 av_dlog(NULL, "packet id type %d is old.", packet_id_type);
00354 continue;
00355 }
00356 }
00357
00358
00359 if(packet_type == SC_PKT_KEEPALIVE) {
00360 send_keepalive_packet(mmst);
00361 continue;
00362 } else if(packet_type == SC_PKT_STREAM_CHANGING) {
00363 handle_packet_stream_changing_type(mmst);
00364 } else if(packet_type == SC_PKT_ASF_MEDIA) {
00365 pad_media_packet(mms);
00366 }
00367 return packet_type;
00368 }
00369 }
00370
00371 static int mms_safe_send_recv(MMSTContext *mmst,
00372 int (*send_fun)(MMSTContext *mmst),
00373 const MMSSCPacketType expect_type)
00374 {
00375 MMSSCPacketType type;
00376 if(send_fun) {
00377 int ret = send_fun(mmst);
00378 if (ret < 0) {
00379 av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
00380 return ret;
00381 }
00382 }
00383
00384 if ((type = get_tcp_server_response(mmst)) != expect_type) {
00385 av_log(NULL, AV_LOG_ERROR,
00386 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
00387 type, expect_type);
00388 return AVERROR_INVALIDDATA;
00389 } else {
00390 return 0;
00391 }
00392 }
00393
00394 static int send_media_header_request(MMSTContext *mmst)
00395 {
00396 MMSContext *mms = &mmst->mms;
00397 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST);
00398 insert_command_prefixes(mms, 1, 0);
00399 bytestream_put_le32(&mms->write_out_ptr, 0);
00400 bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
00401 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00402 bytestream_put_le32(&mms->write_out_ptr, 0);
00403 bytestream_put_le32(&mms->write_out_ptr, 0);
00404 bytestream_put_le32(&mms->write_out_ptr, 0);
00405
00406
00407 bytestream_put_le32(&mms->write_out_ptr, 0);
00408 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
00409 bytestream_put_le32(&mms->write_out_ptr, 2);
00410 bytestream_put_le32(&mms->write_out_ptr, 0);
00411
00412 return send_command_packet(mmst);
00413 }
00414
00416 static int send_startup_packet(MMSTContext *mmst)
00417 {
00418 char data_string[256];
00419 MMSContext *mms = &mmst->mms;
00420
00421
00422
00423
00424 snprintf(data_string, sizeof(data_string),
00425 "NSPlayer/7.0.0.1956; {%s}; Host: %s",
00426 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
00427
00428 start_command_packet(mmst, CS_PKT_INITIAL);
00429 insert_command_prefixes(mms, 0, 0x0004000b);
00430 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
00431 mms_put_utf16(mms, data_string);
00432 return send_command_packet(mmst);
00433 }
00434
00436 static int send_stream_selection_request(MMSTContext *mmst)
00437 {
00438 int i;
00439 MMSContext *mms = &mmst->mms;
00440
00441 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST);
00442 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num);
00443 for(i= 0; i<mms->stream_num; i++) {
00444 bytestream_put_le16(&mms->write_out_ptr, 0xffff);
00445 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id);
00446 bytestream_put_le16(&mms->write_out_ptr, 0);
00447 }
00448 return send_command_packet(mmst);
00449 }
00450
00451 static int send_close_packet(MMSTContext *mmst)
00452 {
00453 start_command_packet(mmst, CS_PKT_STREAM_CLOSE);
00454 insert_command_prefixes(&mmst->mms, 1, 1);
00455
00456 return send_command_packet(mmst);
00457 }
00458
00460 static int mms_close(URLContext *h)
00461 {
00462 MMSTContext *mmst = (MMSTContext *)h->priv_data;
00463 MMSContext *mms = &mmst->mms;
00464 if(mms->mms_hd) {
00465 send_close_packet(mmst);
00466 url_close(mms->mms_hd);
00467 }
00468
00469
00470 av_free(mms->streams);
00471 av_free(mms->asf_header);
00472 av_freep(&h->priv_data);
00473
00474 return 0;
00475 }
00476
00477 static int send_media_packet_request(MMSTContext *mmst)
00478 {
00479 MMSContext *mms = &mmst->mms;
00480 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID);
00481 insert_command_prefixes(mms, 1, 0x0001FFFF);
00482 bytestream_put_le64(&mms->write_out_ptr, 0);
00483 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00485 bytestream_put_byte(&mms->write_out_ptr, 0xff);
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, 0x00);
00489
00490 mmst->packet_id++;
00491 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
00492 return send_command_packet(mmst);
00493 }
00494
00495
00496 static void clear_stream_buffers(MMSContext *mms)
00497 {
00498 mms->remaining_in_len = 0;
00499 mms->read_in_ptr = mms->in_buffer;
00500 }
00501
00502 static int mms_open(URLContext *h, const char *uri, int flags)
00503 {
00504 MMSTContext *mmst;
00505 MMSContext *mms;
00506 int port, err;
00507 char tcpname[256];
00508
00509 h->is_streamed = 1;
00510 mmst = h->priv_data = av_mallocz(sizeof(MMSTContext));
00511 if (!h->priv_data)
00512 return AVERROR(ENOMEM);
00513 mms = &mmst->mms;
00514
00515
00516 av_url_split(NULL, 0, NULL, 0,
00517 mmst->host, sizeof(mmst->host), &port, mmst->path,
00518 sizeof(mmst->path), uri);
00519
00520 if(port<0)
00521 port = 1755;
00522
00523
00524 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
00525 err = url_open(&mms->mms_hd, tcpname, URL_RDWR);
00526 if (err)
00527 goto fail;
00528
00529 mmst->packet_id = 3;
00530 mmst->header_packet_id = 2;
00531 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED);
00532 if (err)
00533 goto fail;
00534 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY);
00535 if (err)
00536 goto fail;
00537 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED);
00538 if (err)
00539 goto fail;
00540 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS);
00541 if (err)
00542 goto fail;
00543 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED);
00544 if (err)
00545 goto fail;
00546 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER);
00547 if (err)
00548 goto fail;
00549 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
00550 av_log(NULL, AV_LOG_ERROR,
00551 "The server does not support MMST (try MMSH or RTSP)\n");
00552 err = AVERROR_NOFMT;
00553 goto fail;
00554 }
00555 err = ff_mms_asf_header_parser(mms);
00556 if (err) {
00557 av_dlog(NULL, "asf header parsed failed!\n");
00558 goto fail;
00559 }
00560 mms->header_parsed = 1;
00561
00562 if (!mms->asf_packet_len || !mms->stream_num)
00563 goto fail;
00564
00565 clear_stream_buffers(mms);
00566 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED);
00567 if (err)
00568 goto fail;
00569
00570 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
00571 if (err) {
00572 goto fail;
00573 }
00574 av_dlog(NULL, "Leaving open (success)\n");
00575 return 0;
00576 fail:
00577 mms_close(h);
00578 av_dlog(NULL, "Leaving open (failure: %d)\n", err);
00579 return err;
00580 }
00581
00583 static int mms_read(URLContext *h, uint8_t *buf, int size)
00584 {
00585
00586 MMSTContext *mmst = h->priv_data;
00587 MMSContext *mms = &mmst->mms;
00588 int result = 0;
00589
00590 do {
00591 if(mms->asf_header_read_size < mms->asf_header_size) {
00592
00593 result = ff_mms_read_header(mms, buf, size);
00594 } else if(mms->remaining_in_len) {
00595
00596
00597 result = ff_mms_read_data(mms, buf, size);
00598 } else {
00599
00600 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
00601 if (err == 0) {
00602 if(mms->remaining_in_len>mms->asf_packet_len) {
00603 av_log(NULL, AV_LOG_ERROR,
00604 "Incoming pktlen %d is larger than ASF pktsize %d\n",
00605 mms->remaining_in_len, mms->asf_packet_len);
00606 result= AVERROR_IO;
00607 } else {
00608
00609 result = ff_mms_read_data(mms, buf, size);
00610 if (result == 0) {
00611 av_dlog(NULL, "read asf media paket size is zero!\n");
00612 break;
00613 }
00614 }
00615 } else {
00616 av_dlog(NULL, "read packet error!\n");
00617 break;
00618 }
00619 }
00620 } while(!result);
00621 return result;
00622 }
00623
00624 URLProtocol ff_mmst_protocol = {
00625 "mmst",
00626 mms_open,
00627 mms_read,
00628 NULL,
00629 NULL,
00630 mms_close,
00631 };