diff options
Diffstat (limited to 'src/demuxers')
-rw-r--r-- | src/demuxers/demux.h | 19 | ||||
-rw-r--r-- | src/demuxers/demux_asf.c | 192 | ||||
-rw-r--r-- | src/demuxers/demux_avi.c | 283 | ||||
-rw-r--r-- | src/demuxers/demux_cda.c | 96 | ||||
-rw-r--r-- | src/demuxers/demux_elem.c | 119 | ||||
-rw-r--r-- | src/demuxers/demux_mpeg.c | 185 | ||||
-rw-r--r-- | src/demuxers/demux_mpeg_block.c | 133 | ||||
-rw-r--r-- | src/demuxers/demux_mpgaudio.c | 104 | ||||
-rw-r--r-- | src/demuxers/demux_ogg.c | 111 | ||||
-rw-r--r-- | src/demuxers/demux_pes.c | 181 | ||||
-rw-r--r-- | src/demuxers/demux_qt.c | 229 | ||||
-rw-r--r-- | src/demuxers/demux_ts.c | 211 |
12 files changed, 1219 insertions, 644 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_pos<cur_pos) - start_pos = cur_pos; + if (start_pos < this->header_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; i<this->avi->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; i<this->avi->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; } |