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); }
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; }
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; }
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; }
/** * 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); }
/** * 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); } }