From 645f84663db1951293a7c821dccba45ebdabfcfe Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Tue, 9 Apr 2002 03:37:59 +0000 Subject: - new (fast) demuxer seeking scheme - updated decoder api to allow reseting internal state on seeks CVS patchset: 1696 CVS date: 2002/04/09 03:37:59 --- src/demuxers/demux.h | 19 ++- src/demuxers/demux_asf.c | 192 ++++++++++++++++----------- src/demuxers/demux_avi.c | 283 +++++++++++++++++++++++----------------- src/demuxers/demux_cda.c | 96 +++++++++----- src/demuxers/demux_elem.c | 119 +++++++++++------ src/demuxers/demux_mpeg.c | 185 ++++++++++++++++++-------- src/demuxers/demux_mpeg_block.c | 133 ++++++++++++------- src/demuxers/demux_mpgaudio.c | 104 ++++++++++----- src/demuxers/demux_ogg.c | 111 ++++++++++------ src/demuxers/demux_pes.c | 181 +++++++++++++++++-------- src/demuxers/demux_qt.c | 229 ++++++++++++++++++++------------ src/demuxers/demux_ts.c | 211 +++++++++++++++++++++--------- src/liba52/xine_decoder.c | 12 +- src/libdivx4/xine_decoder.c | 10 +- src/libdts/xine_decoder.c | 4 +- src/libffmpeg/xine_decoder.c | 9 +- src/liblpcm/xine_decoder.c | 4 +- src/libmad/xine_decoder.c | 4 +- src/libmpeg2/decode.c | 39 +++++- src/libmpeg2/mpeg2.h | 1 + src/libmpeg2/slice.c | 2 + src/libmpeg2/xine_decoder.c | 16 ++- src/libvorbis/xine_decoder.c | 4 +- src/libw32dll/w32codec.c | 29 +++- src/xine-engine/audio_decoder.c | 18 +-- src/xine-engine/buffer.h | 4 +- src/xine-engine/metronom.c | 10 +- src/xine-engine/osd.c | 16 ++- src/xine-engine/video_decoder.c | 15 ++- src/xine-engine/video_out.c | 13 +- src/xine-engine/xine.c | 134 ++++++++++++------- src/xine-engine/xine_internal.h | 7 +- 32 files changed, 1456 insertions(+), 758 deletions(-) diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h index a8228cd1b..8f7d9b480 100644 --- a/src/demuxers/demux.h +++ b/src/demuxers/demux.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: demux.h,v 1.12 2001/10/25 00:46:58 miguelfreitas Exp $ + * $Id: demux.h,v 1.13 2002/04/09 03:37:59 miguelfreitas Exp $ */ #ifndef HAVE_DEMUX_H @@ -35,7 +35,7 @@ extern "C" { #include "input_plugin.h" #endif -#define DEMUXER_PLUGIN_IFACE_VERSION 6 +#define DEMUXER_PLUGIN_IFACE_VERSION 7 #define DEMUX_OK 0 #define DEMUX_FINISHED 1 @@ -91,6 +91,21 @@ struct demux_plugin_s void (*start) (demux_plugin_t *this, fifo_buffer_t *video_fifo, fifo_buffer_t *audio_fifo, off_t start_pos, int start_time); + + /* + * ask running demux thread to seek + * + * for seekable streams, a start position can be specified + * + * start_pos : position in input source + * start_time : position measured in seconds from stream start + * + * if both parameters are !=0 start_pos will be used + * for non-seekable streams both values will be ignored + */ + + void (*seek) (demux_plugin_t *this, + off_t start_pos, int start_time); /* * stop & kill demux thread, free resources associated with current diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index 01a54c8c8..af147781a 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.32 2002/03/26 18:23:35 miguelfreitas Exp $ + * $Id: demux_asf.c,v 1.33 2002/04/09 03:37:59 miguelfreitas Exp $ * * demultiplexer for asf streams * @@ -129,6 +129,7 @@ typedef struct demux_asf_s { int frame; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -141,6 +142,7 @@ typedef struct demux_asf_s { int reorder_w; int reorder_b; + off_t header_size; } demux_asf_t ; @@ -671,13 +673,13 @@ static void asf_send_discontinuity (demux_asf_t *this, int64_t pts) { buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; + buf->type = BUF_CONTROL_NEWPTS; buf->disc_off = pts; this->video_fifo->put (this->video_fifo, buf); if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; + buf->type = BUF_CONTROL_NEWPTS; buf->disc_off = pts; this->audio_fifo->put (this->audio_fifo, buf); } @@ -1129,10 +1131,17 @@ static void *demux_asf_loop (void *this_gen) { this->send_end_buffers = 1; - while (this->status == DEMUX_OK) { - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + asf_read_packet (this); - + + pthread_mutex_unlock( &this->mutex ); + } /* @@ -1156,6 +1165,8 @@ static void *demux_asf_loop (void *this_gen) { } } + + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); @@ -1175,21 +1186,22 @@ static void demux_asf_stop (demux_plugin_t *this_gen) { buf_element_t *buf; int i; void *p; + + pthread_mutex_lock( &this->mutex ); if (this->status != DEMUX_OK) { printf ("demux_asf: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - pthread_cancel (this->thread); + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -1225,87 +1237,115 @@ static void demux_asf_start (demux_plugin_t *this_gen, demux_asf_t *this = (demux_asf_t *) this_gen; buf_element_t *buf; int err; + int starting; + + pthread_mutex_lock( &this->mutex ); - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - - /* - * send start buffer - */ - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + starting = (this->status != DEMUX_OK); + this->status = DEMUX_OK; + + if( starting ) { + this->audio_fifo = audio_fifo; + this->video_fifo = video_fifo; + + /* + * send start buffer + */ - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - /* - * initialize asf engine - */ - - this->num_streams = 0; - this->num_audio_streams = 0; - this->num_video_streams = 0; - this->packet_size = 0; - this->seqno = 0; - this->send_discontinuity = 1; - this->last_video_pts = 0; - this->frame_duration = 3000; + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } - if (this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) - this->input->seek (this->input, 0, SEEK_SET); + /* + * initialize asf engine + */ - if (!asf_read_header (this)) { - - this->status = DEMUX_FINISHED; - return; - } + this->num_streams = 0; + this->num_audio_streams = 0; + this->num_video_streams = 0; + this->packet_size = 0; + this->seqno = 0; + this->frame_duration = 3000; + + if (this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) + this->input->seek (this->input, 0, SEEK_SET); - xine_log (this->xine, XINE_LOG_FORMAT, - _("demux_asf: title : %s\n"), this->title); - xine_log (this->xine, XINE_LOG_FORMAT, - _("demux_asf: author : %s\n"), this->author); - xine_log (this->xine, XINE_LOG_FORMAT, - _("demux_asf: copyright : %s\n"), this->copyright); - xine_log (this->xine, XINE_LOG_FORMAT, - _("demux_asf: comment : %s\n"), this->comment); + if (!asf_read_header (this)) { + + this->status = DEMUX_FINISHED; + } else { + this->header_size = this->input->get_current_pos (this->input); - /* - * seek to start position - */ + xine_log (this->xine, XINE_LOG_FORMAT, + _("demux_asf: title : %s\n"), this->title); + xine_log (this->xine, XINE_LOG_FORMAT, + _("demux_asf: author : %s\n"), this->author); + xine_log (this->xine, XINE_LOG_FORMAT, + _("demux_asf: copyright : %s\n"), this->copyright); + xine_log (this->xine, XINE_LOG_FORMAT, + _("demux_asf: comment : %s\n"), this->comment); + } + } + else { + xine_flush_engine(this->xine); + } + + if( this->status == DEMUX_OK ) + /* + * seek to start position + */ + this->send_discontinuity = 1; + this->last_video_pts = 0; - if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { + if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { - off_t cur_pos = this->input->get_current_pos (this->input); - - if ( (!start_pos) && (start_time)) - start_pos = start_time * this->rate; + if ( (!start_pos) && (start_time)) + start_pos = start_time * this->rate; - if (start_posheader_size) + start_pos = this->header_size; - this->input->seek (this->input, start_pos, SEEK_SET); - } + this->input->seek (this->input, start_pos, SEEK_SET); + } - /* - * now start demuxing - */ + /* + * now start demuxing + */ - this->keyframe_found = 0; - this->status = DEMUX_OK; + this->keyframe_found = 0; - if ((err = pthread_create (&this->thread, - NULL, demux_asf_loop, this)) != 0) { - printf ("demux_asf: can't create new thread (%s)\n", - strerror(err)); - exit (1); + if( starting ) { + if ((err = pthread_create (&this->thread, + NULL, demux_asf_loop, this)) != 0) { + printf ("demux_asf: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + + pthread_mutex_unlock( &this->mutex ); + + if( !starting && this->status != DEMUX_OK ) { + void *p; + pthread_join (this->thread, &p); } } +static void demux_asf_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_asf_t *this = (demux_asf_t *) this_gen; + + demux_asf_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); +} + + static int demux_asf_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { @@ -1387,7 +1427,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_asf_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_asf: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -1407,6 +1447,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_asf_open; this->demux_plugin.start = demux_asf_start; + this->demux_plugin.seek = demux_asf_seek; this->demux_plugin.stop = demux_asf_stop; this->demux_plugin.close = demux_asf_close; this->demux_plugin.get_status = demux_asf_get_status; @@ -1414,5 +1455,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_asf_get_stream_length; this->demux_plugin.get_mimetypes = demux_asf_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 86c6ebeaa..8e8805ea5 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.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_avi.c,v 1.72 2002/03/31 20:38:40 jcdutton Exp $ + * $Id: demux_avi.c,v 1.73 2002/04/09 03:37:59 miguelfreitas Exp $ * * demultiplexer for avi streams * @@ -135,6 +135,7 @@ typedef struct demux_avi_s { avi_t *avi; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -851,7 +852,10 @@ static int demux_avi_next (demux_avi_t *this) { } } - return (buf->size>0); + if( buf ) + return (buf->size>0); + else + return 0; } static void *demux_avi_loop (void *this_gen) { @@ -861,14 +865,19 @@ static void *demux_avi_loop (void *this_gen) { this->send_end_buffers = 1; - do { - - /* printf ("avi loop (status %d)\n", this->status); */ - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + if (!demux_avi_next(this)) this->status = DEMUX_FINISHED; - - } while (this->status == DEMUX_OK) ; + + pthread_mutex_unlock( &this->mutex ); + + } if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -886,6 +895,7 @@ static void *demux_avi_loop (void *this_gen) { printf ("demux_avi: demux loop finished.\n"); + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); return NULL; @@ -896,27 +906,27 @@ static void demux_avi_stop (demux_plugin_t *this_gen) { demux_avi_t *this = (demux_avi_t *) this_gen; buf_element_t *buf; void *p; + + pthread_mutex_lock( &this->mutex ); if (this->status != DEMUX_OK) { printf ("demux_avi: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - pthread_cancel (this->thread); + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); + xine_flush_engine(this->xine); /* AVI_close (this->avi); this->avi = NULL; */ - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ @@ -951,38 +961,44 @@ static void demux_avi_start (demux_plugin_t *this_gen, uint32_t video_pts = 0; int err; unsigned char *sub; + int starting; + + pthread_mutex_lock( &this->mutex ); - this->audio_fifo = audio_fifo; - this->video_fifo = video_fifo; - - this->status = DEMUX_OK; - - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video format = %s\n"), - this->avi->compressor); - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video frame size %ld x %ld\n"), - this->avi->width, this->avi->height); - for(i=0; i < this->avi->n_audio; i++) - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio format[%d] = 0x%lx\n"), - i, this->avi->audio[i]->a_fmt); - this->no_audio = 0; + starting = (this->status != DEMUX_OK); + this->status = DEMUX_OK; - for(i=0; i < this->avi->n_audio; i++) { - this->avi->audio[i]->audio_type = formattag_to_buf_audio (this->avi->audio[i]->a_fmt); + if( starting ) { + this->audio_fifo = audio_fifo; + this->video_fifo = video_fifo; + + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video format = %s\n"), + this->avi->compressor); + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video frame size %ld x %ld\n"), + this->avi->width, this->avi->height); + for(i=0; i < this->avi->n_audio; i++) + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio format[%d] = 0x%lx\n"), + i, this->avi->audio[i]->a_fmt); + this->no_audio = 0; + + for(i=0; i < this->avi->n_audio; i++) { + this->avi->audio[i]->audio_type = formattag_to_buf_audio (this->avi->audio[i]->a_fmt); - if( !this->avi->audio[i]->audio_type ) { - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown audio type 0x%lx\n"), - this->avi->audio[i]->a_fmt); - this->no_audio = 1; - this->avi->audio[i]->audio_type = BUF_CONTROL_NOP; + if( !this->avi->audio[i]->audio_type ) { + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown audio type 0x%lx\n"), + this->avi->audio[i]->a_fmt); + this->no_audio = 1; + this->avi->audio[i]->audio_type = BUF_CONTROL_NOP; + } + else + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio type %s (wFormatTag 0x%x)\n"), + buf_audio_name(this->avi->audio[i]->audio_type), + (int)this->avi->audio[i]->a_fmt); } - else - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio type %s (wFormatTag 0x%x)\n"), - buf_audio_name(this->avi->audio[i]->audio_type), - (int)this->avi->audio[i]->a_fmt); } - + AVI_seek_start (this->avi); - + /* * seek to start pos / time */ @@ -998,7 +1014,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->status = DEMUX_FINISHED; printf ("demux_avi: video seek to start failed\n"); - return; + break; } } @@ -1015,7 +1031,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->status = DEMUX_FINISHED; printf ("demux_avi: video seek to start failed\n"); - return; + break; } } @@ -1024,7 +1040,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, } /* seek audio */ - if (!this->no_audio) { + if (!this->no_audio && this->status == DEMUX_OK) { for(i=0; i < this->avi->n_audio; i++) { while (get_audio_pts (this, i, this->avi->audio[i]->audio_posc, 0) < video_pts) { this->avi->audio[i]->audio_posc++; @@ -1032,110 +1048,135 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->status = DEMUX_FINISHED; printf ("demux_avi: audio seek to start failed\n"); - return; + break; } } } } - /* * send start buffers */ - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - buf->decoder_flags = 0; - this->video_fifo->put (this->video_fifo, buf); - - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if( starting && this->status == DEMUX_OK ) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; buf->decoder_flags = 0; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; - buf->disc_off = video_pts; - this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + buf->decoder_flags = 0; + this->audio_fifo->put (this->audio_fifo, buf); + } + } + else { + xine_flush_engine(this->xine); + } - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; + if( this->status == DEMUX_OK ) + { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; buf->disc_off = video_pts; - this->audio_fifo->put (this->audio_fifo, buf); - } - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->content = buf->mem; - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[1] = this->video_step; - memcpy (buf->content, &this->avi->bih, sizeof (this->avi->bih)); - buf->size = sizeof (this->avi->bih); - - this->avi->video_type = fourcc_to_buf_video((void*)&this->avi->bih.biCompression); - - if ( !this->avi->video_type ) { - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown video codec '%.4s'\n"), - (char*)&this->avi->bih.biCompression); - - this->status = DEMUX_FINISHED; - return; - } - buf->type = this->avi->video_type; - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video codec is '%s'\n"), - buf_video_name(buf->type)); - - this->video_fifo->put (this->video_fifo, buf); - - if(this->audio_fifo) { - for(i=0; iavi->n_audio; i++) { - avi_audio_t *a = this->avi->audio[i]; + this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->content = buf->mem; - buf->decoder_flags = BUF_FLAG_HEADER; - memcpy (buf->content, &a->wavex, sizeof (a->wavex)); - buf->size = sizeof (a->wavex); - buf->type = a->audio_type | i; - buf->decoder_info[0] = 0; /* first package, containing wavex */ - buf->decoder_info[1] = a->a_rate; /* Audio Rate */ - buf->decoder_info[2] = a->a_bits; /* Audio bits */ - buf->decoder_info[3] = a->a_chans; /* Audio bits */ + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = video_pts; this->audio_fifo->put (this->audio_fifo, buf); } } + + if( starting && this->status == DEMUX_OK ) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[1] = this->video_step; + memcpy (buf->content, &this->avi->bih, sizeof (this->avi->bih)); + buf->size = sizeof (this->avi->bih); - /* - * send external spu file pointer, if present - */ + this->avi->video_type = fourcc_to_buf_video((void*)&this->avi->bih.biCompression); + + if ( !this->avi->video_type ) { + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown video codec '%.4s'\n"), + (char*)&this->avi->bih.biCompression); + + this->status = DEMUX_FINISHED; + } + else { + buf->type = this->avi->video_type; + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video codec is '%s'\n"), + buf_video_name(buf->type)); - if (this->input->get_optional_data (this->input, &sub, INPUT_OPTIONAL_DATA_TEXTSPU0)) { + this->video_fifo->put (this->video_fifo, buf); + + if(this->audio_fifo) { + for(i=0; iavi->n_audio; i++) { + avi_audio_t *a = this->avi->audio[i]; + + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER; + memcpy (buf->content, &a->wavex, sizeof (a->wavex)); + buf->size = sizeof (a->wavex); + buf->type = a->audio_type | i; + buf->decoder_info[0] = 0; /* first package, containing wavex */ + buf->decoder_info[1] = a->a_rate; /* Audio Rate */ + buf->decoder_info[2] = a->a_bits; /* Audio bits */ + buf->decoder_info[3] = a->a_chans; /* Audio bits */ + this->audio_fifo->put (this->audio_fifo, buf); + } + } + + /* + * send external spu file pointer, if present + */ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->content = sub; + if (this->input->get_optional_data (this->input, &sub, INPUT_OPTIONAL_DATA_TEXTSPU0)) { - buf->type = BUF_SPU_TEXT; + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->content = sub; + + buf->type = BUF_SPU_TEXT; - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[1] = this->avi->width; - buf->decoder_info[2] = this->avi->height; + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[1] = this->avi->width; + buf->decoder_info[2] = this->avi->height; - this->video_fifo->put (this->video_fifo, buf); + this->video_fifo->put (this->video_fifo, buf); - this->have_spu = 1; + this->have_spu = 1; - printf ("demux_avi: text subtitle file available\n"); + printf ("demux_avi: text subtitle file available\n"); + + } else + this->have_spu = 0; + + if ((err = pthread_create (&this->thread, NULL, demux_avi_loop, this)) != 0) { + printf ("demux_avi: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + } + + pthread_mutex_unlock( &this->mutex ); + + if( !starting && this->status != DEMUX_OK ) { + void *p; + pthread_join (this->thread, &p); + } +} - } else - this->have_spu = 0; - if ((err = pthread_create (&this->thread, NULL, demux_avi_loop, this)) != 0) { - printf ("demux_avi: can't create new thread (%s)\n", - strerror(err)); - exit (1); - } +static void demux_avi_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_avi_t *this = (demux_avi_t *) this_gen; + + demux_avi_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static int demux_avi_open(demux_plugin_t *this_gen, @@ -1250,7 +1291,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_avi_t *this; - if (iface != 6) { + if (iface != 7) { xine_log (xine, XINE_LOG_PLUGIN, _("demux_avi: this plugin doesn't support plugin API version %d.\n" "demux_avi: this means there's a version mismatch between xine and this " @@ -1271,6 +1312,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_avi_open; this->demux_plugin.start = demux_avi_start; + this->demux_plugin.seek = demux_avi_seek; this->demux_plugin.stop = demux_avi_stop; this->demux_plugin.close = demux_avi_close; this->demux_plugin.get_status = demux_avi_get_status; @@ -1278,5 +1320,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_avi_get_stream_length; this->demux_plugin.get_mimetypes = demux_avi_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_cda.c b/src/demuxers/demux_cda.c index 064e83b81..e7a5731a8 100644 --- a/src/demuxers/demux_cda.c +++ b/src/demuxers/demux_cda.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_cda.c,v 1.10 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: demux_cda.c,v 1.11 2002/04/09 03:38:00 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -52,7 +52,8 @@ typedef struct { input_plugin_t *input; pthread_t thread; - + pthread_mutex_t mutex; + off_t start; int status; @@ -92,17 +93,22 @@ static void *demux_cda_loop (void *this_gen) { this->send_end_buffers = 1; - this->input->seek(this->input, this->start, SEEK_SET); - - do { - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + xine_usec_sleep(100000); if (!demux_cda_next(this)) this->status = DEMUX_FINISHED; - - } while (this->status == DEMUX_OK) ; - + + pthread_mutex_unlock( &this->mutex ); + + } + this->status = DEMUX_FINISHED; if (this->send_end_buffers) { @@ -118,6 +124,8 @@ static void *demux_cda_loop (void *this_gen) { this->audio_fifo->put (this->audio_fifo, buf); } } + + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); } @@ -130,23 +138,23 @@ static void demux_cda_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { printf ("demux_cda: stop...ignored\n"); return; } - + /* Force stop */ this->input->stop(this->input); this->send_end_buffers = 0; - this->status = DEMUX_FINISHED; + this->status = DEMUX_FINISHED; - pthread_cancel(this->thread); - pthread_join(this->thread, &p); + pthread_mutex_unlock( &this->mutex ); + pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -182,33 +190,51 @@ static void demux_cda_start (demux_plugin_t *this_gen, buf_element_t *buf; int err; - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - - this->status = DEMUX_OK; + pthread_mutex_lock( &this->mutex ); + this->start = start_pos; this->blocksize = this->input->get_blocksize(this->input); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } + } + /* * now start demuxing */ - - if ((err = pthread_create (&this->thread, - NULL, demux_cda_loop, this)) != 0) { - printf ("demux_cda: can't create new thread (%s)\n", strerror(err)); - exit(1); + this->input->seek(this->input, this->start, SEEK_SET); + + if( this->status != DEMUX_OK ) { + + this->status = DEMUX_OK; + if ((err = pthread_create (&this->thread, + NULL, demux_cda_loop, this)) != 0) { + printf ("demux_cda: can't create new thread (%s)\n", strerror(err)); + exit(1); + } } + pthread_mutex_unlock( &this->mutex ); +} + + +static void demux_cda_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_cda_t *this = (demux_cda_t *) this_gen; + + demux_cda_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } /* @@ -280,7 +306,7 @@ static int demux_cda_get_stream_length (demux_plugin_t *this_gen) { demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_cda_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_cda: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -295,6 +321,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUX_CDA_IFACE_VERSION; this->demux_plugin.open = demux_cda_open; this->demux_plugin.start = demux_cda_start; + this->demux_plugin.seek = demux_cda_seek; this->demux_plugin.stop = demux_cda_stop; this->demux_plugin.close = demux_cda_close; this->demux_plugin.get_status = demux_cda_get_status; @@ -302,5 +329,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_cda_get_stream_length; this->demux_plugin.get_mimetypes = demux_cda_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return &this->demux_plugin; } diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index 78fe22025..9a46a175b 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.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_elem.c,v 1.36 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: demux_elem.c,v 1.37 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for elementary mpeg streams * @@ -43,7 +43,7 @@ #define DEMUX_MPEG_ELEM_IFACE_VERSION 1 -#define VALID_ENDS ".mpv" +#define VALID_ENDS "mpv" typedef struct { @@ -59,6 +59,7 @@ typedef struct { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int blocksize; int status; @@ -83,10 +84,10 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) { return 0; } - if(preview_mode) - buf->decoder_info[0] = 0; + if (preview_mode) + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->pts = 0; /*buf->scr = 0;*/ @@ -107,12 +108,19 @@ static void *demux_mpeg_elem_loop (void *this_gen) { this->send_end_buffers = 1; - do { - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + if (!demux_mpeg_elem_next(this, 0)) this->status = DEMUX_FINISHED; - - } while (this->status == DEMUX_OK) ; + + pthread_mutex_unlock( &this->mutex ); + + } this->status = DEMUX_FINISHED; @@ -129,6 +137,7 @@ static void *demux_mpeg_elem_loop (void *this_gen) { this->audio_fifo->put (this->audio_fifo, buf); } } + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); } @@ -141,16 +150,16 @@ static void demux_mpeg_elem_stop (demux_plugin_t *this_gen) { demux_mpeg_elem_t *this = (demux_mpeg_elem_t *) this_gen; buf_element_t *buf = NULL; void *p; + + pthread_mutex_lock( &this->mutex ); this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - pthread_cancel (this->thread); + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -186,53 +195,79 @@ static void demux_mpeg_elem_start (demux_plugin_t *this_gen, demux_mpeg_elem_t *this = (demux_mpeg_elem_t *) this_gen; buf_element_t *buf; int err; + int starting; + + pthread_mutex_lock( &this->mutex ); - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - - this->blocksize = this->input->get_blocksize(this->input); - if (!this->blocksize) - this->blocksize = 2048; + starting = (this->status != DEMUX_OK); + this->status = DEMUX_OK; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + if( starting ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; + + this->blocksize = this->input->get_blocksize(this->input); + if (!this->blocksize) + this->blocksize = 2048; - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - int num_buffers = NUM_PREVIEW_BUFFERS; + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } + + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { + int num_buffers = NUM_PREVIEW_BUFFERS; - this->input->seek (this->input, 0, SEEK_SET); + this->input->seek (this->input, 0, SEEK_SET); - this->status = DEMUX_OK ; - while ((num_buffers > 0) && (this->status == DEMUX_OK)) { - demux_mpeg_elem_next(this, 1); - num_buffers--; + this->status = DEMUX_OK ; + while ((num_buffers > 0) && (this->status == DEMUX_OK)) { + demux_mpeg_elem_next(this, 1); + num_buffers--; + } } - + } + else { + xine_flush_engine(this->xine); + } + + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { + /* FIXME: implement time seek */ this->input->seek (this->input, start_pos, SEEK_SET); } - + /* * now start demuxing */ this->status = DEMUX_OK; - if ((err = pthread_create (&this->thread, + if( starting ) { + if ((err = pthread_create (&this->thread, NULL, demux_mpeg_elem_loop, this)) != 0) { - printf ("demux_elem: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_elem: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } } + pthread_mutex_unlock( &this->mutex ); } +static void demux_mpeg_elem_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_mpeg_elem_t *this = (demux_mpeg_elem_t *) this_gen; + + demux_mpeg_elem_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); +} + + /* * */ @@ -338,7 +373,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_mpeg_elem_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_elem: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -358,6 +393,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUX_MPEG_ELEM_IFACE_VERSION; this->demux_plugin.open = demux_mpeg_elem_open; this->demux_plugin.start = demux_mpeg_elem_start; + this->demux_plugin.seek = demux_mpeg_elem_seek; this->demux_plugin.stop = demux_mpeg_elem_stop; this->demux_plugin.close = demux_mpeg_elem_close; this->demux_plugin.get_status = demux_mpeg_elem_get_status; @@ -365,5 +401,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_mpeg_elem_get_stream_length; this->demux_plugin.get_mimetypes = demux_mpeg_elem_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return &this->demux_plugin; } diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 80ae1a34f..60fc67b60 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.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_mpeg.c,v 1.52 2002/03/12 03:03:18 miguelfreitas Exp $ + * $Id: demux_mpeg.c,v 1.53 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -61,6 +61,7 @@ typedef struct demux_mpeg_s { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; unsigned char dummy_space[100000]; @@ -72,7 +73,8 @@ typedef struct demux_mpeg_s { int send_end_buffers; int64_t last_scr; - + int send_newpts; + } demux_mpeg_t; static uint32_t read_bytes (demux_mpeg_t *this, int n) { @@ -113,6 +115,28 @@ static uint32_t read_bytes (demux_mpeg_t *this, int n) { return res; } + +static void check_newpts( demux_mpeg_t *this, int64_t pts ) +{ + if( this->send_newpts && !this->preview_mode && pts ) { + + buf_element_t *buf; + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->video_fifo->put (this->video_fifo, buf); + + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->audio_fifo->put (this->audio_fifo, buf); + } + this->send_newpts = 0; + } +} + static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) { int len, i; @@ -143,7 +167,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) w = read_bytes(this, 2); pts |= (w & 0xFFFE) >> 1; - header_len -= 5 ; + header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -198,6 +224,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) pts |= (w & 0xFFFE) >> 1; header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -245,6 +273,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) pts |= (w & 0xFFFE) >> 1; header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -354,6 +384,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } } + check_newpts( this, pts ); if ((stream_id & 0xe0) == 0xc0) { int track = stream_id & 0x1f; @@ -384,7 +415,6 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } else if ((stream_id & 0xf0) == 0xe0) { - buf = this->input->read_block (this->input, this->video_fifo, len); if (buf == NULL) { @@ -485,11 +515,12 @@ static uint32_t parse_pack(demux_mpeg_t *this) { } /* discontinuity ? */ - if( scr ) + if( scr && !this->preview_mode ) { int64_t scr_diff = scr - this->last_scr; - if (abs(scr_diff) > 60000 && !this->preview_mode) { - + + if (abs(scr_diff) > 60000 && !this->send_newpts) { + buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -617,15 +648,23 @@ static void *demux_mpeg_loop (void *this_gen) { demux_mpeg_t *this = (demux_mpeg_t *) this_gen; buf_element_t *buf; - uint32_t w; + uint32_t w=0; - do { + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + w = parse_pack (this); if (w != 0x000001ba) demux_mpeg_resync (this, w); - } while (this->status == DEMUX_OK) ; + pthread_mutex_unlock( &this->mutex ); + + } if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -644,6 +683,8 @@ static void *demux_mpeg_loop (void *this_gen) { printf ("demux_mpeg: demux loop finished (status: %d, buf:%x)\n", this->status, w); + pthread_mutex_unlock( &this->mutex ); + pthread_exit(NULL); return NULL; @@ -655,26 +696,21 @@ static void demux_mpeg_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; - printf ("demux_mpeg: stop...\n"); - + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { - - this->video_fifo->clear(this->video_fifo); - if(this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); - + printf ("demux_mpeg: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } - + this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if(this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -704,64 +740,93 @@ static void demux_mpeg_start (demux_plugin_t *this_gen, buf_element_t *buf; int err; - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; + pthread_mutex_lock( &this->mutex ); - this->rate = 0; /* fixme */ - this->last_scr = 0; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + if( this->status != DEMUX_OK ) { + + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; + + this->rate = 0; /* fixme */ + this->last_scr = 0; - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } - uint32_t w; - int num_buffers = NUM_PREVIEW_BUFFERS; + if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { - this->preview_mode = 1; + uint32_t w; + int num_buffers = NUM_PREVIEW_BUFFERS; - this->input->seek (this->input, 4, SEEK_SET); + this->preview_mode = 1; - this->status = DEMUX_OK ; + this->input->seek (this->input, 4, SEEK_SET); - do { + this->status = DEMUX_OK ; - w = parse_pack_preview (this, &num_buffers); + do { + + w = parse_pack_preview (this, &num_buffers); - if (w != 0x000001ba) - demux_mpeg_resync (this, w); + if (w != 0x000001ba) + demux_mpeg_resync (this, w); - num_buffers --; - - } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ; + num_buffers --; - /* printf ("demux_mpeg: rate %d\n", this->rate); */ + } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ; + /* printf ("demux_mpeg: rate %d\n", this->rate); */ + this->status = DEMUX_FINISHED; + } + } + + if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { + if ( (!start_pos) && (start_time)) start_pos = start_time * this->rate * 50; this->input->seek (this->input, start_pos+4, SEEK_SET); + if( start_pos ) + demux_mpeg_resync (this, read_bytes(this, 4) ); + } else read_bytes(this, 4); + + this->send_newpts = 1; + + if( this->status != DEMUX_OK ) { + this->preview_mode = 0; + this->send_end_buffers = 1; + this->status = DEMUX_OK ; - this->preview_mode = 0; - this->send_end_buffers = 1; - this->status = DEMUX_OK ; - - if ((err = pthread_create (&this->thread, + if ((err = pthread_create (&this->thread, NULL, demux_mpeg_loop, this)) != 0) { - printf ("demux_mpeg: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_mpeg: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + else { + xine_flush_engine(this->xine); } + pthread_mutex_unlock( &this->mutex ); + +} + +static void demux_mpeg_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_mpeg_t *this = (demux_mpeg_t *) this_gen; + + demux_mpeg_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static int demux_mpeg_open(demux_plugin_t *this_gen, @@ -910,7 +975,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_mpeg_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_mpeg: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -934,6 +999,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_mpeg_open; this->demux_plugin.start = demux_mpeg_start; + this->demux_plugin.seek = demux_mpeg_seek; this->demux_plugin.stop = demux_mpeg_stop; this->demux_plugin.close = demux_mpeg_close; this->demux_plugin.get_status = demux_mpeg_get_status; @@ -941,6 +1007,9 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_mpeg_get_stream_length; this->demux_plugin.get_mimetypes = demux_mpeg_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 9d75c4e34..0314fbdca 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.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_mpeg_block.c,v 1.86 2002/04/06 02:23:38 miguelfreitas Exp $ + * $Id: demux_mpeg_block.c,v 1.87 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -61,6 +61,7 @@ typedef struct demux_mpeg_block_s { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -341,7 +342,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m } /* discontinuity ? */ - if (scr) { + if (scr && !preview_mode) { int64_t scr_diff = scr - this->last_scr; #ifdef LOG @@ -349,7 +350,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m scr, this->last_scr, scr_diff); #endif - if ((abs(scr_diff) > DISC_TRESHOLD) && !preview_mode && + if ( (abs(scr_diff) > DISC_TRESHOLD) && !this->ignore_scr_discont) { buf_element_t *buf; @@ -491,7 +492,7 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m } if ((p[0]&0xF0) == 0x80) { - + /* printf ( "ac3 PES packet, track %02x\n",track); */ buf->decoder_info[1] = p[1]; /* Number of frame headers */ buf->decoder_info[2] = p[2] << 8 | p[3]; /* First access unit pointer */ @@ -623,11 +624,18 @@ static void *demux_mpeg_block_loop (void *this_gen) { this->send_end_buffers = 1; - do { - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + demux_mpeg_block_parse_pack(this, 0); - - } while (this->status == DEMUX_OK) ; + + pthread_mutex_unlock( &this->mutex ); + + } /* printf ("demux_mpeg_block: demux loop finished (status: %d)\n", @@ -651,6 +659,8 @@ static void *demux_mpeg_block_loop (void *this_gen) { } + pthread_mutex_unlock( &this->mutex ); + pthread_exit(NULL); return NULL; @@ -805,21 +815,22 @@ static void demux_mpeg_block_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { printf ("demux_mpeg_block: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); - + xine_flush_engine(this->xine); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_USER; @@ -849,44 +860,50 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen, buf_element_t *buf; int err; + pthread_mutex_lock( &this->mutex ); + this->video_fifo = video_fifo; this->audio_fifo = audio_fifo; - /* - * send start buffer - */ - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + if( this->status != DEMUX_OK ) { + /* + * send start buffer + */ - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - if (!this->rate) - this->rate = demux_mpeg_block_estimate_rate (this); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } + if (!this->rate) + this->rate = demux_mpeg_block_estimate_rate (this); - this->last_scr = 0; - this->nav_last_end_pts = 0; - this->ignore_scr_discont = 0; + this->last_scr = 0; + this->nav_last_end_pts = 0; + this->ignore_scr_discont = 0; - if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - int num_buffers = NUM_PREVIEW_BUFFERS; + int num_buffers = NUM_PREVIEW_BUFFERS; - this->input->seek (this->input, 0, SEEK_SET); + this->input->seek (this->input, 0, SEEK_SET); - this->status = DEMUX_OK ; - while ( (num_buffers>0) && (this->status == DEMUX_OK) ) { + this->status = DEMUX_OK ; + while ( (num_buffers>0) && (this->status == DEMUX_OK) ) { - demux_mpeg_block_parse_pack(this, 1); - num_buffers --; + demux_mpeg_block_parse_pack(this, 1); + num_buffers --; + } } - + this->status = DEMUX_FINISHED; + } + + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { if (start_pos) { start_pos /= (off_t) this->blocksize; start_pos *= (off_t) this->blocksize; @@ -923,19 +940,35 @@ static void demux_mpeg_block_start (demux_plugin_t *this_gen, * now start demuxing */ - this->status = DEMUX_OK ; - this->last_scr = 0; - this->nav_last_end_pts = 0; - this->ignore_scr_discont = 0; + if( this->status != DEMUX_OK ) + { + this->status = DEMUX_OK ; + this->last_scr = 0; + this->nav_last_end_pts = 0; + this->ignore_scr_discont = 0; - if ((err = pthread_create (&this->thread, + if ((err = pthread_create (&this->thread, NULL, demux_mpeg_block_loop, this)) != 0) { - printf ("demux_mpeg_block: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_mpeg_block: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + else { + xine_flush_engine(this->xine); } + pthread_mutex_unlock( &this->mutex ); +} + +static void demux_mpeg_block_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen; + + demux_mpeg_block_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } + static void demux_mpeg_block_accept_input (demux_mpeg_block_t *this, input_plugin_t *input) { @@ -1094,6 +1127,9 @@ static char *demux_mpeg_block_get_mimetypes(void) { static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) { demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen; + /* + * find input plugin + */ if (this->rate) return this->input->get_length (this->input) / (this->rate * 50); @@ -1106,7 +1142,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_mpeg_block_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_mpeg_block: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -1130,6 +1166,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_mpeg_block_open; this->demux_plugin.start = demux_mpeg_block_start; + this->demux_plugin.seek = demux_mpeg_block_seek; this->demux_plugin.stop = demux_mpeg_block_stop; this->demux_plugin.close = demux_mpeg_block_close; this->demux_plugin.get_status = demux_mpeg_block_get_status; @@ -1138,6 +1175,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_mimetypes = demux_mpeg_block_get_mimetypes; this->scratch = xine_xmalloc_aligned (512, 4096, (void**) &this->scratch_base); + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 4a3052c0f..b76ffc48e 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.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_mpgaudio.c,v 1.37 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: demux_mpgaudio.c,v 1.38 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -57,6 +57,7 @@ typedef struct { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -208,13 +209,20 @@ static void *demux_mpgaudio_loop (void *this_gen) { this->send_end_buffers = 1; - do { - + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + if (!demux_mpgaudio_next(this)) this->status = DEMUX_FINISHED; - - } while (this->status == DEMUX_OK) ; - + + pthread_mutex_unlock( &this->mutex ); + + } + this->status = DEMUX_FINISHED; if (this->send_end_buffers) { @@ -231,6 +239,7 @@ static void *demux_mpgaudio_loop (void *this_gen) { } } + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); return NULL; @@ -242,20 +251,21 @@ static void demux_mpgaudio_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { printf ("demux_mpgaudio_block: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -308,21 +318,26 @@ static void demux_mpgaudio_start (demux_plugin_t *this_gen, demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen; buf_element_t *buf; int err; + + pthread_mutex_lock( &this->mutex ); - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; - this->status = DEMUX_OK; - this->stream_length = 0; + this->stream_length = 0; + } if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { uint32_t head; - head = demux_mpgaudio_read_head(this->input); - - if (mpg123_head_check(head)) - mpg123_decode_header(this,head); + if( this->status != DEMUX_OK ) { + head = demux_mpgaudio_read_head(this->input); + if (mpg123_head_check(head)) + mpg123_decode_header(this,head); + } + if (!start_pos && start_time && this->stream_length > 0) start_pos = start_time * this->input->get_length(this->input) / this->stream_length; @@ -331,26 +346,41 @@ static void demux_mpgaudio_start (demux_plugin_t *this_gen, this->input->seek (this->input, start_pos, SEEK_SET); } - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); - - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + if( this->status != DEMUX_OK ) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); + + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } - /* - * now start demuxing - */ + /* + * now start demuxing + */ - if ((err = pthread_create (&this->thread, + this->status = DEMUX_OK; + if ((err = pthread_create (&this->thread, NULL, demux_mpgaudio_loop, this)) != 0) { - printf ("demux_mpgaudio: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_mpgaudio: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } } + else { + xine_flush_engine(this->xine); + } + pthread_mutex_unlock( &this->mutex ); +} + +static void demux_mpgaudio_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen; + + demux_mpgaudio_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static int demux_mpgaudio_open(demux_plugin_t *this_gen, @@ -444,7 +474,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_mpgaudio_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_mpeg: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -464,6 +494,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUX_MPGAUDIO_IFACE_VERSION; this->demux_plugin.open = demux_mpgaudio_open; this->demux_plugin.start = demux_mpgaudio_start; + this->demux_plugin.seek = demux_mpgaudio_seek; this->demux_plugin.stop = demux_mpgaudio_stop; this->demux_plugin.close = demux_mpgaudio_close; this->demux_plugin.get_status = demux_mpgaudio_get_status; @@ -471,5 +502,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_mpgaudio_get_stream_length; this->demux_plugin.get_mimetypes = demux_mpgaudio_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return &this->demux_plugin; } diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index c4c7328a5..c910626e5 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.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_ogg.c,v 1.19 2002/04/04 10:36:35 guenter Exp $ + * $Id: demux_ogg.c,v 1.20 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for ogg streams * @@ -94,6 +94,7 @@ typedef struct demux_ogg_s { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -289,8 +290,17 @@ static void *demux_ogg_loop (void *this_gen) { this->send_end_buffers = 1; - while (this->status == DEMUX_OK) { + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + demux_ogg_send_package (this); + + pthread_mutex_unlock( &this->mutex ); + } /* @@ -315,6 +325,7 @@ static void *demux_ogg_loop (void *this_gen) { } + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); return NULL; @@ -333,20 +344,21 @@ static void demux_ogg_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { printf ("demux_ogg: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -376,38 +388,41 @@ static void demux_ogg_start (demux_plugin_t *this_gen, buf_element_t *buf; int err, i; - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; + pthread_mutex_lock( &this->mutex ); - /* - * send start buffer - */ + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + /* + * send start buffer + */ - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - /* - * initialize ogg engine - */ + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } - ogg_sync_init(&this->oy); + /* + * initialize ogg engine + */ - this->num_streams = 0; + ogg_sync_init(&this->oy); - this->input->seek (this->input, 0, SEEK_SET); + this->num_streams = 0; - /* send header */ - this->pkg_count = 0; - for (i=0; i<5; i++) - demux_ogg_send_package (this); + this->input->seek (this->input, 0, SEEK_SET); + /* send header */ + this->pkg_count = 0; + for (i=0; i<5; i++) + demux_ogg_send_package (this); + } /* * seek to start position @@ -428,18 +443,34 @@ static void demux_ogg_start (demux_plugin_t *this_gen, this->input->seek (this->input, start_pos, SEEK_SET); } - /* - * now start demuxing - */ + + if( this->status != DEMUX_OK ) { + /* + * now start demuxing + */ - this->status = DEMUX_OK; + this->status = DEMUX_OK; - if ((err = pthread_create (&this->thread, + if ((err = pthread_create (&this->thread, NULL, demux_ogg_loop, this)) != 0) { - printf ("demux_ogg: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_ogg: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + else { + xine_flush_engine(this->xine); } + + pthread_mutex_unlock( &this->mutex ); +} + +static void demux_ogg_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_ogg_t *this = (demux_ogg_t *) this_gen; + + demux_ogg_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static int demux_ogg_open(demux_plugin_t *this_gen, @@ -537,7 +568,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_ogg_t *this; - if (iface != 6) { + if (iface != 7) { printf( _("demux_ogg: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n"), @@ -557,6 +588,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_ogg_open; this->demux_plugin.start = demux_ogg_start; + this->demux_plugin.seek = demux_ogg_seek; this->demux_plugin.stop = demux_ogg_stop; this->demux_plugin.close = demux_ogg_close; this->demux_plugin.get_status = demux_ogg_get_status; @@ -564,5 +596,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_ogg_get_stream_length; this->demux_plugin.get_mimetypes = demux_ogg_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_pes.c b/src/demuxers/demux_pes.c index cba5ee10a..73383a934 100644 --- a/src/demuxers/demux_pes.c +++ b/src/demuxers/demux_pes.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_pes.c,v 1.22 2002/03/31 20:38:40 jcdutton Exp $ + * $Id: demux_pes.c,v 1.23 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for mpeg 2 PES (Packetized Elementary Streams) * reads streams of variable blocksizes @@ -60,6 +60,7 @@ typedef struct demux_pes_s { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; unsigned char dummy_space[100000]; @@ -67,7 +68,9 @@ typedef struct demux_pes_s { int preview_mode; int send_end_buffers; - + + int64_t last_scr; + int send_newpts; } demux_pes_t ; static uint32_t read_bytes (demux_pes_t *this, int n) { @@ -87,7 +90,6 @@ static uint32_t read_bytes (demux_pes_t *this, int n) { } - switch (n) { case 1: res = buf[0]; @@ -109,6 +111,28 @@ static uint32_t read_bytes (demux_pes_t *this, int n) { return res; } +static void check_newpts( demux_pes_t *this, int64_t pts ) +{ + if( this->send_newpts && !this->preview_mode && pts ) { + + buf_element_t *buf; + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->video_fifo->put (this->video_fifo, buf); + + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->audio_fifo->put (this->audio_fifo, buf); + } + this->send_newpts = 0; + } +} + + static void parse_mpeg2_packet (demux_pes_t *this, int nID) { int nLen, i; @@ -141,6 +165,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { pts |= (w & 0xFFFE) >> 1; header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -165,9 +191,9 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { buf->type = BUF_AUDIO_A52 + track; buf->pts = pts; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; buf->input_pos = this->input->get_current_pos (this->input); @@ -195,6 +221,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { pts |= (w & 0xFFFE) >> 1; header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -210,9 +238,10 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { buf->type = BUF_AUDIO_MPEG + track; buf->pts = pts; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; + buf->input_pos = this->input->get_current_pos(this->input); if(this->audio_fifo) @@ -238,6 +267,8 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { pts |= (w & 0xFFFE) >> 1; header_len -= 5 ; + + check_newpts( this, pts ); } /* read rest of header */ @@ -255,9 +286,10 @@ static void parse_mpeg2_packet (demux_pes_t *this, int nID) { buf->type = BUF_VIDEO_MPEG; buf->pts = pts; if (this->preview_mode) - buf->decoder_info[0] = 0; + buf->decoder_flags = BUF_FLAG_PREVIEW; else - buf->decoder_info[0] = 1; + buf->decoder_flags = 0; + buf->input_pos = this->input->get_current_pos(this->input); this->video_fifo->put (this->video_fifo, buf); @@ -299,15 +331,23 @@ static void *demux_pes_loop (void *this_gen) { demux_pes_t *this = (demux_pes_t *) this_gen; buf_element_t *buf; - uint32_t w; + uint32_t w=0; - do { + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + w = parse_pack (this); if (w != 0x000001) demux_pes_resync (this, w); - } while (this->status == DEMUX_OK) ; + pthread_mutex_unlock( &this->mutex ); + + } if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -326,6 +366,7 @@ static void *demux_pes_loop (void *this_gen) { printf ("demux_pes: demux loop finished (status: %d, buf:%x)\n", this->status, w); + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); return NULL; @@ -337,26 +378,21 @@ static void demux_pes_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; - printf ("demux_pes: stop...\n"); - + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { - - this->video_fifo->clear(this->video_fifo); - if(this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); - + printf ("demux_pes: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if(this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -386,57 +422,88 @@ static void demux_pes_start (demux_plugin_t *this_gen, buf_element_t *buf; int err; - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; + pthread_mutex_lock( &this->mutex ); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + /* + * send start buffer + */ + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); - if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } - uint32_t w; - int num_buffers = NUM_PREVIEW_BUFFERS; + if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { - this->preview_mode = 1; + uint32_t w; + int num_buffers = NUM_PREVIEW_BUFFERS; - this->input->seek (this->input, 3, SEEK_SET); + this->preview_mode = 1; - this->status = DEMUX_OK ; + this->input->seek (this->input, 3, SEEK_SET); - do { - w = parse_pack (this); + this->status = DEMUX_OK ; + + do { + w = parse_pack (this); - if (w != 0x000001) - demux_pes_resync (this, w); + if (w != 0x000001) + demux_pes_resync (this, w); - num_buffers --; - - } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ; + num_buffers --; + } while ( (this->status == DEMUX_OK) && (num_buffers>0)) ; + this->status = DEMUX_FINISHED; + } + } + + if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { + + /* FIXME: implement time seek */ this->input->seek (this->input, start_pos+3, SEEK_SET); - /* FIXME: implement time seek */ + if( start_pos ) + demux_pes_resync (this, read_bytes(this, 3) ); } else read_bytes(this, 3); - this->preview_mode = 0; - this->send_end_buffers = 1; - this->status = DEMUX_OK ; + this->send_newpts = 1; + + if( this->status != DEMUX_OK ) { + this->preview_mode = 0; + this->send_end_buffers = 1; + this->status = DEMUX_OK ; - if ((err = pthread_create (&this->thread, + if ((err = pthread_create (&this->thread, NULL, demux_pes_loop, this)) != 0) { - printf ("demux_pes: can't create new thread (%s)\n", - strerror(err)); - exit (1); + printf ("demux_pes: can't create new thread (%s)\n", + strerror(err)); + exit (1); + } + } + else { + xine_flush_engine(this->xine); } + pthread_mutex_unlock( &this->mutex ); + +} + +static void demux_pes_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_pes_t *this = (demux_pes_t *) this_gen; + + demux_pes_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static int demux_pes_open(demux_plugin_t *this_gen, @@ -562,7 +629,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_pes_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_pes: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -585,6 +652,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_pes_open; this->demux_plugin.start = demux_pes_start; + this->demux_plugin.seek = demux_pes_seek; this->demux_plugin.stop = demux_pes_stop; this->demux_plugin.close = demux_pes_close; this->demux_plugin.get_status = demux_pes_get_status; @@ -592,5 +660,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_pes_get_stream_length; this->demux_plugin.get_mimetypes = demux_pes_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index 7ee9d5cd5..e247a9ecd 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.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_qt.c,v 1.24 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: demux_qt.c,v 1.25 2002/04/09 03:38:00 miguelfreitas Exp $ * * demultiplexer for mpeg-4 system (aka quicktime) streams, based on: * @@ -54,12 +54,13 @@ #include "libw32dll/wine/vfw.h" #include "libw32dll/wine/mmreg.h" - +/* #define LOG +*/ - +/* #define DBG_QT - +*/ #define VALID_ENDS "mov,mp4" @@ -549,6 +550,7 @@ typedef struct demux_qt_s { input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int status; int send_end_buffers; @@ -570,8 +572,32 @@ typedef struct demux_qt_s { uint8_t scratch[64*1024]; + int send_newpts; } demux_qt_t ; + +static void check_newpts( demux_qt_t *this, int64_t pts ) +{ + if( this->send_newpts && pts ) { + + buf_element_t *buf; + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->video_fifo->put (this->video_fifo, buf); + + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->audio_fifo->put (this->audio_fifo, buf); + } + this->send_newpts = 0; + } +} + + /* * openquicktime stuff */ @@ -3747,9 +3773,13 @@ static void *demux_qt_loop (void *this_gen) { idx = 0; - do { - + while(1) { int is_audio, sample_num; + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; if (idx >= this->num_index_entries) break; @@ -3764,6 +3794,8 @@ static void *demux_qt_loop (void *this_gen) { offset = this->index[idx].offset; pts = this->index[idx].pts; + check_newpts( this, pts ); + for (sample_num = this->index[idx].first_sample; sample_num <= this->index[idx].last_sample; sample_num++) { todo = demux_qt_get_sample_size (this->index[idx].track, sample_num); @@ -3816,8 +3848,10 @@ static void *demux_qt_loop (void *this_gen) { } idx++; + + pthread_mutex_unlock( &this->mutex ); - } while (this->status == DEMUX_OK) ; + } printf ("demux_qt: demux loop finished (status: %d)\n", this->status); @@ -3838,6 +3872,8 @@ static void *demux_qt_loop (void *this_gen) { } } + + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); @@ -3861,20 +3897,21 @@ static void demux_qt_stop (demux_plugin_t *this_gen) { buf_element_t *buf; void *p; + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { printf ("demux_qt: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->video_fifo->clear(this->video_fifo); - if (this->audio_fifo) - this->audio_fifo->clear(this->audio_fifo); + xine_flush_engine(this->xine); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; @@ -4038,8 +4075,9 @@ static void demux_qt_index_trak (demux_qt_t *this, quicktime_trak_t *trak, uint3 stts_pts = 0; while (stsc_cur < stco->total_entries) { - +#ifdef LOG printf ("demux_qt: chunk # is %d...\n", stsc_cur); +#endif chunk_offset = stco->table[stsc_cur-1].offset; @@ -4082,8 +4120,9 @@ static void demux_qt_index_trak (demux_qt_t *this, quicktime_trak_t *trak, uint3 stsc_first_sample = stsc_last_sample + 1; stsc_last_sample = stsc_first_sample + stsc_samples - 1; +#ifdef LOG printf ("demux_qt: chunk offset is %lld...\n", chunk_offset); - +#endif /* * find out about pts of sample @@ -4144,26 +4183,29 @@ static void demux_qt_start (demux_plugin_t *this_gen, buf_element_t *buf; int err; - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - this->send_end_buffers = 1; + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; #ifdef DBG_QT - debug_fh = open ("/tmp/t.mp3", O_CREAT | O_WRONLY | O_TRUNC, 0644); + debug_fh = open ("/tmp/t.mp3", O_CREAT | O_WRONLY | O_TRUNC, 0644); #endif - /* - * init quicktime parser - */ + /* + * init quicktime parser + */ - this->qt = quicktime_open (this->input, this->xine); + this->qt = quicktime_open (this->input, this->xine); - if (!this->qt) { - this->status = DEMUX_FINISHED; - return; - } - - xine_log (this->xine, XINE_LOG_FORMAT, + if (!this->qt) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock( &this->mutex ); + return; + } + + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_qt: video codec %s (%f fps), audio codec %s (%ld Hz, %d bits)\n"), quicktime_video_compressor (this->qt,0), quicktime_frame_rate (this->qt,0), @@ -4171,35 +4213,36 @@ static void demux_qt_start (demux_plugin_t *this_gen, quicktime_sample_rate (this->qt,0), quicktime_audio_bits (this->qt,0)); - if (!demux_qt_detect_compressors (this)) { - this->status = DEMUX_FINISHED; - return; - } - - /* - * generate index - */ + if (!demux_qt_detect_compressors (this)) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock( &this->mutex ); + return; + } - demux_qt_create_index (this); + /* + * generate index + */ - /* - * send start buffer - */ + demux_qt_create_index (this); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_START; - this->video_fifo->put (this->video_fifo, buf); + /* + * send start buffer + */ - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; - this->audio_fifo->put (this->audio_fifo, buf); - } + this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } + } + /* * seek to start pos/time */ - if (start_pos) { double f = (double) start_pos / (double) this->input->get_length (this->input) ; @@ -4212,52 +4255,68 @@ static void demux_qt_start (demux_plugin_t *this_gen, quicktime_video_length (this->qt, 0) * f, 0); } + this->send_newpts = 1; + + if( this->status != DEMUX_OK ) { + /* + * send init info to decoders + */ - /* - * send init info to decoders - */ + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[0] = 0; /* first package, containing bih */ + buf->decoder_info[1] = this->video_step; + memcpy (buf->content, &this->bih, sizeof (this->bih)); + buf->size = sizeof (this->bih); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->content = buf->mem; - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[0] = 0; /* first package, containing bih */ - buf->decoder_info[1] = this->video_step; - memcpy (buf->content, &this->bih, sizeof (this->bih)); - buf->size = sizeof (this->bih); + buf->type = this->video_type; - buf->type = this->video_type; + this->video_fifo->put (this->video_fifo, buf); - this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->content = buf->mem; + memcpy (buf->content, &this->wavex, + sizeof (this->wavex)); + buf->size = sizeof (this->wavex); + buf->type = this->audio_type; + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[0] = 0; /* first package, containing wavex */ + buf->decoder_info[1] = quicktime_sample_rate (this->qt, 0); + buf->decoder_info[2] = quicktime_audio_bits (this->qt, 0); + buf->decoder_info[3] = quicktime_track_channels (this->qt, 0); + this->audio_fifo->put (this->audio_fifo, buf); + } - printf ("demux_qt: sent buffer %08x\n", buf); + /* + * now start demuxing + */ - if(this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->content = buf->mem; - memcpy (buf->content, &this->wavex, - sizeof (this->wavex)); - buf->size = sizeof (this->wavex); - buf->type = this->audio_type; - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[0] = 0; /* first package, containing wavex */ - buf->decoder_info[1] = quicktime_sample_rate (this->qt, 0); - buf->decoder_info[2] = quicktime_audio_bits (this->qt, 0); - buf->decoder_info[3] = quicktime_track_channels (this->qt, 0); - this->audio_fifo->put (this->audio_fifo, buf); + this->status = DEMUX_OK ; + this->send_end_buffers = 1; + + if ((err = pthread_create (&this->thread, NULL, demux_qt_loop, this)) != 0) { + printf ("demux_qt: can't create new thread (%s)\n", strerror(err)); + exit (1); + } } + else { + xine_flush_engine(this->xine); + } + pthread_mutex_unlock( &this->mutex ); - /* - * now start demuxing - */ +} - this->status = DEMUX_OK ; +static void demux_qt_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_qt_t *this = (demux_qt_t *) this_gen; - if ((err = pthread_create (&this->thread, NULL, demux_qt_loop, this)) != 0) { - printf ("demux_qt: can't create new thread (%s)\n", strerror(err)); - exit (1); - } + demux_qt_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } + static int demux_qt_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { @@ -4340,7 +4399,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_qt_t *this; - if (iface != 6) { + if (iface != 7) { printf ("demux_qt: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " " demuxer plugin.\nInstalling current demux plugins should help.\n", @@ -4360,6 +4419,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_qt_open; this->demux_plugin.start = demux_qt_start; + this->demux_plugin.seek = demux_qt_seek; this->demux_plugin.stop = demux_qt_stop; this->demux_plugin.close = demux_qt_close; this->demux_plugin.get_status = demux_qt_get_status; @@ -4367,5 +4427,8 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_stream_length = demux_qt_get_stream_length; this->demux_plugin.get_mimetypes = demux_qt_get_mimetypes; + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + return (demux_plugin_t *) this; } diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index eb0e3dcb0..9352c0724 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.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_ts.c,v 1.40 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: demux_ts.c,v 1.41 2002/04/09 03:38:00 miguelfreitas Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -154,12 +154,13 @@ typedef struct { config_values_t *config; - fifo_buffer_t *fifoAudio; - fifo_buffer_t *fifoVideo; + fifo_buffer_t *audio_fifo; + fifo_buffer_t *video_fifo; input_plugin_t *input; pthread_t thread; + pthread_mutex_t mutex; int status; @@ -178,12 +179,17 @@ typedef struct { */ unsigned int programNumber; unsigned int pcrPid; - uint32_t PCR; + int64_t PCR; + int64_t last_PCR; unsigned int pid; unsigned int videoPid; unsigned int audioPid; unsigned int videoMedia; unsigned int audioMedia; + + int send_end_buffers; + int ignore_scr_discont; + int send_newpts; } demux_ts; static void demux_ts_build_crc32_table(demux_ts *this) { @@ -208,6 +214,28 @@ static uint32_t demux_ts_compute_crc32(demux_ts *this, uint8_t *data, uint32_t l return crc32; } +static void check_newpts( demux_ts *this, int64_t pts ) +{ + if( this->send_newpts && pts ) { + + buf_element_t *buf; + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->video_fifo->put (this->video_fifo, buf); + + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_NEWPTS; + buf->disc_off = pts; + this->audio_fifo->put (this->audio_fifo, buf); + } + this->send_newpts = 0; + this->ignore_scr_discont = 1; + } +} + /* * demux_ts_parse_pat @@ -538,6 +566,8 @@ static void demux_ts_buffer_pes(demux_ts *this, unsigned char *ts, m->broken_pes = 1; LOG_MSG (this->xine, _("demux_ts: broken pes encountered\n")); } else { + check_newpts( this, m->PTS ); + m->broken_pes = 0; buf = m->fifo->buffer_pool_alloc(m->fifo); memcpy (buf->mem, ts+len-m->size, m->size); /* FIXME: reconstruct parser to do without memcpys */ @@ -790,7 +820,7 @@ static void demux_ts_parse_pmt (demux_ts *this, #ifdef TS_PMT_LOG printf ("demux_ts: PMT video pid %.4x\n", pid); #endif - demux_ts_pes_new(this, mediaIndex, pid, this->fifoVideo); + demux_ts_pes_new(this, mediaIndex, pid, this->video_fifo); } this->videoPid = pid; this->videoMedia = mediaIndex; @@ -801,7 +831,7 @@ static void demux_ts_parse_pmt (demux_ts *this, #ifdef TS_PMT_LOG printf ("demux_ts: PMT audio pid %.4x\n", pid); #endif - demux_ts_pes_new(this, mediaIndex, pid, this->fifoAudio); + demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo); this->audioPid = pid; this->audioMedia = mediaIndex; } @@ -821,7 +851,7 @@ static void demux_ts_parse_pmt (demux_ts *this, #ifdef TS_PMT_LOG printf ("demux_ts: PMT AC3 audio pid %.4x\n", pid); #endif - demux_ts_pes_new(this, mediaIndex, pid, this->fifoAudio); + demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo); this->audioPid = pid; this->audioMedia = mediaIndex; break; @@ -840,7 +870,7 @@ static void demux_ts_parse_pmt (demux_ts *this, #ifdef TS_PMT_LOG printf ("demux_ts: PMT AC3 audio pid %.4x\n", pid); #endif - demux_ts_pes_new(this, mediaIndex, pid, this->fifoAudio); + demux_ts_pes_new(this, mediaIndex, pid, this->audio_fifo); this->audioPid = pid; this->audioMedia = mediaIndex; } @@ -1060,6 +1090,29 @@ static void demux_ts_parse_packet (demux_ts *this) { if (adaptation_field_length > 0) { this->PCR = demux_ts_adaptation_field_parse (originalPkt+5, adaptation_field_length); + if (this->PCR) { + int64_t scr_diff = this->PCR - this->last_PCR; + + if ((abs(scr_diff) > 90000) && !this->send_newpts && + !this->ignore_scr_discont ) { + + buf_element_t *buf; + + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->disc_off = scr_diff; + this->video_fifo->put (this->video_fifo, buf); + + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); + buf->type = BUF_CONTROL_DISCONTINUITY; + buf->disc_off = scr_diff; + this->audio_fifo->put (this->audio_fifo, buf); + } + } + this->last_PCR = this->PCR; + this->ignore_scr_discont = 0; + } } /* * Skip adaptation header. @@ -1137,26 +1190,39 @@ static void *demux_ts_loop(void *gen_this) { demux_ts *this = (demux_ts *)gen_this; buf_element_t *buf; - do { + while(1) { + + pthread_mutex_lock( &this->mutex ); + + if( this->status != DEMUX_OK) + break; + demux_ts_parse_packet(this); - } while (this->status == DEMUX_OK) ; - + + pthread_mutex_unlock( &this->mutex ); + + } + #ifdef TS_LOG printf ("demux_ts: demux loop finished (status: %d)\n", this->status); #endif - + this->status = DEMUX_FINISHED; - buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo); - buf->type = BUF_CONTROL_END; - buf->decoder_flags = BUF_FLAG_END_STREAM; /* stream finished */ - this->fifoVideo->put(this->fifoVideo, buf); - - if (this->fifoAudio) { - buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio); + if (this->send_end_buffers) { + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_STREAM; /* stream finished */ - this->fifoAudio->put(this->fifoAudio, buf); + this->video_fifo->put (this->video_fifo, buf); + + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_END; + buf->decoder_flags = BUF_FLAG_END_STREAM; /* stream finished */ + this->audio_fifo->put (this->audio_fifo, buf); + } } + + pthread_mutex_unlock( &this->mutex ); pthread_exit(NULL); return NULL; } @@ -1283,32 +1349,35 @@ static int demux_ts_open(demux_plugin_t *this_gen, input_plugin_t *input, } static void demux_ts_start(demux_plugin_t *this_gen, - fifo_buffer_t *fifoVideo, - fifo_buffer_t *fifoAudio, + fifo_buffer_t *video_fifo, + fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_ts *this = (demux_ts *)this_gen; buf_element_t *buf; int err; - this->fifoVideo = fifoVideo; - this->fifoAudio = fifoAudio; + pthread_mutex_lock( &this->mutex ); - /* - * send start buffers - */ - buf = this->fifoVideo->buffer_pool_alloc(this->fifoVideo); - buf->type = BUF_CONTROL_START; - this->fifoVideo->put(this->fifoVideo, buf); - if (this->fifoAudio) { - buf = this->fifoAudio->buffer_pool_alloc(this->fifoAudio); - buf->type = BUF_CONTROL_START; - this->fifoAudio->put(this->fifoAudio, buf); - } + if( this->status != DEMUX_OK ) { + this->video_fifo = video_fifo; + this->audio_fifo = audio_fifo; - this->status = DEMUX_OK ; + /* + * send start buffer + */ + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_START; + this->video_fifo->put (this->video_fifo, buf); + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_START; + this->audio_fifo->put (this->audio_fifo, buf); + } + } + if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0 ) { if ( (!start_pos) && (start_time)) @@ -1317,15 +1386,36 @@ static void demux_ts_start(demux_plugin_t *this_gen, this->input->seek (this->input, start_pos, SEEK_SET); } + this->send_newpts = 1; + this->ignore_scr_discont = 0; + demux_ts_build_crc32_table(this); - - /* - * Now start demuxing. - */ - if ((err = pthread_create(&this->thread, NULL, demux_ts_loop, this)) != 0) { - LOG_MSG_STDERR(this->xine, _("demux_ts: can't create new thread (%s)\n"), strerror(err)); - exit (1); + + if( this->status != DEMUX_OK ) { + /* + * Now start demuxing. + */ + this->status = DEMUX_OK ; + this->send_end_buffers = 1; + this->last_PCR = 0; + + if ((err = pthread_create(&this->thread, NULL, demux_ts_loop, this)) != 0) { + LOG_MSG_STDERR(this->xine, _("demux_ts: can't create new thread (%s)\n"), strerror(err)); + exit (1); + } } + else { + xine_flush_engine(this->xine); + } + pthread_mutex_unlock( &this->mutex ); +} + +static void demux_ts_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time) { + demux_ts *this = (demux_ts *)this_gen; + + demux_ts_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } static void demux_ts_stop(demux_plugin_t *this_gen) @@ -1334,35 +1424,32 @@ static void demux_ts_stop(demux_plugin_t *this_gen) buf_element_t *buf; void *p; - LOG_MSG(this->xine, _("demux_ts: stop...\n")); - + pthread_mutex_lock( &this->mutex ); + if (this->status != DEMUX_OK) { - - this->fifoVideo->clear(this->fifoVideo); - if(this->fifoAudio) - this->fifoAudio->clear(this->fifoAudio); + printf ("demux_ts: stop...ignored\n"); + pthread_mutex_unlock( &this->mutex ); return; } + this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - - pthread_cancel (this->thread); + + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - this->fifoVideo->clear(this->fifoVideo); - if(this->fifoAudio) - this->fifoAudio->clear(this->fifoAudio); + xine_flush_engine(this->xine); - buf = this->fifoVideo->buffer_pool_alloc (this->fifoVideo); + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ - this->fifoVideo->put (this->fifoVideo, buf); + this->video_fifo->put (this->video_fifo, buf); - if (this->fifoAudio) { - buf = this->fifoAudio->buffer_pool_alloc (this->fifoAudio); + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ - this->fifoAudio->put (this->fifoAudio, buf); + this->audio_fifo->put (this->audio_fifo, buf); } } @@ -1379,7 +1466,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { demux_ts *this; int i; - if (iface != 6) { + if (iface != 7) { LOG_MSG (xine, _("demux_ts: plugin doesn't support plugin API version %d.\n" " this means there's a version mismatch between xine and this " @@ -1406,6 +1493,7 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->plugin.open = demux_ts_open; this->plugin.start = demux_ts_start; + this->plugin.seek = demux_ts_seek; this->plugin.stop = demux_ts_stop; this->plugin.close = demux_ts_close; this->plugin.get_status = demux_ts_get_status; @@ -1433,6 +1521,9 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->audioPid = INVALID_PID; this->rate = 16000; /* FIXME */ + + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); return (demux_plugin_t *)this; } diff --git a/src/liba52/xine_decoder.c b/src/liba52/xine_decoder.c index dfcf5b850..484001a15 100644 --- a/src/liba52/xine_decoder.c +++ b/src/liba52/xine_decoder.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: xine_decoder.c,v 1.21 2002/04/06 02:49:47 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.22 2002/04/09 03:38:00 miguelfreitas Exp $ * * stuff needed to turn liba52 into a xine decoder plugin */ @@ -441,16 +441,8 @@ void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - /* - printf ("liba52: got buffer, pts =%d, pts - last_pts=%d\n", - buf->PTS, buf->PTS - this->last_pts); - - this->last_pts = buf->PTS; - */ - if (buf->pts) this->pts = buf->pts; - while (current != end) { @@ -549,7 +541,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { a52dec_decoder_t *this ; config_values_t *cfg; - if (iface_version != 5) { + if (iface_version != 6) { printf( "liba52: plugin doesn't support plugin API version %d.\n" "liba52: this means there's a version mismatch between xine and this " "liba52: decoder plugin.\nInstalling current plugins should help.\n", diff --git a/src/libdivx4/xine_decoder.c b/src/libdivx4/xine_decoder.c index 1aff0ee38..225865a3d 100644 --- a/src/libdivx4/xine_decoder.c +++ b/src/libdivx4/xine_decoder.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: xine_decoder.c,v 1.25 2002/04/07 09:37:11 guenter Exp $ + * $Id: xine_decoder.c,v 1.26 2002/04/09 03:38:00 miguelfreitas Exp $ * * xine decoder plugin using divx4 * @@ -522,6 +522,11 @@ static char *divx4_get_id(void) { static void divx4_flush(video_decoder_t *this_gen) { } +static void divx4_reset(video_decoder_t *this_gen) { + /* seems to handle seeking quite nicelly without any code here */ +} + + /* This is pretty generic. I took the liberty to increase the priority over that of libffmpeg :-) */ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { @@ -532,7 +537,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { decoreFunc libdecore_func = 0; config_values_t *cfg; - if (iface_version != 5) { + if (iface_version != 6) { printf( "divx4: plugin doesn't support plugin API version %d.\n" "divx4: this means there's a version mismatch between xine and this " "divx4: decoder plugin.\nInstalling current plugins should help.\n", @@ -566,6 +571,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { this->video_decoder.close = divx4_close; this->video_decoder.get_identifier = divx4_get_id; this->video_decoder.flush = divx4_flush; + this->video_decoder.reset = divx4_reset; this->video_decoder.priority = cfg->register_num (cfg, "codec.divx4_priority", 4, "priority of the divx4 plugin (>5 => enable)", NULL, NULL, NULL); diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c index 215c32092..3b67d889a 100644 --- a/src/libdts/xine_decoder.c +++ b/src/libdts/xine_decoder.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: xine_decoder.c,v 1.16 2002/04/01 17:59:41 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.17 2002/04/09 03:38:00 miguelfreitas Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton @@ -220,7 +220,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { dts_decoder_t *this ; - if (iface_version != 5) { + if (iface_version != 6) { printf( "libdts: plugin doesn't support plugin API version %d.\n" "libdts: this means there's a version mismatch between xine and this " "libdts: decoder plugin.\nInstalling current plugins should help.\n", diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c index f65dfe443..f4831f4ac 100644 --- a/src/libffmpeg/xine_decoder.c +++ b/src/libffmpeg/xine_decoder.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: xine_decoder.c,v 1.29 2002/04/01 17:59:47 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.30 2002/04/09 03:38:00 miguelfreitas Exp $ * * xine decoder plugin using ffmpeg * @@ -360,6 +360,10 @@ static void ff_flush (video_decoder_t *this_gen) { } +static void ff_reset (video_decoder_t *this_gen) { + /* seems to handle seeking quite nicelly without any code here */ +} + static void ff_close (video_decoder_t *this_gen) { ff_decoder_t *this = (ff_decoder_t *) this_gen; @@ -391,7 +395,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { ff_decoder_t *this ; static pthread_once_t once_control = PTHREAD_ONCE_INIT; - if (iface_version != 5) { + if (iface_version != 6) { printf( "ffmpeg: plugin doesn't support plugin API version %d.\n" "ffmpeg: this means there's a version mismatch between xine and this " "ffmpeg: decoder plugin.\nInstalling current plugins should help.\n", @@ -407,6 +411,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { this->video_decoder.init = ff_init; this->video_decoder.decode_data = ff_decode_data; this->video_decoder.flush = ff_flush; + this->video_decoder.reset = ff_reset; this->video_decoder.close = ff_close; this->video_decoder.get_identifier = ff_get_id; this->video_decoder.priority = 5; diff --git a/src/liblpcm/xine_decoder.c b/src/liblpcm/xine_decoder.c index 07c3f8edd..408c12490 100644 --- a/src/liblpcm/xine_decoder.c +++ b/src/liblpcm/xine_decoder.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: xine_decoder.c,v 1.20 2002/03/11 12:31:25 guenter Exp $ + * $Id: xine_decoder.c,v 1.21 2002/04/09 03:38:00 miguelfreitas Exp $ * * 31-8-2001 Added LPCM rate sensing. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk @@ -153,7 +153,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { lpcm_decoder_t *this ; - if (iface_version != 5) { + if (iface_version != 6) { printf( "liblpcm: plugin doesn't support plugin API version %d.\n" "liblpcm: this means there's a version mismatch between xine and this " "liblpcm: decoder plugin.\nInstalling current plugins should help.\n", diff --git a/src/libmad/xine_decoder.c b/src/libmad/xine_decoder.c index f159481a2..4ec9aa907 100644 --- a/src/libmad/xine_decoder.c +++ b/src/libmad/xine_decoder.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: xine_decoder.c,v 1.16 2002/04/07 12:11:48 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.17 2002/04/09 03:38:00 miguelfreitas Exp $ * * stuff needed to turn libmad into a xine decoder plugin */ @@ -275,7 +275,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { mad_decoder_t *this ; - if (iface_version != 5) { + if (iface_version != 6) { printf( "libmad: plugin doesn't support plugin API version %d.\n" "libmad: this means there's a version mismatch between xine and this " "libmad: decoder plugin.\nInstalling current plugins should help.\n", diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 86d9cc0f4..f5bff3815 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -181,8 +181,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (((picture->picture_structure == FRAME_PICTURE) || (picture->second_field)) ) { - if (!mpeg2dec->drop_frame) - picture->current_frame->bad_frame = 0; + if (mpeg2dec->drop_frame) + picture->current_frame->bad_frame = 1; if (picture->picture_coding_type == B_TYPE) { if( picture->current_frame && !picture->current_frame->drawn ) { @@ -481,6 +481,41 @@ int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end, return ret; } +void mpeg2_reset (mpeg2dec_t * mpeg2dec) { + + picture_t *picture = mpeg2dec->picture; + + if( !picture ) + return; + + mpeg2dec->pts = 0; + + if( !picture->mpeg1 ) + mpeg2dec->is_sequence_needed = 1; + + mpeg2dec->in_slice = 0; + + /* to free reference frames one also needs to fix slice.c to + * abort when they are NULL. unfortunately it seems to break + * DVD menus. + */ + /* + if ( picture->current_frame && + picture->current_frame != picture->backward_reference_frame && + picture->current_frame != picture->forward_reference_frame ) + picture->current_frame->free (picture->current_frame); + picture->current_frame = NULL; + + if (picture->forward_reference_frame) + picture->forward_reference_frame->free (picture->forward_reference_frame); + picture->forward_reference_frame = NULL; + + if (picture->backward_reference_frame) + picture->backward_reference_frame->free (picture->backward_reference_frame); + picture->backward_reference_frame = NULL; + */ +} + void mpeg2_flush (mpeg2dec_t * mpeg2dec) { picture_t *picture = mpeg2dec->picture; diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index 77a96965f..a3994930e 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -64,6 +64,7 @@ void mpeg2_find_sequence_header (mpeg2dec_t * mpeg2dec, uint8_t * data_start, uint8_t * data_end); void mpeg2_flush (mpeg2dec_t * mpeg2dec); +void mpeg2_reset (mpeg2dec_t * mpeg2dec); /* Not needed, it is defined as static in decode.c, and no-one else called it * currently diff --git a/src/libmpeg2/slice.c b/src/libmpeg2/slice.c index 555b10782..07f92ea10 100644 --- a/src/libmpeg2/slice.c +++ b/src/libmpeg2/slice.c @@ -1452,6 +1452,7 @@ static inline int slice_init (picture_t * picture, int code) forward_reference_frame = picture->forward_reference_frame; } else { + /* return 1; */ forward_reference_frame = picture->current_frame; } @@ -1459,6 +1460,7 @@ static inline int slice_init (picture_t * picture, int code) backward_reference_frame = picture->backward_reference_frame; } else { + /* return 1; */ backward_reference_frame = picture->current_frame; } diff --git a/src/libmpeg2/xine_decoder.c b/src/libmpeg2/xine_decoder.c index 56af6324b..3543ce6e2 100644 --- a/src/libmpeg2/xine_decoder.c +++ b/src/libmpeg2/xine_decoder.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: xine_decoder.c,v 1.26 2002/04/04 00:08:36 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.27 2002/04/09 03:38:00 miguelfreitas Exp $ * * stuff needed to turn libmpeg2 into a xine decoder plugin */ @@ -109,6 +109,17 @@ static void mpeg2dec_flush (video_decoder_t *this_gen) { pthread_mutex_unlock (&this->lock); } +static void mpeg2dec_reset (video_decoder_t *this_gen) { + mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; + + pthread_mutex_lock (&this->lock); + + mpeg2_reset (&this->mpeg2); + + pthread_mutex_unlock (&this->lock); +} + + static void mpeg2dec_close (video_decoder_t *this_gen) { mpeg2dec_decoder_t *this = (mpeg2dec_decoder_t *) this_gen; @@ -134,7 +145,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { mpeg2dec_decoder_t *this ; - if (iface_version != 5) { + if (iface_version != 6) { printf( "libmpeg2: plugin doesn't support plugin API version %d.\n" "libmpeg2: this means there's a version mismatch between xine and this " "libmpeg2: decoder plugin.\nInstalling current plugins should help.\n", @@ -150,6 +161,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { this->video_decoder.init = mpeg2dec_init; this->video_decoder.decode_data = mpeg2dec_decode_data; this->video_decoder.flush = mpeg2dec_flush; + this->video_decoder.reset = mpeg2dec_reset; this->video_decoder.close = mpeg2dec_close; this->video_decoder.get_identifier = mpeg2dec_get_id; this->video_decoder.priority = 5; diff --git a/src/libvorbis/xine_decoder.c b/src/libvorbis/xine_decoder.c index 26df1f494..37e618bd7 100644 --- a/src/libvorbis/xine_decoder.c +++ b/src/libvorbis/xine_decoder.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: xine_decoder.c,v 1.7 2002/04/01 18:00:13 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.8 2002/04/09 03:38:01 miguelfreitas Exp $ * * (ogg/)vorbis audio decoder plugin (libvorbis wrapper) for xine */ @@ -239,7 +239,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { vorbis_decoder_t *this ; - if (iface_version != 5) { + if (iface_version != 6) { printf( "libvorbis: plugin doesn't support plugin API version %d.\n" "libvorbis: this means there's a version mismatch between xine and this " "libvorbis: decoder plugin.\nInstalling current plugins should help.\n", diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index d675aeb0d..d92398a40 100644 --- a/src/libw32dll/w32codec.c +++ b/src/libw32dll/w32codec.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: w32codec.c,v 1.69 2002/04/01 18:01:17 miguelfreitas Exp $ + * $Id: w32codec.c,v 1.70 2002/04/09 03:38:01 miguelfreitas Exp $ * * routines for using w32 codecs * DirectShow support by Miguel Freitas (Nov/2001) @@ -818,6 +818,26 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { static void w32v_flush (video_decoder_t *this_gen) { } +static void w32v_reset (video_decoder_t *this_gen) { + + w32v_decoder_t *this = (w32v_decoder_t *) this_gen; + + /* FIXME: need to improve this function. currently it + doesn't avoid artifacts when seeking. */ + + pthread_mutex_lock(&win32_codec_mutex); + if ( !this->ds_driver ) { + if (!this->ex_functions) + ICDecompressBegin(this->hic, &this->bih, &this->o_bih); + else + ICDecompressBeginEx(this->hic, &this->bih, &this->o_bih); + } else { + } + this->size = 0; + pthread_mutex_unlock(&win32_codec_mutex); +} + + static void w32v_close (video_decoder_t *this_gen) { w32v_decoder_t *this = (w32v_decoder_t *) this_gen; @@ -828,6 +848,8 @@ static void w32v_close (video_decoder_t *this_gen) { #endif { if ( !this->ds_driver ) { + ICDecompressEnd(this->hic); + ICClose(this->hic); } else { if( this->ds_dec ) DS_VideoDecoder_Destroy(this->ds_dec); @@ -1282,7 +1304,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { w32v_decoder_t *this ; config_values_t *cfg; - if (iface_version != 5) { + if (iface_version != 6) { printf( "w32codec: plugin doesn't support plugin API version %d.\n" "w32codec: this means there's a version mismatch between xine and this " "w32codec: decoder plugin.\nInstalling current input plugins should help.\n", @@ -1302,6 +1324,7 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, xine_t *xine) { this->video_decoder.init = w32v_init; this->video_decoder.decode_data = w32v_decode_data; this->video_decoder.flush = w32v_flush; + this->video_decoder.reset = w32v_reset; this->video_decoder.close = w32v_close; this->video_decoder.get_identifier = w32v_get_id; this->video_decoder.priority = 1; @@ -1322,7 +1345,7 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, xine_t *xine) { w32a_decoder_t *this ; config_values_t *cfg; - if (iface_version != 5) { + if (iface_version != 6) { printf( "w32codec: plugin doesn't support plugin API version %d.\n" "w32codec: this means there's a version mismatch between xine and this " "w32codec: decoder plugin.\nInstalling current input plugins should help.\n", diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 172557345..04139231d 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.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: audio_decoder.c,v 1.69 2002/04/06 02:56:04 miguelfreitas Exp $ + * $Id: audio_decoder.c,v 1.70 2002/04/09 03:38:01 miguelfreitas Exp $ * * * functions that implement audio decoding @@ -70,7 +70,7 @@ void *audio_decoder_loop (void *this_gen) { if (buf->input_time) this->cur_input_time = buf->input_time; - + switch (buf->type) { case BUF_CONTROL_START: @@ -128,20 +128,16 @@ void *audio_decoder_loop (void *this_gen) { case BUF_CONTROL_NOP: break; - case BUF_CONTROL_DISCONTINUITY: - /* reseting decoder on discontinuities is needed to make sure there will - * be no held back pts values. it's unlikely that it would do any harm - * given metronom's in_discontinuity counter but, at least in theory, - * we might have problems with still frame + audio dvd menus. - */ + case BUF_CONTROL_RESET_DECODER: if (this->cur_audio_decoder_plugin) - this->cur_audio_decoder_plugin->reset (this->cur_audio_decoder_plugin); + this->cur_audio_decoder_plugin->reset (this->cur_audio_decoder_plugin); + break; + + case BUF_CONTROL_DISCONTINUITY: this->metronom->handle_audio_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); break; case BUF_CONTROL_NEWPTS: - if (this->cur_audio_decoder_plugin) - this->cur_audio_decoder_plugin->reset (this->cur_audio_decoder_plugin); this->metronom->handle_audio_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); break; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index e4be9b9bb..3d70f54c6 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.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: buffer.h,v 1.38 2002/03/24 14:15:37 guenter Exp $ + * $Id: buffer.h,v 1.39 2002/04/09 03:38:01 miguelfreitas Exp $ * * * contents: @@ -70,7 +70,7 @@ extern "C" { #define BUF_CONTROL_AUDIO_CHANNEL 0x01050000 #define BUF_CONTROL_SPU_CHANNEL 0x01060000 #define BUF_CONTROL_NEWPTS 0x01070000 -#define BUF_CONTROL_SEEK 0x01080000 +#define BUF_CONTROL_RESET_DECODER 0x01080000 /* video buffer types: (please keep in sync with buffer_types.c) */ diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 5e00d273d..62abe76b3 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.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: metronom.c,v 1.79 2002/04/07 12:09:38 miguelfreitas Exp $ + * $Id: metronom.c,v 1.80 2002/04/09 03:38:01 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -368,14 +368,12 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { #endif if (abs (diff) > VIDEO_DRIFT_TOLERANCE) { - + this->video_vpts = vpts; this->video_drift = 0; - -#ifdef LOG + printf ("metronom: video jump\n"); -#endif - + } else { this->video_drift = diff; diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 69c06bbff..d0c5ef4a6 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -252,12 +252,6 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) { this->event.vpts = vpts; this->video_overlay->add_event(this->video_overlay,(void *)&this->event); - this->event.event_type = EVENT_FREE_HANDLE; - this->event.vpts = vpts+1; - this->video_overlay->add_event(this->video_overlay,(void *)&this->event); - - osd->handle = -1; /* handle will be freed */ - pthread_mutex_unlock (&this->osd_mutex); return 1; @@ -777,6 +771,16 @@ static void osd_free_object (osd_object_t *osd_to_close) { if( osd_to_close->handle >= 0 ) { osd_hide(osd_to_close,0); + + this->event.object.handle = osd_to_close->handle; + + /* not really needed this, but good pratice to clean it up */ + memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) ); + this->event.event_type = EVENT_FREE_HANDLE; + this->event.vpts = 0; + this->video_overlay->add_event(this->video_overlay,(void *)&this->event); + + osd_to_close->handle = -1; /* handle will be freed */ } pthread_mutex_lock (&this->osd_mutex); diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 035326005..359c28274 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.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: video_decoder.c,v 1.80 2002/03/27 15:30:16 miguelfreitas Exp $ + * $Id: video_decoder.c,v 1.81 2002/04/09 03:38:01 miguelfreitas Exp $ * */ @@ -181,13 +181,19 @@ void *video_decoder_loop (void *this_gen) { running = 0; break; + case BUF_CONTROL_RESET_DECODER: + if (this->cur_video_decoder_plugin) { + this->cur_video_decoder_plugin->reset (this->cur_video_decoder_plugin); + } + break; + case BUF_CONTROL_DISCONTINUITY: printf ("video_decoder: discontinuity ahead\n"); this->video_in_discontinuity = 1; this->metronom->handle_video_discontinuity (this->metronom, DISC_RELATIVE, buf->disc_off); - + this->video_in_discontinuity = 0; break; @@ -197,7 +203,7 @@ void *video_decoder_loop (void *this_gen) { this->video_in_discontinuity = 1; this->metronom->handle_video_discontinuity (this->metronom, DISC_ABSOLUTE, buf->disc_off); - + this->video_in_discontinuity = 0; break; @@ -301,8 +307,5 @@ void video_decoder_shutdown (xine_t *this) { this->video_fifo->put (this->video_fifo, buf); pthread_join (this->video_thread, &p); - - this->video_out->exit (this->video_out); - this->video_fifo->dispose (this->video_fifo); } diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index b090cddeb..43ccff317 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.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: video_out.c,v 1.92 2002/04/02 19:29:09 esnel Exp $ + * $Id: video_out.c,v 1.93 2002/04/09 03:38:01 miguelfreitas Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -666,11 +666,14 @@ static void *video_out_loop (void *this_gen) { diff = vpts - this->last_delivery_pts; if (diff > 30000 && !this->display_img_buf_queue->first) { if (this->xine->cur_video_decoder_plugin) { - this->xine->cur_video_decoder_plugin->flush(this->xine->cur_video_decoder_plugin); #ifdef LOG - printf ("video_out: flushing current video decoder plugin\n"); + printf ("video_out: flushing current video decoder plugin (%d %d)\n", + this->display_img_buf_queue->num_buffers, + this->free_img_buf_queue->num_buffers); #endif + + this->xine->cur_video_decoder_plugin->flush(this->xine->cur_video_decoder_plugin); } this->last_delivery_pts = vpts; } @@ -700,6 +703,10 @@ static void *video_out_loop (void *this_gen) { usec_to_sleep, vpts); #endif + if ( (next_frame_vpts - vpts) > 2*90000 ) + printf("video_out: vpts/clock error, next_vpts=%lld cur_vpts=%lld\n", + next_frame_vpts,vpts); + if (usec_to_sleep>0) xine_usec_sleep (usec_to_sleep); diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index abe7d9db9..f6694dcd9 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.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: xine.c,v 1.113 2002/03/24 14:15:37 guenter Exp $ + * $Id: xine.c,v 1.114 2002/04/09 03:38:01 miguelfreitas Exp $ * * top-level xine functions * @@ -92,6 +92,33 @@ void xine_notify_stream_finished (xine_t *this) { } } +/* internal use only - called from demuxers on seek/stop + * warning: after clearing decoders fifos an absolute discontinuity + * indication must be sent. relative discontinuities are likely + * to cause "jumps" on metronom. + */ +void xine_flush_engine (xine_t *this) { + + buf_element_t *buf; + + this->video_fifo->clear(this->video_fifo); + if( this->audio_fifo ) + this->audio_fifo->clear(this->audio_fifo); + + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->type = BUF_CONTROL_RESET_DECODER; + this->video_fifo->put (this->video_fifo, buf); + + if(this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_CONTROL_RESET_DECODER; + this->audio_fifo->put (this->audio_fifo, buf); + } + + this->metronom->adjust_clock(this->metronom, + this->metronom->get_current_time(this->metronom) + 30 * 90000 ); +} + static void xine_internal_osd (xine_t *this, char *str, uint32_t start_time, uint32_t duration) { @@ -282,10 +309,10 @@ int xine_play (xine_t *this, char *mrl, pthread_mutex_lock (&this->xine_lock); /* - * stop engine? + * stop engine only for different mrl */ - if (this->status == XINE_PLAY) { + if (this->status == XINE_PLAY && strcmp (mrl, this->cur_mrl) ) { if(this->cur_demuxer_plugin) { this->cur_demuxer_plugin->stop (this->cur_demuxer_plugin); @@ -305,76 +332,82 @@ int xine_play (xine_t *this, char *mrl, this->status = XINE_STOP; } - /* - * find input plugin - */ - - this->cur_input_plugin = NULL; + if (this->status == XINE_STOP ) { + /* + * find input plugin + */ + this->cur_input_plugin = NULL; - for (i = 0; i < this->num_input_plugins; i++) { - if (this->input_plugins[i]->open(this->input_plugins[i], mrl)) { - this->cur_input_plugin = this->input_plugins[i]; - break; + for (i = 0; i < this->num_input_plugins; i++) { + if (this->input_plugins[i]->open(this->input_plugins[i], mrl)) { + this->cur_input_plugin = this->input_plugins[i]; + break; + } } - } - if (!this->cur_input_plugin) { - xine_log (this, XINE_LOG_FORMAT, - _("xine: cannot find input plugin for this MRL\n")); - this->cur_demuxer_plugin = NULL; - this->err = XINE_ERROR_NO_INPUT_PLUGIN; - pthread_mutex_unlock (&this->xine_lock); + if (!this->cur_input_plugin) { + xine_log (this, XINE_LOG_FORMAT, + _("xine: cannot find input plugin for this MRL\n")); + this->cur_demuxer_plugin = NULL; + this->err = XINE_ERROR_NO_INPUT_PLUGIN; + pthread_mutex_unlock (&this->xine_lock); - return 0; - } + return 0; + } - printf ("xine: using input plugin >%s< for this MRL (%s).\n", - this->cur_input_plugin->get_identifier(this->cur_input_plugin), mrl); + printf ("xine: using input plugin >%s< for this MRL (%s).\n", + this->cur_input_plugin->get_identifier(this->cur_input_plugin), mrl); - xine_log (this, XINE_LOG_FORMAT, - _("using input plugin '%s' for MRL '%s'\n"), - this->cur_input_plugin->get_identifier(this->cur_input_plugin), - mrl); + xine_log (this, XINE_LOG_FORMAT, + _("using input plugin '%s' for MRL '%s'\n"), + this->cur_input_plugin->get_identifier(this->cur_input_plugin), + mrl); - /* - * find demuxer plugin - */ + /* + * find demuxer plugin + */ - if (!find_demuxer(this, mrl)) { - xine_log (this, XINE_LOG_FORMAT, - _("xine: couldn't find demuxer for >%s<\n"), mrl); - this->err = XINE_ERROR_NO_DEMUXER_PLUGIN; - pthread_mutex_unlock (&this->xine_lock); - return 0; - } + if (!find_demuxer(this, mrl)) { + xine_log (this, XINE_LOG_FORMAT, + _("xine: couldn't find demuxer for >%s<\n"), mrl); + this->err = XINE_ERROR_NO_DEMUXER_PLUGIN; + pthread_mutex_unlock (&this->xine_lock); + return 0; + } - xine_log (this, XINE_LOG_FORMAT, - _("system layer format '%s' detected.\n"), - this->cur_demuxer_plugin->get_identifier()); - + xine_log (this, XINE_LOG_FORMAT, + _("system layer format '%s' detected.\n"), + this->cur_demuxer_plugin->get_identifier()); + } + /* * start demuxer */ if (start_pos) { + /* FIXME: do we need to protect concurrent access to input plugin here? */ len = this->cur_input_plugin->get_length (this->cur_input_plugin); share = (double) start_pos / 65535; pos = (off_t) (share * len) ; } else pos = 0; - - this->cur_demuxer_plugin->start (this->cur_demuxer_plugin, - this->video_fifo, - this->audio_fifo, - pos, start_time); + + if( this->status == XINE_STOP ) + this->cur_demuxer_plugin->start (this->cur_demuxer_plugin, + this->video_fifo, + this->audio_fifo, + pos, start_time); + else + this->cur_demuxer_plugin->seek (this->cur_demuxer_plugin, + pos, start_time); if (this->cur_demuxer_plugin->get_status(this->cur_demuxer_plugin) != DEMUX_OK) { xine_log (this, XINE_LOG_MSG, _("xine_play: demuxer failed to start\n")); - this->cur_input_plugin->close(this->cur_input_plugin); - - this->status = XINE_STOP; + if( this->status == XINE_STOP ) + this->cur_input_plugin->close(this->cur_input_plugin); + } else { this->status = XINE_PLAY; @@ -383,6 +416,7 @@ int xine_play (xine_t *this, char *mrl, xine_set_speed_internal (this, SPEED_NORMAL); /* osd */ + xine_usec_sleep(100000); /* FIXME: how do we assure an updated cur_input_time? */ xine_internal_osd (this, ">", this->metronom->get_current_time (this->metronom), 300000); } @@ -426,6 +460,8 @@ void xine_exit (xine_t *this) { video_decoder_shutdown (this); this->osd_renderer->close( this->osd_renderer ); + this->video_out->exit (this->video_out); + this->video_fifo->dispose (this->video_fifo); this->status = XINE_QUIT; diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 7e7f375b1..8afb1d402 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.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: xine_internal.h,v 1.74 2002/03/18 19:34:17 guenter Exp $ + * $Id: xine_internal.h,v 1.75 2002/04/09 03:38:01 miguelfreitas Exp $ * */ @@ -55,7 +55,7 @@ extern "C" { #define INPUT_PLUGIN_MAX 50 #define DEMUXER_PLUGIN_MAX 50 #define DECODER_PLUGIN_MAX 256 -#define DECODER_PLUGIN_IFACE_VERSION 5 +#define DECODER_PLUGIN_IFACE_VERSION 6 #define AUDIO_OUT_PLUGIN_MAX 50 #define VIDEO_OUT_PLUGIN_MAX 50 #define XINE_MAX_EVENT_LISTENERS 50 @@ -80,6 +80,8 @@ struct video_decoder_s { void (*decode_data) (video_decoder_t *this, buf_element_t *buf); + void (*reset) (video_decoder_t *this); + void (*flush) (video_decoder_t *this); void (*close) (video_decoder_t *this); @@ -407,6 +409,7 @@ char **xine_get_autoplay_mrls (xine_t *this, char *plugin_id, int *num_mrls); */ void xine_notify_stream_finished (xine_t *this); +void xine_flush_engine (xine_t *this); /* * video decoder stuff -- cgit v1.2.3