diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-04-23 14:33:01 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-04-23 14:33:01 +0000 |
commit | a3a060c862eafe9e8e204a3d208a585457246879 (patch) | |
tree | b72599d8b0db4691b1fd9ed3bb2cafddc3b87783 | |
parent | 774c7546d0e1308abda154de9279c3e4f8a4537b (diff) | |
download | xine-lib-a3a060c862eafe9e8e204a3d208a585457246879.tar.gz xine-lib-a3a060c862eafe9e8e204a3d208a585457246879.tar.bz2 |
faster seeking (heavily based on Thibaut's patch)
rework xine_play_internal, wait for first frame after seek
CVS patchset: 4660
CVS date: 2003/04/23 14:33:01
-rw-r--r-- | src/xine-engine/metronom.h | 6 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 69 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 3 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 81 |
4 files changed, 107 insertions, 52 deletions
diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 9dd5b946d..03933ce6f 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.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: metronom.h,v 1.45 2003/04/20 21:13:23 guenter Exp $ + * $Id: metronom.h,v 1.46 2003/04/23 14:33:01 miguelfreitas Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -63,10 +63,10 @@ typedef struct scr_plugin_s scr_plugin_t; /* metronom prebuffer can be adjusted with XINE_PARAM_METRONOM_PREBUFFER. * it sets how much the first video/audio frame should be delayed to * have some prebuffering at the output layers. reducing this value (about - * 1/3 sec) may result in faster seeking (good to simulate play backwards, + * 1/10 sec) may result in faster seeking (good to simulate play backwards, * for example). */ -#define PREBUFFER_PTS_OFFSET 30000 +#define PREBUFFER_PTS_OFFSET 9000 /* see below */ #define DISC_STREAMSTART 0 diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 03d60c851..c82ca2e7f 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.152 2003/04/02 12:28:09 hadess Exp $ + * $Id: video_out.c,v 1.153 2003/04/23 14:33:02 miguelfreitas Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -372,6 +372,25 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { printf ("video_out: frame is ok => appending to display buffer\n"); #endif + /* + * check for first frame after seek and mark it + */ + img->is_first = 0; + pthread_mutex_lock(&this->streams_lock); + for (stream = xine_list_first_content(this->streams); stream; + stream = xine_list_next_content(this->streams)) { + pthread_mutex_lock (&stream->first_frame_lock); + if (stream->first_frame_flag == 2) { + stream->first_frame_flag = (this->grab_only)?0:1; + img->is_first = 1; +#ifdef LOG + printf ("video_out: get_next_video_frame first_frame_reached\n"); +#endif + } + pthread_mutex_unlock (&stream->first_frame_lock); + } + pthread_mutex_unlock(&this->streams_lock); + vo_frame_inc_lock( img ); vo_append_to_img_buf_queue (this->display_img_buf_queue, img); @@ -500,6 +519,21 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { diff = 1000000; /* always enter the while-loop */ while (img && (diff > img->duration || this->discard_frames)) { + + if (img->is_first) { +#ifdef LOG + printf("video_out: expire_frames: first_frame !\n"); +#endif + /* + * before displaying the first frame without + * "metronom prebuffering" we should make sure it's + * not used as a decoder reference anymore. + */ + if( img->lock_counter == 1 ) + img->vpts = cur_vpts; + break; + } + pts = img->vpts; diff = cur_vpts - pts; @@ -712,17 +746,19 @@ static void overlay_and_display_frame (vos_t *this, /* * Wake up xine_play if it's waiting for a frame */ - pthread_mutex_lock(&this->streams_lock); - for (stream = xine_list_first_content(this->streams); stream; - stream = xine_list_next_content(this->streams)) { - pthread_mutex_lock (&stream->first_frame_lock); - if (stream->first_frame_flag) { - stream->first_frame_flag = 0; - pthread_cond_broadcast(&stream->first_frame_reached); + if( this->last_frame->is_first ) { + pthread_mutex_lock(&this->streams_lock); + for (stream = xine_list_first_content(this->streams); stream; + stream = xine_list_next_content(this->streams)) { + pthread_mutex_lock (&stream->first_frame_lock); + if (stream->first_frame_flag) { + stream->first_frame_flag = 0; + pthread_cond_broadcast(&stream->first_frame_reached); + } + pthread_mutex_unlock (&stream->first_frame_lock); } - pthread_mutex_unlock (&stream->first_frame_lock); + pthread_mutex_unlock(&this->streams_lock); } - pthread_mutex_unlock(&this->streams_lock); this->redraw_needed = 0; } @@ -802,7 +838,12 @@ static void *video_out_loop (void *this_gen) { int64_t frame_duration, next_frame_vpts; int64_t usec_to_sleep; - /* nice(-2); */ + /* nice(-value) will fail silently for normal users. + * however when running as root this may provide smoother + * playback. follow the link for more information: + * http://cambuca.ldhs.cetuc.puc-rio.br/~miguel/multimedia_sim/ + */ + nice(-2); /* * here it is - the heart of xine (or rather: one of the hearts @@ -838,9 +879,9 @@ static void *video_out_loop (void *this_gen) { printf ("video_out: displaying frame (id=%d)\n", img->id); #endif overlay_and_display_frame (this, img, vpts); - } - else - { + + } else { + check_redraw_needed( this, vpts ); } diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 1c06eb75e..94b7403ed 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.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: video_out.h,v 1.84 2003/04/20 21:13:25 guenter Exp $ + * $Id: video_out.h,v 1.85 2003/04/23 14:33:03 miguelfreitas Exp $ * * * xine version of video_out.h @@ -141,6 +141,7 @@ struct vo_frame_s { pthread_mutex_t mutex; /* protect access to lock_count */ int id; /* debugging - track this frame */ + int is_first; }; diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 5bba920cd..373541243 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.244 2003/04/22 23:30:55 tchamp Exp $ + * $Id: xine.c,v 1.245 2003/04/23 14:33:05 miguelfreitas Exp $ * * top-level xine functions * @@ -903,21 +903,25 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t if (stream->xine->clock->speed != XINE_SPEED_NORMAL) xine_set_speed_internal (stream, XINE_SPEED_NORMAL); - /* Wait until the first frame produced by the previous - * xine_play call is pushed into the video_out fifo - * see video_out.c - */ - pthread_mutex_lock (&stream->first_frame_lock); - /* FIXME: howto detect if video frames will be produced */ - if (stream->first_frame_flag && stream->video_decoder_plugin) { - struct timeval tv; - struct timespec ts; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + 2; - ts.tv_nsec = tv.tv_usec * 1000; - pthread_cond_timedwait(&stream->first_frame_reached, &stream->first_frame_lock, &ts); + if (!stream->demux_plugin) { + xine_log (stream->xine, XINE_LOG_MSG, + _("xine_play: no demux available\n")); + stream->err = XINE_ERROR_NO_DEMUX_PLUGIN; + + return 0; } - pthread_mutex_unlock (&stream->first_frame_lock); + + /* hint demuxer thread we want to interrupt it */ + stream->demux_action_pending = 1; + + /* discard audio/video buffers to get engine going and take the lock faster */ + if (stream->audio_out) + stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); + if (stream->video_out) + stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); + + pthread_mutex_lock( &stream->demux_lock ); + /* demux_lock taken. now demuxer is suspended */ /* * start/seek demux @@ -926,7 +930,6 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t pthread_mutex_lock( &stream->current_extra_info_lock ); len = stream->current_extra_info->input_length; pthread_mutex_unlock( &stream->current_extra_info_lock ); - /* FIXME: do we need to protect concurrent access to input plugin here? */ if ((len == 0) && stream->input_plugin) len = stream->input_plugin->get_length (stream->input_plugin); share = (double) start_pos / 65535; @@ -934,30 +937,28 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t } else pos = 0; - if (!stream->demux_plugin) { - xine_log (stream->xine, XINE_LOG_MSG, - _("xine_play: no demux available\n")); - stream->err = XINE_ERROR_NO_DEMUX_PLUGIN; - - return 0; - } - - stream->demux_action_pending = 1; - if (stream->audio_out) - stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); - if (stream->video_out) - stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); - pthread_mutex_lock( &stream->demux_lock ); + /* seek to new position (no data is sent to decoders yet) */ demux_status = stream->demux_plugin->seek (stream->demux_plugin, pos, start_time); + stream->demux_action_pending = 0; + if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0); if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); + + /* before resuming the demuxer, set first_frame_flag */ pthread_mutex_lock (&stream->first_frame_lock); - stream->first_frame_flag = 1; + stream->first_frame_flag = 2; pthread_mutex_unlock (&stream->first_frame_lock); + + /* before resuming the demuxer, reset current position information */ + pthread_mutex_lock( &stream->current_extra_info_lock ); + extra_info_reset( stream->current_extra_info ); + pthread_mutex_unlock( &stream->current_extra_info_lock ); + + /* now resume demuxer thread if it is running already */ pthread_mutex_unlock( &stream->demux_lock ); if (demux_status != DEMUX_OK) { @@ -973,9 +974,21 @@ static int xine_play_internal (xine_stream_t *stream, int start_pos, int start_t stream->status = XINE_STATUS_PLAY; } - pthread_mutex_lock( &stream->current_extra_info_lock ); - extra_info_reset( stream->current_extra_info ); - pthread_mutex_unlock( &stream->current_extra_info_lock ); + + /* Wait until the first frame produced is displayed + * see video_out.c + */ + pthread_mutex_lock (&stream->first_frame_lock); + /* FIXME: howto detect if video frames will be produced */ + if (stream->first_frame_flag && stream->video_decoder_plugin) { + struct timeval tv; + struct timespec ts; + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec + 2; + ts.tv_nsec = tv.tv_usec * 1000; + pthread_cond_timedwait(&stream->first_frame_reached, &stream->first_frame_lock, &ts); + } + pthread_mutex_unlock (&stream->first_frame_lock); if (stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) printf ("xine: xine_play_internal ...done\n"); |