# HG changeset patch # User bertrand # Date 1021415481 0 # Node ID 1529f01e8108142c1058a42928933c7cd4b98e12 # Parent 8a7bcb49686f859d61f2f22b683b28a603687ef1 Added support for asf mmst protocol. Implementation taken from the xine-mms plugin made by majormms Modified to work with mplayer by Abhijeet Phatak diff -r 8a7bcb49686f -r 1529f01e8108 libmpdemux/asf_mmst_streaming.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/asf_mmst_streaming.c Tue May 14 22:31:21 2002 +0000 @@ -0,0 +1,628 @@ +// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/) +// +// ported to mplayer by Abhijeet Phatak +// date : 16 April 2002 +// +// information about the mms protocol can be find at http://get.to/sdp +// + + +#include +#include +#include +#include +#include + +#include "config.h" + +#include "url.h" +#include "asf.h" + +#include "stream.h" + +#include "network.h" + +int data_length = 0; +int packet_length1; +int media_padding; +int to_skip = 0; + +#include + +#define BUF_SIZE 102400 +int checknum =1; + +typedef struct +{ + uint8_t buf[BUF_SIZE]; + int num_bytes; + +} command_t; + +int seq_num; +int num_stream_ids; +int stream_ids[20]; +int output_fh; + +static int get_data (int s, char *buf, size_t count); +int store_data(int s, int size, char *buffer) +{ +// printf("data_length %d, media_padding %d, size %d \n", data_length, media_padding, size ); + if(data_length >= size) + { + if (!get_data (s, buffer, size)) + { + printf ("media data read failed\n"); + return 0; + } + data_length -= size; + return size; + } + else + { + int temp_size, media_temp_padding; + if(data_length) + { + if (!get_data (s, buffer, data_length)) + { + printf ("media data read failed\n"); + return 0; + } + } + if(media_padding) + { + if(media_padding > size - data_length) + { + memset(buffer+data_length,0,(size - data_length)); + media_padding -= (size - data_length); + data_length = 0; + return size; + } + else + { + memset(buffer+data_length,0,media_padding); + media_temp_padding = media_padding; + media_padding = 0; + temp_size =data_length; + data_length = 0; + return (temp_size + media_temp_padding); + } + } + temp_size = data_length; + data_length = 0; + return temp_size; + } +} + +static void put_32 (command_t *cmd, uint32_t value) +{ + cmd->buf[cmd->num_bytes ] = value % 256; + value = value >> 8; + cmd->buf[cmd->num_bytes+1] = value % 256 ; + value = value >> 8; + cmd->buf[cmd->num_bytes+2] = value % 256 ; + value = value >> 8; + cmd->buf[cmd->num_bytes+3] = value % 256 ; + + cmd->num_bytes += 4; +} + +static uint32_t get_32 (unsigned char *cmd, int offset) +{ + uint32_t ret; + + ret = cmd[offset] ; + ret |= cmd[offset+1]<<8 ; + ret |= cmd[offset+2]<<16 ; + ret |= cmd[offset+3]<<24 ; + + return ret; +} + +static void send_command (int s, int command, uint32_t switches, + uint32_t extra, int length, + char *data) +{ + command_t cmd; + int len8; + + len8 = (length + (length%8)) / 8; + + cmd.num_bytes = 0; + + put_32 (&cmd, 0x00000001); /* start sequence */ + put_32 (&cmd, 0xB00BFACE); /* #-)) */ + put_32 (&cmd, length + 32); + put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ + put_32 (&cmd, len8 + 4); + put_32 (&cmd, seq_num); + seq_num++; + put_32 (&cmd, 0x0); /* unknown */ + put_32 (&cmd, 0x0); + put_32 (&cmd, len8+2); + put_32 (&cmd, 0x00030000 | command); /* dir | command */ + put_32 (&cmd, switches); + put_32 (&cmd, extra); + + memcpy (&cmd.buf[48], data, length); + + if (write (s, cmd.buf, length+48) != (length+48)) { + printf ("write error\n"); + } +} + +static void string_utf16(char *dest, char *src, int len) +{ + int i; + + memset (dest, 0, 1000); + + for (i=0; ibuffer_size!=0 ) { + int buffer_len = stream_ctrl->buffer_size-stream_ctrl->buffer_pos; + len = (sizebuffer)+(stream_ctrl->buffer_pos), len ); + stream_ctrl->buffer_pos += len; + if( stream_ctrl->buffer_pos>=stream_ctrl->buffer_size ) { + free( stream_ctrl->buffer ); + stream_ctrl->buffer = NULL; + stream_ctrl->buffer_size = 0; + stream_ctrl->buffer_pos = 0; + } + + } + + if( lenstreaming_ctrl->url; + int s = stream->fd; + + /* parse url */ + path = strchr(url1->file,'/') + 1; + + url1->port=1755; + s = connect2Server( url1->hostname, url1->port ); + printf ("connected\n"); + + /* + * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. + * This command is sent at the very start of protocol initiation. It sends local information to the serve + * cmd 1 0x01 + * */ + + sprintf (str, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", host); + string_utf16 (data, str, strlen(str)+2); +// send_command(s, commandno ....) + send_command (s, 1, 0, 0x0004000b, strlen(str) * 2+8, data); + + len = read (s, data, BUF_SIZE) ; + + /*This sends details of the local machine IP address to a Funnel system at the server. + * Also, the TCP or UDP transport selection is sent. + * + * here 192.168.0.129 is local ip address TCP/UDP states the tronsport we r using + * and 1037 is the local TCP or UDP socket number + * cmd 2 0x02 + * */ + + string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037\0000", + 28); + memset (data, 0, 8); + send_command (s, 2, 0, 0, 28*2+8, data); + + len = read (s, data, BUF_SIZE) ; + + /* This command sends file path (at server) and file name request to the server. + * 0x5 */ + + string_utf16 (&data[8], path, strlen(path)); + memset (data, 0, 8); + send_command (s, 5, 0, 0, strlen(path)*2+12, data); + + get_answer (s); + + /* The ASF header chunk request. Includes ?session' variable for pre header value. + * After this command is sent, + * the server replies with 0x11 command and then the header chunk with header data follows. + * 0x15 */ + + memset (data, 0, 40); + data[32] = 2; + + send_command (s, 0x15, 1, 0, 40, data); + + num_stream_ids = 0; + /* get_headers(s, asf_header); */ + + asf_header_len = get_header (s, asf_header, stream->streaming_ctrl); +// printf("---------------------------------- asf_header %d\n",asf_header); + packet_length = interp_header (asf_header, asf_header_len); + + + /* + * This command is the media stream MBR selector. Switches are always 6 bytes in length. + * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. + * Where: + * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. + * It is not yet understood what all this means. + * And the last [02] byte is probably the header ?session' value. + * + * 0x33 */ + + memset (data, 0, 40); + + for (i=1; ifd = s; + stream->streaming_ctrl->streaming_read = asf_mmst_streaming_read; + stream->streaming_ctrl->streaming_seek = asf_mmst_streaming_seek; + stream->streaming_ctrl->buffering = 1; + + stream->streaming_ctrl->status = streaming_playing_e; + stream->streaming_ctrl->buffering = 1; + + packet_length1 = packet_length; + + return 0; +}