summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-07-30 00:26:45 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-07-30 00:26:45 +0000
commit0daeb9d1c6f90b0b364421c2ef9e95b3cd6d3aa1 (patch)
treefdd8b147ae712c52e6c40251a9f87ee98a831d4b
parentd18ad5e4e7bcbef62d7e8facd1ee401dc5d7e39c (diff)
downloadxine-lib-0daeb9d1c6f90b0b364421c2ef9e95b3cd6d3aa1.tar.gz
xine-lib-0daeb9d1c6f90b0b364421c2ef9e95b3cd6d3aa1.tar.bz2
- video out fixes (never trigged deadlocks and erroneous flush of overlay
events) - duplicate_frame is now internal use only (api function deprecated) - special case for redrawing screen in paused mode (due overlay changes, resize, window movement, brightness adjusting etc) - xshm brightness may be adjusted with video paused CVS patchset: 2363 CVS date: 2002/07/30 00:26:45
-rw-r--r--src/video_out/video_out_xshm.c24
-rw-r--r--src/xine-engine/video_out.c250
-rw-r--r--src/xine-engine/video_out.h7
-rw-r--r--src/xine-engine/xine.c7
4 files changed, 187 insertions, 101 deletions
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c
index 2a2e98317..55f78da14 100644
--- a/src/video_out/video_out_xshm.c
+++ b/src/video_out/video_out_xshm.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_xshm.c,v 1.81 2002/07/20 21:46:05 esnel Exp $
+ * $Id: video_out_xshm.c,v 1.82 2002/07/30 00:26:45 miguelfreitas Exp $
*
* video_out_xshm.c, X11 shared memory extension interface for xine
*
@@ -74,7 +74,7 @@ typedef struct xshm_frame_s {
int format;
int flags;
- int user_ratio;
+ int user_ratio;
/*
* "ideal" size of this frame :
@@ -136,6 +136,9 @@ typedef struct xshm_driver_s {
uint8_t *yuv2rgb_cmap;
yuv2rgb_factory_t *yuv2rgb_factory;
int user_ratio;
+
+ /* force update screen if gamma changes */
+ int force_redraw;
/* speed tradeoffs */
int scaling_disabled;
@@ -809,8 +812,8 @@ static int xshm_redraw_needed (vo_driver_t *this_gen) {
int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y;
int ret = 0;
- if( this->cur_frame )
- {
+ if( this->cur_frame ) {
+
this->frame_output_cb (this->user_data,
this->cur_frame->ideal_width, this->cur_frame->ideal_height,
&gui_x, &gui_y, &gui_width, &gui_height,
@@ -834,10 +837,11 @@ static int xshm_redraw_needed (vo_driver_t *this_gen) {
}
}
else
- {
ret = 1;
- }
-
+
+ if( this->force_redraw )
+ ret = 1;
+
return ret;
}
@@ -904,7 +908,8 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
}
this->cur_frame = frame;
-
+ this->force_redraw = 0;
+
xoffset = (this->gui_width - frame->output_width) / 2 + this->gui_x;
yoffset = (this->gui_height - frame->output_height) / 2 + this->gui_y;
@@ -1005,7 +1010,10 @@ static int xshm_set_property (vo_driver_t *this_gen,
this->yuv2rgb_gamma = value;
this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, value);
+ this->force_redraw = 1;
+#ifdef LOG
printf ("video_out_xshm: gamma changed to %d\n",value);
+#endif
} else {
printf ("video_out_xshm: tried to set unsupported property %d\n", property);
}
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index f1f4261f7..c54a82932 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.100 2002/07/15 21:42:34 esnel Exp $
+ * $Id: video_out.c,v 1.101 2002/07/30 00:26:45 miguelfreitas Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -87,6 +87,7 @@ struct img_buf_fifo_s {
vo_frame_t *last;
int num_buffers;
+ int locked_for_read;
pthread_mutex_t mutex;
pthread_cond_t not_empty;
} ;
@@ -100,6 +101,7 @@ static img_buf_fifo_t *vo_new_img_buf_queue () {
queue->first = NULL;
queue->last = NULL;
queue->num_buffers = 0;
+ queue->locked_for_read = 0;
pthread_mutex_init (&queue->mutex, NULL);
pthread_cond_init (&queue->not_empty, NULL);
}
@@ -137,7 +139,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
pthread_mutex_lock (&queue->mutex);
- while (!queue->first) {
+ while (!queue->first || queue->locked_for_read) {
pthread_cond_wait (&queue->not_empty, &queue->mutex);
}
@@ -149,10 +151,6 @@ static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) {
if (!queue->first) {
queue->last = NULL;
queue->num_buffers = 0;
- /* I think this is a (pretty long-standing) bug
- guenter 21/03/2002
- pthread_cond_init (&queue->not_empty, NULL);
- */
}
else {
queue->num_buffers--;
@@ -323,6 +321,99 @@ static int vo_frame_draw (vo_frame_t *img) {
*
*/
+/* duplicate_frame(): this function is used to keep playing frames
+ * while video is still or player paused.
+ *
+ * frame allocation inside vo loop is dangerous:
+ * we must never wait for a free frame -> deadlock condition.
+ * to avoid deadlocks we don't use vo_remove_from_img_buf_queue()
+ * and reimplement a slightly modified version here.
+ * free_img_buf_queue->mutex must be grabbed prior entering it.
+ * (must assure that free frames won't be exhausted by decoder thread).
+ */
+static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) {
+
+ vo_frame_t *dupl;
+ int image_size;
+
+ if( !this->free_img_buf_queue->first)
+ return NULL;
+
+ dupl = this->free_img_buf_queue->first;
+ this->free_img_buf_queue->first = dupl->next;
+ dupl->next = NULL;
+ if (!this->free_img_buf_queue->first) {
+ this->free_img_buf_queue->last = NULL;
+ this->free_img_buf_queue->num_buffers = 0;
+ }
+ else {
+ this->free_img_buf_queue->num_buffers--;
+ }
+
+ pthread_mutex_lock (&dupl->mutex);
+ dupl->lock_counter = 1;
+ dupl->width = img->width;
+ dupl->height = img->height;
+ dupl->ratio = img->ratio;
+ dupl->format = img->format;
+
+ this->driver->update_frame_format (this->driver, dupl, dupl->width, dupl->height,
+ dupl->ratio, dupl->format, VO_BOTH_FIELDS);
+
+ pthread_mutex_unlock (&dupl->mutex);
+
+ image_size = img->pitches[0] * img->height;
+
+ if (img->format == IMGFMT_YV12) {
+ if (img->base[0])
+ xine_fast_memcpy(dupl->base[0], img->base[0], image_size);
+ if (img->base[1])
+ xine_fast_memcpy(dupl->base[1], img->base[1], img->pitches[1] * ((img->height+1)/2));
+ if (img->base[2])
+ xine_fast_memcpy(dupl->base[2], img->base[2], img->pitches[2] * ((img->height+1)/2));
+ } else {
+ if (img->base[0])
+ xine_fast_memcpy(dupl->base[0], img->base[0], image_size);
+ }
+
+ dupl->bad_frame = 0;
+ dupl->pts = 0;
+ dupl->vpts = 0;
+ dupl->duration = img->duration;
+
+ if (img->format == IMGFMT_YV12) {
+ if (img->copy) {
+ int height = img->height;
+ uint8_t* src[3];
+
+ src[0] = dupl->base[0];
+ src[1] = dupl->base[1];
+ src[2] = dupl->base[2];
+ while ((height -= 16) >= 0) {
+ dupl->copy(dupl, src);
+ src[0] += 16 * img->pitches[0];
+ src[1] += 8 * img->pitches[1];
+ src[2] += 8 * img->pitches[2];
+ }
+ }
+ } else {
+ if (img->copy) {
+ int height = img->height;
+ uint8_t* src[3];
+
+ src[0] = dupl->base[0];
+
+ while ((height -= 16) >= 0) {
+ dupl->copy(dupl, src);
+ src[0] += 16 * img->pitches[0];
+ }
+ }
+ }
+
+ return dupl;
+}
+
+
static void expire_frames (vos_t *this, int64_t cur_vpts) {
int64_t pts;
@@ -409,11 +500,14 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) {
printf("video_out: generating still frame (cur_vpts = %lld) \n",
cur_vpts);
#endif
-
+
/* keep playing still frames */
- img = this->vo.duplicate_frame (&this->vo, this->img_backup );
- img->vpts = cur_vpts;
-
+ pthread_mutex_lock( &this->free_img_buf_queue->mutex );
+ img = duplicate_frame (this, this->img_backup );
+ pthread_mutex_unlock( &this->free_img_buf_queue->mutex );
+ if( img )
+ img->vpts = cur_vpts;
+
return img;
} else {
@@ -453,6 +547,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) {
/*
* last frame? make backup for possible still image
*/
+ pthread_mutex_lock( &this->free_img_buf_queue->mutex );
if (img && !img->next &&
(this->xine->video_fifo->size(this->xine->video_fifo) < 10
|| this->xine->video_in_discontinuity) ) {
@@ -460,8 +555,9 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) {
printf ("video_out: possible still frame (fifosize = %d)\n",
this->xine->video_fifo->size(this->xine->video_fifo));
- this->img_backup = this->vo.duplicate_frame (&this->vo, img);
+ this->img_backup = duplicate_frame (this, img);
}
+ pthread_mutex_unlock( &this->free_img_buf_queue->mutex );
/*
* remove frame from display queue and show it
@@ -474,7 +570,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts) {
}
static void overlay_and_display_frame (vos_t *this,
- vo_frame_t *img) {
+ vo_frame_t *img, int64_t vpts) {
#ifdef LOG
printf ("video_out: displaying image with vpts = %lld\n",
@@ -482,11 +578,8 @@ static void overlay_and_display_frame (vos_t *this,
#endif
if (this->overlay_source) {
- /* This is the only way for the overlay manager to get pts values
- * for flushing its buffers. So don't remove it! */
-
this->overlay_source->multiple_overlay_blend (this->overlay_source,
- img->vpts,
+ vpts,
this->driver, img,
this->video_loop_running && this->overlay_enabled);
}
@@ -506,9 +599,6 @@ static void overlay_and_display_frame (vos_t *this,
static void check_redraw_needed (vos_t *this, int64_t vpts) {
if (this->overlay_source) {
- /* This is the only way for the overlay manager to get pts values
- * for flushing its buffers. So don't remove it! */
-
if( this->overlay_source->redraw_needed (this->overlay_source, vpts) )
this->redraw_needed = 1;
}
@@ -517,6 +607,57 @@ static void check_redraw_needed (vos_t *this, int64_t vpts) {
this->redraw_needed = 1;
}
+/* special loop for paused mode
+ * needed to update screen due overlay changes, resize, window
+ * movement, brightness adjusting etc.
+ */
+static void paused_loop( vos_t *this, int64_t vpts )
+{
+ vo_frame_t *img;
+
+ pthread_mutex_lock( &this->free_img_buf_queue->mutex );
+ /* prevent decoder thread from allocating new frames */
+ this->free_img_buf_queue->locked_for_read = 1;
+
+ while( this->xine->speed == SPEED_PAUSE ) {
+
+ /* we need at least one free frame to keep going */
+ if( this->display_img_buf_queue->first &&
+ !this->free_img_buf_queue->first ) {
+
+ img = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
+ img->next = NULL;
+ this->free_img_buf_queue->first = img;
+ this->free_img_buf_queue->last = img;
+ this->free_img_buf_queue->num_buffers = 1;
+ }
+
+ /* set img_backup to play the same frame several times */
+ if( this->display_img_buf_queue->first && !this->img_backup ) {
+ this->img_backup = vo_remove_from_img_buf_queue (this->display_img_buf_queue);
+ this->redraw_needed = 1;
+ }
+
+ check_redraw_needed( this, vpts );
+
+ if( this->redraw_needed && this->img_backup ) {
+ img = duplicate_frame (this, this->img_backup );
+ if( img ) {
+ pthread_mutex_unlock( &this->free_img_buf_queue->mutex );
+ overlay_and_display_frame (this, img, vpts);
+ pthread_mutex_lock( &this->free_img_buf_queue->mutex );
+ }
+ }
+
+ xine_usec_sleep (20000);
+ }
+
+ this->free_img_buf_queue->locked_for_read = 0;
+
+ if( this->free_img_buf_queue->first )
+ pthread_cond_signal (&this->free_img_buf_queue->not_empty);
+ pthread_mutex_unlock( &this->free_img_buf_queue->mutex );
+}
static void *video_out_loop (void *this_gen) {
@@ -559,7 +700,7 @@ static void *video_out_loop (void *this_gen) {
#ifdef LOG
printf ("video_out: displaying frame (id=%d)\n", img->id);
#endif
- overlay_and_display_frame (this, img);
+ overlay_and_display_frame (this, img, vpts);
}
else
{
@@ -604,6 +745,9 @@ static void *video_out_loop (void *this_gen) {
do {
vpts = this->metronom->get_current_time (this->metronom);
+
+ if( this->xine->speed == SPEED_PAUSE )
+ paused_loop( this, vpts );
usec_to_sleep = (next_frame_vpts - vpts) * 100 / 9;
@@ -653,70 +797,6 @@ static uint32_t vo_get_capabilities (vo_instance_t *this_gen) {
return this->driver->get_capabilities (this->driver);
}
-static vo_frame_t * vo_duplicate_frame( vo_instance_t *this_gen, vo_frame_t *img ) {
-
- vo_frame_t *dupl;
- /* vos_t *this = (vos_t *) this_gen; */
- int image_size;
-
- dupl = vo_get_frame (this_gen, img->width, img->height, img->ratio,
- img->format, VO_BOTH_FIELDS );
-
- image_size = img->pitches[0] * img->height;
-
- if (img->format == IMGFMT_YV12) {
- /* The dxr3 video out plugin does not allocate memory for the dxr3
- * decoder, so we must check for NULL */
- if (img->base[0])
- xine_fast_memcpy(dupl->base[0], img->base[0], image_size);
- if (img->base[1])
- xine_fast_memcpy(dupl->base[1], img->base[1], img->pitches[1] * ((img->height+1)/2));
- if (img->base[2])
- xine_fast_memcpy(dupl->base[2], img->base[2], img->pitches[2] * ((img->height+1)/2));
- } else {
- if (img->base[0])
- xine_fast_memcpy(dupl->base[0], img->base[0], image_size);
- }
-
- dupl->bad_frame = 0;
- dupl->pts = 0;
- dupl->vpts = 0;
- dupl->duration = img->duration;
-
- /* Support copy; Dangerous, since some decoders may use a source that's
- * not dupl->base. It's up to the copy implementation to check for NULL */
- if (img->format == IMGFMT_YV12) {
- if (img->copy) {
- int height = img->height;
- uint8_t* src[3];
-
- src[0] = dupl->base[0];
- src[1] = dupl->base[1];
- src[2] = dupl->base[2];
- while ((height -= 16) >= 0) {
- dupl->copy(dupl, src);
- src[0] += 16 * img->pitches[0];
- src[1] += 8 * img->pitches[1];
- src[2] += 8 * img->pitches[2];
- }
- }
- } else {
- if (img->copy) {
- int height = img->height;
- uint8_t* src[3];
-
- src[0] = dupl->base[0];
-
- while ((height -= 16) >= 0) {
- dupl->copy(dupl, src);
- src[0] += 16 * img->pitches[0];
- }
- }
- }
-
- return dupl;
-}
-
static void vo_open (vo_instance_t *this_gen) {
vos_t *this = (vos_t *) this_gen;
@@ -822,7 +902,7 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, xine_t *xine) {
this->vo.open = vo_open;
this->vo.get_frame = vo_get_frame;
- this->vo.duplicate_frame = vo_duplicate_frame;
+ this->vo.duplicate_frame = NULL; /* deprecated */
this->vo.get_last_frame = vo_get_last_frame;
this->vo.close = vo_close;
this->vo.exit = vo_exit;
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index 13a8df7f5..9f52e29a3 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.55 2002/07/15 21:42:34 esnel Exp $
+ * $Id: video_out.h,v 1.56 2002/07/30 00:26:45 miguelfreitas Exp $
*
*
* xine version of video_out.h
@@ -154,8 +154,9 @@ struct vo_instance_s {
vo_frame_t* (*get_last_frame) (vo_instance_t *this);
/*
- * duplicate_frame - allocate an image buffer from display driver
- * and copy the frame into it.
+ * duplicate_frame is deprecated and should be removed
+ * on the next api change.
+ * (will remain as an internal function only)
*/
vo_frame_t* (*duplicate_frame) (vo_instance_t *this, vo_frame_t *img );
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 80c9642e3..e4a43505e 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.145 2002/07/14 20:55:17 miguelfreitas Exp $
+ * $Id: xine.c,v 1.146 2002/07/30 00:26:45 miguelfreitas Exp $
*
* top-level xine functions
*
@@ -859,7 +859,7 @@ void xine_set_speed (xine_t *this, int speed) {
pthread_mutex_lock (&this->osd_lock);
switch (speed) {
case SPEED_PAUSE:
- xine_internal_osd (this, "<", 10000);
+ xine_internal_osd (this, "<", 90000);
break;
case SPEED_SLOW_4:
xine_internal_osd (this, "<>", 20000 * speed);
@@ -879,9 +879,6 @@ void xine_set_speed (xine_t *this, int speed) {
}
pthread_mutex_unlock (&this->osd_lock);
- /* make sure osd can be displayed */
- xine_usec_sleep(100000);
-
printf ("xine: set_speed %d\n", speed);
xine_set_speed_internal (this, speed);