diff options
Diffstat (limited to 'sys/ximage/gstximagesrc.c')
-rw-r--r-- | sys/ximage/gstximagesrc.c | 140 |
1 files changed, 135 insertions, 5 deletions
diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c index e705ccb..36c0b44 100644 --- a/sys/ximage/gstximagesrc.c +++ b/sys/ximage/gstximagesrc.c @@ -49,6 +49,8 @@ #include <gst/gst.h> #include <gst/gst-i18n-plugin.h> +#include "gst/glib-compat-private.h" + GST_DEBUG_CATEGORY_STATIC (gst_debug_ximage_src); #define GST_CAT_DEFAULT gst_debug_ximage_src @@ -71,6 +73,8 @@ enum PROP_ENDX, PROP_ENDY, PROP_REMOTE, + PROP_XID, + PROP_XNAME, }; GST_BOILERPLATE (GstXImageSrc, gst_ximage_src, GstPushSrc, GST_TYPE_PUSH_SRC); @@ -99,11 +103,41 @@ gst_ximage_src_return_buf (GstXImageSrc * ximagesrc, /* need to increment the refcount again to recycle */ gst_buffer_ref (GST_BUFFER (ximage)); g_mutex_lock (ximagesrc->pool_lock); + GST_BUFFER_FLAGS (GST_BUFFER (ximage)) = 0; /* clear out any flags from the previous use */ ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage); g_mutex_unlock (ximagesrc->pool_lock); } } +static Window +gst_ximage_src_find_window (GstXImageSrc * src, Window root, const char *name) +{ + Window *children; + Window window = 0, root_return, parent_return; + unsigned int nchildren; + char *tmpname; + int n, status; + + status = XFetchName (src->xcontext->disp, root, &tmpname); + if (status && !strcmp (name, tmpname)) + return root; + + status = + XQueryTree (src->xcontext->disp, root, &root_return, &parent_return, + &children, &nchildren); + if (!status || !children) + return (Window) 0; + + for (n = 0; n < nchildren; ++n) { + window = gst_ximage_src_find_window (src, children[n], name); + if (window != 0) + break; + } + + XFree (children); + return window; +} + static gboolean gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name) { @@ -124,8 +158,51 @@ gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name) s->width = s->xcontext->width; s->height = s->xcontext->height; - /* Always capture root window, for now */ s->xwindow = s->xcontext->root; + if (s->xid != 0 || s->xname) { + int status; + XWindowAttributes attrs; + Window window; + + if (s->xid != 0) { + status = XGetWindowAttributes (s->xcontext->disp, s->xid, &attrs); + if (status) { + GST_DEBUG_OBJECT (s, "Found window XID %" G_GUINT64_FORMAT, s->xid); + s->xwindow = s->xid; + goto window_found; + } else { + GST_WARNING_OBJECT (s, "Failed to get window %" G_GUINT64_FORMAT + " attributes", s->xid); + } + } + + if (s->xname) { + GST_DEBUG_OBJECT (s, "Looking for window %s", s->xname); + window = gst_ximage_src_find_window (s, s->xcontext->root, s->xname); + if (window != 0) { + GST_DEBUG_OBJECT (s, "Found window named %s, ", s->xname); + status = XGetWindowAttributes (s->xcontext->disp, window, &attrs); + if (status) { + s->xwindow = window; + goto window_found; + } else { + GST_WARNING_OBJECT (s, "Failed to get window attributes for " + "window named %s", s->xname); + } + } + } + + GST_INFO_OBJECT (s, "Using root window"); + goto use_root_window; + + window_found: + g_assert (s->xwindow != 0); + s->width = attrs.width; + s->height = attrs.height; + GST_INFO_OBJECT (s, "Using default window size of %dx%d", + s->width, s->height); + } +use_root_window: #ifdef HAVE_XFIXES /* check if xfixes supported */ @@ -835,6 +912,21 @@ gst_ximage_src_set_property (GObject * object, guint prop_id, case PROP_REMOTE: src->remote = g_value_get_boolean (value); break; + case PROP_XID: + if (src->xcontext != NULL) { + g_warning ("ximagesrc window ID must be set before opening display"); + break; + } + src->xid = g_value_get_uint64 (value); + break; + case PROP_XNAME: + if (src->xcontext != NULL) { + g_warning ("ximagesrc window name must be set before opening display"); + break; + } + g_free (src->xname); + src->xname = g_strdup (g_value_get_string (value)); + break; default: break; } @@ -878,6 +970,12 @@ gst_ximage_src_get_property (GObject * object, guint prop_id, GValue * value, case PROP_REMOTE: g_value_set_boolean (value, src->remote); break; + case PROP_XID: + g_value_set_uint64 (value, src->xid); + break; + case PROP_XNAME: + g_value_set_string (value, src->xname); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -910,7 +1008,7 @@ gst_ximage_src_base_init (gpointer g_class) "Lutz Mueller <lutz@users.sourceforge.net>, " "Jan Schmidt <thaytan@mad.scientist.com>, " "Zaheer Merali <zaheerabbas at merali dot org>"); - gst_element_class_add_pad_template (ec, gst_static_pad_template_get (&t)); + gst_element_class_add_static_pad_template (ec, &t); } static void @@ -930,6 +1028,7 @@ gst_ximage_src_finalize (GObject * object) if (src->xcontext) ximageutil_xcontext_clear (src->xcontext); + g_free (src->xname); g_mutex_free (src->pool_lock); g_mutex_free (src->x_lock); @@ -954,9 +1053,16 @@ gst_ximage_src_get_caps (GstBaseSrc * bs) (s)->srcpad)); xcontext = s->xcontext; - - width = xcontext->width; - height = xcontext->height; + width = s->xcontext->width; + height = s->xcontext->height; + if (s->xwindow != 0) { + XWindowAttributes attrs; + int status = XGetWindowAttributes (s->xcontext->disp, s->xwindow, &attrs); + if (status) { + width = attrs.width; + height = attrs.height; + } + } /* property comments say 0 means right/bottom, means we can't capture the top left pixel alone */ @@ -1137,6 +1243,30 @@ gst_ximage_src_class_init (GstXImageSrcClass * klass) "Whether the display is remote", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstXImageSrc:xid + * + * The XID of the window to capture. 0 for the root window (default). + * + * Since: 0.10.31 + **/ + g_object_class_install_property (gc, PROP_XID, + g_param_spec_uint64 ("xid", "Window XID", + "Window XID to capture from", 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXImageSrc:xname + * + * The name of the window to capture, if any. + * + * Since: 0.10.31 + **/ + g_object_class_install_property (gc, PROP_XNAME, + g_param_spec_string ("xname", "Window name", + "Window name to capture from", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + parent_class = g_type_class_peek_parent (klass); push_class->create = gst_ximage_src_create; |