diff options
-rw-r--r-- | src/xine-engine/audio_out.c | 72 | ||||
-rw-r--r-- | src/xine-engine/demux.c | 38 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 101 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 28 |
4 files changed, 123 insertions, 116 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 7aa771866..6a786f2fc 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -17,7 +17,7 @@ * along with self program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_out.c,v 1.91 2002/12/21 16:12:25 miguelfreitas Exp $ + * $Id: audio_out.c,v 1.92 2002/12/22 23:30:29 miguelfreitas Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> @@ -524,11 +524,32 @@ static void *ao_loop (void *this_gen) { } if (this->flush_audio_driver) { + audio_buffer_t *buf; + int num_buffers; #ifdef LOG printf ("audio_out: flush audio driver\n"); #endif + pthread_mutex_lock (&this->out_fifo->mutex); + + num_buffers = this->out_fifo->num_buffers; + + printf ("audio_out: flush fifo (%d buffers)\n", num_buffers); + + while ( num_buffers-- ) { + buf = fifo_remove_int (this->out_fifo); + fifo_append (this->free_fifo, buf); + } + + pthread_mutex_unlock (&this->out_fifo->mutex); + + if (in_buf) { + fifo_append (this->free_fifo, in_buf); + in_buf = NULL; + } + this->control(this, AO_CTRL_FLUSH_BUFFERS); this->flush_audio_driver = 0; + continue; } /* @@ -862,20 +883,8 @@ static void ao_put_buffer (xine_audio_port_t *this, audio_buffer_t *buf, xine_st pts, buf->vpts); #endif - if ( buf->vpts + AO_MAX_GAP < this->last_audio_vpts) { - - /* reject buffer */ - printf ("audio_out: rejected buffer vpts=%lld, last_audio_vpts=%lld\n", - buf->vpts, this->last_audio_vpts); - - fifo_append (this->free_fifo, buf); - - } else { - - fifo_append (this->out_fifo, buf); - this->last_audio_vpts = buf->vpts; - - } + fifo_append (this->out_fifo, buf); + this->last_audio_vpts = buf->vpts; #ifdef LOG printf ("audio_out: ao_put_buffer done\n"); @@ -1042,31 +1051,18 @@ static int ao_control (xine_audio_port_t *this, int cmd, ...) { static void ao_flush (xine_audio_port_t *this) { audio_buffer_t *buf; - int i, num_buffers; - - pthread_mutex_lock (&this->out_fifo->mutex); - pthread_mutex_lock (&this->free_fifo->mutex); - num_buffers = this->out_fifo->num_buffers; - - printf ("audio_out: flush fifo (%d buffers)\n", num_buffers); - - for (i = 0; i < num_buffers; i++) { - buf = fifo_remove_int (this->out_fifo); - fifo_append_int (this->free_fifo, buf); + if( this->audio_loop_running ) { + this->flush_audio_driver = 1; + + buf = fifo_remove (this->free_fifo); + buf->num_frames = 0; + fifo_append (this->out_fifo, buf); + + /* do not try this in paused mode */ + while( this->flush_audio_driver ) + xine_usec_sleep (20000); /* pthread_cond_t could be used here */ } - - /* - * make sure ao_loop can savely quit - */ - - buf = fifo_remove_int (this->free_fifo); - buf->num_frames = 0; - fifo_append_int (this->out_fifo, buf); - - this->flush_audio_driver = 1; - pthread_mutex_unlock (&this->free_fifo->mutex); - pthread_mutex_unlock (&this->out_fifo->mutex); } xine_audio_port_t *ao_new_port (xine_t *xine, ao_driver_t *driver) { diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index 5f4ce9d70..20474d71f 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -31,8 +31,9 @@ #include "demuxers/demux.h" #include "buffer.h" +/* #define LOG - +*/ /* internal use only - called from demuxers on seek/stop * warning: after clearing decoders fifos an absolute discontinuity @@ -57,6 +58,11 @@ void xine_demux_flush_engine (xine_stream_t *stream) { buf->type = BUF_CONTROL_RESET_DECODER; stream->audio_fifo->put (stream->audio_fifo, buf); } + + /* on seeking we must wait decoder fifos to process before doing flush. + * otherwise we flush too early (before the old data has left decoders) + */ + xine_demux_control_headers_done (stream); if (stream->video_out) { stream->video_out->flush(stream->video_out); @@ -65,11 +71,6 @@ void xine_demux_flush_engine (xine_stream_t *stream) { if (stream->audio_out) { stream->audio_out->flush(stream->audio_out); } - - /* FIXME: Messing with the clock is bad as long as the clock is global to all streams. - * But it is currently the best solution to have good seeking performance. */ - stream->xine->clock->adjust_clock(stream->xine->clock, - stream->xine->clock->get_current_time(stream->xine->clock) + 30 * 90000 ); } @@ -92,10 +93,21 @@ void xine_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t fla } } +/* sync with decoder fifos, making sure everything gets processed */ void xine_demux_control_headers_done (xine_stream_t *stream) { + int header_count_audio; + int header_count_video; buf_element_t *buf; - + + pthread_mutex_lock (&stream->counter_lock); + if (stream->audio_fifo) + header_count_audio = stream->header_count_audio + 1; + else + header_count_audio = 0; + + header_count_video = stream->header_count_video + 1; + buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_HEADERS_DONE; stream->video_fifo->put (stream->video_fifo, buf); @@ -105,6 +117,18 @@ void xine_demux_control_headers_done (xine_stream_t *stream) { buf->type = BUF_CONTROL_HEADERS_DONE; stream->audio_fifo->put (stream->audio_fifo, buf); } + + while ((stream->header_count_audio<header_count_audio) || + (stream->header_count_video<header_count_video)) { +#ifdef LOG + printf ("xine: waiting for headers.\n"); +#endif + pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + } +#ifdef LOG + printf ("xine: headers processed.\n"); +#endif + pthread_mutex_unlock (&stream->counter_lock); } void xine_demux_control_start( xine_stream_t *stream ) { diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 16611629e..356a261bf 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.123 2002/12/22 15:02:07 miguelfreitas Exp $ + * $Id: video_out.c,v 1.124 2002/12/22 23:30:29 miguelfreitas Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -63,6 +63,7 @@ typedef struct { vo_frame_t *last_frame; vo_frame_t *img_backup; int redraw_needed; + int flush_frames; int video_loop_running; int video_opened; @@ -477,56 +478,67 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { diff = 1000000; /* always enter the while-loop */ - while (img && (diff > img->duration)) { + while (img && (diff > img->duration || this->flush_frames)) { pts = img->vpts; diff = cur_vpts - pts; - if (diff > img->duration) { + if (diff > img->duration || this->flush_frames) { - /* do not print this message in stop/exit (scr is adjusted to force - * discarding audio and video frames) - */ - if( diff < 20 * 90000 ) + if( !this->flush_frames ) { xine_log(this->xine, XINE_LOG_MSG, _("video_out: throwing away image with pts %lld because " "it's too old (diff : %lld).\n"), pts, diff); - this->num_frames_discarded++; - + this->num_frames_discarded++; + } + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue); extra_info_merge( img->stream->current_extra_info, img->extra_info ); - /* - * last frame? back it up for - * still frame creation - */ - - if (!this->display_img_buf_queue->first) { + /* when flushing frames, keep the first one as backup */ + if( this->flush_frames ) { + + if (!this->img_backup) { + this->img_backup = img; + + this->redraw_needed = 1; + } else { + vo_frame_dec_lock( img ); + } + + } else { + /* + * last frame? back it up for + * still frame creation + */ + + if (!this->display_img_buf_queue->first) { - if (this->img_backup) { + if (this->img_backup) { #ifdef LOG - printf("video_out: overwriting frame backup\n"); + printf("video_out: overwriting frame backup\n"); #endif - vo_frame_dec_lock( this->img_backup ); - } + vo_frame_dec_lock( this->img_backup ); + } #ifdef LOG - printf("video_out: possible still frame (old)\n"); + printf("video_out: possible still frame (old)\n"); #endif - this->img_backup = img; + this->img_backup = img; - /* wait 4 frames before drawing this one. - this allow slower systems to recover. */ - this->redraw_needed = 4; - } else { - vo_frame_dec_lock( img ); + /* wait 4 frames before drawing this one. + this allow slower systems to recover. */ + this->redraw_needed = 4; + } else { + vo_frame_dec_lock( img ); + } } - img = this->display_img_buf_queue->first; } } - + this->flush_frames = 0; + pthread_mutex_unlock(&this->display_img_buf_queue->mutex); } @@ -737,6 +749,8 @@ static void *video_out_loop (void *this_gen) { vos_t *this = (vos_t *) this_gen; int64_t frame_duration, next_frame_vpts; int64_t usec_to_sleep; + + /* nice(-2); */ /* * here it is - the heart of xine (or rather: one of the hearts @@ -886,6 +900,7 @@ static void vo_open (xine_video_port_t *this_gen, xine_stream_t *stream) { vos_t *this = (vos_t *) this_gen; this->video_opened = 1; + this->flush_frames = 0; this->last_delivery_pts = 0; if (!this->overlay_enabled && stream->spu_channel_user > -2) /* enable overlays if our new stream might want to show some */ @@ -1012,28 +1027,16 @@ static void vo_enable_overlay (xine_video_port_t *this_gen, int overlay_enabled) */ static void vo_flush (xine_video_port_t *this_gen) { vos_t *this = (vos_t *) this_gen; - vo_frame_t *img, *first; - int i, num_buffers; - - pthread_mutex_lock (&this->display_img_buf_queue->mutex); - num_buffers = this->display_img_buf_queue->num_buffers; - /* we keep the first frame so that we have something to display when - * seeking wildly around, but we schedule it in the past, so that it - * will expire immediately and does not block anything */ - first = this->display_img_buf_queue->first; - if (first) { - vo_frame_inc_lock(first); - first->vpts -= 30 * 90000; - } - printf ("video_out: flush fifo (%d buffers)\n", num_buffers); - for (i = 0; i < num_buffers; i++) { - img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue); - vo_frame_dec_lock( img ); + + if( this->video_loop_running ) { + pthread_mutex_lock(&this->display_img_buf_queue->mutex); + this->flush_frames = 1; + pthread_mutex_unlock(&this->display_img_buf_queue->mutex); + + /* do not try this in paused mode */ + while(this->flush_frames) + xine_usec_sleep (20000); /* pthread_cond_t could be used here */ } - if (first) - vo_append_to_img_buf_queue_int(this->display_img_buf_queue, first); - this->redraw_needed = 1; - pthread_mutex_unlock (&this->display_img_buf_queue->mutex); } diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 31d13ca11..94c1e81cd 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.c,v 1.201 2002/12/21 16:13:43 miguelfreitas Exp $ + * $Id: xine.c,v 1.202 2002/12/22 23:30:29 miguelfreitas Exp $ * * top-level xine functions * @@ -134,7 +134,7 @@ static void xine_set_speed_internal (xine_stream_t *stream, int speed) { * samples from the sound driver */ if (speed != XINE_SPEED_NORMAL && speed != XINE_SPEED_PAUSE) - stream->audio_out->flush(stream->audio_out); + stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS); stream->audio_out->control(stream->audio_out, speed == XINE_SPEED_PAUSE ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME); @@ -380,8 +380,6 @@ xine_stream_t *xine_stream_new (xine_t *this, static int xine_open_internal (xine_stream_t *stream, const char *mrl) { - int header_count_audio; - int header_count_video; char *stream_setup; #ifdef LOG @@ -644,9 +642,11 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) { stream->err = XINE_ERROR_NO_DEMUX_PLUGIN; /* remove buffered samples from the sound device driver */ - if (stream->audio_out) + /* why? */ + /*if (stream->audio_out) stream->audio_out->control (stream->audio_out, AO_CTRL_FLUSH_BUFFERS); - + */ + stream->status = XINE_STATUS_STOP; printf ("xine: return from xine_open_internal\n"); @@ -654,24 +654,8 @@ static int xine_open_internal (xine_stream_t *stream, const char *mrl) { return 0; } - pthread_mutex_lock (&stream->counter_lock); - if (stream->audio_fifo) - header_count_audio = stream->header_count_audio + 1; - else - header_count_audio = 0; - - header_count_video = stream->header_count_video + 1; - xine_demux_control_headers_done (stream); - while ((stream->header_count_audio<header_count_audio) || - (stream->header_count_video<header_count_video)) { - printf ("xine: waiting for headers.\n"); - pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); - } - printf ("xine: headers processed.\n"); - pthread_mutex_unlock (&stream->counter_lock); - #ifdef LOG printf ("xine: xine_open_internal done\n"); #endif |