summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Moutte <julien@moutte.net>2007-01-07 18:50:13 +0000
committerJulien Moutte <julien@moutte.net>2007-01-07 18:50:13 +0000
commit50d428b9563fb89309d7606e8cc8eb9f984e9f09 (patch)
tree6250ab7af995f0c4c85f52dd9b2e873b0c0eb857
parente69b94048d852d8a618ba2cf3fce864faec1b790 (diff)
sys/: Use flow_lock much more to protect every access to xwindow.
Original commit message from CVS: 2007-01-07 Julien MOUTTE <julien@moutte.net> * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), (gst_ximagesink_handle_xerror), (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_destroy), (gst_ximagesink_ximage_put), (gst_ximagesink_handle_xevents), (gst_ximagesink_setcaps), (gst_ximagesink_change_state), (gst_ximagesink_set_xwindow_id), (gst_ximagesink_expose), (gst_ximagesink_set_event_handling): * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), (gst_xvimage_buffer_finalize), (gst_xvimagesink_handle_xerror), (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_put), (gst_xvimagesink_handle_xevents), (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state), (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_expose), (gst_xvimagesink_set_event_handling): Use flow_lock much more to protect every access to xwindow. Try to catch erros while creating images in case some drivers are just generating an XError when the requested image is too big. Should fix : #354698, #384008, #384060. * tests/icles/stress-xoverlay.c: (cycle_window), (create_window): Implement some stress testing of setting window xid.
-rw-r--r--ChangeLog21
-rw-r--r--sys/ximage/ximagesink.c110
-rw-r--r--sys/xvimage/xvimagesink.c86
-rw-r--r--tests/icles/stress-xoverlay.c44
4 files changed, 201 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ad039ff..b13b0598 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2007-01-07 Julien MOUTTE <julien@moutte.net>
+
+ * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize),
+ (gst_ximagesink_handle_xerror), (gst_ximagesink_ximage_new),
+ (gst_ximagesink_ximage_destroy), (gst_ximagesink_ximage_put),
+ (gst_ximagesink_handle_xevents), (gst_ximagesink_setcaps),
+ (gst_ximagesink_change_state), (gst_ximagesink_set_xwindow_id),
+ (gst_ximagesink_expose), (gst_ximagesink_set_event_handling):
+ * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy),
+ (gst_xvimage_buffer_finalize), (gst_xvimagesink_handle_xerror),
+ (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_put),
+ (gst_xvimagesink_handle_xevents), (gst_xvimagesink_setcaps),
+ (gst_xvimagesink_change_state), (gst_xvimagesink_set_xwindow_id),
+ (gst_xvimagesink_expose), (gst_xvimagesink_set_event_handling):
+ Use flow_lock much more to protect every access to xwindow.
+ Try to catch erros while creating images in case some drivers are
+ just generating an XError when the requested image is too big.
+ Should fix : #354698, #384008, #384060.
+ * tests/icles/stress-xoverlay.c: (cycle_window), (create_window):
+ Implement some stress testing of setting window xid.
+
2007-01-07 Sébastien Moutte <sebastien@moutte.net>
* win32/common/libgsaudio.def:
diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c
index 7ca9d6c8..06ec5486 100644
--- a/sys/ximage/ximagesink.c
+++ b/sys/ximage/ximagesink.c
@@ -202,7 +202,7 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
g_return_if_fail (ximage != NULL);
ximagesink = ximage->ximagesink;
- if (!ximagesink) {
+ if (G_UNLIKELY (ximagesink == NULL)) {
GST_WARNING_OBJECT (ximagesink, "no sink found");
goto beach;
}
@@ -301,7 +301,7 @@ gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
char error_msg[1024];
XGetErrorText (display, xevent->error_code, error_msg, 1024);
- GST_DEBUG ("ximagesink failed to use XShm calls. error: %s", error_msg);
+ GST_DEBUG ("ximagesink triggered an XError. error: %s", error_msg);
error_caught = TRUE;
return 0;
}
@@ -406,6 +406,7 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
GstXImageBuffer *ximage = NULL;
GstStructure *structure = NULL;
gboolean succeeded = FALSE;
+ int (*handler) (Display *, XErrorEvent *);
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
@@ -423,14 +424,22 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
g_mutex_lock (ximagesink->x_lock);
+ /* Setting an error handler to catch failure */
+ error_caught = FALSE;
+ handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
+
#ifdef HAVE_XSHM
if (ximagesink->xcontext->use_xshm) {
ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
ximagesink->xcontext->visual,
ximagesink->xcontext->depth,
ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
- if (!ximage->ximage) {
+ if (!ximage->ximage || error_caught) {
g_mutex_unlock (ximagesink->x_lock);
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+ /* Push an error */
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels",
ximage->width, ximage->height),
@@ -494,8 +503,12 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
ximagesink->xcontext->depth,
ZPixmap, 0, NULL,
ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
- if (!ximage->ximage) {
+ if (!ximage->ximage || error_caught) {
g_mutex_unlock (ximagesink->x_lock);
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+ /* Push an error */
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels",
ximage->width, ximage->height),
@@ -510,6 +523,11 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
XSync (ximagesink->xcontext->disp, FALSE);
}
+
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+
succeeded = TRUE;
GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
@@ -536,14 +554,14 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
g_return_if_fail (ximage != NULL);
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
+ /* Hold the object lock to ensure the XContext doesn't disappear */
+ GST_OBJECT_LOCK (ximagesink);
+
/* If the destroyed image is the current one we destroy our reference too */
if (ximagesink->cur_image == ximage) {
ximagesink->cur_image = NULL;
}
- /* Hold the object lock to ensure the XContext doesn't disappear */
- GST_OBJECT_LOCK (ximagesink);
-
/* We might have some buffers destroyed after changing state to NULL */
if (!ximagesink->xcontext) {
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
@@ -640,6 +658,11 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
concurrently from the data flow thread */
g_mutex_lock (ximagesink->flow_lock);
+ if (G_UNLIKELY (ximagesink->xwindow == NULL)) {
+ g_mutex_unlock (ximagesink->flow_lock);
+ return;
+ }
+
/* Draw borders when displaying the first frame. After this
draw borders only on expose event. */
if (!ximagesink->cur_image) {
@@ -875,10 +898,12 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
/* Then we get all pointer motion events, only the last position is
interesting. */
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, PointerMotionMask, &e)) {
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) {
case MotionNotify:
@@ -889,10 +914,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
default:
break;
}
-
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
}
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
if (pointer_moved) {
GST_DEBUG ("ximagesink pointer moved over window at %d,%d",
@@ -903,6 +929,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
}
/* We get all remaining events on our window to throw them upstream */
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win,
@@ -912,6 +939,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
/* We lock only for the X function call */
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) {
case ButtonPress:
@@ -949,17 +977,21 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)",
e.type);
}
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
}
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
{
gboolean exposed = FALSE;
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, ExposureMask, &e)) {
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) {
case Expose:
@@ -968,10 +1000,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
default:
break;
}
-
+ g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock);
}
g_mutex_unlock (ximagesink->x_lock);
+ g_mutex_unlock (ximagesink->flow_lock);
if (exposed) {
gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
@@ -1335,17 +1368,28 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
/* Notify application to set xwindow id now */
+ g_mutex_lock (ximagesink->flow_lock);
if (!ximagesink->xwindow) {
+ g_mutex_unlock (ximagesink->flow_lock);
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink));
+ } else {
+ g_mutex_unlock (ximagesink->flow_lock);
}
/* Creating our window and our image */
- g_assert (GST_VIDEO_SINK_WIDTH (ximagesink) > 0);
- g_assert (GST_VIDEO_SINK_HEIGHT (ximagesink) > 0);
+ if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 ||
+ GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0) {
+ GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL),
+ ("Invalid image size."));
+ return FALSE;
+ }
+
+ g_mutex_lock (ximagesink->flow_lock);
if (!ximagesink->xwindow) {
ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink,
GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
}
+ g_mutex_unlock (ximagesink->flow_lock);
/* If our ximage has changed we destroy it, next chain iteration will create
a new one */
@@ -1402,6 +1446,10 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
g_mutex_unlock (ximagesink->x_lock);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
+ g_mutex_lock (ximagesink->flow_lock);
+ if (ximagesink->xwindow)
+ gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
+ g_mutex_unlock (ximagesink->flow_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@@ -1417,8 +1465,6 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- if (ximagesink->xwindow)
- gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
ximagesink->fps_n = 0;
ximagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
@@ -1440,10 +1486,13 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
gst_ximagesink_bufferpool_clear (ximagesink);
+ g_mutex_lock (ximagesink->flow_lock);
if (ximagesink->xwindow) {
+ gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
ximagesink->xwindow = NULL;
}
+ g_mutex_unlock (ximagesink->flow_lock);
gst_ximagesink_xcontext_clear (ximagesink);
break;
@@ -1774,25 +1823,25 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
GstXWindow *xwindow = NULL;
XWindowAttributes attr;
+ /* We acquire the stream lock while setting this window in the element.
+ We are basically cleaning tons of stuff replacing the old window, putting
+ images while we do that would surely crash */
+ g_mutex_lock (ximagesink->flow_lock);
+
/* If we already use that window return */
- if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win))
+ if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win)) {
+ g_mutex_unlock (ximagesink->flow_lock);
return;
+ }
/* If the element has not initialized the X11 context try to do so */
- if (!ximagesink->xcontext)
- ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink);
-
- if (!ximagesink->xcontext) {
- GST_WARNING_OBJECT (ximagesink,
- "ximagesink was unable to obtain the X11 context.");
+ if (!ximagesink->xcontext &&
+ !(ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink))) {
+ g_mutex_unlock (ximagesink->flow_lock);
+ /* we have thrown a GST_ELEMENT_ERROR now */
return;
}
- /* We acquire the stream lock while setting this window in the element.
- We are basically cleaning tons of stuff replacing the old window, putting
- images while we do that would surely crash */
- g_mutex_lock (ximagesink->flow_lock);
-
/* If a window is there already we destroy it */
if (ximagesink->xwindow) {
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
@@ -1841,9 +1890,6 @@ gst_ximagesink_expose (GstXOverlay * overlay)
{
GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
- if (!ximagesink->xwindow)
- return;
-
gst_ximagesink_ximage_put (ximagesink, NULL);
}
@@ -1855,8 +1901,12 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay,
ximagesink->handle_events = handle_events;
- if (!ximagesink->xwindow)
+ g_mutex_lock (ximagesink->flow_lock);
+
+ if (G_UNLIKELY (!ximagesink->xwindow)) {
+ g_mutex_unlock (ximagesink->flow_lock);
return;
+ }
g_mutex_lock (ximagesink->x_lock);
@@ -1875,6 +1925,8 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay,
}
g_mutex_unlock (ximagesink->x_lock);
+
+ g_mutex_unlock (ximagesink->flow_lock);
}
static void
diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
index 01efd4b0..0fbfb579 100644
--- a/sys/xvimage/xvimagesink.c
+++ b/sys/xvimage/xvimagesink.c
@@ -217,17 +217,18 @@ gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
xvimagesink = xvimage->xvimagesink;
- if (xvimagesink == NULL)
+ if (G_UNLIKELY (xvimagesink == NULL))
goto no_sink;
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+ GST_OBJECT_LOCK (xvimagesink);
+
/* If the destroyed image is the current one we destroy our reference too */
if (xvimagesink->cur_image == xvimage)
xvimagesink->cur_image = NULL;
/* We might have some buffers destroyed after changing state to NULL */
- GST_OBJECT_LOCK (xvimagesink);
if (xvimagesink->xcontext == NULL) {
GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
#ifdef HAVE_XSHM
@@ -293,6 +294,8 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
if (G_UNLIKELY (xvimagesink == NULL))
goto no_sink;
+ g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+
GST_OBJECT_LOCK (xvimagesink);
running = xvimagesink->running;
GST_OBJECT_UNLOCK (xvimagesink);
@@ -389,7 +392,7 @@ gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
char error_msg[1024];
XGetErrorText (display, xevent->error_code, error_msg, 1024);
- GST_DEBUG ("xvimagesink failed to use XShm calls. error: %s", error_msg);
+ GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
error_caught = TRUE;
return 0;
}
@@ -499,6 +502,7 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
GstXvImageBuffer *xvimage = NULL;
GstStructure *structure = NULL;
gboolean succeeded = FALSE;
+ int (*handler) (Display *, XErrorEvent *);
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
@@ -528,14 +532,22 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
g_mutex_lock (xvimagesink->x_lock);
+ /* Setting an error handler to catch failure */
+ error_caught = FALSE;
+ handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
+
#ifdef HAVE_XSHM
if (xvimagesink->xcontext->use_xshm) {
xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id,
xvimage->im_format, NULL,
xvimage->width, xvimage->height, &xvimage->SHMInfo);
- if (!xvimage->xvimage) {
+ if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock);
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+ /* Push an error */
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels",
xvimage->width, xvimage->height),
@@ -598,8 +610,12 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id,
xvimage->im_format, NULL, xvimage->width, xvimage->height);
- if (!xvimage->xvimage) {
+ if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock);
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+ /* Push an error */
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
("Failed to create outputimage buffer of %dx%d pixels",
xvimage->width, xvimage->height),
@@ -614,6 +630,11 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
XSync (xvimagesink->xcontext->disp, FALSE);
}
+
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+
succeeded = TRUE;
GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
@@ -675,12 +696,16 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
gboolean draw_border = FALSE;
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
- g_return_if_fail (xvimagesink->xwindow != NULL);
/* We take the flow_lock. If expose is in there we don't want to run
concurrently from the data flow thread */
g_mutex_lock (xvimagesink->flow_lock);
+ if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
+ g_mutex_unlock (xvimagesink->flow_lock);
+ return;
+ }
+
/* Draw borders when displaying the first frame. After this
draw borders only on expose event. */
if (!xvimagesink->cur_image) {
@@ -996,10 +1021,12 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
/* We get all pointer motion events, only the last position is
interesting. */
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
xvimagesink->xwindow->win, PointerMotionMask, &e)) {
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
switch (e.type) {
case MotionNotify:
@@ -1010,10 +1037,11 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
default:
break;
}
-
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
}
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
if (pointer_moved) {
GST_DEBUG ("xvimagesink pointer moved over window at %d,%d",
@@ -1023,6 +1051,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
}
/* We get all events on our window to throw them upstream */
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
xvimagesink->xwindow->win,
@@ -1032,6 +1061,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
/* We lock only for the X function call */
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
switch (e.type) {
case ButtonPress:
@@ -1070,20 +1100,23 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
default:
GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type);
}
-
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
}
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
/* Handle Expose */
{
gboolean exposed = FALSE, configured = FALSE;
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask,
&e)) {
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
switch (e.type) {
case Expose:
@@ -1094,10 +1127,11 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
default:
break;
}
-
+ g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
}
g_mutex_unlock (xvimagesink->x_lock);
+ g_mutex_unlock (xvimagesink->flow_lock);
if (exposed || configured) {
gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
@@ -1862,8 +1896,12 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink));
/* Notify application to set xwindow id now */
+ g_mutex_lock (xvimagesink->flow_lock);
if (!xvimagesink->xwindow) {
+ g_mutex_unlock (xvimagesink->flow_lock);
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink));
+ } else {
+ g_mutex_unlock (xvimagesink->flow_lock);
}
/* Creating our window and our image with the display size in pixels */
@@ -1874,10 +1912,13 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
return FALSE;
}
- if (!xvimagesink->xwindow)
+ g_mutex_lock (xvimagesink->flow_lock);
+ if (!xvimagesink->xwindow) {
xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
GST_VIDEO_SINK_WIDTH (xvimagesink),
GST_VIDEO_SINK_HEIGHT (xvimagesink));
+ }
+ g_mutex_unlock (xvimagesink->flow_lock);
/* We renew our xvimage only if size or format changed;
* the xvimage is the same size as the video pixel size */
@@ -1936,8 +1977,10 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
gst_xvimagesink_update_colorbalance (xvimagesink);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
+ g_mutex_lock (xvimagesink->flow_lock);
if (xvimagesink->xwindow)
gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
+ g_mutex_unlock (xvimagesink->flow_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@@ -2325,17 +2368,21 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+ g_mutex_lock (xvimagesink->flow_lock);
+
/* If we already use that window return */
- if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win))
+ if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) {
+ g_mutex_unlock (xvimagesink->flow_lock);
return;
+ }
/* If the element has not initialized the X11 context try to do so */
if (!xvimagesink->xcontext &&
- !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink)))
+ !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) {
+ g_mutex_unlock (xvimagesink->flow_lock);
/* we have thrown a GST_ELEMENT_ERROR now */
return;
-
- g_mutex_lock (xvimagesink->flow_lock);
+ }
gst_xvimagesink_update_colorbalance (xvimagesink);
@@ -2399,9 +2446,6 @@ gst_xvimagesink_expose (GstXOverlay * overlay)
{
GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
- if (!xvimagesink->xwindow)
- return;
-
gst_xvimagesink_xvimage_put (xvimagesink, NULL);
}
@@ -2413,8 +2457,12 @@ gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
xvimagesink->handle_events = handle_events;
- if (!xvimagesink->xwindow)
+ g_mutex_lock (xvimagesink->flow_lock);
+
+ if (G_UNLIKELY (!xvimagesink->xwindow)) {
+ g_mutex_unlock (xvimagesink->flow_lock);
return;
+ }
g_mutex_lock (xvimagesink->x_lock);
@@ -2433,6 +2481,8 @@ gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
}
g_mutex_unlock (xvimagesink->x_lock);
+
+ g_mutex_unlock (xvimagesink->flow_lock);
}
static void
diff --git a/tests/icles/stress-xoverlay.c b/tests/icles/stress-xoverlay.c
index 63d8bb06..8dcaaef6 100644
--- a/tests/icles/stress-xoverlay.c
+++ b/tests/icles/stress-xoverlay.c
@@ -33,7 +33,7 @@
static GMainLoop *loop;
static Display *disp;
-static Window root, win;
+static Window root, win = 0;
static GC gc;
static gint width = 320, height = 240, x = 0, y = 0;
static gint disp_width, disp_height;
@@ -111,10 +111,37 @@ toggle_events (GstXOverlay * ov)
return TRUE;
}
+static gboolean
+cycle_window (GstXOverlay * ov)
+{
+ XGCValues values;
+ Window old_win = win;
+ GC old_gc = gc;
+
+ win = XCreateSimpleWindow (disp, root, 0, 0, width, height, 0, 0, 0);
+
+ XSetWindowBackgroundPixmap (disp, win, None);
+
+ gc = XCreateGC (disp, win, 0, &values);
+
+ XMapRaised (disp, win);
+
+ XSync (disp, FALSE);
+
+ gst_x_overlay_set_xwindow_id (ov, win);
+
+ if (old_win) {
+ XDestroyWindow (disp, old_win);
+ XFreeGC (disp, old_gc);
+ XSync (disp, FALSE);
+ }
+
+ return TRUE;
+}
+
static GstBusSyncReply
create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
- XGCValues values;
const GstStructure *s;
GstXOverlay *ov = NULL;
@@ -127,20 +154,11 @@ create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
g_print ("Creating our own window\n");
- win = XCreateSimpleWindow (disp, root, 0, 0, width, height, 0, 0, 0);
-
- XSetWindowBackgroundPixmap (disp, win, None);
-
- gc = XCreateGC (disp, win, 0, &values);
-
- XMapRaised (disp, win);
-
- XSync (disp, FALSE);
-
- gst_x_overlay_set_xwindow_id (ov, win);
+ cycle_window (ov);
g_timeout_add (50, (GSourceFunc) resize_window, pipeline);
g_timeout_add (50, (GSourceFunc) move_window, pipeline);
+ g_timeout_add (100, (GSourceFunc) cycle_window, ov);
g_timeout_add (2000, (GSourceFunc) toggle_events, ov);
return GST_BUS_DROP;