Commit 50d428b9 authored by Julien Moutte's avatar Julien Moutte
Browse files

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.
parent e69b9404
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> 2007-01-07 Sébastien Moutte <sebastien@moutte.net>
   
* win32/common/libgsaudio.def: * win32/common/libgsaudio.def:
...@@ -202,7 +202,7 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage) ...@@ -202,7 +202,7 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
g_return_if_fail (ximage != NULL); g_return_if_fail (ximage != NULL);
ximagesink = ximage->ximagesink; ximagesink = ximage->ximagesink;
if (!ximagesink) { if (G_UNLIKELY (ximagesink == NULL)) {
GST_WARNING_OBJECT (ximagesink, "no sink found"); GST_WARNING_OBJECT (ximagesink, "no sink found");
goto beach; goto beach;
} }
...@@ -301,7 +301,7 @@ gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent) ...@@ -301,7 +301,7 @@ gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
char error_msg[1024]; char error_msg[1024];
XGetErrorText (display, xevent->error_code, 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; error_caught = TRUE;
return 0; return 0;
} }
...@@ -406,6 +406,7 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps) ...@@ -406,6 +406,7 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
GstXImageBuffer *ximage = NULL; GstXImageBuffer *ximage = NULL;
GstStructure *structure = NULL; GstStructure *structure = NULL;
gboolean succeeded = FALSE; gboolean succeeded = FALSE;
int (*handler) (Display *, XErrorEvent *);
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL); g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
...@@ -423,14 +424,22 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps) ...@@ -423,14 +424,22 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
g_mutex_lock (ximagesink->x_lock); 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 #ifdef HAVE_XSHM
if (ximagesink->xcontext->use_xshm) { if (ximagesink->xcontext->use_xshm) {
ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp, ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
ximagesink->xcontext->visual, ximagesink->xcontext->visual,
ximagesink->xcontext->depth, ximagesink->xcontext->depth,
ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height); ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
if (!ximage->ximage) { if (!ximage->ximage || error_caught) {
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
/* Push an error */
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels", ("Failed to create output image buffer of %dx%d pixels",
ximage->width, ximage->height), ximage->width, ximage->height),
...@@ -494,8 +503,12 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps) ...@@ -494,8 +503,12 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
ximagesink->xcontext->depth, ximagesink->xcontext->depth,
ZPixmap, 0, NULL, ZPixmap, 0, NULL,
ximage->width, ximage->height, ximagesink->xcontext->bpp, 0); ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
if (!ximage->ximage) { if (!ximage->ximage || error_caught) {
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
/* Push an error */
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels", ("Failed to create output image buffer of %dx%d pixels",
ximage->width, ximage->height), ximage->width, ximage->height),
...@@ -510,6 +523,11 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps) ...@@ -510,6 +523,11 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
XSync (ximagesink->xcontext->disp, FALSE); XSync (ximagesink->xcontext->disp, FALSE);
} }
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
succeeded = TRUE; succeeded = TRUE;
GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data; GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
...@@ -536,14 +554,14 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink, ...@@ -536,14 +554,14 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
g_return_if_fail (ximage != NULL); g_return_if_fail (ximage != NULL);
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); 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 the destroyed image is the current one we destroy our reference too */
if (ximagesink->cur_image == ximage) { if (ximagesink->cur_image == ximage) {
ximagesink->cur_image = NULL; 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 */ /* We might have some buffers destroyed after changing state to NULL */
if (!ximagesink->xcontext) { if (!ximagesink->xcontext) {
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext"); GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
...@@ -640,6 +658,11 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) ...@@ -640,6 +658,11 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
concurrently from the data flow thread */ concurrently from the data flow thread */
g_mutex_lock (ximagesink->flow_lock); 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 when displaying the first frame. After this
draw borders only on expose event. */ draw borders only on expose event. */
if (!ximagesink->cur_image) { if (!ximagesink->cur_image) {
...@@ -875,10 +898,12 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -875,10 +898,12 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
/* Then we get all pointer motion events, only the last position is /* Then we get all pointer motion events, only the last position is
interesting. */ interesting. */
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp, while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, PointerMotionMask, &e)) { ximagesink->xwindow->win, PointerMotionMask, &e)) {
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) { switch (e.type) {
case MotionNotify: case MotionNotify:
...@@ -889,10 +914,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -889,10 +914,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
default: default:
break; break;
} }
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
} }
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
if (pointer_moved) { if (pointer_moved) {
GST_DEBUG ("ximagesink pointer moved over window at %d,%d", GST_DEBUG ("ximagesink pointer moved over window at %d,%d",
...@@ -903,6 +929,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -903,6 +929,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
} }
/* We get all remaining events on our window to throw them upstream */ /* We get all remaining events on our window to throw them upstream */
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp, while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, ximagesink->xwindow->win,
...@@ -912,6 +939,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -912,6 +939,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
/* We lock only for the X function call */ /* We lock only for the X function call */
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) { switch (e.type) {
case ButtonPress: case ButtonPress:
...@@ -949,17 +977,21 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -949,17 +977,21 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)", GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)",
e.type); e.type);
} }
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
} }
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
{ {
gboolean exposed = FALSE; gboolean exposed = FALSE;
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
while (XCheckWindowEvent (ximagesink->xcontext->disp, while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, ExposureMask, &e)) { ximagesink->xwindow->win, ExposureMask, &e)) {
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
switch (e.type) { switch (e.type) {
case Expose: case Expose:
...@@ -968,10 +1000,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) ...@@ -968,10 +1000,11 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
default: default:
break; break;
} }
g_mutex_lock (ximagesink->flow_lock);
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
} }
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
if (exposed) { if (exposed) {
gst_ximagesink_expose (GST_X_OVERLAY (ximagesink)); gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
...@@ -1335,17 +1368,28 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) ...@@ -1335,17 +1368,28 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
ximagesink->fps_d = gst_value_get_fraction_denominator (fps); ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
/* Notify application to set xwindow id now */ /* Notify application to set xwindow id now */
g_mutex_lock (ximagesink->flow_lock);
if (!ximagesink->xwindow) { if (!ximagesink->xwindow) {
g_mutex_unlock (ximagesink->flow_lock);
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink)); gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink));
} else {
g_mutex_unlock (ximagesink->flow_lock);
} }
/* Creating our window and our image */ /* Creating our window and our image */
g_assert (GST_VIDEO_SINK_WIDTH (ximagesink) > 0); if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 ||
g_assert (GST_VIDEO_SINK_HEIGHT (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) { if (!ximagesink->xwindow) {
ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink, ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink,
GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (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 /* If our ximage has changed we destroy it, next chain iteration will create
a new one */ a new one */
...@@ -1402,6 +1446,10 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition) ...@@ -1402,6 +1446,10 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: 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; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break; break;
...@@ -1417,8 +1465,6 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition) ...@@ -1417,8 +1465,6 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
if (ximagesink->xwindow)
gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
ximagesink->fps_n = 0; ximagesink->fps_n = 0;
ximagesink->fps_d = 1; ximagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (ximagesink) = 0; GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
...@@ -1440,10 +1486,13 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition) ...@@ -1440,10 +1486,13 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
gst_ximagesink_bufferpool_clear (ximagesink); gst_ximagesink_bufferpool_clear (ximagesink);
g_mutex_lock (ximagesink->flow_lock);
if (ximagesink->xwindow) { if (ximagesink->xwindow) {
gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
ximagesink->xwindow = NULL; ximagesink->xwindow = NULL;
} }
g_mutex_unlock (ximagesink->flow_lock);
gst_ximagesink_xcontext_clear (ximagesink); gst_ximagesink_xcontext_clear (ximagesink);
break; break;
...@@ -1774,25 +1823,25 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id) ...@@ -1774,25 +1823,25 @@ gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
GstXWindow *xwindow = NULL; GstXWindow *xwindow = NULL;
XWindowAttributes attr; 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 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; return;
}
/* If the element has not initialized the X11 context try to do so */ /* If the element has not initialized the X11 context try to do so */
if (!ximagesink->xcontext) if (!ximagesink->xcontext &&
ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink); !(ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink))) {
g_mutex_unlock (ximagesink->flow_lock);
if (!ximagesink->xcontext) { /* we have thrown a GST_ELEMENT_ERROR now */
GST_WARNING_OBJECT (ximagesink,
"ximagesink was unable to obtain the X11 context.");
return; 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 a window is there already we destroy it */
if (ximagesink->xwindow) { if (ximagesink->xwindow) {
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
...@@ -1841,9 +1890,6 @@ gst_ximagesink_expose (GstXOverlay * overlay) ...@@ -1841,9 +1890,6 @@ gst_ximagesink_expose (GstXOverlay * overlay)
{ {
GstXImageSink *ximagesink = GST_XIMAGESINK (overlay); GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
if (!ximagesink->xwindow)
return;
gst_ximagesink_ximage_put (ximagesink, NULL); gst_ximagesink_ximage_put (ximagesink, NULL);
} }
...@@ -1855,8 +1901,12 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay, ...@@ -1855,8 +1901,12 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay,
ximagesink->handle_events = handle_events; 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; return;
}
g_mutex_lock (ximagesink->x_lock); g_mutex_lock (ximagesink->x_lock);
...@@ -1875,6 +1925,8 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay, ...@@ -1875,6 +1925,8 @@ gst_ximagesink_set_event_handling (GstXOverlay * overlay,
} }
g_mutex_unlock (ximagesink->x_lock); g_mutex_unlock (ximagesink->x_lock);
g_mutex_unlock (ximagesink->flow_lock);
} }
static void static void
......
...@@ -217,17 +217,18 @@ gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage) ...@@ -217,17 +217,18 @@ gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
GST_DEBUG_OBJECT (xvimage, "Destroying buffer"); GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
xvimagesink = xvimage->xvimagesink; xvimagesink = xvimage->xvimagesink;
if (xvimagesink == NULL) if (G_UNLIKELY (xvimagesink == NULL))
goto no_sink; goto no_sink;
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); 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 the destroyed image is the current one we destroy our reference too */
if (xvimagesink->cur_image == xvimage) if (xvimagesink->cur_image == xvimage)
xvimagesink->cur_image = NULL; xvimagesink->cur_image = NULL;
/* We might have some buffers destroyed after changing state to NULL */ /* We might have some buffers destroyed after changing state to NULL */
GST_OBJECT_LOCK (xvimagesink);
if (xvimagesink->xcontext == NULL) { if (xvimagesink->xcontext == NULL) {
GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext"); GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
#ifdef HAVE_XSHM #ifdef HAVE_XSHM
...@@ -293,6 +294,8 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage) ...@@ -293,6 +294,8 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
if (G_UNLIKELY (xvimagesink == NULL)) if (G_UNLIKELY (xvimagesink == NULL))
goto no_sink; goto no_sink;
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
GST_OBJECT_LOCK (xvimagesink); GST_OBJECT_LOCK (xvimagesink);
running = xvimagesink->running; running = xvimagesink->running;
GST_OBJECT_UNLOCK (xvimagesink); GST_OBJECT_UNLOCK (xvimagesink);
...@@ -389,7 +392,7 @@ gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent) ...@@ -389,7 +392,7 @@ gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
char error_msg[1024]; char error_msg[1024];
XGetErrorText (display, xevent->error_code, 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; error_caught = TRUE;
return 0; return 0;
} }
...@@ -499,6 +502,7 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps) ...@@ -499,6 +502,7 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
GstXvImageBuffer *xvimage = NULL; GstXvImageBuffer *xvimage = NULL;
GstStructure *structure = NULL; GstStructure *structure = NULL;
gboolean succeeded = FALSE; gboolean succeeded = FALSE;
int (*handler) (Display *, XErrorEvent *);
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
...@@ -528,14 +532,22 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps) ...@@ -528,14 +532,22 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
g_mutex_lock (xvimagesink->x_lock); 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 #ifdef HAVE_XSHM
if (xvimagesink->xcontext->use_xshm) { if (xvimagesink->xcontext->use_xshm) {
xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp, xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id, xvimagesink->xcontext->xv_port_id,
xvimage->im_format, NULL, xvimage->im_format, NULL,
xvimage->width, xvimage->height, &xvimage->SHMInfo); xvimage->width, xvimage->height, &xvimage->SHMInfo);
if (!xvimage->xvimage) { if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock); g_mutex_unlock (xvimagesink->x_lock);
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
/* Push an error */
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels", ("Failed to create output image buffer of %dx%d pixels",
xvimage->width, xvimage->height), xvimage->width, xvimage->height),
...@@ -598,8 +610,12 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps) ...@@ -598,8 +610,12 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp, xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id, xvimagesink->xcontext->xv_port_id,
xvimage->im_format, NULL, xvimage->width, xvimage->height); xvimage->im_format, NULL, xvimage->width, xvimage->height);
if (!xvimage->xvimage) { if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock); g_mutex_unlock (xvimagesink->x_lock);
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
/* Push an error */
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
("Failed to create outputimage buffer of %dx%d pixels", ("Failed to create outputimage buffer of %dx%d pixels",
xvimage->width, xvimage->height), xvimage->width, xvimage->height),
...@@ -614,6 +630,11 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps) ...@@ -614,6 +630,11 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
XSync (xvimagesink->xcontext->disp, FALSE); XSync (xvimagesink->xcontext->disp, FALSE);
} }
/* Reset error handler */
error_caught = FALSE;
XSetErrorHandler (handler);
succeeded = TRUE; succeeded = TRUE;
GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;