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.c172
1 files changed, 167 insertions, 5 deletions
diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c
index 15c7d6ce4..10e81fb3d 100644
--- a/sys/ximage/gstximagesrc.c
+++ b/sys/ximage/gstximagesrc.c
@@ -62,8 +62,12 @@ GST_ELEMENT_DETAILS ("Ximage video source",
"Zaheer Merali <zaheerabbas at merali dot org>");
static GstStaticPadTemplate t =
-GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-rgb, "
+ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-damaged-raw-rgb, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
+ "pixel-aspect-ratio = (fraction) [ 0, MAX ];"
+ "video/x-raw-rgb, "
"framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
"pixel-aspect-ratio = (fraction) [ 0, MAX ]"));
@@ -364,6 +368,129 @@ composite_pixel (GstXContext * xcontext, guchar * dest, guchar * src)
}
#endif
+static GstBuffer *
+gst_ximage_src_ximage_get_damaged (GstXImageSrc * ximagesrc)
+{
+ GstBuffer *outbuf = NULL;
+ guint32 requiredsize;
+
+ XEvent ev;
+
+ GST_DEBUG_OBJECT (ximagesrc, "Retrieving screen using XDamage");
+
+ do {
+ XNextEvent (ximagesrc->xcontext->disp, &ev);
+
+ if (ev.type == ximagesrc->damage_event_base + XDamageNotify) {
+ XserverRegion parts;
+ XRectangle *rects;
+ int nrects;
+
+ parts = XFixesCreateRegion (ximagesrc->xcontext->disp, 0, 0);
+ XDamageSubtract (ximagesrc->xcontext->disp, ximagesrc->damage, None,
+ parts);
+ /* Now copy out all of the damaged rectangles. */
+ rects = XFixesFetchRegion (ximagesrc->xcontext->disp, parts, &nrects);
+ if (rects != NULL) {
+ int i;
+
+ GST_DEBUG ("Calculating required memory");
+ for (i = 0; i < nrects; i++) {
+ if (ximagesrc->endx > ximagesrc->startx &&
+ ximagesrc->endy > ximagesrc->starty) {
+ /* see if damage area intersects */
+ if (rects[i].x + rects[i].width < ximagesrc->startx ||
+ rects[i].x > ximagesrc->endx) {
+ /* trivial reject */
+ } else if (rects[i].y + rects[i].height < ximagesrc->starty ||
+ rects[i].y > ximagesrc->endy) {
+ /* trivial reject */
+ } else {
+ /* find intersect region */
+ int startx, starty, width, height;
+
+ startx = (rects[i].x < ximagesrc->startx) ? ximagesrc->startx :
+ rects[i].x;
+ starty = (rects[i].y < ximagesrc->starty) ? ximagesrc->starty :
+ rects[i].y;
+ width = (rects[i].x + rects[i].width < ximagesrc->endx) ?
+ rects[i].x + rects[i].width - startx :
+ ximagesrc->endx - startx;
+ height = (rects[i].y + rects[i].height < ximagesrc->endy) ?
+ rects[i].y + rects[i].height - starty : ximagesrc->endy -
+ starty;
+
+ requiredsize += (width * height * ximagesrc->xcontext->bpp) / 8;
+ }
+ } else {
+ requiredsize +=
+ (rects[i].width * rects[i].height * ximagesrc->xcontext->bpp) /
+ 8;
+ }
+ }
+
+ GST_DEBUG ("requiredsize : %d bytes, nbrects : %d", requiredsize,
+ nrects);
+ outbuf = gst_buffer_new_and_alloc (requiredsize);
+
+ for (i = 0; i < nrects; i++) {
+ GST_LOG_OBJECT (ximagesrc,
+ "Damaged sub-region @ %d,%d size %dx%d reported",
+ rects[i].x, rects[i].y, rects[i].width, rects[i].height);
+
+ /* if we only want a small area, clip this damage region to
+ * area we want */
+ if (ximagesrc->endx > ximagesrc->startx &&
+ ximagesrc->endy > ximagesrc->starty) {
+ /* see if damage area intersects */
+ if (rects[i].x + rects[i].width < ximagesrc->startx ||
+ rects[i].x > ximagesrc->endx) {
+ /* trivial reject */
+ } else if (rects[i].y + rects[i].height < ximagesrc->starty ||
+ rects[i].y > ximagesrc->endy) {
+ /* trivial reject */
+ } else {
+ /* find intersect region */
+ int startx, starty, width, height;
+
+ startx = (rects[i].x < ximagesrc->startx) ? ximagesrc->startx :
+ rects[i].x;
+ starty = (rects[i].y < ximagesrc->starty) ? ximagesrc->starty :
+ rects[i].y;
+ width = (rects[i].x + rects[i].width < ximagesrc->endx) ?
+ rects[i].x + rects[i].width - startx :
+ ximagesrc->endx - startx;
+ height = (rects[i].y + rects[i].height < ximagesrc->endy) ?
+ rects[i].y + rects[i].height - starty : ximagesrc->endy -
+ starty;
+
+ GST_LOG_OBJECT (ximagesrc,
+ "Retrieving damaged sub-region @ %d,%d size %dx%d as intersect region",
+ startx, starty, width, height);
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ startx, starty, width, height, AllPlanes, ZPixmap,
+ ximage->ximage, startx - ximagesrc->startx,
+ starty - ximagesrc->starty);
+ }
+ } else {
+
+ GST_LOG_OBJECT (ximagesrc,
+ "Retrieving damaged sub-region @ %d,%d size %dx%d",
+ rects[i].x, rects[i].y, rects[i].width, rects[i].height);
+
+ XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow,
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height,
+ AllPlanes, ZPixmap, ximage->ximage, rects[i].x, rects[i].y);
+ }
+ }
+ free (rects);
+ }
+ }
+ } while (XPending (ximagesrc->xcontext->disp));
+
+}
+
/* Retrieve an XImageSrcBuffer, preferably from our
* pool of existing images and populate it from the window */
static GstXImageSrcBuffer *
@@ -406,7 +533,10 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
xcontext = ximagesrc->xcontext;
- caps = gst_caps_new_simple ("video/x-raw-rgb",
+ caps =
+ gst_caps_new_simple (ximagesrc->output_damaged ?
+ "video/x-damaged-raw-rgb" :
+ "video/x-raw-rgb",
"bpp", G_TYPE_INT, xcontext->bpp,
"depth", G_TYPE_INT, xcontext->depth,
"endianness", G_TYPE_INT, xcontext->endianness,
@@ -788,7 +918,10 @@ gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
s->last_frame_no = next_frame_no;
GST_OBJECT_UNLOCK (s);
- image = gst_ximage_src_ximage_get (s);
+ if (!s->output_damaged)
+ image = gst_ximage_src_ximage_get (s);
+ else
+ image = gst_ximage_src_ximage_get_damaged (s);
if (!image)
return GST_FLOW_ERROR;
@@ -930,6 +1063,7 @@ gst_ximage_src_get_caps (GstBaseSrc * bs)
{
GstXImageSrc *s = GST_XIMAGE_SRC (bs);
GstXContext *xcontext;
+ GstCaps *c1, *c2 = NULL;
gint width, height;
if ((!s->xcontext) && (!gst_ximage_src_open_display (s, s->display_name)))
@@ -969,7 +1103,8 @@ gst_ximage_src_get_caps (GstBaseSrc * bs)
s->endy = 0;
}
GST_DEBUG ("width = %d, height=%d", width, height);
- return gst_caps_new_simple ("video/x-raw-rgb",
+
+ c1 = gst_caps_new_simple ("video/x-raw-rgb",
"bpp", G_TYPE_INT, xcontext->bpp,
"depth", G_TYPE_INT, xcontext->depth,
"endianness", G_TYPE_INT, xcontext->endianness,
@@ -981,6 +1116,26 @@ gst_ximage_src_get_caps (GstBaseSrc * bs)
"framerate", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
"pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
NULL);
+
+#ifdef HAVE_XDAMAGE
+ if (s->have_xdamage) {
+ c2 = gst_caps_new_simple ("video/x-damaged-raw-rgb",
+ "bpp", G_TYPE_INT, xcontext->bpp,
+ "depth", G_TYPE_INT, xcontext->depth,
+ "endianness", G_TYPE_INT, xcontext->endianness,
+ "red_mask", G_TYPE_INT, xcontext->r_mask_output,
+ "green_mask", G_TYPE_INT, xcontext->g_mask_output,
+ "blue_mask", G_TYPE_INT, xcontext->b_mask_output,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ "framerate", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
+ NULL);
+ gst_caps_append (c2, c1);
+ c1 = c2;
+ }
+#endif
+ return c1;
}
static gboolean
@@ -1006,6 +1161,11 @@ gst_ximage_src_set_caps (GstBaseSrc * bs, GstCaps * caps)
GST_DEBUG_OBJECT (s, "peer wants %d/%d fps", s->fps_n, s->fps_d);
+ s->output_damaged =
+ gst_structure_has_name (structure, "video/x-damaged-raw-rgb");
+
+ GST_DEBUG_OBJECT (s, "outputting damaged region : %d", s->output_damaged);
+
return TRUE;
}
@@ -1015,6 +1175,8 @@ gst_ximage_src_fixate (GstPad * pad, GstCaps * caps)
gint i;
GstStructure *structure;
+ GST_DEBUG ("Fixating...");
+
for (i = 0; i < gst_caps_get_size (caps); ++i) {
structure = gst_caps_get_structure (caps, i);