From b7a84a23a7c682fa8fb4a6a7cfc0f3394be4c331 Mon Sep 17 00:00:00 2001 From: Thibaut Mattern Date: Sun, 23 May 2004 21:30:26 +0000 Subject: Improve seeking smoothness. 1 - When a first frame is still referenced, poll until there is only one reference. (with a limit, see FIRST_FRAME_MAX_POLL). This way the frame is displayed as soon as possible. 2 - When a "flush" occured, don't wait the full duration of the frame and exit the waing loop as soon as possible. The problems have been identified and fixed using a toxine script to stress seeking. It's available here (requires toxine cvs) : http://xine.sourceforge.net/tmattern/seek_test_1.toxine It performs approx. 500 seeks. I have tested avi, asf, mov, mpg, mkv streams. The engine can do a bit more than 10 seeks per second here (athlon 2.6 GHz), with all kind of streams. ;) toxine has been improved to support a such script (env vars, and the "repeat" command), thanks to Daniel. CVS patchset: 6585 CVS date: 2004/05/23 21:30:26 --- src/xine-engine/video_out.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index a6b6e3e2e..c52b04ad8 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.193 2004/05/13 21:38:49 jstembridge Exp $ + * $Id: video_out.c,v 1.194 2004/05/23 21:30:26 tmattern Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -55,6 +55,10 @@ #define MAX_USEC_TO_SLEEP 20000 #define DEFAULT_FRAME_DURATION 3000 /* 30 frames per second */ +/* wait this delay if the first frame is still referenced */ +#define FIRST_FRAME_POLL_DELAY 3000 +#define FIRST_FRAME_MAX_POLL 10 /* poll n times at most */ + #define NULL_STREAM (xine_stream_t *)-1 typedef struct { @@ -401,7 +405,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { } frames_to_skip = ((-1 * diff) / duration + this->frame_drop_limit) * 2; - if (frames_to_skip<0) + if (frames_to_skip < 0) frames_to_skip = 0; lprintf ("delivery diff : %" PRId64 ", current vpts is %" PRId64 ", %d frames to skip\n", @@ -440,8 +444,8 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if (stream == NULL_STREAM) continue; 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; + stream->first_frame_flag = (this->grab_only) ? 0 : 1; + img->is_first = FIRST_FRAME_MAX_POLL; lprintf ("get_next_video_frame first_frame_reached\n"); } @@ -649,8 +653,15 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { * "metronom prebuffering" we should make sure it's * not used as a decoder reference anymore. */ - if( img->lock_counter == 1 ) + if( img->lock_counter == 1 ) { + /* display it immediately */ img->vpts = cur_vpts; + } else { + /* poll */ + lprintf("frame still referenced %d times, is_first=%d\n", img->lock_counter, img->is_first); + img->vpts = cur_vpts + FIRST_FRAME_POLL_DELAY; + } + img->is_first--; break; } @@ -1071,13 +1082,15 @@ static void *video_out_loop (void *this_gen) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); - if (usec_to_sleep > 0) + if (usec_to_sleep > 0) xine_usec_sleep (usec_to_sleep); + if (this->discard_frames) + break; + } while ( (usec_to_sleep > 0) && this->video_loop_running); } - /* * throw away undisplayed frames */ @@ -1456,7 +1469,7 @@ static void vo_flush (xine_video_port_t *this_gen) { pthread_mutex_lock(&this->display_img_buf_queue->mutex); this->discard_frames++; pthread_mutex_unlock(&this->display_img_buf_queue->mutex); - + /* do not try this in paused mode */ while(this->clock->speed != XINE_SPEED_PAUSE) { pthread_mutex_lock(&this->display_img_buf_queue->mutex); @@ -1491,7 +1504,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon pthread_mutex_init(&this->streams_lock, NULL); pthread_mutex_init(&this->driver_lock, NULL ); - + this->vo.open = vo_open; this->vo.get_frame = vo_get_frame; this->vo.get_last_frame = vo_get_last_frame; -- cgit v1.2.3