diff options
Diffstat (limited to 'src/demuxers/demux_avi.c')
-rw-r--r-- | src/demuxers/demux_avi.c | 283 |
1 files changed, 164 insertions, 119 deletions
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; } |