summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;