diff options
-rw-r--r-- | src/demuxers/demux_asf.c | 251 |
1 files changed, 153 insertions, 98 deletions
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index 053ca5af7..c25da05b7 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.127 2003/07/27 23:35:44 tmattern Exp $ + * $Id: demux_asf.c,v 1.128 2003/09/07 20:10:59 tmattern Exp $ * * demultiplexer for asf streams * @@ -77,6 +77,7 @@ typedef struct { uint8_t *buffer; int skip; int resync; + int first_seq; } asf_stream_t; typedef struct demux_asf_s { @@ -681,7 +682,8 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream, #ifdef LOG printf ("demux_asf: asf_send_buffer_nodefrag: timestamp=%lld, pts=%lld\n", timestamp, timestamp * 90); #endif - if (stream->frag_offset == 0) { + + if ((stream->frag_offset == 0) && (frag_offset == 0)) { /* new packet */ stream->seq = seq; } else { @@ -690,15 +692,17 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream, /* continuing packet */ } else { /* cannot continue current packet: free it */ - stream->frag_offset = 0; if (frag_offset != 0) { - /* cannot create new packet */ + /* cannot create new packet, will die soon */ printf ("demux_asf: asf_send_buffer_nodefrag: invalid offset\n"); this->input->seek (this->input, frag_len, SEEK_CUR); return ; + } else { /* create new packet */ + printf ("demux_asf: asf_send_buffer_nodefrag: packet not complete\n"); stream->seq = seq; + stream->frag_offset = 0; } } } @@ -733,7 +737,7 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_stream_t *stream, stream->frag_offset += bufsize; frag_len -= bufsize; - package_done = (stream->frag_offset == payload_size); + package_done = (stream->frag_offset >= payload_size); if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) check_newpts (this, buf->pts, PTS_VIDEO, package_done); @@ -767,6 +771,7 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, int frag_len, int payload_size) { buf_element_t *buf; + int package_done; /* printf("asf_send_buffer seq=%d frag_offset=%d frag_len=%d\n", @@ -776,42 +781,66 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, printf ("demux_asf: asf_send_buffer_defrag: timestamp=%lld, pts=%lld\n", timestamp, timestamp * 90); #endif - if (stream->frag_offset == 0) { + if ((stream->frag_offset == 0) && (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 (frag_offset != 0) { + /* cannot create new packet, will die soon */ + printf ("demux_asf: asf_send_buffer_defrag: invalid offset\n"); + this->input->seek (this->input, frag_len, SEEK_CUR); + return ; + + } else { + /* create new packet */ + printf ("demux_asf: asf_send_buffer_defrag: packet not complete\n"); + stream->seq = seq; + stream->frag_offset = 0; + } + } + } + + if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) { + printf ("demux_asf: buffer overflow on defrag!\n"); + } else { + this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len); + stream->frag_offset += frag_len; + } + + package_done = (stream->frag_offset >= payload_size); + + if (package_done) + { + 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); - } + 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; + 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 = 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->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; #if 0 /* tm: not needed */ @@ -819,62 +848,31 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_stream_t *stream, (p-stream->buffer) / 1024; #endif - /* send the same pts for the entire frame */ - buf->pts = stream->timestamp * 90; + /* send the same pts for the entire frame */ + buf->pts = stream->timestamp * 90; - buf->type = stream->buf_type; - buf->size = bufsize; + 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); + stream->frag_offset -= bufsize; + p+=bufsize; - /* test if whole packet read */ - if ( !stream->frag_offset ) - buf->decoder_flags |= BUF_FLAG_FRAME_END; + 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); - stream->fifo->put (stream->fifo, buf); - } - } else { - printf ("demux_asf: asf_send_buffer_defrag: invalid offset\n"); - } - stream->frag_offset = 0; - if (frag_offset != 0) { - /* cannot create new packet */ - this->input->seek (this->input, frag_len, SEEK_CUR); - return ; - } else { - /* create new packet */ - stream->seq = seq; - } - } - } + /* test if whole packet read */ + if ( !stream->frag_offset ) + buf->decoder_flags |= BUF_FLAG_FRAME_END; - if( frag_offset ) { -#if 0 - /* tm: not needed */ - if( timestamp ) - stream->ts_per_kbyte = (timestamp - stream->timestamp) * 1024 * 90 / frag_offset; -#endif - } else { - stream->ts_per_kbyte = 0; - stream->timestamp = timestamp; - } - - if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) { - printf ("demux_asf: buffer overflow on defrag!\n"); - } else { - this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len); - stream->frag_offset += frag_len; + stream->fifo->put (stream->fifo, buf); + } } } @@ -1024,6 +1022,8 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, uint8_t stream_id; int i; uint32_t s_hdr_size = 0; + uint32_t exp_seq = 0; + buf_element_t *buf; stream_id = raw_id & 0x7f; *stream = NULL; @@ -1051,17 +1051,22 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, #endif } - /* keyframe detection for non-seekable input plugins */ - if (*stream && (*stream)->skip && (raw_id & 0x80) && !this->keyframe_ts) - this->keyframe_ts = 1; - switch ((this->segtype >> 4) & 3){ case 1: - *seq = get_byte(this); s_hdr_size += 1; break; + *seq = get_byte(this); s_hdr_size += 1; + if (*stream) + exp_seq = ((*stream)->seq + 1) % 256; + break; case 2: - *seq = get_le16(this); s_hdr_size += 2; break; + *seq = get_le16(this); s_hdr_size += 2; + if (*stream) + exp_seq = ((*stream)->seq + 1) % 65536; + break; case 3: - *seq = get_le32(this); s_hdr_size += 4; break; + *seq = get_le32(this); s_hdr_size += 4; + if (*stream) + exp_seq = (*stream)->seq + 1; + break; default: #ifdef LOG printf ("demux_asf: seq=0\n"); @@ -1069,6 +1074,39 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, *seq = 0; } + /* check seq number */ +#ifdef LOG + printf ("demux_asf: stream_id = %d, seq = %d\n", (*stream)->stream_id, *seq); +#endif + if (*stream) { + if ((*stream)->first_seq || (*stream)->skip) { + exp_seq = *seq; + (*stream)->first_seq = 0; + } else if ((*stream)->frag_offset) { + /* should be the same seq */ + exp_seq = (*stream)->seq; + } + if (exp_seq != *seq) { + printf ("demux_asf: bad seq: seq = %d, expected = %d, stream seq = %d!\n", *seq, exp_seq, (*stream)->seq); + + /* the stream is corrupted, reset the decoder and restart at a new keyframe */ + if ((*stream)->fifo) { + buf = (*stream)->fifo->buffer_pool_alloc ((*stream)->fifo); + buf->type = BUF_CONTROL_RESET_DECODER; + (*stream)->fifo->put((*stream)->fifo, buf); + } + if ((*stream) == &this->streams[this->video_stream]) { +#ifdef LOG + printf ("demux_asf: bad seq: waiting for keyframe\n"); +#endif + (*stream)->resync = 1; + (*stream)->skip = 1; + this->keyframe_ts = 0; + } + this->send_newpts = 1; + } + } + switch ((this->segtype >> 2) & 3) { case 1: *frag_offset = get_byte(this); s_hdr_size += 1; break; @@ -1112,6 +1150,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, /* return 0 if ok */ static int asf_parse_packet_payload_single(demux_asf_t *this, asf_stream_t *stream, + uint8_t raw_id, uint32_t frag_offset, uint32_t seq, int64_t *timestamp) { @@ -1171,6 +1210,13 @@ static int asf_parse_packet_payload_single(demux_asf_t *this, if (stream && stream->fifo) { + /* keyframe detection for non-seekable input plugins */ + if (stream->skip && (raw_id & 0x80) && !this->keyframe_ts) { + if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) + printf ("demux_asf: keyframe detected\n"); + this->keyframe_ts = 1; + } + if (stream->resync && (*timestamp >= this->keyframe_ts) && (this->keyframe_ts)) { if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) printf ("demux_asf: stream resynced\n"); @@ -1213,6 +1259,7 @@ static int asf_parse_packet_payload_single(demux_asf_t *this, /* return 0 if ok */ static int asf_parse_packet_payload_multiple(demux_asf_t *this, asf_stream_t *stream, + uint8_t raw_id, uint32_t frag_offset, uint32_t rlen, uint32_t seq, @@ -1277,16 +1324,23 @@ static int asf_parse_packet_payload_multiple(demux_asf_t *this, this->packet_size_left -= s_hdr_size; if (stream && stream->fifo) { - if (stream->resync && (*timestamp >= this->keyframe_ts) && - this->keyframe_ts && !frag_offset) { - if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) - printf ("demux_asf: stream resynced\n"); - stream->resync = 0; - stream->skip = 0; + if (!frag_offset) { + /* keyframe detection for non-seekable input plugins */ + if (stream->skip && (raw_id & 0x80) && !this->keyframe_ts) { + if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) + printf ("demux_asf: keyframe detected\n"); + this->keyframe_ts = 1; + } + if (stream->resync && (*timestamp >= this->keyframe_ts) && + this->keyframe_ts && !frag_offset) { + if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) + 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 @@ -1617,10 +1671,10 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) { 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)) + if (asf_parse_packet_payload_single(this, stream, raw_id, frag_offset, seq, &ts)) break; } else { - if (asf_parse_packet_payload_multiple(this, stream, frag_offset, rlen, seq, &ts)) + if (asf_parse_packet_payload_multiple(this, stream, raw_id, frag_offset, rlen, seq, &ts)) break; } } @@ -1798,9 +1852,10 @@ static int demux_asf_seek (demux_plugin_t *this_gen, * seek to start position */ 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->streams[i].frag_offset = 0; + this->streams[i].first_seq = 1; + this->streams[i].seq = 0; + this->streams[i].timestamp = 0; } this->last_frame_pts = 0; this->last_pts[PTS_VIDEO] = 0; @@ -1871,10 +1926,10 @@ static int demux_asf_seek (demux_plugin_t *this_gen, break; if (rlen == 1) { - if (asf_parse_packet_payload_single(this, stream, frag_offset, seq, &ts)) + if (asf_parse_packet_payload_single(this, stream, raw_id, frag_offset, seq, &ts)) break; } else { - if (asf_parse_packet_payload_multiple(this, stream, frag_offset, rlen, seq, &ts)) + if (asf_parse_packet_payload_multiple(this, stream, raw_id, frag_offset, rlen, seq, &ts)) break; } |