summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibaut Mattern <tmattern@users.sourceforge.net>2004-04-06 00:25:29 +0000
committerThibaut Mattern <tmattern@users.sourceforge.net>2004-04-06 00:25:29 +0000
commit77ab2d6c6a0e8ac45f7936d71ef5f8e923275cbe (patch)
tree59aa23ca3afd9d441893bd37fa5772fe91d6a360
parent7c56dc4a7f9bcfa9b0a117e29deafe03193c52cd (diff)
downloadxine-lib-77ab2d6c6a0e8ac45f7936d71ef5f8e923275cbe.tar.gz
xine-lib-77ab2d6c6a0e8ac45f7936d71ef5f8e923275cbe.tar.bz2
Asf demuxer:
- fix error correction handling. - detect properly the end of the stream using packet_count (now that mms plugin handles correctly current_pos). - rename some properties mmst/mmsh: - handle current stream pos correctly, based on packet sequence_id (needed for seeking). mmsh: - some reverse ingeneering to support for grouped ASF streams like mmst (mmsh://wms03.nordicwebradio.com/chelsea) - fix a potential crash at the end of stream CVS patchset: 6334 CVS date: 2004/04/06 00:25:29
-rw-r--r--src/demuxers/demux_asf.c138
-rw-r--r--src/input/input_mms.c61
-rw-r--r--src/input/mms.c25
-rw-r--r--src/input/mms.h4
-rw-r--r--src/input/mmsh.c178
-rw-r--r--src/input/mmsh.h4
6 files changed, 252 insertions, 158 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index 0f86a15b2..aeae83101 100644
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.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: demux_asf.c,v 1.154 2004/04/02 06:52:39 tmattern Exp $
+ * $Id: demux_asf.c,v 1.155 2004/04/06 00:25:29 tmattern Exp $
*
* demultiplexer for asf streams
*
@@ -106,8 +106,9 @@ typedef struct demux_asf_s {
int seqno;
uint32_t packet_size;
- uint8_t packet_flags;
+ uint8_t packet_len_flags;
uint32_t data_size;
+ uint64_t packet_count;
asf_stream_t streams[MAX_NUM_STREAMS];
uint32_t bitrates[MAX_NUM_STREAMS];
@@ -131,8 +132,8 @@ typedef struct demux_asf_s {
char copyright[512];
char comment[512];
- uint32_t length;
- uint32_t rate;
+ uint64_t length;
+ uint32_t rate;
uint64_t preroll;
/* packet filling */
@@ -149,7 +150,7 @@ typedef struct demux_asf_s {
uint32_t packet_padsize;
int nb_frames;
uint8_t frame_flag;
- uint8_t segtype;
+ uint8_t packet_prop_flags;
int frame;
int status;
@@ -376,14 +377,14 @@ static int asf_read_header (demux_asf_t *this) {
file_size = get_le64(this); /* file size */
get_le64(this); /* creation time */
- get_le64(this); /* nb packets */
-
+ this->packet_count = get_le64(this); /* nb packets */
+
this->length = get_le64(this) / 10000; /* duration */
send_time = get_le64(this); /* send time */
this->preroll = get_le64(this); /* preroll in 1/1000 s */
this->length -= this->preroll;
-
+
flags = get_le32(this); /* flags */
get_le32(this); /* min packet size */
this->packet_size = get_le32(this); /* max packet size */
@@ -981,21 +982,54 @@ static int asf_parse_packet_align(demux_asf_t *this) {
uint64_t current_pos, packet_pos;
uint32_t mod;
+ uint64_t packet_num;
+
+ /* skip padding */
+ current_pos = this->input->seek (this->input, this->packet_size_left, SEEK_CUR);
+
/* seek to the beginning of the next packet */
- current_pos = this->input->get_current_pos (this->input);
mod = (current_pos - this->first_packet_pos) % this->packet_size;
this->packet_size_left = mod ? this->packet_size - mod : 0;
packet_pos = current_pos + this->packet_size_left;
if (this->packet_size_left) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: last packet is not finished\n");
current_pos = this->input->seek (this->input, packet_pos, SEEK_SET);
if (current_pos != packet_pos) {
- this->status = DEMUX_FINISHED;
return 1;
}
}
this->packet_size_left = 0;
+ /* check packet_count */
+ packet_num = (current_pos - this->first_packet_pos) / this->packet_size;
+ if (packet_num == this->packet_count) {
+ /* end of payload data */
+ current_pos = this->input->get_current_pos (this->input);
+ lprintf("demux_asf: end of payload data, current_pos=%lld\n", current_pos);
+ {
+ /* check new asf header */
+ GUID g;
+ int i;
+
+ g.Data1 = (get_byte(this)) + (get_byte(this) << 8) +
+ (get_byte(this) << 16) + (get_byte(this) << 24);
+ g.Data2 = get_le16(this);
+ g.Data3 = get_le16(this);
+ for(i = 0; i < 8; i++) {
+ g.Data4[i] = get_byte(this);
+ }
+ if (get_guid_id(this, g) == GUID_ASF_HEADER) {
+ lprintf("demux_asf: new asf header detected\n");
+ if (demux_asf_send_headers_common(this, 0))
+ return 1;
+ } else {
+ /* not an ASF stream */
+ return 1;
+ }
+ }
+ }
+
return 0;
}
@@ -1005,48 +1039,38 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) {
uint8_t ecd_flags;
uint8_t buf[16];
int invalid_packet;
- uint32_t rsize;
do {
ecd_flags = get_byte(this); *p_hdr_size = 1;
if (this->status == DEMUX_FINISHED)
return 1;
invalid_packet = 0;
-
- /* check new asf header */
- if (ecd_flags == 0x30) {
- GUID g;
- int i;
+ {
+ int ecd_len;
+ int ecd_opaque;
+ int ecd_len_type;
+ int ecd_present;
+
+ ecd_len = ecd_flags & 0xF;
+ ecd_opaque = (ecd_flags >> 4) & 0x1;
+ ecd_len_type = (ecd_flags >> 5) & 0x3;
+ ecd_present = (ecd_flags >> 7) & 0x1;
- g.Data1 = (ecd_flags) + (get_byte(this) << 8) +
- (get_byte(this) << 16) + (get_byte(this) << 24);
- g.Data2 = get_le16(this);
- g.Data3 = get_le16(this);
- for(i = 0; i < 8; i++) {
- g.Data4[i] = get_byte(this);
- }
- if (get_guid_id(this, g) == GUID_ASF_HEADER) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: new asf header detected\n");
- if (demux_asf_send_headers_common(this, 0))
- return 1;
- invalid_packet = 1;
- }
- } else {
-
/* skip ecd */
- if (ecd_flags & 0x80) {
- rsize = this->input->read (this->input, buf, ecd_flags & 0x0F);
- if (rsize != (ecd_flags & 0x0F)) {
+ if (ecd_present && !ecd_opaque && !ecd_len_type) {
+ int read_size;
+
+ read_size = this->input->read (this->input, buf, ecd_len);
+ if (read_size != ecd_len) {
this->status = DEMUX_FINISHED;
return 1;
}
- *p_hdr_size += rsize;
- }
+ *p_hdr_size += read_size;
- if (ecd_flags & 0x70) {
- /* skip invalid packet */
- lprintf("skip invalid packet: %d\n", ecd_flags);
+ } else {
+ /* skip invalid packet */
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: skip invalid packet: %2X\n", ecd_flags);
this->input->seek (this->input, this->packet_size - *p_hdr_size, SEEK_CUR);
invalid_packet = 1;
}
@@ -1062,11 +1086,11 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
int64_t timestamp;
int64_t duration;
- this->packet_flags = get_byte(this); p_hdr_size += 1;
- this->segtype = get_byte(this); p_hdr_size += 1;
+ this->packet_len_flags = get_byte(this); p_hdr_size += 1;
+ this->packet_prop_flags = get_byte(this); p_hdr_size += 1;
/* packet size */
- switch((this->packet_flags >> 5) & 3) {
+ switch((this->packet_len_flags >> 5) & 3) {
case 1:
this->data_size = get_byte(this); p_hdr_size += 1; break;
case 2:
@@ -1078,7 +1102,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
}
/* sequence */
- switch ((this->packet_flags >> 1) & 3) {
+ switch ((this->packet_len_flags >> 1) & 3) {
case 1:
get_byte(this); p_hdr_size += 1; break;
case 2:
@@ -1088,7 +1112,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
}
/* padding size */
- switch ((this->packet_flags >> 3) & 3){
+ switch ((this->packet_len_flags >> 3) & 3){
case 1:
this->packet_padsize = get_byte(this); p_hdr_size += 1; break;
case 2:
@@ -1104,7 +1128,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
lprintf ("timestamp=%lld, duration=%lld\n", timestamp, duration);
- if ((this->packet_flags >> 5) & 3) {
+ if ((this->packet_len_flags >> 5) & 3) {
/* absolute data size */
lprintf ("absolute data size\n");
@@ -1123,7 +1147,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
}
/* Multiple frames */
- if (this->packet_flags & 0x01) {
+ if (this->packet_len_flags & 0x01) {
this->frame_flag = get_byte(this); p_hdr_size += 1;
this->nb_frames = (this->frame_flag & 0x3F);
@@ -1136,7 +1160,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
/* this->packet_size_left = this->packet_size - p_hdr_size; */
this->packet_size_left = this->data_size - p_hdr_size;
lprintf ("new packet, size = %d, size_left = %d, flags = 0x%02x, padsize = %d, this->packet_size = %d\n",
- this->data_size, this->packet_size_left, this->packet_flags, this->packet_padsize, this->packet_size);
+ this->data_size, this->packet_size_left, this->packet_len_flags, this->packet_padsize, this->packet_size);
return 0;
}
@@ -1157,11 +1181,12 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
stream_id = raw_id & 0x7f;
*stream = NULL;
- lprintf ("got raw_id=%d\n", raw_id);
+ lprintf ("got raw_id=%d, stream_id=%d\n", raw_id, stream_id);
for (i = 0; i < this->num_streams; i++) {
- if (this->streams[i].stream_id == stream_id &&
- (stream_id == this->audio_stream_id || stream_id == this->video_stream_id)) {
+ lprintf ("this->streams[i].stream_id=%d\n", this->streams[i].stream_id);
+ if ((this->streams[i].stream_id == stream_id) &&
+ ((stream_id == this->audio_stream_id) || (stream_id == this->video_stream_id))) {
*stream = &this->streams[i];
break;
}
@@ -1177,10 +1202,8 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
return 1;
}
#endif
- if (*stream == NULL)
- return 1;
- switch ((this->segtype >> 4) & 3){
+ switch ((this->packet_prop_flags >> 4) & 3){
case 1:
*seq = get_byte(this); s_hdr_size += 1;
if (*stream)
@@ -1202,7 +1225,6 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
}
/* check seq number */
-
if (*stream) {
lprintf ("stream_id = %d, seq = %d\n", (*stream)->stream_id, *seq);
if ((*stream)->first_seq || (*stream)->skip) {
@@ -1233,7 +1255,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
}
}
- switch ((this->segtype >> 2) & 3) {
+ switch ((this->packet_prop_flags >> 2) & 3) {
case 1:
*frag_offset = get_byte(this); s_hdr_size += 1; break;
case 2:
@@ -1245,7 +1267,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
*frag_offset = 0;
}
- switch (this->segtype & 3) {
+ switch (this->packet_prop_flags & 3) {
case 1:
*rlen = get_byte(this); s_hdr_size += 1; break;
case 2:
@@ -1287,7 +1309,7 @@ static int asf_parse_packet_compressed_payload(demux_asf_t *this,
frag_offset = 0;
get_byte (this); s_hdr_size += 1;
- if (this->packet_flags & 0x01) {
+ if (this->packet_len_flags & 0x01) {
/* multiple frames */
switch ((this->frame_flag >> 6) & 3) {
case 1:
@@ -1390,7 +1412,7 @@ static int asf_parse_packet_payload(demux_asf_t *this,
s_hdr_size += rlen;
}
- if (this->packet_flags & 0x01) {
+ if (this->packet_len_flags & 0x01) {
switch ((this->frame_flag >> 6) & 3) {
case 1:
frag_len = get_byte(this); s_hdr_size += 1; break;
diff --git a/src/input/input_mms.c b/src/input/input_mms.c
index 8c4718ac3..d353895b6 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.46 2004/02/17 13:40:57 valtri Exp $
+ * $Id: input_mms.c,v 1.47 2004/04/06 00:25:29 tmattern Exp $
*
* mms input plugin based on work from major mms
*/
@@ -82,8 +82,6 @@ typedef struct {
char *mrl;
- off_t curpos;
-
nbc_t *nbc;
char scratch[1025];
@@ -110,8 +108,6 @@ static off_t mms_plugin_read (input_plugin_t *this_gen,
lprintf ("mms_plugin_read: %lld bytes ...\n", len);
- nbc_check_buffers (this->nbc);
-
switch (this->protocol) {
case PROTOCOL_MMST:
n = mms_read (this->mms, buf, len);
@@ -120,8 +116,6 @@ static off_t mms_plugin_read (input_plugin_t *this_gen,
n = mmsh_read (this->mmsh, buf, len);
break;
}
-
- this->curpos += n;
return n;
}
@@ -151,37 +145,45 @@ static buf_element_t *mms_plugin_read_block (input_plugin_t *this_gen,
static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) {
mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen;
- off_t dest = this->curpos;
+ off_t dest = 0;
+ off_t curpos = 0;
lprintf ("mms_plugin_seek: %lld offset, %d origin...\n", offset, origin);
+
+ switch (this->protocol) {
+ case PROTOCOL_MMST:
+ curpos = mms_get_current_pos (this->mms);
+ break;
+ case PROTOCOL_MMSH:
+ curpos = mmsh_get_current_pos (this->mmsh);
+ break;
+ }
+
switch (origin) {
case SEEK_SET:
dest = offset;
break;
case SEEK_CUR:
- dest = this->curpos + offset;
+ dest = curpos + offset;
break;
- case SEEK_END:
- printf ("input_mms: SEEK_END not implemented!\n");
- return this->curpos;
default:
printf ("input_mms: unknown origin in seek!\n");
- return this->curpos;
+ return curpos;
}
- if (this->curpos > dest) {
+ if (curpos > dest) {
printf ("input_mms: cannot seek back!\n");
- return this->curpos;
+ return curpos;
}
-
- while (this->curpos<dest) {
+
+ while (curpos < dest) {
int n = 0;
int diff;
- diff = dest - this->curpos;
+ diff = dest - curpos;
- if (diff>1024)
+ if (diff > 1024)
diff = 1024;
switch (this->protocol) {
@@ -193,14 +195,14 @@ static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin
break;
}
- this->curpos += n;
+ curpos += n;
if (n < diff)
- return this->curpos;
+ return curpos;
}
- return this->curpos;
+ return curpos;
}
static off_t mms_plugin_get_length (input_plugin_t *this_gen) {
@@ -235,12 +237,21 @@ static uint32_t mms_plugin_get_blocksize (input_plugin_t *this_gen) {
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;
+
/*
printf ("current pos is %lld\n", this->curpos);
*/
+ switch (this->protocol) {
+ case PROTOCOL_MMST:
+ curpos = mms_get_current_pos(this->mms);
+ break;
+ case PROTOCOL_MMSH:
+ curpos = mmsh_get_current_pos(this->mmsh);
+ break;
+ }
- return this->curpos;
+ return curpos;
}
static void mms_plugin_dispose (input_plugin_t *this_gen) {
@@ -351,7 +362,6 @@ static int mms_plugin_open (input_plugin_t *this_gen) {
this->mms = mms;
this->mmsh = mmsh;
- this->curpos = 0;
return 1;
}
@@ -385,7 +395,6 @@ static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stre
this->mmsh = NULL;
this->protocol = protocol;
this->mrl = mrl;
- this->curpos = 0;
this->nbc = nbc_init (this->stream);
if (xine_config_lookup_entry (stream->xine, "input.mms_network_bandwidth",
diff --git a/src/input/mms.c b/src/input/mms.c
index a101e1324..e5e4ce027 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.43 2004/04/04 12:19:06 tmattern Exp $
+ * $Id: mms.c,v 1.44 2004/04/06 00:25:29 tmattern Exp $
*
* MMS over TCP protocol
* based on work from major mms
@@ -25,7 +25,7 @@
*
* TODO:
* general cleanup, error messages
- * allways check packet size
+ * always check packet size
* enable seeking !
*/
@@ -126,6 +126,7 @@ struct mms_s {
int has_audio;
int has_video;
int live_flag;
+ off_t current_pos;
};
@@ -487,6 +488,7 @@ static void interp_header (mms_t *this) {
/*
* parse header
*/
+
i = 30;
while (i < this->asf_header_len) {
@@ -804,6 +806,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
this->has_audio = 0;
this->has_video = 0;
this->bandwidth = bandwidth;
+ this->current_pos = 0;
report_progress (stream, 0);
@@ -963,6 +966,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) {
#endif
lprintf("mms_connect: passed\n" );
+
return this;
fail:
@@ -1007,10 +1011,16 @@ static int get_media_packet (mms_t *this) {
if (pre_header[4] == 0x04) {
- uint32_t packet_len;
+ uint32_t packet_len, sequence;
- packet_len = (pre_header[7] << 8 | pre_header[6]) - 8;
+ 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 = this->asf_header_len + sequence * 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,
@@ -1109,6 +1119,7 @@ static int get_media_packet (mms_t *this) {
"failed to send command 0x07\n");
return 0;
}
+ this->current_pos = 0;
} else if (command != 0x05) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
@@ -1157,6 +1168,7 @@ int mms_read (mms_t *this, char *data, int len) {
this->asf_header_read += n;
total += n;
+ this->current_pos += n;
} else {
int n, bytes_left ;
@@ -1181,6 +1193,7 @@ int mms_read (mms_t *this, char *data, int len) {
this->buf_read += n;
total += n;
+ this->current_pos += n;
}
}
return total;
@@ -1210,3 +1223,7 @@ void mms_close (mms_t *this) {
uint32_t mms_get_length (mms_t *this) {
return this->file_length;
}
+
+off_t mms_get_current_pos (mms_t *this) {
+ return this->current_pos;
+}
diff --git a/src/input/mms.h b/src/input/mms.h
index b18a90f45..3c1b4af81 100644
--- a/src/input/mms.h
+++ b/src/input/mms.h
@@ -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.h,v 1.10 2003/12/09 00:02:30 f1rmb Exp $
+ * $Id: mms.h,v 1.11 2004/04/06 00:25:29 tmattern Exp $
*
* libmms public header
*/
@@ -39,5 +39,7 @@ void mms_close (mms_t *this);
int mms_peek_header (mms_t *this, char *data, int maxsize);
+off_t mms_get_current_pos (mms_t *this);
+
#endif
diff --git a/src/input/mmsh.c b/src/input/mmsh.c
index 425b957f8..67c2dc7fa 100644
--- a/src/input/mmsh.c
+++ b/src/input/mmsh.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: mmsh.c,v 1.27 2004/01/23 00:01:15 valtri Exp $
+ * $Id: mmsh.c,v 1.28 2004/04/06 00:25:29 tmattern Exp $
*
* MMS over HTTP protocol
* written by Thibaut Mattern
@@ -53,7 +53,6 @@
/*
#define LOG
*/
-
#include "xine_internal.h"
#include "xineutils.h"
@@ -113,8 +112,6 @@ static const char* mmsh_LiveRequest =
"Pragma: stream-switch-entry=%s\r\n"
"Connection: Close\r\n\r\n";
-
-#if 0
/* Unused requests */
static const char* mmsh_PostRequest =
"POST %s HTTP/1.0\r\n"
@@ -122,7 +119,8 @@ static const char* mmsh_PostRequest =
USERAGENT
"Host: %s\r\n"
"Pragma: client-id=%u\r\n"
-/* "Pragma: log-line=no-cache,rate=1.000000,stream-time=%u,stream-offset=%u:%u,request-context=2,max-duration=%u\r\n" */
+/* "Pragma: log-line=no-cache,rate=1.000000,stream-time=%u,stream-offset=%u:%u,request-context=2,max-duration=%u\r\n"
+ */
"Pragma: Content-Length: 0\r\n"
CLIENTGUID
"\r\n";
@@ -135,7 +133,6 @@ static const char* mmsh_RangeRequest =
"Range: bytes=%Lu-\r\n"
CLIENTGUID
"Connection: Close\r\n\r\n";
-#endif
@@ -169,7 +166,6 @@ struct mmsh_s {
uint16_t chunk_type;
uint16_t chunk_length;
uint16_t chunk_seq_number;
- int chunk_eos;
uint8_t buf[CHUNK_SIZE];
int buf_size;
@@ -190,6 +186,9 @@ struct mmsh_s {
int has_audio;
int has_video;
+
+ off_t current_pos;
+ int user_bandwitdh;
};
static int get_guid (unsigned char *buffer, int offset) {
@@ -345,22 +344,25 @@ static int get_chunk_header (mmsh_t *this) {
this->chunk_type = LE_16 (chunk_header);
this->chunk_length = LE_16 (chunk_header + 2) - 8;
this->chunk_seq_number = LE_32 (chunk_header + 4);
-
+
+
/* display debug infos */
#ifdef LOG
switch (this->chunk_type) {
case CHUNK_TYPE_DATA:
printf ("libmmsh: chunk type: CHUNK_TYPE_DATA\n");
+ printf ("libmmsh: chunk length: %d\n", this->chunk_length);
+ printf ("libmmsh: chunk seq: %d\n", this->chunk_seq_number);
break;
case CHUNK_TYPE_END:
printf ("libmmsh: chunk type: CHUNK_TYPE_END\n");
+ printf ("libmmsh: continue: %d\n", this->chunk_seq_number);
break;
case CHUNK_TYPE_ASF_HEADER:
printf ("libmmsh: chunk type: CHUNK_TYPE_ASF_HEADER\n");
+ printf ("libmmsh: chunk length: %d\n", this->chunk_length);
break;
}
- printf ("libmmsh: chunk length: %d\n", this->chunk_length);
- printf ("libmmsh: chunk seq_number: %d\n", this->chunk_seq_number);
#endif
return 1;
@@ -372,7 +374,8 @@ static int get_header (mmsh_t *this) {
lprintf("get_header\n");
this->asf_header_len = 0;
-
+ this->asf_header_read = 0;
+
/* read chunk */
while (1) {
if (get_chunk_header(this)) {
@@ -411,7 +414,7 @@ static void interp_header (mmsh_t *this) {
int i;
- lprintf ("interp_header\n");
+ lprintf ("interp_header, header_len=%d\n", this->asf_header_len);
this->packet_length = 0;
@@ -585,8 +588,8 @@ static int mmsh_tcp_connect(mmsh_t *this) {
return 0;
}
-mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
- mmsh_t *this;
+
+static int mmsh_connect_int(mmsh_t *this, int bandwidth) {
int i;
int video_stream = -1;
int audio_stream = -1;
@@ -597,49 +600,11 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
int bandwitdh_left;
char stream_selection[10 * ASF_MAX_NUM_STREAMS]; /* 10 chars per stream */
int offset;
-
- if (!url)
- return NULL;
-
- report_progress (stream, 0);
-
- this = (mmsh_t*) xine_xmalloc (sizeof (mmsh_t));
-
- this->stream = stream;
- this->url = strdup(url);
- this->s = -1;
- this->asf_header_len = 0;
- this->asf_header_read = 0;
- this->num_stream_ids = 0;
- this->packet_length = 0;
- this->buf_size = 0;
- this->buf_read = 0;
- this->has_audio = 0;
- this->has_video = 0;
- this->chunk_eos = 0;
-
- report_progress (stream, 0);
-
- if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port,
- &this->user, &this->password, &this->uri)) {
- xine_log (this->stream->xine, XINE_LOG_MSG, _("invalid url\n"));
- goto fail;
- }
-
- if (!mmsh_valid_proto(this->proto)) {
- xine_log (this->stream->xine, XINE_LOG_MSG, _("unsupported protocol\n"));
- goto fail;
- }
-
- if (mmsh_tcp_connect(this)) {
- goto fail;
- }
- report_progress (stream, 30);
-
/*
* let the negotiations begin...
*/
-
+ this->num_stream_ids = 0;
+
/* first request */
lprintf("first http request\n");
@@ -657,7 +622,7 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
interp_header(this);
close(this->s);
- report_progress (stream, 20);
+ report_progress (this->stream, 20);
/* choose the best quality for the audio stream */
@@ -769,7 +734,8 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
if (!get_answer (this))
goto fail;
- get_header(this);
+ if (!get_header(this))
+ goto fail;
interp_header(this);
for (i = 0; i < this->num_stream_ids; i++) {
@@ -784,9 +750,59 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
this->asf_header[this->bitrates_pos[this->stream_ids[i]] + 3] = 0;
}
}
+ return 1;
+
+fail:
+ return 0;
+}
- report_progress (stream, 100);
+mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) {
+ mmsh_t *this;
+
+ if (!url)
+ return NULL;
+
+ report_progress (stream, 0);
+
+ this = (mmsh_t*) xine_xmalloc (sizeof (mmsh_t));
+
+ this->stream = stream;
+ this->url = strdup(url);
+ this->s = -1;
+ this->asf_header_len = 0;
+ this->asf_header_read = 0;
+ this->num_stream_ids = 0;
+ this->packet_length = 0;
+ this->buf_size = 0;
+ this->buf_read = 0;
+ this->has_audio = 0;
+ this->has_video = 0;
+ this->current_pos = 0;
+ this->user_bandwitdh = bandwidth;
+
+ report_progress (stream, 0);
+
+ if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port,
+ &this->user, &this->password, &this->uri)) {
+ xine_log (this->stream->xine, XINE_LOG_MSG, _("invalid url\n"));
+ goto fail;
+ }
+
+ if (!mmsh_valid_proto(this->proto)) {
+ xine_log (this->stream->xine, XINE_LOG_MSG, _("unsupported protocol\n"));
+ goto fail;
+ }
+
+ if (mmsh_tcp_connect(this))
+ goto fail;
+
+ report_progress (stream, 30);
+
+ if (!mmsh_connect_int(this, this->user_bandwitdh))
+ goto fail;
+ report_progress (stream, 100);
+
lprintf("mmsh_connect: passed\n" );
return this;
@@ -820,11 +836,31 @@ static int get_media_packet (mmsh_t *this) {
lprintf("get_media_packet: this->packet_length: %d\n", this->packet_length);
- if (!this->chunk_eos && get_chunk_header(this)) {
+ if (get_chunk_header(this)) {
switch (this->chunk_type) {
case CHUNK_TYPE_END:
- this->chunk_eos = 1;
+ /* this->chunk_seq_number:
+ * 0: stop
+ * 1: a new stream follows
+ */
+ if (this->chunk_seq_number == 0) {
+ return 0;
+ } else {
+ close(this->s);
+
+ if (mmsh_tcp_connect(this))
+ return 0;
+
+ if (!mmsh_connect_int(this, this->user_bandwitdh))
+ return 0;
+
+ this->current_pos = 0;
+ this->buf_size = 0;
+ return 1;
+ }
+ break;
case CHUNK_TYPE_DATA:
+ this->current_pos = this->asf_header_len + this->chunk_seq_number * this->packet_length;
break;
default:
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
@@ -884,6 +920,7 @@ int mmsh_read (mmsh_t *this, char *data, int len) {
this->asf_header_read += n;
total += n;
+ this->current_pos += n;
} else {
int n, bytes_left ;
@@ -891,24 +928,25 @@ int mmsh_read (mmsh_t *this, char *data, int len) {
bytes_left = this->buf_size - this->buf_read;
if (bytes_left == 0) {
- this->buf_read = 0;
- if (!get_media_packet (this)) {
+ this->buf_read = 0;
+ if (!get_media_packet (this)) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "libmmsh: get_media_packet failed\n");
- return total;
- }
- bytes_left = this->buf_size;
+ "libmmsh: get_media_packet failed\n");
+ return total;
+ }
+ bytes_left = this->buf_size;
}
- if ((len-total) < bytes_left)
- n = len-total;
+ if ((len - total) < bytes_left)
+ n = len - total;
else
- n = bytes_left;
+ n = bytes_left;
xine_fast_memcpy (&data[total], &this->buf[this->buf_read], n);
this->buf_read += n;
total += n;
+ this->current_pos += n;
}
}
return total;
@@ -941,3 +979,7 @@ void mmsh_close (mmsh_t *this) {
uint32_t mmsh_get_length (mmsh_t *this) {
return this->file_length;
}
+
+off_t mmsh_get_current_pos (mmsh_t *this) {
+ return this->current_pos;
+}
diff --git a/src/input/mmsh.h b/src/input/mmsh.h
index 756629ee1..4ae838526 100644
--- a/src/input/mmsh.h
+++ b/src/input/mmsh.h
@@ -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: mmsh.h,v 1.3 2003/12/09 00:02:30 f1rmb Exp $
+ * $Id: mmsh.h,v 1.4 2004/04/06 00:25:29 tmattern Exp $
*
* libmmsh public header
*/
@@ -39,4 +39,6 @@ void mmsh_close (mmsh_t *this);
int mmsh_peek_header (mmsh_t *this, char *data, int maxsize);
+off_t mmsh_get_current_pos (mmsh_t *this);
+
#endif