Author: spyfeng Date: Thu Aug 12 17:12:33 2010 New Revision: 5893 Log: update mmst.c to the svn trunk version.
Modified: mms/mmst.c Modified: mms/mmst.c ============================================================================== --- mms/mmst.c Thu Aug 12 17:08:57 2010 (r5892) +++ mms/mmst.c Thu Aug 12 17:12:33 2010 (r5893) @@ -28,6 +28,7 @@ * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx */ +#include "avformat.h" #include "mms.h" #include "internal.h" #include "libavutil/intreadwrite.h" @@ -37,19 +38,6 @@ #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address. #define LOCAL_PORT 1037 // as above. - -typedef struct { - MMSContext *ff_ctx; - int outgoing_packet_seq; ///< Outgoing packet sequence number. - char path[256]; ///< Path of the resource being asked for. - char host[128]; ///< Host of the resources. - int incoming_packet_seq; ///< Incoming packet sequence number. - int incoming_flags; ///< Incoming packet flags. - int packet_id; ///< Identifier for packets in the current stream. - unsigned int header_packet_id; ///< default is 2. -} MMSTContext; - - /** Client to server packet types. */ typedef enum { CS_PKT_INITIAL = 0x01, @@ -96,10 +84,21 @@ typedef enum { /*...@}*/ } MMSSCPacketType; +typedef struct { + MMSContext mms; + int outgoing_packet_seq; ///< Outgoing packet sequence number. + char path[256]; ///< Path of the resource being asked for. + char host[128]; ///< Host of the resources. + int incoming_packet_seq; ///< Incoming packet sequence number. + int incoming_flags; ///< Incoming packet flags. + int packet_id; ///< Identifier for packets in the current stream. + unsigned int header_packet_id; ///< default is 2. +} MMSTContext; + /** Create MMST command packet header */ -static void start_command_packet(MMSTContext *mmst_ctx, MMSCSPacketType packet_type) +static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type) { - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; mms->write_out_ptr = mms->out_buffer; bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence @@ -107,7 +106,7 @@ static void start_command_packet(MMSTCon bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); bytestream_put_le32(&mms->write_out_ptr, 0); - bytestream_put_le32(&mms->write_out_ptr, mmst_ctx->outgoing_packet_seq++); + bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++); bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp bytestream_put_le32(&mms->write_out_ptr, 0); bytestream_put_le16(&mms->write_out_ptr, packet_type); @@ -115,20 +114,19 @@ static void start_command_packet(MMSTCon } /** Add prefixes to MMST command packet. */ -static void insert_command_prefixes(MMSTContext *mmst_ctx, +static void insert_command_prefixes(MMSContext *mms, uint32_t prefix1, uint32_t prefix2) { - MMSContext *mms = mmst_ctx->ff_ctx; bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix } /** Send a prepared MMST command packet. */ -static int send_command_packet(MMSTContext *mmst_ctx) +static int send_command_packet(MMSTContext *mmst) { - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; int len= mms->write_out_ptr - mms->out_buffer; - int exact_length = (len + 7) & ~7; + int exact_length = FFALIGN(len, 8); int first_length= exact_length - 16; int len8= first_length/8; int write_result; @@ -153,9 +151,8 @@ static int send_command_packet(MMSTConte return 0; } -static void mms_put_utf16(MMSTContext *mmst_ctx, uint8_t *src) +static void mms_put_utf16(MMSContext *mms, uint8_t *src) { - MMSContext *mms = mmst_ctx->ff_ctx; ByteIOContext bic; int size = mms->write_out_ptr - mms->out_buffer; int len; @@ -166,20 +163,20 @@ static void mms_put_utf16(MMSTContext *m mms->write_out_ptr += len; } -static int send_time_test_data(MMSTContext *mmst_ctx) +static int send_time_test_data(MMSTContext *mmst) { - start_command_packet(mmst_ctx, CS_PKT_TIMING_DATA_REQUEST); - insert_command_prefixes(mmst_ctx, 0xf0f0f0f1, 0x0004000b); - return send_command_packet(mmst_ctx); + start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST); + insert_command_prefixes(&mmst->mms, 0xf0f0f0f1, 0x0004000b); + return send_command_packet(mmst); } -static int send_protocol_select(MMSTContext *mmst_ctx) +static int send_protocol_select(MMSTContext *mmst) { char data_string[256]; - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; - start_command_packet(mmst_ctx, CS_PKT_PROTOCOL_SELECT); - insert_command_prefixes(mmst_ctx, 0, 0xffffffff); + start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT); + insert_command_prefixes(mms, 0, 0xffffffff); bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode @@ -191,46 +188,44 @@ static int send_protocol_select(MMSTCont "TCP", // or UDP LOCAL_PORT); - mms_put_utf16(mmst_ctx, data_string); - return send_command_packet(mmst_ctx); + mms_put_utf16(mms, data_string); + return send_command_packet(mmst); } -static int send_media_file_request(MMSTContext *mmst_ctx) +static int send_media_file_request(MMSTContext *mmst) { - MMSContext *mms = mmst_ctx->ff_ctx; - - start_command_packet(mmst_ctx, CS_PKT_MEDIA_FILE_REQUEST); - insert_command_prefixes(mmst_ctx, 1, 0xffffffff); + MMSContext *mms = &mmst->mms; + start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST); + insert_command_prefixes(mms, 1, 0xffffffff); bytestream_put_le32(&mms->write_out_ptr, 0); bytestream_put_le32(&mms->write_out_ptr, 0); - mms_put_utf16(mmst_ctx, mmst_ctx->path + 1); // +1 for skip "/" + mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/" - return send_command_packet(mmst_ctx); + return send_command_packet(mmst); } -static void handle_packet_stream_changing_type(MMSTContext *mmst_ctx) +static void handle_packet_stream_changing_type(MMSTContext *mmst) { - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; dprintf(NULL, "Stream changing!\n"); // 40 is the packet header size, 7 is the prefix size. - mmst_ctx->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); - dprintf(NULL, "Changed header prefix to 0x%x", mmst_ctx->header_packet_id); + mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); + dprintf(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id); } -static int send_keepalive_packet(MMSTContext *mmst_ctx) +static int send_keepalive_packet(MMSTContext *mmst) { // respond to a keepalive with a keepalive... - start_command_packet(mmst_ctx, CS_PKT_KEEPALIVE); - insert_command_prefixes(mmst_ctx, 1, 0x100FFFF); - return send_command_packet(mmst_ctx); + start_command_packet(mmst, CS_PKT_KEEPALIVE); + insert_command_prefixes(&mmst->mms, 1, 0x100FFFF); + return send_command_packet(mmst); } /** Pad media packets smaller than max_packet_size and/or adjust read position * after a seek. */ -static void pad_media_packet(MMSTContext *mmst_ctx) +static void pad_media_packet(MMSContext *mms) { - MMSContext *mms = mmst_ctx->ff_ctx; if(mms->remaining_in_len<mms->asf_packet_len) { int padding_size = mms->asf_packet_len - mms->remaining_in_len; memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size); @@ -239,11 +234,11 @@ static void pad_media_packet(MMSTContext } /** Read incoming MMST media, header or command packet. */ -static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst_ctx) +static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) { int read_result; MMSSCPacketType packet_type= -1; - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; for(;;) { read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); if (read_result != 8) { @@ -264,7 +259,7 @@ static MMSSCPacketType get_tcp_server_re if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { int length_remaining, hr; - mmst_ctx->incoming_flags= mms->in_buffer[3]; + mmst->incoming_flags= mms->in_buffer[3]; read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result != 4) { av_log(NULL, AV_LOG_ERROR, @@ -309,11 +304,11 @@ static MMSSCPacketType get_tcp_server_re // note we cache the first 8 bytes, // then fill up the buffer with the others - tmp = AV_RL16(mms->in_buffer + 6); - length_remaining = (tmp - 8) & 0xffff; - mmst_ctx->incoming_packet_seq = AV_RL32(mms->in_buffer); - packet_id_type = mms->in_buffer[4]; - mmst_ctx->incoming_flags = mms->in_buffer[5]; + tmp = AV_RL16(mms->in_buffer + 6); + length_remaining = (tmp - 8) & 0xffff; + mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); + packet_id_type = mms->in_buffer[4]; + mmst->incoming_flags = mms->in_buffer[5]; if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { @@ -335,7 +330,7 @@ static MMSSCPacketType get_tcp_server_re } // if we successfully read everything. - if(packet_id_type == mmst_ctx->header_packet_id) { + if(packet_id_type == mmst->header_packet_id) { packet_type = SC_PKT_ASF_HEADER; // Store the asf header if(!mms->header_parsed) { @@ -351,9 +346,9 @@ static MMSSCPacketType get_tcp_server_re mms->asf_header_size += mms->remaining_in_len; } // 0x04 means asf header is sent in multiple packets. - if (mmst_ctx->incoming_flags == 0x04) + if (mmst->incoming_flags == 0x04) continue; - } else if(packet_id_type == mmst_ctx->packet_id) { + } else if(packet_id_type == mmst->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { dprintf(NULL, "packet id type %d is old.", packet_id_type); @@ -363,31 +358,31 @@ static MMSSCPacketType get_tcp_server_re // preprocess some packet type if(packet_type == SC_PKT_KEEPALIVE) { - send_keepalive_packet(mmst_ctx); + send_keepalive_packet(mmst); continue; } else if(packet_type == SC_PKT_STREAM_CHANGING) { - handle_packet_stream_changing_type(mmst_ctx); + handle_packet_stream_changing_type(mmst); } else if(packet_type == SC_PKT_ASF_MEDIA) { - pad_media_packet(mmst_ctx); + pad_media_packet(mms); } return packet_type; } } -static int mms_safe_send_recv(MMSTContext *mmst_ctx, - int (*send_fun)(MMSTContext *mmst_ctx), +static int mms_safe_send_recv(MMSTContext *mmst, + int (*send_fun)(MMSTContext *mmst), const MMSSCPacketType expect_type) { MMSSCPacketType type; if(send_fun) { - int ret = send_fun(mmst_ctx); + int ret = send_fun(mmst); if (ret < 0) { dprintf(NULL, "Send Packet error before expecting recv packet %d\n", expect_type); return ret; } } - if ((type = get_tcp_server_response(mmst_ctx)) != expect_type) { + if ((type = get_tcp_server_response(mmst)) != expect_type) { av_log(NULL, AV_LOG_ERROR, "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", type, expect_type); @@ -397,11 +392,11 @@ static int mms_safe_send_recv(MMSTContex } } -static int send_media_header_request(MMSTContext *mmst_ctx) +static int send_media_header_request(MMSTContext *mmst) { - MMSContext *mms = mmst_ctx->ff_ctx; - start_command_packet(mmst_ctx, CS_PKT_MEDIA_HEADER_REQUEST); - insert_command_prefixes(mmst_ctx, 1, 0); + MMSContext *mms = &mmst->mms; + start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST); + insert_command_prefixes(mms, 1, 0); bytestream_put_le32(&mms->write_out_ptr, 0); bytestream_put_le32(&mms->write_out_ptr, 0x00800000); bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); @@ -415,75 +410,75 @@ static int send_media_header_request(MMS bytestream_put_le32(&mms->write_out_ptr, 2); bytestream_put_le32(&mms->write_out_ptr, 0); - return send_command_packet(mmst_ctx); + return send_command_packet(mmst); } /** Send the initial handshake. */ -static int send_startup_packet(MMSTContext *mmst_ctx) +static int send_startup_packet(MMSTContext *mmst) { char data_string[256]; + MMSContext *mms = &mmst->mms; // SubscriberName is defined in MS specification linked below. // The guid value can be any valid value. // http://download.microsoft.com/ // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf snprintf(data_string, sizeof(data_string), "NSPlayer/7.0.0.1956; {%s}; Host: %s", - "7E667F5D-A661-495E-A512-F55686DDA178", mmst_ctx->host); + "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host); - start_command_packet(mmst_ctx, CS_PKT_INITIAL); - insert_command_prefixes(mmst_ctx, 0, 0x0004000b); - bytestream_put_le32(&(mmst_ctx->ff_ctx->write_out_ptr), 0x0003001c); - mms_put_utf16(mmst_ctx, data_string); - return send_command_packet(mmst_ctx); + start_command_packet(mmst, CS_PKT_INITIAL); + insert_command_prefixes(mms, 0, 0x0004000b); + bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); + mms_put_utf16(mms, data_string); + return send_command_packet(mmst); } /** Send MMST stream selection command based on the AVStream->discard values. */ -static int send_stream_selection_request(MMSTContext *mmst_ctx) +static int send_stream_selection_request(MMSTContext *mmst) { int i; - MMSContext *mms = mmst_ctx->ff_ctx; + MMSContext *mms = &mmst->mms; // send the streams we want back... - start_command_packet(mmst_ctx, CS_PKT_STREAM_ID_REQUEST); + start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST); bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums for(i= 0; i<mms->stream_num; i++) { bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id bytestream_put_le16(&mms->write_out_ptr, 0); // selection } - return send_command_packet(mmst_ctx); + return send_command_packet(mmst); } -static int send_close_packet(MMSTContext *mmst_ctx) +static int send_close_packet(MMSTContext *mmst) { - start_command_packet(mmst_ctx, CS_PKT_STREAM_CLOSE); - insert_command_prefixes(mmst_ctx, 1, 1); + start_command_packet(mmst, CS_PKT_STREAM_CLOSE); + insert_command_prefixes(&mmst->mms, 1, 1); - return send_command_packet(mmst_ctx); + return send_command_packet(mmst); } /** Close the MMSH/MMST connection */ static int mms_close(URLContext *h) { - MMSTContext *mmst_ctx = (MMSTContext *)h->priv_data; - MMSContext *mms = mmst_ctx->ff_ctx; + MMSTContext *mmst = (MMSTContext *)h->priv_data; + MMSContext *mms = &mmst->mms; if(mms->mms_hd) { - send_close_packet(mmst_ctx); + send_close_packet(mmst); url_close(mms->mms_hd); } /* free all separately allocated pointers in mms */ av_free(mms->asf_header); - av_free(mmst_ctx->ff_ctx); av_freep(&h->priv_data); return 0; } -static int send_media_packet_request(MMSTContext *mmst_ctx) +static int send_media_packet_request(MMSTContext *mmst) { - MMSContext *mms = mmst_ctx->ff_ctx; - start_command_packet(mmst_ctx, CS_PKT_START_FROM_PKT_ID); - insert_command_prefixes(mmst_ctx, 1, 0x0001FFFF); + MMSContext *mms = &mmst->mms; + start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID); + insert_command_prefixes(mms, 1, 0x0001FFFF); bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset @@ -492,68 +487,66 @@ static int send_media_packet_request(MMS bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag - mmst_ctx->packet_id++; // new packet_id - bytestream_put_le32(&mms->write_out_ptr, mmst_ctx->packet_id); - return send_command_packet(mmst_ctx); + mmst->packet_id++; // new packet_id + bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id); + return send_command_packet(mmst); } -static void clear_stream_buffers(MMSTContext *mmst_ctx) + +static void clear_stream_buffers(MMSContext *mms) { - MMSContext *mms = mmst_ctx->ff_ctx; mms->remaining_in_len = 0; mms->read_in_ptr = mms->in_buffer; } static int mms_open(URLContext *h, const char *uri, int flags) { - MMSTContext *mmst_ctx; + MMSTContext *mmst; MMSContext *mms; int port, err; char tcpname[256]; h->is_streamed = 1; - mmst_ctx = h->priv_data = av_mallocz(sizeof(MMSTContext)); + mmst = h->priv_data = av_mallocz(sizeof(MMSTContext)); if (!h->priv_data) return AVERROR(ENOMEM); - mms = mmst_ctx->ff_ctx = av_mallocz(sizeof(MMSContext)); - if (!mmst_ctx->ff_ctx ) - return AVERROR(ENOMEM); + mms = &mmst->mms; // only for MMS over TCP, so set proto = NULL av_url_split(NULL, 0, NULL, 0, - mmst_ctx->host, sizeof(mmst_ctx->host), &port, mmst_ctx->path, - sizeof(mmst_ctx->path), uri); + mmst->host, sizeof(mmst->host), &port, mmst->path, + sizeof(mmst->path), uri); if(port<0) port = 1755; // defaut mms protocol port // establish tcp connection. - ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst_ctx->host, port, NULL); + ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); err = url_open(&mms->mms_hd, tcpname, URL_RDWR); if (err) goto fail; - mmst_ctx->packet_id = 3; // default, initial value. - mmst_ctx->header_packet_id = 2; // default, initial value. - err = mms_safe_send_recv(mmst_ctx, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); + mmst->packet_id = 3; // default, initial value. + mmst->header_packet_id = 2; // default, initial value. + err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); if (err) goto fail; - err = mms_safe_send_recv(mmst_ctx, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); + err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); if (err) goto fail; - err = mms_safe_send_recv(mmst_ctx, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); + err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); if (err) goto fail; - err = mms_safe_send_recv(mmst_ctx, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); + err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); if (err) goto fail; - err = mms_safe_send_recv(mmst_ctx, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); + err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); if (err) goto fail; - err = mms_safe_send_recv(mmst_ctx, NULL, SC_PKT_ASF_HEADER); + err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER); if (err) goto fail; - if((mmst_ctx->incoming_flags != 0X08) && (mmst_ctx->incoming_flags != 0X0C)) + if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) goto fail; err = ff_mms_asf_header_parser(mms); if (err) { @@ -565,20 +558,15 @@ static int mms_open(URLContext *h, const if (!mms->asf_packet_len || !mms->stream_num) goto fail; - /* Since we read the header at open(), this shouldn't be possible */ - assert(mmst_ctx->ff_ctx->header_parsed); - - dprintf(NULL, "mms_read() before play().\n"); - clear_stream_buffers(mmst_ctx); - err = mms_safe_send_recv(mmst_ctx, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); + clear_stream_buffers(mms); + err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); if (err) goto fail; // send media packet request - err = mms_safe_send_recv(mmst_ctx, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); + err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); if (err) { goto fail; } - dprintf(NULL, "Leaving open (success)\n"); return 0; fail: @@ -591,19 +579,21 @@ fail: static int mms_read(URLContext *h, uint8_t *buf, int size) { /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ - MMSTContext *mmst_ctx = h->priv_data; - int result = 0; - MMSContext *mms = mmst_ctx->ff_ctx; + MMSTContext *mmst = h->priv_data; + MMSContext *mms = &mmst->mms; + int result = 0; + do { if(mms->asf_header_read_size < mms->asf_header_size) { - result = ff_mms_read_header(mms, buf, size); + /* Read from ASF header buffer */ + result = ff_mms_read_header(mms, buf, size); } else if(mms->remaining_in_len) { /* Read remaining packet data to buffer. * the result can not be zero because remaining_in_len is positive.*/ result = ff_mms_read_data(mms, buf, size); } else { /* Read from network */ - int err = mms_safe_send_recv(mmst_ctx, NULL, SC_PKT_ASF_MEDIA); + int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA); if (err == 0) { if(mms->remaining_in_len>mms->asf_packet_len) { av_log(NULL, AV_LOG_ERROR, _______________________________________________ FFmpeg-soc mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc
