diff options
author | Reinhard Nißl <rnissl@gmx.de> | 2007-04-15 21:08:32 +0200 |
---|---|---|
committer | Reinhard Nißl <rnissl@gmx.de> | 2007-04-15 21:08:32 +0200 |
commit | 3b03ad66fd2d5a475938a28cbcd55ba0319204a9 (patch) | |
tree | 75340c4feedfb8422f6cc706c6c5af28b0ea6eeb /src | |
parent | ee7faf25388d4a2890bf3fa55288391cfe04851a (diff) | |
download | xine-lib-3b03ad66fd2d5a475938a28cbcd55ba0319204a9.tar.gz xine-lib-3b03ad66fd2d5a475938a28cbcd55ba0319204a9.tar.bz2 |
Make sleeps in video out loops interruptable for immediate OSD
redrawing.
The video out loop sleeps up to 20 ms (and the paused loop 20 ms)
which means that pending OSD events are delayed too from beeing
processed. When an OSD is used for example to scroll through a
list of VDR recordings, this delay may slow down scrolling
unnecessarily.
Especially when the OSD manager is able to render the OSD content
indepently from drawing a frame to screen, this change will allow
the fastest OSD update possible.
Diffstat (limited to 'src')
-rw-r--r-- | src/xine-engine/post.c | 9 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 49 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 3 |
3 files changed, 59 insertions, 2 deletions
diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index 58e9b633c..0dba50c82 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -149,6 +149,14 @@ static void post_video_flush(xine_video_port_t *port_gen) { if (port->port_lock) pthread_mutex_unlock(port->port_lock); } +static void post_video_trigger_drawing(xine_video_port_t *port_gen) { + post_video_port_t *port = (post_video_port_t *)port_gen; + + if (port->port_lock) pthread_mutex_lock(port->port_lock); + port->original_port->trigger_drawing(port->original_port); + if (port->port_lock) pthread_mutex_unlock(port->port_lock); +} + static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream, int *width, int *height, int64_t *img_duration) { post_video_port_t *port = (post_video_port_t *)port_gen; @@ -225,6 +233,7 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ port->new_port.exit = post_video_exit; port->new_port.get_overlay_manager = post_video_get_overlay_manager; port->new_port.flush = post_video_flush; + port->new_port.trigger_drawing = post_video_trigger_drawing; port->new_port.status = post_video_status; port->new_port.get_property = post_video_get_property; port->new_port.set_property = post_video_set_property; diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 2a3ee1980..d61df1eb2 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -1043,6 +1043,32 @@ static void check_redraw_needed (vos_t *this, int64_t vpts) { this->redraw_needed = 1; } +static int interruptable_sleep(vos_t *this, int usec_to_sleep) +{ + int timedout = 0; + + struct timeval now; + gettimeofday(&now, 0); + + pthread_mutex_lock (&this->trigger_drawing_mutex); + if (!this->trigger_drawing) { + struct timespec abstime; + abstime.tv_sec = now.tv_sec + usec_to_sleep / 1000000; + abstime.tv_nsec = now.tv_usec * 1000 + (usec_to_sleep % 1000000) * 1000; + + if (abstime.tv_nsec > 1000000000) { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } + + timedout = pthread_cond_timedwait(&this->trigger_drawing_cond, &this->trigger_drawing_mutex, &abstime); + } + this->trigger_drawing = 0; + pthread_mutex_unlock (&this->trigger_drawing_mutex); + + return timedout; +} + /* special loop for paused mode * needed to update screen due overlay changes, resize, window * movement, brightness adjusting etc. @@ -1088,7 +1114,7 @@ static void paused_loop( vos_t *this, int64_t vpts ) } pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); - xine_usec_sleep (20000); + interruptable_sleep(this, 20000); pthread_mutex_lock( &this->free_img_buf_queue->mutex ); } @@ -1218,7 +1244,10 @@ static void *video_out_loop (void *this_gen) { "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); if (usec_to_sleep > 0) - xine_usec_sleep (usec_to_sleep); + { + if (0 == interruptable_sleep(this, usec_to_sleep)) + break; + } if (this->discard_frames) break; @@ -1601,6 +1630,9 @@ static void vo_exit (xine_video_port_t *this_gen) { free (this->free_img_buf_queue); free (this->display_img_buf_queue); + pthread_cond_destroy(&this->trigger_drawing_cond); + pthread_mutex_destroy(&this->trigger_drawing_mutex); + free (this); } @@ -1670,6 +1702,15 @@ static void vo_flush (xine_video_port_t *this_gen) { } } +static void vo_trigger_drawing (xine_video_port_t *this_gen) { + vos_t *this = (vos_t *) this_gen; + + pthread_mutex_lock (&this->trigger_drawing_mutex); + this->trigger_drawing = 1; + pthread_cond_signal (&this->trigger_drawing_cond); + pthread_mutex_unlock (&this->trigger_drawing_mutex); +} + /* crop_frame() will allocate a new frame to copy in the given image * while cropping. maybe someday this will be an automatic post plugin. */ @@ -1765,6 +1806,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon this->vo.enable_ovl = vo_enable_overlay; this->vo.get_overlay_manager = vo_get_overlay_manager; this->vo.flush = vo_flush; + this->vo.trigger_drawing = vo_trigger_drawing; this->vo.get_property = vo_get_property; this->vo.set_property = vo_set_property; this->vo.status = vo_status; @@ -1842,6 +1884,9 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon "were not scheduled for display in time, xine sends a notification."), 20, NULL, NULL); + pthread_mutex_init(&this->trigger_drawing_mutex, NULL); + pthread_cond_init(&this->trigger_drawing_cond, NULL); + this->trigger_drawing = 0; if (grabonly) { diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 7b42c43ed..06e5eaaa9 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -205,6 +205,9 @@ struct xine_video_port_s { /* flush video_out fifo */ void (*flush) (xine_video_port_t *self); + /* trigger immediate drawing */ + void (*trigger_drawing) (xine_video_port_t *self); + /* Get/Set video property * * See VO_PROP_* bellow |