summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-04-23 14:33:01 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-04-23 14:33:01 +0000
commita3a060c862eafe9e8e204a3d208a585457246879 (patch)
treeb72599d8b0db4691b1fd9ed3bb2cafddc3b87783
parent774c7546d0e1308abda154de9279c3e4f8a4537b (diff)
downloadxine-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.h6
-rw-r--r--src/xine-engine/video_out.c69
-rw-r--r--src/xine-engine/video_out.h3
-rw-r--r--src/xine-engine/xine.c81
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");