summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input/input_mms.c28
-rw-r--r--src/input/mms.c824
2 files changed, 451 insertions, 401 deletions
diff --git a/src/input/input_mms.c b/src/input/input_mms.c
index 0473f4fd3..f0fd655c6 100644
--- a/src/input/input_mms.c
+++ b/src/input/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: input_mms.c,v 1.49 2004/04/10 15:45:11 mroi Exp $
+ * $Id: input_mms.c,v 1.50 2004/04/15 22:10:55 tmattern Exp $
*
* mms input plugin based on work from major mms
*/
@@ -161,15 +161,15 @@ static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin
}
switch (origin) {
- case SEEK_SET:
- dest = offset;
- break;
- case SEEK_CUR:
- dest = curpos + offset;
- break;
- default:
- printf ("input_mms: unknown origin in seek!\n");
- return curpos;
+ case SEEK_SET:
+ dest = offset;
+ break;
+ case SEEK_CUR:
+ dest = curpos + offset;
+ break;
+ default:
+ printf ("input_mms: unknown origin in seek!\n");
+ return curpos;
}
if (curpos > dest) {
@@ -228,7 +228,10 @@ static off_t mms_plugin_get_length (input_plugin_t *this_gen) {
}
static uint32_t mms_plugin_get_capabilities (input_plugin_t *this_gen) {
- return INPUT_CAP_PREVIEW;
+ mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen;
+ uint32_t cap = INPUT_CAP_PREVIEW;
+
+ return cap;
}
static uint32_t mms_plugin_get_blocksize (input_plugin_t *this_gen) {
@@ -239,9 +242,6 @@ static off_t mms_plugin_get_current_pos (input_plugin_t *this_gen){
mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen;
off_t curpos = 0;
- /*
- printf ("current pos is %lld\n", this->curpos);
- */
switch (this->protocol) {
case PROTOCOL_MMST:
curpos = mms_get_current_pos(this->mms);
diff --git a/src/input/mms.c b/src/input/mms.c
index 110311b13..a113f062e 100644
--- a/src/input/mms.c
+++ b/src/input/mms.c
@@ -17,15 +17,14 @@
* 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.47 2004/04/14 01:42:55 miguelfreitas Exp $
+ * $Id: mms.c,v 1.48 2004/04/15 22:10:55 tmattern Exp $
*
* MMS over TCP protocol
* based on work from major mms
* utility functions to handle communication with an mms server
*
* TODO:
- * general cleanup, error messages
- * always check packet size
+ * error messages
* enable seeking !
*/
@@ -77,11 +76,37 @@
#define BUF_SIZE 102400
-#define CMD_HEADER_LEN 48
+#define CMD_HEADER_LEN 40
+#define CMD_PREFIX_LEN 8
#define CMD_BODY_LEN 1024
#define ASF_HEADER_LEN 8192
+
+#define MMS_PACKET_ERR 0
+#define MMS_PACKET_COMMAND 1
+#define MMS_PACKET_ASF_HEADER 2
+#define MMS_PACKET_ASF_PACKET 3
+
+#define ASF_HEADER_PACKET_ID_TYPE 2
+#define ASF_MEDIA_PACKET_ID_TYPE 4
+
+
+typedef struct mms_buffer_s mms_buffer_t;
+struct mms_buffer_s {
+ uint8_t *buffer;
+ int pos;
+};
+
+typedef struct mms_packet_header_s mms_packet_header_t;
+struct mms_packet_header_s {
+ uint32_t packet_len;
+ uint8_t flags;
+ uint8_t packet_id_type;
+ uint32_t packet_seq;
+};
+
+
struct mms_s {
xine_stream_t *stream;
@@ -116,8 +141,8 @@ struct mms_s {
int num_stream_ids;
int stream_ids[ASF_MAX_NUM_STREAMS];
int stream_types[ASF_MAX_NUM_STREAMS];
- int packet_length;
- uint32_t file_length;
+ int asf_packet_len;
+ uint32_t file_len;
char guid[37];
uint32_t bitrates[ASF_MAX_NUM_STREAMS];
uint32_t bitrates_pos[ASF_MAX_NUM_STREAMS];
@@ -127,18 +152,40 @@ struct mms_s {
int has_video;
int live_flag;
off_t current_pos;
+ int eos;
};
+static void mms_buffer_init (mms_buffer_t *mms_buffer, uint8_t *buffer) {
+ mms_buffer->buffer = buffer;
+ mms_buffer->pos = 0;
+}
+
+static void mms_buffer_put_8 (mms_buffer_t *mms_buffer, uint8_t value) {
+
+ mms_buffer->buffer[mms_buffer->pos] = value & 0xff;
+
+ mms_buffer->pos += 1;
+}
+
+#if 0
+static void mms_buffer_put_16 (mms_buffer_t *mms_buffer, uint16_t value) {
+
+ mms_buffer->buffer[mms_buffer->pos] = value & 0xff;
+ mms_buffer->buffer[mms_buffer->pos + 1] = (value >> 8) & 0xff;
+
+ mms_buffer->pos += 2;
+}
+#endif
-static void put_32 (mms_t *this, uint32_t value) {
+static void mms_buffer_put_32 (mms_buffer_t *mms_buffer, uint32_t value) {
- this->scmd[this->scmd_len ] = value & 0xff;
- this->scmd[this->scmd_len + 1] = (value >> 8) & 0xff;
- this->scmd[this->scmd_len + 2] = (value >> 16) & 0xff;
- this->scmd[this->scmd_len + 3] = (value >> 24) & 0xff;
+ mms_buffer->buffer[mms_buffer->pos] = value & 0xff;
+ mms_buffer->buffer[mms_buffer->pos + 1] = (value >> 8) & 0xff;
+ mms_buffer->buffer[mms_buffer->pos + 2] = (value >> 16) & 0xff;
+ mms_buffer->buffer[mms_buffer->pos + 3] = (value >> 24) & 0xff;
- this->scmd_len += 4;
+ mms_buffer->pos += 4;
}
static int get_guid (unsigned char *buffer, int offset) {
@@ -168,82 +215,84 @@ static int get_guid (unsigned char *buffer, int offset) {
return GUID_ERROR;
}
+
+static void print_command (char *data, int len) {
+
+#ifdef LOG
+ int i;
+ int dir = LE_32 (data + 36) >> 16;
+ int comm = LE_32 (data + 36) & 0xFFFF;
+
+ printf ("----------------------------------------------\n");
+ if (dir == 3) {
+ printf ("send command 0x%02x, %d bytes\n", comm, len);
+ } else {
+ printf ("receive command 0x%02x, %d bytes\n", comm, len);
+ }
+ 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 (" protocol %08x\n", LE_32 (data + 12));
+ 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));
+ if (len >= 4)
+ printf (" prefix1 %08x\n", LE_32 (data + 40));
+ if (len >= 8)
+ printf (" prefix2 %08x\n", LE_32 (data + 44));
+
+ for (i = (CMD_HEADER_LEN + CMD_PREFIX_LEN); i < (CMD_HEADER_LEN + CMD_PREFIX_LEN + len); i += 1) {
+ unsigned char c = data[i];
+
+ if ((c >= 32) && (c < 128))
+ printf ("%c", c);
+ else
+ printf (" %02x ", c);
+
+ }
+ if (len > CMD_HEADER_LEN)
+ printf ("\n");
+ printf ("----------------------------------------------\n");
+#endif
+}
+
+
+
static int send_command (mms_t *this, int command,
uint32_t prefix1, uint32_t prefix2,
int length) {
int len8;
off_t n;
+ mms_buffer_t command_buffer;
len8 = (length + 7) / 8;
this->scmd_len = 0;
- put_32 (this, 0x00000001); /* start sequence */
- put_32 (this, 0xB00BFACE); /* #-)) */
- put_32 (this, length + 32);
- put_32 (this, 0x20534d4d); /* protocol type "MMS " */
- put_32 (this, len8 + 4);
- put_32 (this, this->seq_num);
+ mms_buffer_init(&command_buffer, this->scmd);
+ mms_buffer_put_32 (&command_buffer, 0x00000001); /* start sequence */
+ mms_buffer_put_32 (&command_buffer, 0xB00BFACE); /* #-)) */
+ mms_buffer_put_32 (&command_buffer, length + 32);
+ mms_buffer_put_32 (&command_buffer, 0x20534d4d); /* protocol type "MMS " */
+ mms_buffer_put_32 (&command_buffer, len8 + 4);
+ mms_buffer_put_32 (&command_buffer, this->seq_num);
this->seq_num++;
- put_32 (this, 0x0); /* timestamp */
- put_32 (this, 0x0);
- put_32 (this, len8+2);
- put_32 (this, 0x00030000 | command); /* dir | command */
+ mms_buffer_put_32 (&command_buffer, 0x0); /* timestamp */
+ mms_buffer_put_32 (&command_buffer, 0x0);
+ mms_buffer_put_32 (&command_buffer, len8+2);
+ mms_buffer_put_32 (&command_buffer, 0x00030000 | command); /* dir | command */
/* end of the 40 byte command header */
- put_32 (this, prefix1);
- put_32 (this, prefix2);
-
- /* memcpy (&cmd->buf[48], data, length); */
+ mms_buffer_put_32 (&command_buffer, prefix1);
+ mms_buffer_put_32 (&command_buffer, prefix2);
- n = _x_io_tcp_write (this->stream, this->s, this->scmd, length + 48);
- if (n != (length + 48)) {
+ n = _x_io_tcp_write (this->stream, this->s, this->scmd, length + CMD_HEADER_LEN + CMD_PREFIX_LEN);
+ if (n != (length + CMD_HEADER_LEN + CMD_PREFIX_LEN)) {
return 0;
}
-#ifdef LOG
- {
- int i;
- unsigned char c;
-
- printf ("\nlibmms: ***************************************************\ncommand sent, %d bytes\n", length + 48);
-
- 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) {
- c = this->scmd[i];
-
- if ((c >= 32) && (c <= 128))
- printf ("%c", c);
- else
- printf (".");
- }
- printf ("\n");
-
- printf ("libmms: complete hexdump of package follows:\n");
- for (i = 0; i < (length + 48); i++) {
- c = this->scmd[i];
-
- printf ("%02x", c);
-
- if ((i % 16) == 15)
- printf ("\nlibmms: ");
-
- if ((i % 2) == 1)
- printf (" ");
-
- }
- printf ("\n");
- }
-#endif
+ print_command (this->scmd, length);
return 1;
}
@@ -298,192 +347,179 @@ static void string_utf16(int unused, char *dest, char *src, int len) {
}
#endif
-static void print_answer (char *data, int len) {
-
-#ifdef LOG
- int i;
-
- printf ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\nanswer received, %d bytes\n", len);
- 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];
+/*
+ * return packet type
+ */
+static int get_packet_header (mms_t *this, mms_packet_header_t *header) {
+ size_t len;
+ int packet_type;
+
+ header->packet_len = 0;
+ header->packet_seq = 0;
+ header->flags = 0;
+ header->packet_id_type = 0;
+ len = _x_io_tcp_read (this->stream, this->s, this->buf, 8);
+ if (len != 8)
+ goto error;
- if ((c >= 32) && (c < 128))
- printf ("%c", c);
- else
- printf (" %02x ", c);
+ if (LE_32(this->buf + 4) == 0xb00bface) {
+ /* command packet */
+ header->flags = this->buf[3];
+ len = _x_io_tcp_read (this->stream, this->s, this->buf + 8, 4);
+ if (len != 4)
+ goto error;
+ header->packet_len = LE_32(this->buf + 8) + 4;
+ lprintf("mms command\n");
+ packet_type = MMS_PACKET_COMMAND;
+ } else {
+ header->packet_seq = LE_32(this->buf);
+ header->packet_id_type = this->buf[4];
+ header->flags = this->buf[5];
+ header->packet_len = LE_16(this->buf + 6) - 8;
+ if (header->packet_id_type == ASF_HEADER_PACKET_ID_TYPE) {
+ lprintf("asf header\n");
+ packet_type = MMS_PACKET_ASF_HEADER;
+ } else {
+ lprintf("asf packet\n");
+ packet_type = MMS_PACKET_ASF_PACKET;
+ }
}
- printf ("\n");
-#endif
-}
+ return packet_type;
+
+error:
+ lprintf("read error, len=%d\n", len);
+ return MMS_PACKET_ERR;
+}
-/*
- * TODO: error messages (READ ERROR)
- */
-static int get_answer (mms_t *this) {
-
- int command = 0x1b;
- while (command == 0x1b) {
- off_t len;
- uint32_t length;
+static int get_packet_command (mms_t *this, uint32_t packet_len) {
- len = _x_io_tcp_read (this->stream, this->s, this->buf, 12);
- if (len != 12) {
- return 0;
- }
- length = LE_32 (this->buf + 8);
+ int command = 0;
+ size_t len;
+
+ /* always enter this loop */
+ lprintf("packet_len: %d bytes\n", packet_len);
- lprintf ("packet length: %d\n", length);
- if (length > (BUF_SIZE - 12)) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: invalid packet length: %d\n", length);
- return 0;
- }
-
- len = _x_io_tcp_read (this->stream, this->s, this->buf + 12, length + 4) ;
- if (len != (length + 4)) {
- return 0;
- }
+ len = _x_io_tcp_read (this->stream, this->s, this->buf + 12, packet_len) ;
+ if (len != packet_len) {
+ return 0;
+ }
+
+ print_command (this->buf, len);
+
+ /* check protocol type ("MMS ") */
+ if (LE_32(this->buf + 12) != 0x20534D4D) {
+ lprintf("unknown protocol type: %c%c%c%c (0x%08X)\n",
+ this->buf[12], this->buf[13], this->buf[14], this->buf[15],
+ LE_32(this->buf + 12));
+ return 0;
+ }
+
+ command = LE_32 (this->buf + 36) & 0xFFFF;
+ lprintf("command = 0x%2x\n", command);
- len += 12;
- print_answer (this->buf, len);
+ return command;
+}
- command = LE_32 (this->buf + 36) & 0xFFFF;
+static int get_answer (mms_t *this) {
+ int command = 0;
+ mms_packet_header_t header;
- /* reply to a ping command */
- if (command == 0x1b) {
- if (!send_command (this, 0x1b, 0, 0, 0)) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: failed to send command\n");
- return 0;
+ switch (get_packet_header (this, &header)) {
+ case MMS_PACKET_ERR:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to read mms packet header\n");
+ break;
+ case MMS_PACKET_COMMAND:
+ command = get_packet_command (this, header.packet_len);
+
+ if (command == 0x1b) {
+
+ if (!send_command (this, 0x1b, 0, 0, 0)) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command\n");
+ return 0;
+ }
+ /* FIXME: limit recursion */
+ command = get_answer (this);
}
- }
+ break;
+ case MMS_PACKET_ASF_HEADER:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: unexpected asf header packet\n");
+ break;
+ case MMS_PACKET_ASF_PACKET:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: unexpected asf packet\n");
+ break;
}
-
+
return command;
}
-static int get_header (mms_t *this) {
- uint8_t pre_header[8];
+static int get_asf_header (mms_t *this) {
+
off_t len;
+ int stop = 0;
this->asf_header_read = 0;
this->asf_header_len = 0;
- while (1) {
-
- len = _x_io_tcp_read (this->stream, this->s, pre_header, 8) ;
- if (len != 8) {
- return 0;
- }
-
-#ifdef LOG
- {
- int i;
- for (i = 0; i < 8; i++)
- 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) || (pre_header[4] == 0xff)){
-
- uint32_t packet_len;
-
- packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
-
- lprintf ("asf header packet detected, len=%d\n", packet_len);
- if (packet_len > (ASF_HEADER_LEN - this->asf_header_len)) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: invalid packet length: %d\n", packet_len);
- return 0;
- }
-
- len = _x_io_tcp_read (this->stream, this->s,
- &this->asf_header[this->asf_header_len], packet_len);
- if (len != packet_len) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_header failed\n");
- return 0;
- }
-
- this->asf_header_len += packet_len;
-
- if ( (this->asf_header[this->asf_header_len - 1] == 1)
- && (this->asf_header[this->asf_header_len - 2] == 1)) {
-
- lprintf ("get header packet finished\n");
- return 1;
- }
-
- } else {
-
- uint32_t packet_len;
- int command;
-
- len = _x_io_tcp_read (this->stream, this->s, (uint8_t *) &packet_len, 4);
- if (len != 4) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_header failed\n");
- return 0;
- }
-
- packet_len = LE_32 ((uint8_t *)&packet_len + 0) + 4;
-
- lprintf ("command packet detected, len=%d\n", packet_len);
+ while (!stop) {
+ mms_packet_header_t header;
+ int command;
- if (packet_len > (BUF_SIZE)) {
+ switch (get_packet_header (this, &header)) {
+ case MMS_PACKET_ERR:
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: invalid packet length: %d\n", packet_len);
+ "libmms: failed to read mms packet header\n");
return 0;
- }
-
- len = _x_io_tcp_read (this->stream, this->s, this->buf, packet_len);
- if (len < packet_len) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_header failed\n");
- return 0;
- }
-
- command = LE_32 (this->buf + 24) & 0xFFFF;
- lprintf ("command: %02x\n", command);
+ break;
+ case MMS_PACKET_COMMAND:
+ command = get_packet_command (this, header.packet_len);
- /* reply to a ping command */
- if (command == 0x1b) {
- if (!send_command (this, 0x1b, 0, 0, 0)) {
+ if (command == 0x1b) {
+
+ if (!send_command (this, 0x1b, 0, 0, 0)) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command\n");
+ return 0;
+ }
+ command = get_answer (this);
+ } else {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: invalid packet length: %d\n", packet_len);
- return 0;
+ "libmms: unexpected command packet\n");
}
- }
+ break;
+ case MMS_PACKET_ASF_HEADER:
+ case MMS_PACKET_ASF_PACKET:
+ len = _x_io_tcp_read (this->stream, this->s,
+ this->asf_header + this->asf_header_len, header.packet_len);
+ if (len != header.packet_len) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: get_header failed\n");
+ return 0;
+ }
+ this->asf_header_len += header.packet_len;
+ lprintf("header flags: %d\n", header.flags);
+ if ((header.flags == 0X08) || (header.flags == 0X0C))
+ stop = 1;
+ break;
}
-
- lprintf ("get header packet succ\n");
}
-
+ lprintf ("get header packet succ\n");
return 1;
}
-static void interp_header (mms_t *this) {
+static void interp_asf_header (mms_t *this) {
int i;
- this->packet_length = 0;
+ this->asf_packet_len = 0;
this->num_stream_ids = 0;
/*
* parse header
@@ -505,10 +541,10 @@ static void interp_header (mms_t *this) {
case GUID_ASF_FILE_PROPERTIES:
- this->packet_length = LE_32(this->asf_header + i + 92 - 24);
- this->file_length = LE_32(this->asf_header + i + 40 - 24);
+ this->asf_packet_len = LE_32(this->asf_header + i + 92 - 24);
+ this->file_len = 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));
+ this->asf_packet_len, LE_32(this->asf_header + i + 96 - 24));
break;
case GUID_ASF_STREAM_PROPERTIES:
@@ -784,7 +820,6 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
int url_conv = 0;
#endif
mms_t *this;
- int i;
int res;
if (!url)
@@ -796,17 +831,18 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
this->url = strdup (url);
this->s = -1;
this->seq_num = 0;
- this->scmd_body = &this->scmd[CMD_HEADER_LEN];
+ this->scmd_body = this->scmd + CMD_HEADER_LEN + CMD_PREFIX_LEN;
this->asf_header_len = 0;
this->asf_header_read = 0;
this->num_stream_ids = 0;
- this->packet_length = 0;
+ this->asf_packet_len = 0;
this->buf_size = 0;
this->buf_read = 0;
this->has_audio = 0;
this->has_video = 0;
this->bandwidth = bandwidth;
this->current_pos = 0;
+ this->eos = 0;
report_progress (stream, 0);
@@ -834,6 +870,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
*/
/* command 0x1 */
+ lprintf("send command 0x01\n");
mms_gen_guid(this->guid);
sprintf (this->str, "\x1c\x03NSPlayer/7.0.0.1956; {%s}; Host: %s",
this->guid, this->host);
@@ -855,6 +892,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
/* TODO: insert network timing request here */
/* command 0x2 */
+ lprintf("send command 0x02\n");
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)) {
@@ -880,11 +918,18 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
report_progress (stream, 50);
/* command 0x5 */
- string_utf16 (url_conv, &this->scmd_body[8], this->uri, strlen(this->uri));
- memset (this->scmd_body, 0, 8);
- if (!send_command (this, 5, 0, 0, strlen(this->uri) * 2 + 12))
- goto fail;
-
+ {
+ mms_buffer_t command_buffer;
+
+ lprintf("send command 0x05\n");
+ mms_buffer_init(&command_buffer, this->scmd_body);
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ string_utf16 (url_conv, this->scmd_body + command_buffer.pos, this->uri, strlen(this->uri));
+ if (!send_command (this, 5, 1, 0xffffffff, strlen(this->uri) * 2 + 12))
+ goto fail;
+ }
+
switch (res = get_answer (this)) {
case 0x06:
{
@@ -913,15 +958,27 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
report_progress (stream, 60);
/* command 0x15 */
- memset (this->scmd_body, 0, 40);
- this->scmd_body[32] = 2;
-
- if (!send_command (this, 0x15, 1, 0, 40)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: failed to send command 0x15\n");
- goto fail;
+ lprintf("send command 0x15\n");
+ {
+ mms_buffer_t command_buffer;
+ mms_buffer_init(&command_buffer, this->scmd_body);
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00800000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0x40AC2000); /* ?? */
+ mms_buffer_put_32 (&command_buffer, ASF_HEADER_PACKET_ID_TYPE); /* Header Packet ID type */
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */
+ if (!send_command (this, 0x15, 1, 0, command_buffer.pos)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command 0x15\n");
+ goto fail;
+ }
}
-
+
if ((res = get_answer (this)) != 0x11) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
"libmms: unexpected response: %02x (0x11)\n", res);
@@ -930,10 +987,10 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
this->num_stream_ids = 0;
- if (!get_header (this))
+ if (!get_asf_header (this))
goto fail;
- interp_header (this);
+ interp_asf_header (this);
report_progress (stream, 70);
@@ -946,17 +1003,23 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
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)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: failed to send command 0x07\n");
- goto fail;
+ {
+ mms_buffer_t command_buffer;
+ mms_buffer_init(&command_buffer, this->scmd_body);
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */
+ mms_buffer_put_32 (&command_buffer, 0x00000000);
+ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */
+ mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */
+ mms_buffer_put_8 (&command_buffer, 0xFF);
+ mms_buffer_put_8 (&command_buffer, 0xFF);
+ mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */
+ mms_buffer_put_32 (&command_buffer, ASF_MEDIA_PACKET_ID_TYPE); /* asf media packet id type */
+ if (!send_command (this, 0x07, 1, 0x0001FFFF, command_buffer.pos)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command 0x07\n");
+ goto fail;
+ }
}
report_progress (stream, 100);
@@ -990,144 +1053,135 @@ fail:
}
static int get_media_packet (mms_t *this) {
- unsigned char pre_header[8];
+ mms_packet_header_t header;
off_t len;
- len = _x_io_tcp_read (this->stream, this->s, pre_header, 8) ;
- if (len != 8) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_media_packet_failed\n");
- return 0;
- }
-
-#ifdef LOG
- {
- int i;
- for (i = 0; i < 8; i++)
- printf ("pre_header[%d] = %02x (%d)\n",
- i, pre_header[i], pre_header[i]);
- }
-#endif
-
- if (pre_header[4] == 0x04) {
-
- uint32_t packet_len, sequence;
-
- packet_len = LE_16(&pre_header[6]) - 8;
-
- sequence = LE_32(&pre_header[0]);
- lprintf ("sequence=%d\n", sequence);
-
- /* simulate a seek */
- this->current_pos = (off_t)this->asf_header_len + (off_t)sequence * (off_t)this->packet_length;
-
- lprintf ("asf media packet detected, len=%d\n", packet_len);
- if (packet_len > (BUF_SIZE)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_media_packet: invalid packet length: %d\n", packet_len);
- return 0;
- }
-
- len = _x_io_tcp_read (this->stream, this->s, this->buf, packet_len);
- if (len < packet_len) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_media_packet_failed\n");
- return 0;
- }
-
- /* explicit padding with 0 */
- memset(this->buf + packet_len, 0, this->packet_length - packet_len);
- this->buf_size = this->packet_length;
-
- } else {
-
- uint32_t packet_len;
- int command;
-
- this->buf_size = 0;
- len = _x_io_tcp_read (this->stream, this->s, (uint8_t *)&packet_len, 4);
- if (len != 4) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_media_packet: read error\n");
- return 0;
- }
-
- packet_len = LE_32 ((uint8_t *)&packet_len) + 4;
-
- lprintf ("command packet detected, len=%d\n", packet_len);
- if (packet_len > (BUF_SIZE)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: get_media_packet: invalid packet length: %d\n", packet_len);
- return 0;
- }
-
- len = _x_io_tcp_read (this->stream, this->s, this->buf, packet_len);
- if (len < 0) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: read error\n");
- return 0;
- }
-
- if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) ||
- (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) {
-
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmms: missing signature\n");
+ switch (get_packet_header (this, &header)) {
+ case MMS_PACKET_ERR:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to read mms packet header\n");
return 0;
- }
-
- command = LE_32 (this->buf + 24) & 0xFFFF;
-
- lprintf ("command: %02x\n", command);
-
- if (command == 0x1b) {
- send_command (this, 0x1b, 0, 0, 0);
- } else if (command == 0x1e) {
- uint32_t error_code;
-
- /* Warning: sdp is incomplete. Do not stop if error_code==1 */
- error_code = LE_32(this->buf + 28);
- lprintf ("End of the current stream. Continue=%d\n", error_code);
-
- if (!error_code) {
- return 0;
- }
-
- } else if (command == 0x20) {
-
- lprintf ("new stream.\n");
- /* asf header */
- if (!get_header (this)) {
- lprintf ("bad header\n");
- return 0;
+ break;
+
+ case MMS_PACKET_COMMAND:
+ {
+ int command;
+ command = get_packet_command (this, header.packet_len);
+
+ switch (command) {
+ case 0x1e:
+ {
+ uint32_t error_code;
+
+ /* Warning: sdp is incomplete. Do not stop if error_code==1 */
+ error_code = LE_32(this->buf + CMD_HEADER_LEN);
+ lprintf ("End of the current stream. Continue=%d\n", error_code);
+
+ if (error_code == 0) {
+ this->eos = 1;
+ return 0;
+ }
+
+ }
+ break;
+
+ case 0x20:
+ {
+ lprintf ("new stream.\n");
+ /* asf header */
+ if (!get_asf_header (this)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "failed to read new ASF header\n");
+ return 0;
+ }
+
+ interp_asf_header (this);
+
+ if (!mms_choose_best_streams(this))
+ return 0;
+
+ /* send command 0x07 */
+ /* TODO: ugly */
+ /* command 0x07 */
+ {
+ mms_buffer_t command_buffer;
+ mms_buffer_init(&command_buffer, this->scmd_body);
+ mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */
+ mms_buffer_put_32 (&command_buffer, 0x00000000);
+ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */
+ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */
+ mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */
+ mms_buffer_put_8 (&command_buffer, 0xFF);
+ mms_buffer_put_8 (&command_buffer, 0xFF);
+ mms_buffer_put_8 (&command_buffer, 0x00); /* stream time limit flag */
+ mms_buffer_put_32 (&command_buffer, ASF_MEDIA_PACKET_ID_TYPE); /* asf media packet id type */
+ if (!send_command (this, 0x07, 1, 0x0001FFFF, command_buffer.pos)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command 0x07\n");
+ return 0;
+ }
+ }
+ this->current_pos = 0;
+ }
+ break;
+
+ case 0x1b:
+ {
+ if (!send_command (this, 0x1b, 0, 0, 0)) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: failed to send command\n");
+ return 0;
+ }
+ }
+ break;
+
+ case 0x05:
+ break;
+
+ default:
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "unexpected mms command %02x\n", command);
+ }
+ this->buf_size = 0;
}
+ break;
- interp_header (this);
+ case MMS_PACKET_ASF_HEADER:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: unexpected asf header packet\n");
+ this->buf_size = 0;
+ break;
- if (!mms_choose_best_streams(this))
- return 0;
+ case MMS_PACKET_ASF_PACKET:
+ {
+ /* media packet */
- /* command 0x07 */
- memset (this->scmd_body, 0, 40);
- memset (this->scmd_body + 8, 0xFF, 8);
- this->scmd_body[20] = 0x04;
+ lprintf ("asf media packet detected, packet_len=%d, packet_seq=%d\n",
+ header.packet_len, header.packet_seq);
+ if (header.packet_len > this->asf_packet_len) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: invalid asf packet len: %d bytes\n", header.packet_len);
+ return 0;
+ }
+
+ /* simulate a seek */
+ this->current_pos = (off_t)this->asf_header_len + (off_t)header.packet_seq * (off_t)this->asf_packet_len;
+
+ len = _x_io_tcp_read (this->stream, this->s, this->buf, header.packet_len);
+ if (len != header.packet_len) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "libmms: read failed\n");
+ return 0;
+ }
- if (!send_command (this, 0x07, 1,
- 0xFFFF | this->stream_ids[0] << 16,
- 24)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "failed to send command 0x07\n");
- return 0;
+ /* explicit padding with 0 */
+ lprintf("padding: %d bytes\n", this->asf_packet_len - header.packet_len);
+ memset(this->buf + header.packet_len, 0, this->asf_packet_len - header.packet_len);
+ this->buf_size = this->asf_packet_len;
}
- this->current_pos = 0;
-
- } else if (command != 0x05) {
- xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "unknown command %02x\n", command);
- return 0;
- }
+ break;
}
-
+
lprintf ("get media packet succ\n");
return 1;
@@ -1148,18 +1202,14 @@ int mms_read (mms_t *this, char *data, int len) {
int total;
total = 0;
-
- while (total < len) {
-
- /* not really usefull, even in debug mode */
- lprintf ("read, got %d / %d bytes\n", total, len);
+ while (total < len && !this->eos) {
if (this->asf_header_read < this->asf_header_len) {
int n, bytes_left ;
bytes_left = this->asf_header_len - this->asf_header_read ;
- if ((len-total) < bytes_left)
+ if ((len - total) < bytes_left)
n = len-total;
else
n = bytes_left;
@@ -1221,7 +1271,7 @@ void mms_close (mms_t *this) {
}
uint32_t mms_get_length (mms_t *this) {
- return this->file_length;
+ return this->file_len;
}
off_t mms_get_current_pos (mms_t *this) {