summaryrefslogtreecommitdiff
path: root/sys/ximage/gstximagesrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ximage/gstximagesrc.c')
-rw-r--r--sys/ximage/gstximagesrc.c140
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;