ximagesrc: add xid and xname properties to allow capturing a particular window

A particular window may be selected using the new xid (X-Window
XID, eg a pointer) and xname (window title) properties. If both
are specified, the XID is used in preference, falling back to
xname if not found.

Default (if none of xid and xname are specified, or if no such
window is found) is to capture the root window.

https://bugzilla.gnome.org/show_bug.cgi?id=546932
This commit is contained in:
Vincent Penquerc'h 2011-09-20 12:11:47 +01:00 committed by Tim-Philipp Müller
parent b6b072e948
commit 82927d6bdd
2 changed files with 135 additions and 5 deletions

View file

@ -71,6 +71,8 @@ enum
PROP_ENDX,
PROP_ENDY,
PROP_REMOTE,
PROP_XID,
PROP_XNAME,
};
GST_BOILERPLATE (GstXImageSrc, gst_ximage_src, GstPushSrc, GST_TYPE_PUSH_SRC);
@ -105,6 +107,35 @@ gst_ximage_src_return_buf (GstXImageSrc * ximagesrc,
}
}
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)
{
@ -125,8 +156,49 @@ 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 %p", s->xid);
s->xwindow = s->xid;
goto window_found;
} else {
GST_WARNING_OBJECT (s, "Failed to get window %p 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 as %p, ", s->xname, window);
status = XGetWindowAttributes (s->xcontext->disp, window, &attrs);
if (status) {
s->xwindow = window;
goto window_found;
} else {
GST_WARNING_OBJECT (s, "Failed to get window %p attributes", window);
}
}
}
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 %p, size of %dx%d", s->xwindow,
s->width, s->height);
}
use_root_window:
#ifdef HAVE_XFIXES
/* check if xfixes supported */
@ -592,7 +664,8 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
} else
#endif /* HAVE_XSHM */
{
GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XGetImage");
GST_DEBUG_OBJECT (ximagesrc,
"Retrieving screen using XGetImage, window %p", ximagesrc->xwindow);
if (ximagesrc->remote) {
XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
ximagesrc->startx, ximagesrc->starty, ximagesrc->width,
@ -836,6 +909,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;
}
@ -879,6 +967,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;
@ -931,6 +1025,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);
@ -955,9 +1050,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 */
@ -1138,6 +1240,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;

View file

@ -56,6 +56,10 @@ struct _GstXImageSrc
gchar *display_name;
guint screen_num;
/* Window selection */
guint64 xid;
gchar *xname;
/* Desired output framerate */
gint fps_n;
gint fps_d;