summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/demux_asf.c952
1 files changed, 567 insertions, 385 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index f1b1428ea..04484d91d 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.118 2003/05/27 15:20:01 jstembridge Exp $
+ * $Id: demux_asf.c,v 1.119 2003/06/12 23:10:16 tmattern Exp $
*
* demultiplexer for asf streams
*
@@ -45,9 +45,9 @@
#include "asfheader.h"
#include "xmlparser.h"
-/*
+
#define LOG
-*/
+
#define CODEC_TYPE_AUDIO 0
#define CODEC_TYPE_VIDEO 1
@@ -75,6 +75,8 @@ typedef struct {
fifo_buffer_t *fifo;
uint8_t *buffer;
+ int skip;
+ int resync;
} asf_stream_t;
typedef struct demux_asf_s {
@@ -87,8 +89,7 @@ typedef struct demux_asf_s {
input_plugin_t *input;
- int keyframe_found;
-
+ int64_t keyframe_ts;
int seqno;
uint32_t packet_size;
uint8_t packet_flags;
@@ -122,7 +123,6 @@ typedef struct demux_asf_s {
int packet_size_left;
/* frame rate calculations, discontinuity detection */
-
int64_t last_pts[2];
int32_t frame_duration;
int send_newpts;
@@ -149,6 +149,7 @@ typedef struct demux_asf_s {
int64_t first_packet_pos;
int reference_mode;
+
} demux_asf_t ;
typedef struct {
@@ -323,7 +324,7 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->decoder_flags = BUF_FLAG_HEADER;
- buf->decoder_info[1] = 3000; /* FIXME ? */
+ buf->decoder_info[1] = 3000; /* FIXME ! */
memcpy (buf->content, &this->bih, this->bih_size);
buf->size = this->bih_size;
buf->type = this->streams[stream].buf_type ;
@@ -389,7 +390,7 @@ static int asf_read_header (demux_asf_t *this) {
{
int type;
uint32_t total_size, stream_data_size;
- uint16_t stream_id;
+ uint16_t stream_id;
uint64_t pos1, pos2;
xine_bmiheader *bih = (xine_bmiheader *) this->bih;
xine_waveformatex *wavex = (xine_waveformatex *) this->wavex ;
@@ -606,104 +607,6 @@ static void asf_reorder(demux_asf_t *this, uint8_t *src, int len){
free(dst);
}
-static uint32_t asf_get_packet(demux_asf_t *this) {
-
- int64_t timestamp;
- int duration;
- uint8_t ecd_flags;
- uint8_t buf[16];
- uint32_t p_hdr_size;
- int invalid_packet;
-
- do {
- ecd_flags = get_byte(this); p_hdr_size = 1;
- invalid_packet = 0;
-
- /* skip ecd */
- if (ecd_flags & 0x80)
- p_hdr_size += this->input->read (this->input, buf, ecd_flags & 0x0F);
-
- /* skip invalid packet */
- if (ecd_flags & 0x70) {
-#ifdef LOG
- printf("demux_asf: skip invalid packet: %d\n", ecd_flags);
-#endif
- this->input->seek (this->input, this->packet_size - p_hdr_size, SEEK_CUR);
- invalid_packet = 1;
- }
-
- if( this->status != DEMUX_OK )
- return 0;
-
- } while (invalid_packet);
-
- if( this->status != DEMUX_OK )
- return 0;
-
- this->packet_flags = get_byte(this); p_hdr_size += 1;
- this->segtype = get_byte(this); p_hdr_size += 1;
-
- /* packet size */
- switch((this->packet_flags >> 5) & 3) {
- case 1:
- this->data_size = get_byte(this); p_hdr_size += 1; break;
- case 2:
- this->data_size = get_le16(this); p_hdr_size += 2; break;
- case 3:
- this->data_size = get_le32(this); p_hdr_size += 4; break;
- default:
- this->data_size = 0;
- }
-
- /* sequence */
- switch ((this->packet_flags >> 1) & 3) {
- case 1:
- get_byte(this); p_hdr_size += 1; break;
- case 2:
- get_le16(this); p_hdr_size += 2; break;
- case 3:
- get_le32(this); p_hdr_size += 4; break;
- }
-
- /* padding size */
- switch ((this->packet_flags >> 3) & 3){
- case 1:
- this->packet_padsize = get_byte(this); p_hdr_size += 1; break;
- case 2:
- this->packet_padsize = get_le16(this); p_hdr_size += 2; break;
- case 3:
- this->packet_padsize = get_le32(this); p_hdr_size += 4; break;
- default:
- this->packet_padsize = 0;
- }
-
- timestamp = get_le32(this); p_hdr_size += 4;
- duration = get_le16(this); p_hdr_size += 2;
-
- if ((this->packet_flags >> 5) & 3) {
- /* absolute data size */
-#ifdef LOG
- printf ("demux_asf: absolute data size\n");
-#endif
- this->packet_padsize = this->packet_size - this->data_size; /* not used */
- } else {
- /* relative data size */
-#ifdef LOG
- printf ("demux_asf: relative data size\n");
-#endif
- this->data_size = this->packet_size - this->packet_padsize;
- }
-
- /* this->packet_size_left = this->packet_size - p_hdr_size; */
- this->packet_size_left = this->data_size - p_hdr_size;
-#ifdef LOG
- printf ("demux_asf: 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);
-#endif
-
- return 1;
-}
-
static void hexdump (unsigned char *data, int len, xine_t *xine) {
int i;
@@ -745,7 +648,6 @@ static void check_newpts (demux_asf_t *this, int64_t pts, int video, int frame_e
/*
* frame rate estimation
*/
-
if (pts && video && frame_end) {
if (this->last_frame_pts) {
@@ -777,7 +679,11 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
buf_element_t *buf;
int bufsize;
int package_done;
+ int send_ts = 1;
+#ifdef LOG
+ printf ("demux_asf: asf_send_buffer_nodefrag: timestamp=%lld, pts=%lld\n", timestamp, timestamp * 90);
+#endif
if (stream->frag_offset == 0) {
/* new packet */
stream->seq = seq;
@@ -799,7 +705,6 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
}
}
-
while( frag_len ) {
if ( frag_len < stream->fifo->buffer_pool_buf_size )
bufsize = frag_len;
@@ -822,8 +727,12 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
buf->extra_info->input_time);
#endif
- buf->pts = timestamp * 90;
-
+ if (send_ts) {
+ buf->pts = timestamp * 90;
+ send_ts = 0;
+ } else {
+ buf->pts = 0;
+ }
buf->type = stream->buf_type;
buf->size = bufsize;
timestamp = 0;
@@ -837,7 +746,7 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
check_newpts (this, buf->pts, PTS_VIDEO, package_done);
else
check_newpts (this, buf->pts, PTS_AUDIO, package_done);
-
+
/* test if whole packet read */
if (package_done) {
@@ -855,9 +764,6 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream,
}
- if( !this->keyframe_found && ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) )
- buf->decoder_flags |= BUF_FLAG_PREVIEW;
-
#ifdef LOG
printf ("demux_asf: buffer type %08x %8d bytes, %8lld pts\n",
buf->type, buf->size, buf->pts);
@@ -877,81 +783,88 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream,
printf("asf_send_buffer seq=%d frag_offset=%d frag_len=%d\n",
seq, frag_offset, frag_len );
*/
+#ifdef LOG
+ printf ("demux_asf: asf_send_buffer_defrag: timestamp=%lld, pts=%lld\n", timestamp, timestamp * 90);
+#endif
if (stream->frag_offset == 0) {
/* new packet */
stream->seq = seq;
+ stream->timestamp = timestamp;
} else {
if (seq == stream->seq &&
- frag_offset == stream->frag_offset) {
+ frag_offset == stream->frag_offset) {
/* continuing packet */
} else {
/* cannot continue current packet: free it */
if( stream->frag_offset )
- {
- int bufsize;
- uint8_t *p;
-
- if (stream->fifo == this->audio_fifo &&
- this->reorder_h > 1 && this->reorder_w > 1 ) {
- asf_reorder(this,stream->buffer,stream->frag_offset);
- }
-
- p = stream->buffer;
- while( stream->frag_offset ) {
- if ( stream->frag_offset < stream->fifo->buffer_pool_buf_size )
- bufsize = stream->frag_offset;
- else
- bufsize = stream->fifo->buffer_pool_buf_size;
-
- buf = stream->fifo->buffer_pool_alloc (stream->fifo);
- xine_fast_memcpy (buf->content, p, bufsize);
-
- buf->extra_info->input_pos = this->input->get_current_pos (this->input);
- if (this->rate)
- buf->extra_info->input_time = (int)((int64_t)buf->extra_info->input_pos
- * 1000 / this->rate);
- else
- buf->extra_info->input_time = 0;
-
- buf->pts = stream->timestamp * 90 + stream->ts_per_kbyte *
- (p-stream->buffer) / 1024;
-
- buf->type = stream->buf_type;
- buf->size = bufsize;
-
+ {
+ int bufsize;
+ uint8_t *p;
+
+ if (stream->fifo == this->audio_fifo &&
+ this->reorder_h > 1 && this->reorder_w > 1 ) {
+ asf_reorder(this,stream->buffer,stream->frag_offset);
+ }
+
+ p = stream->buffer;
+ while( stream->frag_offset ) {
+ if ( stream->frag_offset < stream->fifo->buffer_pool_buf_size )
+ bufsize = stream->frag_offset;
+ else
+ bufsize = stream->fifo->buffer_pool_buf_size;
+
+ buf = stream->fifo->buffer_pool_alloc (stream->fifo);
+ xine_fast_memcpy (buf->content, p, bufsize);
+
+ buf->extra_info->input_pos = this->input->get_current_pos (this->input);
+ if (this->rate)
+ buf->extra_info->input_time = (int)((int64_t)buf->extra_info->input_pos
+ * 1000 / this->rate);
+ else
+ buf->extra_info->input_time = 0;
+
+
+ buf->pts = stream->timestamp * 90 + stream->ts_per_kbyte *
+ (p-stream->buffer) / 1024;
+/*
+ if (p == stream->buffer)
+ buf->pts = timestamp * 90;
+ else
+ buf->pts = 0;
+ */
+ buf->type = stream->buf_type;
+ buf->size = bufsize;
+
#ifdef LOG
- printf ("demux_asf: buffer type %08x %8d bytes, %8lld pts\n",
- buf->type, buf->size, buf->pts);
+ printf ("demux_asf: buffer type %08x %8d bytes, %8lld pts\n",
+ buf->type, buf->size, buf->pts);
#endif
-
- stream->frag_offset -= bufsize;
- p+=bufsize;
-
- if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
- check_newpts (this, buf->pts, PTS_VIDEO, !stream->frag_offset);
- else
- check_newpts (this, buf->pts, PTS_AUDIO, !stream->frag_offset);
-
- /* test if whole packet read */
- if ( !stream->frag_offset )
- buf->decoder_flags |= BUF_FLAG_FRAME_END;
-
- if( !this->keyframe_found && ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) )
- buf->decoder_flags |= BUF_FLAG_PREVIEW;
-
- stream->fifo->put (stream->fifo, buf);
- }
- }
+
+ stream->frag_offset -= bufsize;
+ p+=bufsize;
+
+ if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
+ check_newpts (this, buf->pts, PTS_VIDEO, !stream->frag_offset);
+ else
+ check_newpts (this, buf->pts, PTS_AUDIO, !stream->frag_offset);
+
+ /* test if whole packet read */
+ if ( !stream->frag_offset )
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
+
+ stream->fifo->put (stream->fifo, buf);
+ }
+ }
stream->frag_offset = 0;
if (frag_offset != 0) {
- /* cannot create new packet */
- this->input->seek (this->input, frag_len, SEEK_CUR);
- return ;
+ /* cannot create new packet */
+ this->input->seek (this->input, frag_len, SEEK_CUR);
+ return ;
} else {
- /* create new packet */
- stream->seq = seq;
+ /* create new packet */
+ stream->seq = seq;
}
}
}
@@ -967,303 +880,433 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream,
if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) {
printf ("demux_asf: buffer overflow on defrag!\n");
- }
- else {
+ } else {
this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len);
stream->frag_offset += frag_len;
}
}
-static void asf_read_packet(demux_asf_t *this) {
+/* return 0 of ok */
+static int asf_parse_packet_header(demux_asf_t *this, uint8_t *raw_id) {
- uint8_t raw_id, stream_id;
- uint32_t seq, frag_offset, payload_size, frag_len, rlen;
- int i;
- int64_t timestamp;
- asf_stream_t *stream;
- uint32_t s_hdr_size = 0;
- uint64_t current_pos;
- uint32_t mod;
- uint32_t psl;
-
- if ((++this->frame == (this->nb_frames & 0x3f)) ) {
- psl = this->packet_size_left;
- 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;
+ int64_t timestamp;
+ int duration;
+ uint8_t ecd_flags;
+ uint8_t buf[16];
+ uint32_t p_hdr_size;
+ int invalid_packet;
+ uint64_t current_pos, packet_pos;
+ uint32_t mod, rsize;
+
+ /* 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) {
+ 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;
+ do {
+ ecd_flags = get_byte(this); p_hdr_size = 1;
+ if (this->status == DEMUX_FINISHED)
+ return 1;
+ invalid_packet = 0;
+ /* skip ecd */
+ if (ecd_flags & 0x80) {
+ rsize = this->input->read (this->input, buf, ecd_flags & 0x0F);
+ if (rsize != (ecd_flags & 0x0F)) {
+ this->status = DEMUX_FINISHED;
+ return 1;
+ }
+ p_hdr_size += rsize;
+ }
+ /* skip invalid packet */
+ if (ecd_flags & 0x70) {
#ifdef LOG
- printf ("demux_asf: reading new packet, packet size left psl=%d, pad=%d, %d\n", psl, this->packet_padsize, this->packet_size_left);
+ printf("demux_asf: skip invalid packet: %d\n", ecd_flags);
#endif
+ this->input->seek (this->input, this->packet_size - p_hdr_size, SEEK_CUR);
+ invalid_packet = 1;
+ }
+ } while (invalid_packet);
- if (this->packet_size_left)
- this->input->seek (this->input, this->packet_size_left, SEEK_CUR);
+ this->packet_flags = get_byte(this); p_hdr_size += 1;
+ this->segtype = get_byte(this); p_hdr_size += 1;
- if (!asf_get_packet(this)) {
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: get_packet failed\n");
- this->status = DEMUX_FINISHED;
- return ;
- }
+ /* packet size */
+ switch((this->packet_flags >> 5) & 3) {
+ case 1:
+ this->data_size = get_byte(this); p_hdr_size += 1; break;
+ case 2:
+ this->data_size = get_le16(this); p_hdr_size += 2; break;
+ case 3:
+ this->data_size = get_le32(this); p_hdr_size += 4; break;
+ default:
+ this->data_size = 0;
+ }
- if (this->packet_padsize > this->packet_size) {
- /* skip packet */
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: invalid padsize: %d\n", this->packet_padsize);
- this->frame = this->nb_frames - 1;
- return;
- }
+ /* sequence */
+ switch ((this->packet_flags >> 1) & 3) {
+ case 1:
+ get_byte(this); p_hdr_size += 1; break;
+ case 2:
+ get_le16(this); p_hdr_size += 2; break;
+ case 3:
+ get_le32(this); p_hdr_size += 4; break;
+ }
- /* Multiple frames */
- this->frame = 0;
- if (this->packet_flags & 0x01) {
- this->frame_flag = get_byte(this); s_hdr_size += 1;
- this->nb_frames = this->frame_flag & 0x3F;
+ /* padding size */
+ switch ((this->packet_flags >> 3) & 3){
+ case 1:
+ this->packet_padsize = get_byte(this); p_hdr_size += 1; break;
+ case 2:
+ this->packet_padsize = get_le16(this); p_hdr_size += 2; break;
+ case 3:
+ this->packet_padsize = get_le32(this); p_hdr_size += 4; break;
+ default:
+ this->packet_padsize = 0;
+ }
+
+ timestamp = get_le32(this); p_hdr_size += 4;
+ duration = get_le16(this); p_hdr_size += 2;
#ifdef LOG
- printf ("demux_asf: multiple frames %d\n", this->nb_frames);
+ printf ("demux_asf: timestamp=%lld, duration=%hd\n", timestamp, duration);
#endif
- } else {
- this->frame_flag = 0;
- this->nb_frames = 1;
- }
+
+ if ((this->packet_flags >> 5) & 3) {
+ /* absolute data size */
+#ifdef LOG
+ printf ("demux_asf: absolute data size\n");
+#endif
+ this->packet_padsize = this->packet_size - this->data_size; /* not used */
+ } else {
+ /* relative data size */
+#ifdef LOG
+ printf ("demux_asf: relative data size\n");
+#endif
+ this->data_size = this->packet_size - this->packet_padsize;
}
- /* read segment header, find stream */
- raw_id = get_byte(this); s_hdr_size += 1;
- stream_id = raw_id & 0x7f;
+ if (this->packet_padsize > this->packet_size) {
+ /* skip packet */
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: invalid padsize: %d\n", this->packet_padsize);
+ return 1;
+ }
+
+ /* Multiple frames */
+ if (this->packet_flags & 0x01) {
+ this->frame_flag = get_byte(this); p_hdr_size += 1;
+ this->nb_frames = (this->frame_flag & 0x3F);
+#ifdef LOG
+ printf ("demux_asf: multiple frames %d\n", this->nb_frames);
+#endif
+ } else {
+ this->frame_flag = 0;
+ this->nb_frames = 1;
+ }
- stream = NULL;
+ /* this->packet_size_left = this->packet_size - p_hdr_size; */
+ this->packet_size_left = this->data_size - p_hdr_size;
#ifdef LOG
- printf ("demux_asf: got raw_id =%d keyframe_found=%d\n", raw_id, this->keyframe_found);
+ printf ("demux_asf: 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);
#endif
- if ( (raw_id & 0x80) || this->keyframe_found || (stream_id == this->audio_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)) {
- stream = &this->streams[i];
- }
+ return 0;
+}
+
+/* return 0 if ok */
+static int asf_parse_packet_payload_common(demux_asf_t *this,
+ uint8_t raw_id,
+ asf_stream_t **stream,
+ uint32_t *frag_offset,
+ uint32_t *rlen,
+ uint32_t *seq) {
+
+ uint8_t stream_id;
+ int i;
+ uint32_t s_hdr_size = 0;
+
+ stream_id = raw_id & 0x7f;
+ *stream = NULL;
+#ifdef LOG
+ printf ("demux_asf: got raw_id=%d\n", raw_id);
+#endif
+
+ 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)) {
+ *stream = &this->streams[i];
}
#ifdef LOG
- /* display control stream content */
+ /* display "control stream" content */
if (stream_id == this->control_stream_id) {
printf("demux_asf: Control Stream : begin\n");
for (i = 0; i < (this->packet_size_left - s_hdr_size); i++){
printf("%c", get_byte(this));
}
printf("\ndemux_asf: Control Stream : end\n");
- return;
+ return 1;
}
#endif
}
switch ((this->segtype >> 4) & 3){
case 1:
- seq = get_byte(this); s_hdr_size += 1; break;
+ *seq = get_byte(this); s_hdr_size += 1; break;
case 2:
- seq = get_le16(this); s_hdr_size += 2; break;
+ *seq = get_le16(this); s_hdr_size += 2; break;
case 3:
- seq = get_le32(this); s_hdr_size += 4; break;
+ *seq = get_le32(this); s_hdr_size += 4; break;
default:
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+#ifdef LOG
printf ("demux_asf: seq=0\n");
- seq = 0;
+#endif
+ *seq = 0;
}
switch ((this->segtype >> 2) & 3) {
case 1:
- frag_offset = get_byte(this); s_hdr_size += 1; break;
+ *frag_offset = get_byte(this); s_hdr_size += 1; break;
case 2:
- frag_offset = get_le16(this); s_hdr_size += 2; break;
+ *frag_offset = get_le16(this); s_hdr_size += 2; break;
case 3:
- frag_offset = get_le32(this); s_hdr_size += 4; break;
+ *frag_offset = get_le32(this); s_hdr_size += 4; break;
default:
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: frag_offset=0\n");
- frag_offset = 0;
+#ifdef LOG
+ printf ("demux_asf: frag_offset=0\n");
+#endif
+ *frag_offset = 0;
}
- /* only set keyframe_found if we have it's beginning */
- if( (raw_id & 0x80) && stream && !frag_offset )
- this->keyframe_found = 1;
-
switch (this->segtype & 3) {
case 1:
- rlen = get_byte(this); s_hdr_size += 1; break;
+ *rlen = get_byte(this); s_hdr_size += 1; break;
case 2:
- rlen = get_le16(this); s_hdr_size += 2; break;
+ *rlen = get_le16(this); s_hdr_size += 2; break;
case 3:
- rlen = get_le32(this); s_hdr_size += 4; break;
+ *rlen = get_le32(this); s_hdr_size += 4; break;
default:
- rlen = 0;
+ *rlen = 0;
}
- if (rlen > this->packet_size_left) {
+ if (*rlen > this->packet_size_left) {
/* skip packet */
if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: invalid rlen %d\n", rlen);
- this->frame = this->nb_frames - 1;
- return;
+ printf ("demux_asf: invalid rlen %d\n", *rlen);
+ return 1;
}
#ifdef LOG
- printf ("demux_asf: segment header, stream id %02x, frag_offset %d, flags : %02x\n",
- stream_id, frag_offset, rlen);
+ printf ("demux_asf: segment header, stream id %02x, frag_offset %d, flags : %02x\n",
+ stream_id, *frag_offset, *rlen);
#endif
+ this->packet_size_left -= s_hdr_size;
+ return 0;
+}
- if (rlen == 1) {
- int data_length, data_sent=0;
-
- /* multiple part segment */
- timestamp = frag_offset;
- get_byte (this); s_hdr_size += 1;
-
- if (this->packet_flags & 0x01) {
- /* multiple frames */
- switch ((this->frame_flag >> 6) & 3) {
- case 1:
- data_length = get_byte(this); s_hdr_size += 1; break;
- case 2:
- data_length = get_le16(this); s_hdr_size += 2; break;
- case 3:
- data_length = get_le32(this); s_hdr_size += 4; break;
- default:
+/* return 0 if ok */
+static int asf_parse_packet_payload_single(demux_asf_t *this,
+ asf_stream_t *stream,
+ uint32_t frag_offset,
+ uint32_t seq,
+ int64_t *timestamp) {
+ uint32_t s_hdr_size = 0;
+ uint32_t data_length = 0;
+ uint32_t data_sent=0;
+
+ printf ("demux_asf: asf_parse_packet_payload_single\n");
+ *timestamp = frag_offset;
+ frag_offset = 0;
+ get_byte (this); s_hdr_size += 1;
+
+ if (this->packet_flags & 0x01) {
+ /* multiple frames */
+ switch ((this->frame_flag >> 6) & 3) {
+ case 1:
+ data_length = get_byte(this); s_hdr_size += 1; break;
+ case 2:
+ data_length = get_le16(this); s_hdr_size += 2; break;
+ case 3:
+ data_length = get_le32(this); s_hdr_size += 4; break;
+ default:
#ifdef LOG
- printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
+ printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
#endif
- data_length = get_le16(this); s_hdr_size += 2;
- }
+ data_length = get_le16(this); s_hdr_size += 2;
+ }
#ifdef LOG
- printf ("demux_asf: reading grouping part segment, size = %d\n", data_length);
+ printf ("demux_asf: reading grouping part segment, size = %d\n", data_length);
#endif
- } else {
- data_length = this->packet_size_left - s_hdr_size;
+ } else {
+ data_length = this->packet_size_left - s_hdr_size;
#ifdef LOG
- printf ("demux_asf: reading grouping single segment, size = %d\n", data_length);
+ printf ("demux_asf: reading grouping single segment, size = %d\n", data_length);
#endif
- }
+ }
- if (data_length > this->packet_size_left) {
- /* skip packet */
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: invalid data_length\n");
- this->frame = this->nb_frames - 1;
- return;
- }
+ if (data_length > this->packet_size_left) {
+ /* skip packet */
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: invalid data_length\n");
+ return 1;
+ }
- this->packet_size_left -= s_hdr_size;
+ this->packet_size_left -= s_hdr_size;
- while (data_sent < data_length) {
- int object_length = get_byte(this);
+ while (data_sent < data_length) {
+ int object_length = get_byte(this);
#ifdef LOG
- printf ("demux_asf: sending grouped object, len = %d\n", object_length);
+ printf ("demux_asf: sending grouped object, len = %d\n", object_length);
#endif
- if (stream && stream->fifo) {
-#ifdef LOG
+ if (stream && stream->fifo) {
+ if (stream->resync && (*timestamp >= this->keyframe_ts)) {
+ printf ("demux_asf: stream resynced\n");
+ stream->resync = 0;
+ stream->skip = 0;
+ }
+
+ if (!stream->skip) {
+ #ifdef LOG
printf ("demux_asf: sending buffer of type %08x\n", stream->buf_type);
-#endif
-
+ #endif
+
if (stream->defrag)
- asf_send_buffer_defrag (this, stream, 0, seq, timestamp,
+ asf_send_buffer_defrag (this, stream, 0, seq, *timestamp,
object_length, object_length);
else
- asf_send_buffer_nodefrag (this, stream, 0, seq, timestamp,
+ asf_send_buffer_nodefrag (this, stream, 0, seq, *timestamp,
object_length, object_length);
} else {
-#ifdef LOG
- printf ("demux_asf: unhandled stream type, id %d\n", stream_id);
-#endif
+ #ifdef LOG
+ printf ("demux_asf: skip object\n");
+ #endif
this->input->seek (this->input, object_length, SEEK_CUR);
}
- seq++;
- data_sent += object_length + 1;
- this->packet_size_left -= object_length + 1;
- timestamp = 0;
+ } else {
+#ifdef LOG
+ printf ("demux_asf: unhandled stream type\n");
+#endif
+ this->input->seek (this->input, object_length, SEEK_CUR);
}
+ seq++;
+ data_sent += object_length + 1;
+ this->packet_size_left -= object_length + 1;
+ *timestamp = 0;
+ }
+ *timestamp = frag_offset;
+ return 0;
+}
+/* return 0 if ok */
+static int asf_parse_packet_payload_multiple(demux_asf_t *this,
+ asf_stream_t *stream,
+ uint32_t frag_offset,
+ uint32_t rlen,
+ uint32_t seq,
+ int64_t *timestamp) {
+ uint32_t s_hdr_size = 0;
+ uint32_t payload_size, frag_len;
+
+ printf ("demux_asf: asf_parse_packet_payload_multiple\n");
+ if (rlen >= 8) {
+ payload_size = get_le32(this); s_hdr_size += 4;
+ *timestamp = get_le32(this); s_hdr_size += 4;
+ this->input->seek (this->input, rlen - 8, SEEK_CUR);
+ s_hdr_size += rlen - 8;
} else {
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: strange rlen %d\n", rlen);
+ *timestamp = 0;
+ payload_size = 0;
+ this->input->seek (this->input, rlen, SEEK_CUR);
+ s_hdr_size += rlen;
+ }
- /* single part segment */
- if (rlen >= 8) {
- payload_size = get_le32(this); s_hdr_size += 4;
- timestamp = get_le32(this); s_hdr_size += 4;
- this->input->seek (this->input, rlen - 8, SEEK_CUR);
- s_hdr_size += rlen - 8;
- } else {
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: strange rlen %d\n", rlen);
- timestamp = 0;
- payload_size = 0;
- this->input->seek (this->input, rlen, SEEK_CUR);
- s_hdr_size += rlen;
- }
-
- if (this->packet_flags & 0x01) {
- switch ((this->frame_flag >> 6) & 3) {
- case 1:
- frag_len = get_byte(this); s_hdr_size += 1; break;
- case 2:
- frag_len = get_le16(this); s_hdr_size += 2; break;
- case 3:
- frag_len = get_le32(this); s_hdr_size += 4; break;
- default:
+ if (this->packet_flags & 0x01) {
+ switch ((this->frame_flag >> 6) & 3) {
+ case 1:
+ frag_len = get_byte(this); s_hdr_size += 1; break;
+ case 2:
+ frag_len = get_le16(this); s_hdr_size += 2; break;
+ case 3:
+ frag_len = get_le32(this); s_hdr_size += 4; break;
+ default:
#ifdef LOG
- printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
+ printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
#endif
- frag_len = get_le16(this); s_hdr_size += 2;
- }
+ frag_len = get_le16(this); s_hdr_size += 2;
+ }
#ifdef LOG
- printf ("demux_asf: reading part segment, size = %d\n", frag_len);
+ printf ("demux_asf: reading part segment, size = %d\n", frag_len);
#endif
- } else {
- frag_len = this->packet_size_left - s_hdr_size;
+ } else {
+ frag_len = this->packet_size_left - s_hdr_size;
#ifdef LOG
- printf ("demux_asf: reading single segment, size = %d\n", frag_len);
+ printf ("demux_asf: reading single segment, size = %d\n", frag_len);
#endif
- }
+ }
- if (frag_len > this->packet_size_left) {
- /* skip packet */
- if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
- printf ("demux_asf: invalid frag_len %d\n", frag_len);
- this->frame = this->nb_frames - 1;
- return;
- }
+ if (frag_len > this->packet_size_left) {
+ /* skip packet */
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: invalid frag_len %d\n", frag_len);
+ return 1;
+ }
- if (!payload_size) {
- payload_size = frag_len;
- }
+ if (!payload_size) {
+ payload_size = frag_len;
+ }
- this->packet_size_left -= s_hdr_size;
+ this->packet_size_left -= s_hdr_size;
- if (stream && stream->fifo) {
+ if (stream && stream->fifo) {
+ if (stream->resync && (*timestamp >= this->keyframe_ts) && !frag_offset) {
+ printf ("demux_asf: stream resynced\n");
+ stream->resync = 0;
+ stream->skip = 0;
+ }
+
+ if (!stream->skip) {
#ifdef LOG
- printf ("demux_asf: sending buffer of type %08x\n", stream->buf_type);
+ printf ("demux_asf: sending buffer of type %08x\n", stream->buf_type);
#endif
-
if (stream->defrag)
- asf_send_buffer_defrag (this, stream, frag_offset, seq, timestamp,
+ asf_send_buffer_defrag (this, stream, frag_offset, seq, *timestamp,
frag_len, payload_size);
else
- asf_send_buffer_nodefrag (this, stream, frag_offset, seq, timestamp,
- frag_len, payload_size);
+ asf_send_buffer_nodefrag (this, stream, frag_offset, seq, *timestamp,
+ frag_len, payload_size);
} else {
#ifdef LOG
- printf ("demux_asf: unhandled stream type, id %d\n", stream_id);
+ printf ("demux_asf: skip fragment\n");
#endif
this->input->seek (this->input, frag_len, SEEK_CUR);
}
- this->packet_size_left -= frag_len;
+ } else {
+#ifdef LOG
+ printf ("demux_asf: unhandled stream type\n");
+#endif
+ this->input->seek (this->input, frag_len, SEEK_CUR);
}
+ this->packet_size_left -= frag_len;
+ return 0;
}
/*
@@ -1534,9 +1577,14 @@ __failure:
*/
static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
-
demux_asf_t *this = (demux_asf_t *) this_gen;
-
+ asf_stream_t *stream = NULL;
+ uint32_t frag_offset = 0;
+ uint32_t rlen = 0;
+ uint32_t seq = 0;
+ uint8_t raw_id = 0;
+ int64_t ts = 0;
+
switch (this->reference_mode) {
case 1:
return demux_asf_parse_asx_references(this);
@@ -1551,7 +1599,42 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
break;
default:
- asf_read_packet (this);
+
+
+ printf ("demux_asf: demux_asf_send_chunk, %d, %d\n", ++this->frame, (this->nb_frames & 0x3f));
+ /*
+ if ((++this->frame == (this->nb_frames & 0x3f)) ) {
+ if (!asf_parse_packet_header(this, &raw_id)) {
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: get_packet failed\n");
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ } else {
+ raw_id = get_byte(this); this->packet_size_left -= 1;
+ }
+*/
+ if (asf_parse_packet_header(this, &raw_id)) {
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: get_packet failed\n");
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+
+ for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) {
+ raw_id = get_byte(this); this->packet_size_left -= 1;
+
+ printf ("demux_asf: raw_id = %d\n", raw_id);
+ if (asf_parse_packet_payload_common(this, raw_id, &stream, &frag_offset, &rlen, &seq))
+ break;
+ if (rlen == 1) {
+ if (asf_parse_packet_payload_single(this, stream, frag_offset, seq, &ts))
+ break;
+ } else {
+ if (asf_parse_packet_payload_multiple(this, stream, frag_offset, rlen, seq, &ts))
+ break;
+ }
+ }
return this->status;
}
}
@@ -1695,59 +1778,158 @@ static void demux_asf_send_headers (demux_plugin_t *this_gen) {
#endif
}
-
- this->frame = 0;
- this->nb_frames = 1;
}
static int demux_asf_seek (demux_plugin_t *this_gen,
off_t start_pos, int start_time) {
demux_asf_t *this = (demux_asf_t *) this_gen;
- int i;
-
- this->status = DEMUX_OK;
+ asf_stream_t *stream = NULL;
+ uint32_t frag_offset = 0;
+ uint32_t rlen = 0;
+ uint32_t seq = 0;
+ uint8_t raw_id, stream_id, keyframe;
+ int i, state;
+ int64_t ts;
- xine_demux_flush_engine(this->stream);
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: start_pos = %lld, start_time=%d\n",
+ start_pos, start_time);
+#endif
+ this->status = DEMUX_OK;
+
/*
* seek to start position
*/
- this->send_newpts = 1;
- this->frame = 0;
- this->nb_frames = 1;
- this->packet_size_left = 0;
- this->keyframe_found = (this->num_video_streams==0);
-
for(i = 0; i < this->num_streams; i++) {
this->streams[i].frag_offset = 0;
this->streams[i].seq = 0;
this->streams[i].timestamp = 0;
}
+ this->last_frame_pts = 0;
+ this->last_pts[0] = 0;
+ this->last_pts[1] = 0;
+ this->keyframe_ts = 0;
if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
+ this->buf_flag_seek = 1;
+ xine_demux_flush_engine(this->stream);
+
if ( (!start_pos) && (start_time))
start_pos = start_time * this->rate;
- if (start_pos < this->header_size)
- start_pos = this->header_size;
+ if (start_pos < this->first_packet_pos)
+ start_pos = this->first_packet_pos;
- this->input->seek (this->input, start_pos, SEEK_SET);
-
- }
+ /*
+ * Find the previous keyframe
+ *
+ * states : 0 start, search a video keyframe
+ * 1 video keyframe found, search an audio packet
+ * 2 no video stream, search an audio packet
+ * 5 end
+ */
+ state = 0;
- /*
- * now start demuxing
- */
+ /* no video stream */
+ if (this->video_stream_id == 0) {
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: no video stream\n");
+#endif
+ state = 2;
+ }
- if( !this->stream->demux_thread_running ) {
- this->buf_flag_seek = 0;
- } else {
- this->buf_flag_seek = 1;
- xine_demux_flush_engine(this->stream);
+ /* force the demuxer to not send data to decoders */
+ this->streams[this->video_stream].skip = 1;
+ this->streams[this->audio_stream].skip = 1;
+ this->streams[this->video_stream].resync = 0;
+ this->streams[this->audio_stream].resync = 0;
+
+ start_pos -= (start_pos - this->first_packet_pos) % this->packet_size;
+ while ((start_pos >= this->first_packet_pos) && (state != 5)){
+ /* seek to the beginning of the previous packet */
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: seek back\n");
+#endif
+ if (this->input->seek (this->input, start_pos, SEEK_SET) != start_pos) {
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: demux_asf_seek: seek failed\n");
+ goto error;
+ }
+
+ if (asf_parse_packet_header(this, &raw_id)) {
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
+ printf ("demux_asf: demux_asf_seek: get_packet failed\n");
+ goto error;
+ }
+
+ for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) {
+ raw_id = get_byte(this); this->packet_size_left -= 1;
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: raw_id = %d\n", raw_id);
+#endif
+ stream_id = raw_id & 0x7f;
+ keyframe = raw_id & 0x80;
+ if (asf_parse_packet_payload_common(this, raw_id, &stream, &frag_offset, &rlen, &seq))
+ break;
+
+ if (rlen == 1) {
+ if (asf_parse_packet_payload_single(this, stream, frag_offset, seq, &ts))
+ break;
+ } else {
+ if (asf_parse_packet_payload_multiple(this, stream, frag_offset, rlen, seq, &ts))
+ break;
+ }
+
+ if (state == 0) {
+ if (keyframe && (stream_id == this->video_stream_id) && !frag_offset) {
+ this->keyframe_ts = ts;
+ state = 1; /* search an audio packet with pts < keyframe pts */
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: keyframe found at %lld, timestamp = %lld\n", start_pos, ts);
+#endif
+ }
+ } else if (state == 1) {
+ if ((stream_id == this->audio_stream_id) && ts &&
+ (ts <= this->keyframe_ts)) {
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: audio packet found at %lld, ts = %lld\n", start_pos, ts);
+#endif
+ state = 5; /* end */
+ break;
+ }
+ } else if (state == 2) {
+ if ((stream_id == this->audio_stream_id) && !frag_offset) {
+ this->keyframe_ts = ts;
+ state = 5; /* end */
+#ifdef LOG
+ printf ("demux_asf: demux_asf_seek: audio packet found at %lld, timestamp = %lld\n", start_pos, ts);
+#endif
+ }
+ }
+ }
+ start_pos -= this->packet_size;
+ }
+ if (state != 5) {
+ /* begining of the stream */
+ printf ("demux_asf: demux_asf_seek: begining of the stream\n");
+ this->input->seek (this->input, this->first_packet_pos, SEEK_SET);
+ } else {
+ this->input->seek (this->input, start_pos + this->packet_size, SEEK_SET);
+ }
}
-
+ this->send_newpts = 1;
+ this->buf_flag_seek = 1;
+ this->streams[this->video_stream].resync = 1;
+ this->streams[this->video_stream].skip = 1;
+ this->streams[this->audio_stream].resync = 1;
+ this->streams[this->audio_stream].skip = 1;
+ return this->status;
+
+error:
+ this->status = DEMUX_FINISHED;
return this->status;
}