From c5db5836e1ccd424eb16978de7f13c23fb868621 Mon Sep 17 00:00:00 2001 From: Thibaut Mattern Date: Sat, 11 Oct 2003 20:42:38 +0000 Subject: - use LE_* macros - use lprintf - first attempt to support the command 0x20 tested with mms://wms03.nordicwebradio.com/visby CVS patchset: 5483 CVS date: 2003/10/11 20:42:38 --- src/input/mms.c | 650 ++++++++++++++++++++++++++------------------------------ 1 file changed, 299 insertions(+), 351 deletions(-) diff --git a/src/input/mms.c b/src/input/mms.c index de6945531..e7a27e2a1 100644 --- a/src/input/mms.c +++ b/src/input/mms.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: mms.c,v 1.31 2003/10/08 05:33:28 valtri Exp $ + * $Id: mms.c,v 1.32 2003/10/11 20:42:38 tmattern Exp $ * * MMS over TCP protocol * based on work from major mms @@ -53,6 +53,13 @@ #include #endif +/********** logging **********/ +#define LOG_MODULE "libmms" +#define LOG_VERBOSE +/* +#define LOG +*/ + #include "xine_internal.h" #include "xineutils.h" @@ -61,9 +68,6 @@ #include "mms.h" #include "../demuxers/asfheader.h" -/* -#define LOG -*/ /* * mms specific types @@ -114,9 +118,11 @@ struct mms_s { char guid[37]; uint32_t bitrates[ASF_MAX_NUM_STREAMS]; uint32_t bitrates_pos[ASF_MAX_NUM_STREAMS]; + int bandwidth; int has_audio; int has_video; + int live_flag; }; @@ -131,60 +137,20 @@ static void put_32 (mms_t *this, uint32_t value) { this->scmd_len += 4; } -static uint32_t get_64 (uint8_t *buffer, int offset) { - - uint64_t ret; - - ret = ((uint64_t)buffer[offset]) | - ((uint64_t)buffer[offset + 1] << 8) | - ((uint64_t)buffer[offset + 2] << 16) | - ((uint64_t)buffer[offset + 2] << 24) | - ((uint64_t)buffer[offset + 2] << 32) | - ((uint64_t)buffer[offset + 2] << 40) | - ((uint64_t)buffer[offset + 2] << 48) | - ((uint64_t)buffer[offset + 2] << 56); - - return ret; -} - -static uint32_t get_32 (uint8_t *buffer, int offset) { - - uint32_t ret; - - ret = buffer[offset] | - buffer[offset + 1] << 8 | - buffer[offset + 2] << 16 | - buffer[offset + 3] << 24 ; - - return ret; -} - -static uint16_t get_16 (unsigned char *buffer, int offset) { - - uint16_t ret; - - ret = buffer[offset] | - buffer[offset + 1] << 8; - - return ret; -} - static int get_guid (unsigned char *buffer, int offset) { int i; GUID g; - g.Data1 = get_32(buffer, offset); - g.Data2 = get_16(buffer, offset + 4); - g.Data3 = get_16(buffer, offset + 6); + g.Data1 = LE_32(buffer + offset); + g.Data2 = LE_16(buffer + offset + 4); + g.Data3 = LE_16(buffer + offset + 6); for(i = 0; i < 8; i++) { g.Data4[i] = buffer[offset + 8 + i]; } for (i = 1; i < GUID_END; i++) { if (!memcmp(&g, &guids[i].guid, sizeof(GUID))) { -#ifdef LOG - printf ("libmms: GUID: %s\n", guids[i].name); -#endif + lprintf ("GUID: %s\n", guids[i].name); return i; } } @@ -193,7 +159,7 @@ static int get_guid (unsigned char *buffer, int offset) { "{ 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx }\n", g.Data1, g.Data2, g.Data3, g.Data4[0], g.Data4[1], g.Data4[2], g.Data4[3], - g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]); + g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]); return GUID_ERROR; } @@ -206,17 +172,16 @@ static int send_data (int s, char *buf, int len) { n = write (s, &buf[total], len - total); -#ifdef LOG - printf ("mms: sending data, %d of %d\n", n, len); -#endif + lprintf ("sending data, %d of %d\n", n, len); if (n > 0) total += n; else if (n < 0) { if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) { - sleep (1); timeout--; - } else - return -1; + sleep (1); timeout--; + } else { + return -1; + } } } return total; @@ -247,7 +212,7 @@ static int send_command (mms_t *this, int command, uint32_t switches, /* memcpy (&cmd->buf[48], data, length); */ if (send_data (this->s, this->scmd, length+48) != (length+48)) { - printf ("libmms: send error\n"); + lprintf ("send error\n"); return 0; } @@ -258,14 +223,14 @@ static int send_command (mms_t *this, int command, uint32_t switches, printf ("\nlibmms: ***************************************************\ncommand sent, %d bytes\n", length + 48); - printf ("start sequence %08x\n", get_32 (this->scmd, 0)); - printf ("command id %08x\n", get_32 (this->scmd, 4)); - printf ("length %8x \n", get_32 (this->scmd, 8)); - printf ("len8 %8x \n", get_32 (this->scmd, 16)); - printf ("sequence # %08x\n", get_32 (this->scmd, 20)); - printf ("len8 (II) %8x \n", get_32 (this->scmd, 32)); - printf ("dir | comm %08x\n", get_32 (this->scmd, 36)); - printf ("switches %08x\n", get_32 (this->scmd, 40)); + printf ("start sequence %08x\n", LE_32 (this->scmd + 0)); + printf ("command id %08x\n", LE_32 (this->scmd + 4)); + printf ("length %8x \n", LE_32 (this->scmd + 8)); + printf ("len8 %8x \n", LE_32 (this->scmd + 16)); + printf ("sequence # %08x\n", LE_32 (this->scmd + 20)); + printf ("len8 (II) %8x \n", LE_32 (this->scmd + 32)); + printf ("dir | comm %08x\n", LE_32 (this->scmd + 36)); + printf ("switches %08x\n", LE_32 (this->scmd + 40)); printf ("ascii contents>"); for (i = 48; i < (length + 48); i += 2) { @@ -341,14 +306,14 @@ static void print_answer (char *data, int len) { printf ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\nanswer received, %d bytes\n", len); - printf ("start sequence %08x\n", get_32 (data, 0)); - printf ("command id %08x\n", get_32 (data, 4)); - printf ("length %8x \n", get_32 (data, 8)); - printf ("len8 %8x \n", get_32 (data, 16)); - printf ("sequence # %08x\n", get_32 (data, 20)); - printf ("len8 (II) %8x \n", get_32 (data, 32)); - printf ("dir | comm %08x\n", get_32 (data, 36)); - printf ("switches %08x\n", get_32 (data, 40)); + printf ("start sequence %08x\n", LE_32 (data + 0)); + printf ("command id %08x\n", LE_32 (data + 4)); + printf ("length %8x \n", LE_32 (data + 8)); + printf ("len8 %8x \n", LE_32 (data + 16)); + printf ("sequence # %08x\n", LE_32 (data + 20)); + printf ("len8 (II) %8x \n", LE_32 (data + 32)); + printf ("dir | comm %08x\n", LE_32 (data + 36)); + printf ("switches %08x\n", LE_32 (data + 40)); for (i = 48; i < len; i += 2) { unsigned char c = data[i]; @@ -361,7 +326,6 @@ static void print_answer (char *data, int len) { } printf ("\n"); #endif - } /* @@ -377,41 +341,39 @@ static int get_answer (mms_t *this) { len = xio_tcp_read (this->stream, this->s, this->buf, 12); if (len < 0) { - printf ("\nlibmms: get_answer: read error\n"); + lprintf ("get_answer: read error\n"); return 0; } else if (len != 12) { - printf ("\nlibmms: get_answer: end of stream\n"); + lprintf ("get_answer: end of stream\n"); return 0; } - length = get_32 (this->buf, 8); + length = LE_32 (this->buf + 8); -#ifdef LOG - printf ("\n\npacket length: %d\n", length); -#endif + lprintf ("packet length: %d\n", length); if (length > (BUF_SIZE - 12)) { - printf ("libmms: get_answer: invalid packet length: %d\n", length); + lprintf ("get_answer: invalid packet length: %d\n", length); return 0; } - len = xio_tcp_read (this->stream, this->s, this->buf+12, length+4) ; + len = xio_tcp_read (this->stream, this->s, this->buf + 12, length + 4) ; if (len < 0) { - printf ("\nlibmms: get_answer: read error\n"); + lprintf ("get_answer: read error\n"); return 0; } else if (len != (length + 4)) { - printf ("\nlibmms: get_answer: end of stream\n"); + lprintf ("get_answer: end of stream\n"); return 0; } len += 12; print_answer (this->buf, len); - command = get_32 (this->buf, 36) & 0xFFFF; + command = LE_32 (this->buf + 36) & 0xFFFF; /* reply to a ping command */ if (command == 0x1b) { if (!send_command (this, 0x1b, 0, 0, 0)) { - printf("libmms: failed to send command 0x1b\n"); + lprintf("failed to send command 0x1b\n"); return 0; } } @@ -431,10 +393,10 @@ static int get_header (mms_t *this) { len = xio_tcp_read (this->stream, this->s, pre_header, 8) ; if (len < 0) { - printf ("\nlibmms: get_header: read error\n"); + lprintf ("get_header: read error\n"); return 0; } else if (len != 8) { - printf ("\nlibmms: get_header: end of stream\n"); + lprintf ("get_header: end of stream\n"); return 0; } @@ -445,29 +407,28 @@ static int get_header (mms_t *this) { printf ("libmms: pre_header[%d] = %02x (%d)\n", i, pre_header[i], pre_header[i]); } + printf ("libmms: asf header packet detected, len=%d\n", + pre_header[7] << 8 | pre_header[6]); #endif - if (pre_header[4] == 0x02) { + if ((pre_header[4] == 0x02) || (pre_header[4] == 0xff)){ uint32_t packet_len; packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; -#ifdef LOG - printf ("libmms: asf header packet detected, len=%d\n", - packet_len); -#endif + lprintf ("asf header packet detected, len=%d\n", packet_len); if (packet_len > (ASF_HEADER_LEN - this->asf_header_len)) { - printf ("libmms: get_header: invalid packet length: %d\n", packet_len); + lprintf ("get_header: invalid packet length: %d\n", packet_len); return 0; } len = xio_tcp_read (this->stream, this->s, &this->asf_header[this->asf_header_len], packet_len); if (len < 0) { - printf ("\nlibmms: get_header: read error\n"); + lprintf ("get_header: read error\n"); return 0; } else if (len != packet_len) { - printf ("\nlibmms: get_header: end of stream\n"); + lprintf ("get_header: end of stream\n"); return 0; } @@ -476,9 +437,7 @@ static int get_header (mms_t *this) { if ( (this->asf_header[this->asf_header_len - 1] == 1) && (this->asf_header[this->asf_header_len - 2] == 1)) { -#ifdef LOG - printf ("libmms: get header packet finished\n"); -#endif + lprintf ("get header packet finished\n"); return 1; } @@ -489,50 +448,44 @@ static int get_header (mms_t *this) { len = xio_tcp_read (this->stream, this->s, (uint8_t *) &packet_len, 4); if (len < 0) { - printf ("\nlibmms: get_header: read error\n"); + lprintf ("get_header: read error\n"); return 0; } else if (len != 4) { - printf ("\nlibmms: get_header: end of stream\n"); + lprintf ("get_header: end of stream\n"); return 0; } - packet_len = get_32 ((uint8_t *)&packet_len, 0) + 4; + packet_len = LE_32 ((uint8_t *)&packet_len + 0) + 4; -#ifdef LOG - printf ("command packet detected, len=%d\n", - packet_len); -#endif + lprintf ("command packet detected, len=%d\n", packet_len); + if (packet_len > (BUF_SIZE)) { - printf ("libmms: get_header: invalid packet length: %d\n", packet_len); + lprintf ("get_header: invalid packet length: %d\n", packet_len); return 0; } len = xio_tcp_read (this->stream, this->s, this->buf, packet_len); if (len < 0) { - printf ("\nlibmms: get_header: read error\n"); + lprintf ("get_header: read error\n"); return 0; } else if (len != packet_len) { - printf ("\nlibmms: get_header: end of stream\n"); + lprintf ("get_header: end of stream\n"); return 0; } - command = get_32 (this->buf, 24) & 0xFFFF; -#ifdef LOG - printf ("command: %02x\n", command); -#endif + command = LE_32 (this->buf + 24) & 0xFFFF; + lprintf ("command: %02x\n", command); /* reply to a ping command */ if (command == 0x1b) { if (!send_command (this, 0x1b, 0, 0, 0)) { - printf("libmms: failed to send command 0x1b\n"); + lprintf("libmms: failed to send command 0x1b\n"); return 0; } } } -#ifdef LOG - printf ("mms: get header packet succ\n"); -#endif + lprintf ("mms: get header packet succ\n"); } return 1; @@ -543,7 +496,7 @@ static void interp_header (mms_t *this) { int i; this->packet_length = 0; - + this->num_stream_ids = 0; /* * parse header */ @@ -556,19 +509,17 @@ static void interp_header (mms_t *this) { guid = get_guid(this->asf_header, i); i += 16; - length = get_64(this->asf_header, i); + length = LE_64(this->asf_header + i); i += 8; switch (guid) { case GUID_ASF_FILE_PROPERTIES: - this->packet_length = get_32(this->asf_header, i + 92 - 24); - this->file_length = get_32(this->asf_header, i + 40 - 24); -#ifdef LOG - printf ("libmms: file object, packet length = %d (%d)\n", - this->packet_length, get_32(this->asf_header, i + 96 - 24)); -#endif + this->packet_length = LE_32(this->asf_header + i + 92 - 24); + this->file_length = LE_32(this->asf_header + i + 40 - 24); + lprintf ("file object, packet length = %d (%d)\n", + this->packet_length, LE_32(this->asf_header + i + 96 - 24)); break; case GUID_ASF_STREAM_PROPERTIES: @@ -596,11 +547,9 @@ static void interp_header (mms_t *this) { type = ASF_STREAM_TYPE_UNKNOWN; } - stream_id = get_16(this->asf_header, i + 48); + stream_id = LE_16(this->asf_header + i + 48); -#ifdef LOG - printf ("libmms: stream object, stream id: %d\n", stream_id); -#endif + lprintf ("stream object, stream id: %d\n", stream_id); this->stream_types[stream_id] = type; this->stream_ids[this->num_stream_ids] = stream_id; this->num_stream_ids++; @@ -610,40 +559,30 @@ static void interp_header (mms_t *this) { case GUID_ASF_STREAM_BITRATE_PROPERTIES: { - uint16_t streams = get_16(this->asf_header, i); + uint16_t streams = LE_16(this->asf_header + i); uint16_t stream_id; int j; -#ifdef LOG - printf ("libmms: stream bitrate properties\n"); -#endif + lprintf ("stream bitrate properties\n"); + lprintf ("streams %d\n", streams); -#ifdef LOG - printf ("libmms: streams %d\n", streams); -#endif for(j = 0; j < streams; j++) { - stream_id = get_16(this->asf_header, i + 2 + j * 6); -#ifdef LOG - printf ("libmms: stream id %d\n", stream_id); -#endif - this->bitrates[stream_id] = get_32(this->asf_header, i + 4 + j * 6); + stream_id = LE_16(this->asf_header + i + 2 + j * 6); + lprintf ("stream id %d\n", stream_id); + this->bitrates[stream_id] = LE_32(this->asf_header + i + 4 + j * 6); this->bitrates_pos[stream_id] = i + 4 + j * 6; - printf ("libmms: stream id %d, bitrate %d\n", stream_id, - this->bitrates[stream_id]); + lprintf ("stream id %d, bitrate %d\n", stream_id, + this->bitrates[stream_id]); } } break; default: -#ifdef LOG - printf ("libmms: unknown object\n"); -#endif + lprintf ("unknown object\n"); break; } -#ifdef LOG - printf ("libmms: length : %lld\n", length); -#endif + lprintf ("length : %lld\n", length); if (length > 24) { i += length - 24; @@ -706,9 +645,7 @@ static int mms_parse_url(mms_t *this) { _host = _url; /* extract hostname */ -#ifdef LOG - printf ("libmms: extracting host name \n"); -#endif + lprintf ("extracting host name \n"); hostend = strchr(_host, '/'); /* if ((!hostend) || (strlen(hostend) <= 1)) { @@ -717,9 +654,7 @@ static int mms_parse_url(mms_t *this) { } */ if (!hostend) { -#ifdef LOG - printf ("libmms: no trailing /\n"); -#endif + lprintf ("no trailing /\n"); hostend = _host + strlen(_host); } else { *hostend++ = '\0'; @@ -746,14 +681,12 @@ static int mms_tcp_connect(mms_t *this) { /* * try to connect */ -#ifdef LOG - printf("libmms: try to connect to %s on port %d \n", this->host, this->port); -#endif + lprintf("try to connect to %s on port %d \n", this->host, this->port); this->s = xio_tcp_connect (this->stream, this->host, this->port); if (this->s == -1) { - printf ("libmms: failed to connect '%s'\n", this->host); + lprintf ("failed to connect '%s'\n", this->host); return 1; } @@ -767,10 +700,7 @@ static int mms_tcp_connect(mms_t *this) { if (res != XIO_READY) { return 1; } -#ifdef LOG - printf ("libmms: connected\n"); -#endif - + lprintf ("libmms: connected\n"); return 0; } @@ -786,25 +716,130 @@ static void mms_gen_guid(char guid[]) { guid[36] = '\0'; } +/* + * return 0 on error + */ +int static mms_choose_best_streams(mms_t *this) { + int i; + int video_stream = 0; + int audio_stream = 0; + int max_arate = 0; + int min_vrate = 0; + int min_bw_left = 0; + int stream_id; + int bandwitdh_left; + int res; + + /* command 0x33 */ + /* choose the best quality for the audio stream */ + /* i've never seen more than one audio stream */ + lprintf("num_stream_ids=%d\n", this->num_stream_ids); + for (i = 0; i < this->num_stream_ids; i++) { + stream_id = this->stream_ids[i]; + switch (this->stream_types[stream_id]) { + case ASF_STREAM_TYPE_AUDIO: + if (this->bitrates[stream_id] > max_arate) { + audio_stream = stream_id; + max_arate = this->bitrates[stream_id]; + } + break; + default: + break; + } + } + + /* choose a video stream adapted to the user bandwidth */ + bandwitdh_left = this->bandwidth - max_arate; + if (bandwitdh_left < 0) { + bandwitdh_left = 0; + } + lprintf("libmms: bandwitdh %d, left %d\n", this->bandwidth, bandwitdh_left); + + min_bw_left = bandwitdh_left; + for (i = 0; i < this->num_stream_ids; i++) { + stream_id = this->stream_ids[i]; + switch (this->stream_types[stream_id]) { + case ASF_STREAM_TYPE_VIDEO: + if (((bandwitdh_left - this->bitrates[stream_id]) < min_bw_left) && + (bandwitdh_left >= this->bitrates[stream_id])) { + video_stream = stream_id; + min_bw_left = bandwitdh_left - this->bitrates[stream_id]; + } + break; + default: + break; + } + } + + /* choose the lower bitrate of */ + if (!video_stream && this->has_video) { + for (i = 0; i < this->num_stream_ids; i++) { + stream_id = this->stream_ids[i]; + switch (this->stream_types[stream_id]) { + case ASF_STREAM_TYPE_VIDEO: + if ((this->bitrates[stream_id] < min_vrate) || + (!min_vrate)) { + video_stream = stream_id; + min_vrate = this->bitrates[stream_id]; + } + break; + default: + break; + } + } + } + + lprintf("selected streams: audio %d, video %d\n", audio_stream, video_stream); + lprintf("disabling other streams\n"); + memset (this->scmd_body, 0, 40); + for (i = 1; i < this->num_stream_ids; i++) { + this->scmd_body [ (i - 1) * 6 + 2 ] = 0xFF; + this->scmd_body [ (i - 1) * 6 + 3 ] = 0xFF; + this->scmd_body [ (i - 1) * 6 + 4 ] = this->stream_ids[i] ; + this->scmd_body [ (i - 1) * 6 + 5 ] = this->stream_ids[i] >> 8; + if ((this->stream_ids[i] == audio_stream) || + (this->stream_ids[i] == video_stream)) { + this->scmd_body [ (i - 1) * 6 + 6 ] = 0x00; + this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; + } else { + lprintf("disabling stream %d\n", this->stream_ids[i]); + this->scmd_body [ (i - 1) * 6 + 6 ] = 0x02; + this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; + + /* forces the asf demuxer to not choose this stream */ + this->asf_header[this->bitrates_pos[this->stream_ids[i]]] = 0; + this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 1] = 0; + this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 2] = 0; + this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0; + } + } + + if (!send_command (this, 0x33, this->num_stream_ids, + 0xFFFF | this->stream_ids[0] << 16, + this->num_stream_ids * 6 + 2)) { + lprintf("failed to send command 0x33\n"); + return 0; + } + + if ((res = get_answer (this)) != 0x21) { + lprintf("unexpected response: %02x (0x21)\n", res); + } + + return 1; +} + /* * TODO: error messages * network timing request */ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { - mms_t *this; #ifdef USE_ICONV iconv_t url_conv; #else int url_conv = 0; #endif + mms_t *this; int i; - int video_stream = 0; - int audio_stream = 0; - int max_arate = 0; - int min_vrate = 0; - int min_bw_left = 0; - int stream_id; - int bandwitdh_left; int res; if (!url) @@ -815,6 +850,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->stream = stream; this->url = strdup (url); this->host = NULL; + this->port = MMS_PORT; this->path = NULL; this->file = NULL; this->s = -1; @@ -828,10 +864,9 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->buf_read = 0; this->has_audio = 0; this->has_video = 0; + this->bandwidth = bandwidth; report_progress (stream, 0); - - this->port = MMS_PORT; if (mms_parse_url(this)) { goto fail; } @@ -839,15 +874,8 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { if (mms_tcp_connect(this)) { goto fail; } - report_progress (stream, 30); - -#ifdef LOG - printf ("libmms: url=%s\nlibmms: host=%s\nlibmms: " - "path=%s\nlibmms: file=%s\n", url, host, path, file); -#endif - #ifdef USE_ICONV url_conv = string_utf16_open(); #endif @@ -862,12 +890,12 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { string_utf16 (url_conv, this->scmd_body, this->str, strlen(this->str) + 2); if (!send_command (this, 1, 0, 0x0004000b, strlen(this->str) * 2 + 8)) { - printf("libmms: failed to send command 0x01\n"); + lprintf("failed to send command 0x01\n"); goto fail; } if ((res = get_answer (this)) != 0x01) { - printf("libmms: unexpected response: %02x (0x01)\n", res); + lprintf("unexpected response: %02x (0x01)\n", res); goto fail; } @@ -878,7 +906,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { string_utf16 (url_conv, &this->scmd_body[8], "\002\000\\\\192.168.0.129\\TCP\\1037\0000", 28); memset (this->scmd_body, 0, 8); if (!send_command (this, 2, 0, 0, 28 * 2 + 8)) { - printf("libmms: failed to send command 0x02\n"); + lprintf("failed to send command 0x02\n"); goto fail; } @@ -887,11 +915,11 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { /* protocol accepted */ break; case 0x03: - printf("libmms: protocol failed\n"); + lprintf("protocol failed\n"); goto fail; break; default: - printf("libmms: unexpected response: %02x (0x02 or 0x03)\n", res); + lprintf("unexpected response: %02x (0x02 or 0x03)\n", res); goto fail; } @@ -906,14 +934,15 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { switch (res = get_answer (this)) { case 0x06: /* no authentication required */ + this->live_flag = ((this->buf[62] == 0) && (this->buf[63] == 2)); break; case 0x1A: /* authentication request, not yet supported */ - printf("libmms: authentication request, not yet supported\n"); + lprintf("authentication request, not yet supported\n"); goto fail; break; default: - printf("libmms: unexpected response: %02x (0x06 or 0x1A)\n", res); + lprintf("unexpected response: %02x (0x06 or 0x1A)\n", res); goto fail; } @@ -924,12 +953,12 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->scmd_body[32] = 2; if (!send_command (this, 0x15, 1, 0, 40)) { - printf("libmms: failed to send command 0x15\n"); + lprintf("failed to send command 0x15\n"); goto fail; } if ((res = get_answer (this)) != 0x11) { - printf("libmms: unexpected response: %02x (0x11)\n", res); + lprintf("unexpected response: %02x (0x11)\n", res); goto fail; } @@ -942,118 +971,21 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { report_progress (stream, 70); - /* command 0x33 */ - /* choose the best quality for the audio stream */ - /* i've never seen more than one audio stream */ - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_AUDIO: - if (this->bitrates[stream_id] > max_arate) { - audio_stream = stream_id; - max_arate = this->bitrates[stream_id]; - } - break; - default: - break; - } - } - - /* choose a video stream adapted to the user bandwidth */ - bandwitdh_left = bandwidth - max_arate; - if (bandwitdh_left < 0) { - bandwitdh_left = 0; - } -#ifdef LOG - printf("libmms: bandwitdh %d, left %d\n", bandwidth, bandwitdh_left); -#endif - - min_bw_left = bandwitdh_left; - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_VIDEO: - if (((bandwitdh_left - this->bitrates[stream_id]) < min_bw_left) && - (bandwitdh_left >= this->bitrates[stream_id])) { - video_stream = stream_id; - min_bw_left = bandwitdh_left - this->bitrates[stream_id]; - } - break; - default: - break; - } - } - - /* choose the lower bitrate of */ - if (!video_stream && this->has_video) { - for (i = 0; i < this->num_stream_ids; i++) { - stream_id = this->stream_ids[i]; - switch (this->stream_types[stream_id]) { - case ASF_STREAM_TYPE_VIDEO: - if ((this->bitrates[stream_id] < min_vrate) || - (!min_vrate)) { - video_stream = stream_id; - min_vrate = this->bitrates[stream_id]; - } - break; - default: - break; - } - } - } - - printf("libmms: audio stream %d, video stream %d\n", audio_stream, video_stream); - - memset (this->scmd_body, 0, 40); - for (i = 1; i < this->num_stream_ids; i++) { - this->scmd_body [ (i - 1) * 6 + 2 ] = 0xFF; - this->scmd_body [ (i - 1) * 6 + 3 ] = 0xFF; - this->scmd_body [ (i - 1) * 6 + 4 ] = this->stream_ids[i] ; - this->scmd_body [ (i - 1) * 6 + 5 ] = this->stream_ids[i] >> 8; - if ((this->stream_ids[i] == audio_stream) || - (this->stream_ids[i] == video_stream)) { - this->scmd_body [ (i - 1) * 6 + 6 ] = 0x00; - this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; - } else { - printf("libmms: disabling stream %d\n", this->stream_ids[i]); - this->scmd_body [ (i - 1) * 6 + 6 ] = 0x02; - this->scmd_body [ (i - 1) * 6 + 7 ] = 0x00; - - /* forces the asf demuxer to not choose this stream */ - this->asf_header[this->bitrates_pos[this->stream_ids[i]]] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 1] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 2] = 0; - this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0; - } - } - - if (!send_command (this, 0x33, this->num_stream_ids, - 0xFFFF | this->stream_ids[0] << 16, - this->num_stream_ids * 6 + 2)) { - printf("libmms: failed to send command 0x33\n"); - goto fail; - } - - if ((res = get_answer (this)) != 0x21) { - printf("libmms: unexpected response: %02x (0x21)\n", res); + if (!mms_choose_best_streams(this)) goto fail; - } - - report_progress (stream, 70); + report_progress (stream, 80); /* command 0x07 */ memset (this->scmd_body, 0, 40); - for (i = 8; i < 16; i++) this->scmd_body[i] = 0xFF; - this->scmd_body[20] = 0x04; if (!send_command (this, 0x07, 1, - 0xFFFF | this->stream_ids[0] << 16, - 24)) { - printf("libmms: failed to send command 0x07\n"); + 0xFFFF | this->stream_ids[0] << 16, + 24)) { + lprintf("failed to send command 0x07\n"); goto fail; } @@ -1063,12 +995,10 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { string_utf16_close(url_conv); #endif -#ifdef LOG - printf(" mms_connect: passed\n" ); -#endif + lprintf("mms_connect: passed\n" ); return this; - fail: +fail: if (this->s != -1) close (this->s); if (this->url) @@ -1088,12 +1018,12 @@ static int get_media_packet (mms_t *this) { unsigned char pre_header[8]; off_t len; - len = xine_read_abort (this->stream, this->s, pre_header, 8) ; + len = xio_tcp_read (this->stream, this->s, pre_header, 8) ; if (len < 0) { - printf ("\nlibmms: get_media_packet: read error\n"); + lprintf ("get_media_packet: read error\n"); return 0; } else if (len != 8) { - printf ("\nlibmms: get_media_packet: end of stream\n"); + lprintf ("get_media_packet: end of stream\n"); return 0; } @@ -1102,7 +1032,7 @@ static int get_media_packet (mms_t *this) { int i; for (i = 0; i < 8; i++) printf ("pre_header[%d] = %02x (%d)\n", - i, pre_header[i], pre_header[i]); + i, pre_header[i], pre_header[i]); } #endif @@ -1112,21 +1042,18 @@ static int get_media_packet (mms_t *this) { packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; -#ifdef LOG - printf ("asf media packet detected, len=%d\n", - packet_len); -#endif + lprintf ("asf media packet detected, len=%d\n", packet_len); if (packet_len > (BUF_SIZE)) { - printf ("libmms: get_media_packet: invalid packet length: %d\n", packet_len); + lprintf ("get_media_packet: invalid packet length: %d\n", packet_len); return 0; } - len = xine_read_abort (this->stream, this->s, this->buf, packet_len); + len = xio_tcp_read (this->stream, this->s, this->buf, packet_len); if (len < 0) { - printf ("\nlibmms: get_media_packet: read error\n"); + lprintf ("get_media_packet: read error\n"); return 0; } else if (len != packet_len) { - printf ("\nlibmms: get_media_packet: end of stream\n"); + lprintf ("get_media_packet: end of stream\n"); return 0; } @@ -1139,69 +1066,91 @@ static int get_media_packet (mms_t *this) { uint32_t packet_len; int command; - len = xine_read_abort (this->stream, this->s, (uint8_t *)&packet_len, 4); + this->buf_size = 0; + len = xio_tcp_read (this->stream, this->s, (uint8_t *)&packet_len, 4); if (len < 0) { - printf ("\nlibmms: get_media_packet: read error\n"); + lprintf ("get_media_packet: read error\n"); return 0; } else if (len != 4) { - printf ("\nlibmms: get_media_packet: end of stream\n"); + lprintf ("get_media_packet: end of stream\n"); return 0; } - packet_len = get_32 ((uint8_t *)&packet_len, 0) + 4; + packet_len = LE_32 ((uint8_t *)&packet_len) + 4; -#ifdef LOG - printf ("command packet detected, len=%d\n", - packet_len); -#endif + lprintf ("command packet detected, len=%d\n", packet_len); if (packet_len > (BUF_SIZE)) { - printf ("libmms: get_media_packet: invalid packet length: %d\n", packet_len); + lprintf ("get_media_packet: invalid packet length: %d\n", packet_len); return 0; } - len = xine_read_abort (this->stream, this->s, this->buf, packet_len); + len = xio_tcp_read (this->stream, this->s, this->buf, packet_len); if (len < 0) { - printf ("\nlibmms: get_media_packet: read error\n"); + lprintf ("\nlibmms: get_media_packet: read error\n"); return 0; } else if (len != packet_len) { - printf ("\nlibmms: get_media_packet: end of stream\n"); + lprintf ("\nlibmms: get_media_packet: end of stream\n"); return 0; } - if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) - || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { - - printf ("missing signature\n"); - abort(); + if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) || + (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { + lprintf ("libmms: missing signature\n"); + return 0; } - command = get_32 (this->buf, 24) & 0xFFFF; + command = LE_32 (this->buf + 24) & 0xFFFF; -#ifdef LOG - printf ("command: %02x\n", command); -#endif + lprintf ("command: %02x\n", command); - if (command == 0x1b) + if (command == 0x1b) { send_command (this, 0x1b, 0, 0, 0); - else if (command == 0x1e) { + } else if (command == 0x1e) { + lprintf ("end of the current stream.\n"); + + /* might be followed by a new stream cmd 0x20 */ + if (!this->live_flag) + return 0; - printf ("libmms: everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); + } else if (command == 0x20) { + + lprintf ("libmms: new stream.\n"); + /* asf header */ + if (!get_header (this)) { + lprintf ("libmms: bad header\n"); + return 0; + } + + interp_header (this); + + if (!mms_choose_best_streams(this)) + return 0; + + /* command 0x07 */ + memset (this->scmd_body, 0, 40); + memset (this->scmd_body + 8, 0xFF, 8); + this->scmd_body[20] = 0x04; + + if (!send_command (this, 0x07, 1, + 0xFFFF | this->stream_ids[0] << 16, + 24)) { + lprintf("failed to send command 0x07\n"); + return 0; + } - return 0; } else if (command != 0x05) { - printf ("unknown command %02x\n", command); - abort(); + lprintf ("unknown command %02x\n", command); + return 0; } } -#ifdef LOG - printf ("get media packet succ\n"); -#endif + lprintf ("get media packet succ\n"); return 1; } + int mms_peek_header (mms_t *this, char *data, int maxsize) { int len; @@ -1219,9 +1168,8 @@ int mms_read (mms_t *this, char *data, int len) { while (total < len) { -#ifdef LOG - printf ("libmms: read, got %d / %d bytes\n", total, len); -#endif + /* not really usefull, even in debug mode */ + lprintf ("libmms: read, got %d / %d bytes\n", total, len); if (this->asf_header_read < this->asf_header_len) { int n, bytes_left ; @@ -1229,9 +1177,9 @@ int mms_read (mms_t *this, char *data, int len) { bytes_left = this->asf_header_len - this->asf_header_read ; if ((len-total) < bytes_left) - n = len-total; + n = len-total; else - n = bytes_left; + n = bytes_left; memcpy (&data[total], &this->asf_header[this->asf_header_read], n); @@ -1244,21 +1192,21 @@ int mms_read (mms_t *this, char *data, int len) { bytes_left = this->buf_size - this->buf_read; while (!bytes_left) { - - this->buf_read = 0; - - if (!get_media_packet (this)) { - printf ("libmms: get_media_packet failed\n"); - return total; - } - bytes_left = this->buf_size - this->buf_read; + + this->buf_read = 0; + + if (!get_media_packet (this)) { + lprintf ("get_media_packet failed\n"); + return total; + } + bytes_left = this->buf_size - this->buf_read; } if ((len-total)buf[this->buf_read], n); -- cgit v1.2.3