Beispiel #1
0
int
xcb_image_shm_get (xcb_connection_t *      conn,
		   xcb_drawable_t          draw,
		   xcb_image_t *           image,
		   xcb_shm_segment_info_t  shminfo,
		   int16_t                 x,
		   int16_t                 y,
		   uint32_t                plane_mask)
{
  xcb_shm_get_image_reply_t *  setup;
  xcb_shm_get_image_cookie_t   cookie;
  xcb_generic_error_t *        err = 0;

  if (!shminfo.shmaddr)
      return 0;
  cookie = xcb_shm_get_image(conn, draw,
			     x, y,
			     image->width, image->height,
			     plane_mask,
			     image->format,
			     shminfo.shmseg,
			     image->data - shminfo.shmaddr);
  setup = xcb_shm_get_image_reply(conn, cookie, &err);
  if (err) {
      fprintf(stderr, "ShmGetImageReply error %d\n", (int)err->error_code);
      free(err);
      return 0;
  } else {
      free (setup);
      return 1;
  }
}
cairo_status_t
_cairo_xcb_connection_shm_get_image (cairo_xcb_connection_t *connection,
                                     xcb_drawable_t src,
                                     int16_t src_x,
                                     int16_t src_y,
                                     uint16_t width,
                                     uint16_t height,
                                     uint32_t shmseg,
                                     uint32_t offset)
{
    xcb_shm_get_image_reply_t *reply;
    xcb_generic_error_t *error;

    reply = xcb_shm_get_image_reply (connection->xcb_connection,
                                     xcb_shm_get_image (connection->xcb_connection,
                                             src,
                                             src_x, src_y,
                                             width, height,
                                             (uint32_t) -1,
                                             XCB_IMAGE_FORMAT_Z_PIXMAP,
                                             shmseg, offset),
                                     &error);
    free (reply);

    if (error) {
        /* an error here should be impossible */
        free (error);
        return _cairo_error (CAIRO_STATUS_READ_ERROR);
    }

    return _cairo_xcb_connection_take_socket (connection);
}
Beispiel #3
0
int krad_x11_capture_getptr (krad_x11_t *x11, uint8_t **buffer) {

  int32_t size;

  if (buffer == NULL) {
    return 0;
  }
  
  x11->number = xcb_image_shm_get (x11->connection,
                                   x11->screen->root,
                                   x11->img,
                                   x11->shminfo,
                                   x11->x,
                                   x11->y,
                                   0xffffffff);

  x11->reply = xcb_shm_get_image_reply (x11->connection,
                                        x11->cookie,
                                        NULL);
  
  if (x11->reply) {
    free (x11->reply);
  }

  size = x11->img->width * x11->img->height * 4;

  *buffer = x11->img->data;

  return size;
}
Beispiel #4
0
ExcCode screen_shot(int x, int y, int width, int height,
		Imlib_Image *res) {
	int x1 = x + width;
	int y1 = y + height;
	x = MAX(x, 0);
	y = MAX(y, 0);
	x1 = MIN(x1, screen->width_in_pixels);
	y1 = MIN(y1, screen->height_in_pixels);
	width = x1 - x;
	height = y1 - y;
	
	*res = NULL;
	if (shm_available) {
		xcb_shm_get_image_cookie_t cookie =
				xcb_shm_get_image(display,
				root, x, y, width, height,
				XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP,
				shmseg, 0);
		xcb_shm_get_image_reply_t *reply =
				xcb_shm_get_image_reply(display, cookie, NULL);
		if (reply != NULL) {
			*res = imlib_create_image_using_copied_data(width, height,
					(unsigned *) shmaddr);
			free(reply);
		}
	}
	if (*res == NULL) {
		// If shm can't be used due to lack of the libraries or
		// because we connect to X11 on another machine (e.g. via SSH),
		// try to get an image via sockets.

		xcb_get_image_cookie_t cookie = xcb_get_image(display,
				XCB_IMAGE_FORMAT_Z_PIXMAP, root, x, y, width, height,
				XCB_ALL_PLANES);
		xcb_get_image_reply_t *reply =
				xcb_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) xcb_get_image_data(reply));
		free(reply);
	}
	if (*res == NULL)
		PANIC(ERR_IMAGE);
		
	if (cursor_capturing_enabled && cursor_available)
		screen_cursor_blend(x, y, *res);
	return 0;
}
Beispiel #5
0
ExcCode screen_shot(int x, int y, int width, int height,
		Imlib_Image *res) {
	int x1 = x + width;
	int y1 = y + height;
	x = MAX(x, 0);
	y = MAX(y, 0);
	x1 = MIN(x1, screen->width_in_pixels);
	y1 = MIN(y1, screen->height_in_pixels);
	width = x1 - x;
	height = y1 - y;
	
	if (shm_available) {
		xcb_shm_get_image_cookie_t cookie =
				xcb_shm_get_image(display,
				root, x, y, width, height,
				XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP,
				shmseg, 0);
		xcb_shm_get_image_reply_t *reply =
				xcb_shm_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_shm_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) shmaddr);
		free(reply);
	} else {
		xcb_get_image_cookie_t cookie = xcb_get_image(display,
				XCB_IMAGE_FORMAT_Z_PIXMAP, root, x, y, width, height,
				XCB_ALL_PLANES);
		xcb_get_image_reply_t *reply =
				xcb_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) xcb_get_image_data(reply));
		free(reply);
	}
	if (*res == NULL)
		PANIC(ERR_IMAGE);
		
	if (cursor_capturing_enabled && cursor_available)
		screen_cursor_blend(x, y, *res);
	return 0;
}
Beispiel #6
0
/**
 * Prepare the capture data
 */
static void xshm_video_tick(void *vptr, float seconds)
{
	UNUSED_PARAMETER(seconds);
	XSHM_DATA(vptr);

	if (!data->texture)
		return;
	if (!obs_source_showing(data->source))
		return;

	xcb_shm_get_image_cookie_t           img_c;
	xcb_shm_get_image_reply_t            *img_r;
	xcb_xfixes_get_cursor_image_cookie_t cur_c;
	xcb_xfixes_get_cursor_image_reply_t  *cur_r;

	img_c = xcb_shm_get_image_unchecked(data->xcb, data->xcb_screen->root,
			data->x_org, data->y_org, data->width, data->height,
			~0, XCB_IMAGE_FORMAT_Z_PIXMAP, data->xshm->seg, 0);
	cur_c = xcb_xfixes_get_cursor_image_unchecked(data->xcb);

	img_r = xcb_shm_get_image_reply(data->xcb, img_c, NULL);
	cur_r = xcb_xfixes_get_cursor_image_reply(data->xcb, cur_c, NULL);

	if (!img_r)
		goto exit;

	obs_enter_graphics();

	gs_texture_set_image(data->texture, (void *) data->xshm->data,
		data->width * 4, false);
	xcb_xcursor_update(data->cursor, cur_r);

	obs_leave_graphics();

exit:
	free(img_r);
	free(cur_r);
}
Beispiel #7
0
/**
 * Processing callback
 */
static void Demux (void *opaque)
{
    demux_t *demux = opaque;
    demux_sys_t *sys = demux->p_sys;
    xcb_connection_t *conn = sys->conn;

    /* Determine capture region */
    xcb_get_geometry_cookie_t gc;
    xcb_query_pointer_cookie_t qc;

    gc = xcb_get_geometry (conn, sys->window);
    if (sys->follow_mouse)
        qc = xcb_query_pointer (conn, sys->window);

    xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
    if (geo == NULL)
    {
        msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window);
discard:
        if (sys->follow_mouse)
            xcb_discard_reply (conn, gc.sequence);
        return;
    }

    int w = sys->w;
    int h = sys->h;
    int x, y;

    if (sys->follow_mouse)
    {
        xcb_query_pointer_reply_t *ptr =
            xcb_query_pointer_reply (conn, qc, NULL);
        if (ptr == NULL)
        {
            free (geo);
            return;
        }

        if (w == 0 || w > geo->width)
            w = geo->width;
        x = ptr->win_x;
        if (x < w / 2)
            x = 0;
        else if (x >= (int)geo->width - (w / 2))
            x = geo->width - w;
        else
            x -= w / 2;

        if (h == 0 || h > geo->height)
            h = geo->height;
        y = ptr->win_y;
        if (y < h / 2)
            y = 0;
        else if (y >= (int)geo->height - (h / 2))
            y = geo->height - h;
        else
            y -= h / 2;
    }
    else
    {
        int max;

        x = sys->x;
        max = (int)geo->width - x;
        if (max <= 0)
            goto discard;
        if (w == 0 || w > max)
            w = max;

        y = sys->y;
        max = (int)geo->height - y;
        if (max <= 0)
            goto discard;
        if (h == 0 || h > max)
            h = max;
    }

    /* Update elementary stream format (if needed) */
    if (w != sys->cur_w || h != sys->cur_h)
    {
        if (sys->es != NULL)
            es_out_Del (demux->out, sys->es);

        /* Update composite pixmap */
        if (sys->window != geo->root)
        {
            xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */
            xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap);
            xcb_create_pixmap (conn, geo->depth, sys->pixmap,
                               geo->root, geo->width, geo->height);
        }

        sys->es = InitES (demux, w, h, geo->depth, &sys->bpp);
        if (sys->es != NULL)
        {
            sys->cur_w = w;
            sys->cur_h = h;
            sys->bpp /= 8; /* bits -> bytes */
        }
    }

    /* Capture screen */
    xcb_drawable_t drawable =
        (sys->window != geo->root) ? sys->pixmap : sys->window;
    free (geo);

    block_t *block = NULL;
#if HAVE_SYS_SHM_H
    if (sys->shm)
    {   /* Capture screen through shared memory */
        size_t size = w * h * sys->bpp;
        int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
        if (id == -1) /* XXX: fallback */
        {
            msg_Err (demux, "shared memory allocation error: %m");
            goto noshm;
        }

        /* Attach the segment to X and capture */
        xcb_shm_get_image_reply_t *img;
        xcb_shm_get_image_cookie_t ck;

        xcb_shm_attach (conn, sys->segment, id, 0 /* read/write */);
        ck = xcb_shm_get_image (conn, drawable, x, y, w, h, ~0,
                                XCB_IMAGE_FORMAT_Z_PIXMAP, sys->segment, 0);
        xcb_shm_detach (conn, sys->segment);
        img = xcb_shm_get_image_reply (conn, ck, NULL);
        xcb_flush (conn); /* ensure eventual detach */

        if (img == NULL)
        {
            shmctl (id, IPC_RMID, 0);
            goto noshm;
        }
        free (img);

        /* Attach the segment to VLC */
        void *shm = shmat (id, NULL, 0 /* read/write */);
        shmctl (id, IPC_RMID, 0);
        if (-1 == (intptr_t)shm)
        {
            msg_Err (demux, "shared memory attachment error: %m");
            return;
        }

        block = block_shm_Alloc (shm, size);
        if (unlikely(block == NULL))
            shmdt (shm);
    }
noshm:
#endif
    if (block == NULL)
    {   /* Capture screen through socket (fallback) */
        xcb_get_image_reply_t *img;

        img = xcb_get_image_reply (conn,
            xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
                           x, y, w, h, ~0), NULL);
        if (img == NULL)
            return;

        uint8_t *data = xcb_get_image_data (img);
        size_t datalen = xcb_get_image_data_length (img);
        block = block_heap_Alloc (img, data + datalen - (uint8_t *)img);
        if (block == NULL)
            return;
        block->p_buffer = data;
        block->i_buffer = datalen;
    }

    /* Send block - zero copy */
    if (sys->es != NULL)
    {
        block->i_pts = block->i_dts = mdate ();

        es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
        es_out_Send (demux->out, sys->es, block);
    }
}