📄 x11grab.c
字号:
} *x = -1; *y = -1; }}/** * Mouse painting helper function that applies an 'and' and 'or' mask pair to * '*dst' pixel. It actually draws a mouse pointer pixel to grabbed frame. * * @param dst Destination pixel * @param and Part of the mask that must be applied using a bitwise 'and' * operator * @param or Part of the mask that must be applied using a bitwise 'or' * operator * @param bits_per_pixel Bits per pixel used in the grabbed image */static void inlineapply_masks(uint8_t *dst, int and, int or, int bits_per_pixel){ switch (bits_per_pixel) { case 32: *(uint32_t*)dst = (*(uint32_t*)dst & and) | or; break; case 16: *(uint16_t*)dst = (*(uint16_t*)dst & and) | or; break; case 8: *dst = !!or; break; }}/** * Paints a mouse pointer in an X11 image. * * @param image Image where to paint the mouse pointer * @param s context used to retrieve original grabbing rectangle * coordinates * @param x Mouse pointer coordinate * @param y Mouse pointer coordinate */static voidpaint_mouse_pointer(XImage *image, x11_grab_t *s, int x, int y){ /* 16x20x1bpp bitmap for the black channel of the mouse pointer */ static const uint16_t const mousePointerBlack[] = { 0x0000, 0x0003, 0x0005, 0x0009, 0x0011, 0x0021, 0x0041, 0x0081, 0x0101, 0x0201, 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120, 0x0120, 0x0240, 0x0240, 0x0380, 0x0000 }; /* 16x20x1bpp bitmap for the white channel of the mouse pointer */ static const uint16_t const mousePointerWhite[] = { 0x0000, 0x0000, 0x0002, 0x0006, 0x000e, 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000 }; int x_off = s->x_off; int y_off = s->y_off; int width = s->width; int height = s->height; if ( x - x_off >= 0 && x < width + x_off && y - y_off >= 0 && y < height + y_off) { uint8_t *im_data = (uint8_t*)image->data; int bytes_per_pixel; int line; int masks; /* Select correct masks and pixel size */ if (image->bits_per_pixel == 8) { masks = 1; } else { masks = (image->red_mask|image->green_mask|image->blue_mask); } bytes_per_pixel = image->bits_per_pixel>>3; /* Shift to right line */ im_data += image->bytes_per_line * (y - y_off); /* Shift to right pixel in the line */ im_data += bytes_per_pixel * (x - x_off); /* Draw the cursor - proper loop */ for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) { uint8_t *cursor = im_data; int column; uint16_t bm_b; uint16_t bm_w; bm_b = mousePointerBlack[line]; bm_w = mousePointerWhite[line]; for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) { apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1), image->bits_per_pixel); cursor += bytes_per_pixel; bm_b >>= 1; bm_w >>= 1; } im_data += image->bytes_per_line; } }}/** * Reads new data in the image structure. * * @param dpy X11 display to grab from * @param d * @param image Image where the grab will be put * @param x Top-Left grabbing rectangle horizontal coordinate * @param y Top-Left grabbing rectangle vertical coordinate * @return 0 if error, !0 if successful */static intxget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y){ xGetImageReply rep; xGetImageReq *req; long nbytes; if (!image) { return 0; } LockDisplay(dpy); GetReq(GetImage, req); /* First set up the standard stuff in the request */ req->drawable = d; req->x = x; req->y = y; req->width = image->width; req->height = image->height; req->planeMask = (unsigned int)AllPlanes; req->format = ZPixmap; if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) { UnlockDisplay(dpy); SyncHandle(); return 0; } nbytes = (long)rep.length << 2; _XReadPad(dpy, image->data, nbytes); UnlockDisplay(dpy); SyncHandle(); return 1;}/** * Grabs a frame from x11 (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the brabbed frame * @return frame size in bytes */static intx11grab_read_packet(AVFormatContext *s1, AVPacket *pkt){ x11_grab_t *s = s1->priv_data; Display *dpy = s->dpy; XImage *image = s->image; int x_off = s->x_off; int y_off = s->y_off; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += INT64_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * av_q2d(s->time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { s->time_frame += INT64_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } if (av_new_packet(pkt, s->frame_size) < 0) { return AVERROR(EIO); } pkt->pts = curtime; if(s->use_shm) { if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } { int pointer_x, pointer_y; get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1); paint_mouse_pointer(image, s, pointer_x, pointer_y); } /* XXX: avoid memcpy */ memcpy(pkt->data, image->data, s->frame_size); return s->frame_size;}/** * Closes x11 frame grabber (public device demuxer API). * * @param s1 Context from avformat core * @return 0 success, !0 failure */static intx11grab_read_close(AVFormatContext *s1){ x11_grab_t *x11grab = s1->priv_data; /* Detach cleanly from shared mem */ if (x11grab->use_shm) { XShmDetach(x11grab->dpy, &x11grab->shminfo); shmdt(x11grab->shminfo.shmaddr); shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); } /* Destroy X11 image */ if (x11grab->image) { XDestroyImage(x11grab->image); x11grab->image = NULL; } /* Free X11 display */ XCloseDisplay(x11grab->dpy); return 0;}/** x11 grabber device demuxer declaration */AVInputFormat x11_grab_device_demuxer ={ "x11grab", "X11grab", sizeof(x11_grab_t), NULL, x11grab_read_header, x11grab_read_packet, x11grab_read_close, .flags = AVFMT_NOFILE,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -