summaryrefslogtreecommitdiff
path: root/sys/ximage/ximagesink.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ximage/ximagesink.c')
-rw-r--r--sys/ximage/ximagesink.c110
1 files changed, 81 insertions, 29 deletions
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