From 2614bc1a48175d5339d3d7b063435aba6c2f33f1 Mon Sep 17 00:00:00 2001 From: Julien Moutte Date: Wed, 28 Jan 2004 00:29:42 +0000 Subject: [PATCH] sys/: Our Original commit message from CVS: 2004-01-28 Julien MOUTTE * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror), (gst_ximagesink_check_xshm_calls), (gst_ximagesink_ximage_destroy), (gst_ximagesink_xcontext_get), (gst_ximagesink_class_init): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xerror), (gst_xvimagesink_check_xshm_calls), (gst_xvimagesink_xvimage_destroy), (gst_xvimagesink_xcontext_get): Our X plugins are now able to detect that XShm calls will fail even if the server claims that it has XShm support (remote displays most of the time). We then log the error as a GST_DEBUG and set use_shm to FALSE so that we use non XShm functions. This feature is almost useless for xvimagesink as Xv is not supported on remote displays anyway, but it might happen than even on the local display XShm calls fail. --- ChangeLog | 15 ++++++ sys/ximage/ximagesink.c | 75 ++++++++++++++++++++++++++-- sys/xvimage/xvimagesink.c | 100 ++++++++++++++++++++++++++++++++------ 3 files changed, 173 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 609365433a..795d009206 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2004-01-28 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror), + (gst_ximagesink_check_xshm_calls), (gst_ximagesink_ximage_destroy), + (gst_ximagesink_xcontext_get), (gst_ximagesink_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xerror), + (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_destroy), (gst_xvimagesink_xcontext_get): Our + X plugins are now able to detect that XShm calls will fail even if the + server claims that it has XShm support (remote displays most of the + time). We then log the error as a GST_DEBUG and set use_shm to FALSE + so that we use non XShm functions. This feature is almost useless for + xvimagesink as Xv is not supported on remote displays anyway, but + it might happen than even on the local display XShm calls fail. + 2004-01-27 David Schleef * ext/esd/esdsink.c: (gst_esdsink_class_init), (gst_esdsink_init), diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c index 8012a0e962..fc1b4faec4 100644 --- a/sys/ximage/ximagesink.c +++ b/sys/ximage/ximagesink.c @@ -59,6 +59,7 @@ enum { }; static GstVideoSinkClass *parent_class = NULL; +static gboolean error_catched = FALSE; /* ============================================================= */ /* */ @@ -68,6 +69,71 @@ static GstVideoSinkClass *parent_class = NULL; /* X11 stuff */ +static int +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); + error_catched = TRUE; + return 0; +} + +/* This function checks that it is actually really possible to create an image + using XShm */ +static gboolean +gst_ximagesink_check_xshm_calls (GstXContext *xcontext) +{ + GstXImage *ximage = NULL; + int (*handler)(Display *, XErrorEvent *); + + g_return_val_if_fail (xcontext != NULL, FALSE); + +#ifdef HAVE_XSHM + ximage = g_new0 (GstXImage, 1); + + /* Setting an error handler to catch failure */ + handler = XSetErrorHandler (gst_ximagesink_handle_xerror); + + ximage->size = (xcontext->bpp / 8); + + /* Trying to create a 1x1 picture */ + ximage->ximage = XShmCreateImage (xcontext->disp, xcontext->visual, + xcontext->depth, ZPixmap, NULL, + &ximage->SHMInfo, 1, 1); + + ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size, IPC_CREAT | 0777); + ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, 0, 0); + ximage->ximage->data = ximage->SHMInfo.shmaddr; + ximage->SHMInfo.readOnly = FALSE; + + XShmAttach (xcontext->disp, &ximage->SHMInfo); + + error_catched = FALSE; + + XSync(xcontext->disp, 0); + + XSetErrorHandler (handler); + + if (error_catched) + { /* Failed, detaching shared memory, destroying image and telling we can't + use XShm */ + error_catched = FALSE; + XDestroyImage (ximage->ximage); + shmdt (ximage->SHMInfo.shmaddr); + shmctl (ximage->SHMInfo.shmid, IPC_RMID, 0); + g_free (ximage); + XSync(xcontext->disp, 0); + return FALSE; + } + else +#endif /* HAVE_XSHM */ + { + return TRUE; + } +} + /* This function handles GstXImage creation depending on XShm availability */ static GstXImage * gst_ximagesink_ximage_new (GstXImageSink *ximagesink, gint width, gint height) @@ -171,7 +237,9 @@ gst_ximagesink_ximage_destroy (GstXImageSink *ximagesink, GstXImage *ximage) if (ximage->ximage) XDestroyImage (ximage->ximage); } - + + XSync(ximagesink->xcontext->disp, 0); + g_mutex_unlock (ximagesink->x_lock); g_free (ximage); @@ -486,7 +554,8 @@ gst_ximagesink_xcontext_get (GstXImageSink *ximagesink) #ifdef HAVE_XSHM /* Search for XShm extension support */ - if (XQueryExtension (xcontext->disp, "MIT-SHM", &i, &i, &i)) + if (XShmQueryExtension (xcontext->disp) && + gst_ximagesink_check_xshm_calls (xcontext)) { xcontext->use_xshm = TRUE; GST_DEBUG ("ximagesink is using XShm extension"); @@ -1216,7 +1285,7 @@ gst_ximagesink_class_init (GstXImageSinkClass *klass) gstelement_class = (GstElementClass *) klass; parent_class = g_type_class_ref (GST_TYPE_VIDEOSINK); - + g_object_class_install_property (gobject_class, ARG_DISPLAY, g_param_spec_string ("display", "Display", "X Display name", NULL, G_PARAM_READWRITE)); diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index 853e2792a9..aa8c149c75 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -70,6 +70,7 @@ enum { }; static GstVideoSinkClass *parent_class = NULL; +static gboolean error_catched = FALSE; /* ============================================================= */ /* */ @@ -79,6 +80,72 @@ static GstVideoSinkClass *parent_class = NULL; /* X11 stuff */ +static int +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); + error_catched = TRUE; + return 0; +} + +/* This function checks that it is actually really possible to create an image + using XShm */ +static gboolean +gst_xvimagesink_check_xshm_calls (GstXContext *xcontext) +{ + GstXvImage *xvimage = NULL; + int (*handler)(Display *, XErrorEvent *); + + g_return_val_if_fail (xcontext != NULL, FALSE); + +#ifdef HAVE_XSHM + xvimage = g_new0 (GstXvImage, 1); + + /* Setting an error handler to catch failure */ + handler = XSetErrorHandler (gst_xvimagesink_handle_xerror); + + xvimage->size = (xcontext->bpp / 8); + + /* Trying to create a 1x1 picture */ + xvimage->xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id, + xcontext->im_format, NULL, 1, 1, + &xvimage->SHMInfo); + + xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size, + IPC_CREAT | 0777); + xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, 0, 0); + xvimage->xvimage->data = xvimage->SHMInfo.shmaddr; + xvimage->SHMInfo.readOnly = FALSE; + + XShmAttach (xcontext->disp, &xvimage->SHMInfo); + + error_catched = FALSE; + + XSync(xcontext->disp, 0); + + XSetErrorHandler (handler); + + if (error_catched) + { /* Failed, detaching shared memory, destroying image and telling we can't + use XShm */ + error_catched = FALSE; + XFree (xvimage->xvimage); + shmdt (xvimage->SHMInfo.shmaddr); + shmctl (xvimage->SHMInfo.shmid, IPC_RMID, 0); + g_free (xvimage); + XSync(xcontext->disp, 0); + return FALSE; + } + else +#endif /* HAVE_XSHM */ + { + return TRUE; + } +} + /* This function handles GstXvImage creation depending on XShm availability */ static GstXvImage * gst_xvimagesink_xvimage_new (GstXvImageSink *xvimagesink, @@ -183,6 +250,8 @@ gst_xvimagesink_xvimage_destroy (GstXvImageSink *xvimagesink, XFree (xvimage->xvimage); } + XSync(xvimagesink->xcontext->disp, 0); + g_mutex_unlock (xvimagesink->x_lock); g_free (xvimage); @@ -669,20 +738,6 @@ gst_xvimagesink_xcontext_get (GstXvImageSink *xvimagesink) xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN:G_BIG_ENDIAN; -#ifdef HAVE_XSHM - /* Search for XShm extension support */ - if (XQueryExtension (xcontext->disp, "MIT-SHM", &i, &i, &i)) - { - xcontext->use_xshm = TRUE; - GST_DEBUG ("xvimagesink is using XShm extension"); - } - else - { - xcontext->use_xshm = FALSE; - GST_DEBUG ("xvimagesink is not using XShm extension"); - } -#endif /* HAVE_XSHM */ - /* our caps system handles 24/32bpp RGB as big-endian. */ if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) { @@ -707,6 +762,23 @@ gst_xvimagesink_xcontext_get (GstXvImageSink *xvimagesink) return NULL; } +#ifdef HAVE_XSHM + /* Search for XShm extension support */ + if (XShmQueryExtension (xcontext->disp) && + gst_xvimagesink_check_xshm_calls (xcontext)) + { + xcontext->use_xshm = TRUE; + GST_DEBUG ("xvimagesink is using XShm extension"); + g_message ("using XShm"); + } + else + { + xcontext->use_xshm = FALSE; + GST_DEBUG ("xvimagesink is not using XShm extension"); + g_message ("not using XShm"); + } +#endif /* HAVE_XSHM */ + xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);