44 #include <X11/cursorfont.h> 
   47 #include <X11/Xlibint.h> 
   48 #include <X11/Xproto.h> 
   49 #include <X11/Xutil.h> 
   51 #include <X11/extensions/shape.h> 
   52 #include <X11/extensions/Xfixes.h> 
   53 #include <X11/extensions/XShm.h> 
   92 #define REGION_WIN_BORDER 3 
  101     Display *dpy = s->
dpy;
 
  103     int screen = DefaultScreen(dpy);
 
  104     GC gc = XCreateGC(dpy, win, 0, 0);
 
  106     XSetForeground(dpy, gc, WhitePixel(dpy, screen));
 
  107     XSetBackground(dpy, gc, BlackPixel(dpy, screen));
 
  109     XDrawRectangle(dpy, win, gc, 1, 1,
 
  122     Display *dpy = s->
dpy;
 
  124     XSetWindowAttributes attribs = { .override_redirect = True };
 
  125     int screen = DefaultScreen(dpy);
 
  127     s->
region_win = XCreateWindow(dpy, RootWindow(dpy, screen),
 
  133                                   InputOutput, CopyFromParent,
 
  134                                   CWOverrideRedirect, &attribs);
 
  137     rect.width  = s->
width;
 
  141                             &rect, 1, ShapeSubtract, 0);
 
  143     XSelectInput(dpy, s->
region_win, ExposureMask | StructureNotifyMask);
 
  150     int scr           = XDefaultScreen(dpy);
 
  151     XImage *
img       = XShmCreateImage(dpy, DefaultVisual(dpy, scr),
 
  152                                         DefaultDepth(dpy, scr), ZPixmap, 
NULL,
 
  155     g->
shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line * img->height,
 
  166     if (!XShmAttach(dpy, &g->
shminfo)) {
 
  180     if (XFixesQueryExtension(dpy, &ev_ret, &ev_err)) {
 
  181         Window root = RootWindow(dpy, screen);
 
  182         XFixesSelectCursorInput(dpy, root, XFixesDisplayCursorNotifyMask);
 
  192            "Image r 0x%.6lx g 0x%.6lx b 0x%.6lx and depth %i\n",
 
  196            image->bits_per_pixel);
 
  200     switch (image->bits_per_pixel) {
 
  205         if (image->red_mask   == 0xf800 &&
 
  206             image->green_mask == 0x07e0 &&
 
  207             image->blue_mask  == 0x001f) {
 
  209         } 
else if (image->red_mask   == 0x7c00 &&
 
  210                    image->green_mask == 0x03e0 &&
 
  211                    image->blue_mask  == 0x001f) {
 
  216         if (image->red_mask   == 0xff0000 &&
 
  217             image->green_mask == 0x00ff00 &&
 
  218             image->blue_mask  == 0x0000ff) {
 
  220         } 
else if (image->red_mask   == 0x0000ff &&
 
  221                    image->green_mask == 0x00ff00 &&
 
  222                    image->blue_mask  == 0xff0000) {
 
  227         if (image->red_mask   == 0xff0000 &&
 
  228             image->green_mask == 0x00ff00 &&
 
  229             image->blue_mask  == 0x0000ff ) {
 
  236                "XImages with RGB mask 0x%.6lx 0x%.6lx 0x%.6lx and depth %i " 
  237                "are currently not supported.\n",
 
  241                image->bits_per_pixel);
 
  265     int x_off = 0, y_off = 0, ret = 0, screen, use_shm = 0;
 
  275     offset = strchr(dpyname, 
'+');
 
  277         sscanf(offset, 
"%d,%d", &x_off, &y_off);
 
  278         if (strstr(offset, 
"nomouse")) {
 
  280                    "'nomouse' specification in argument is deprecated: " 
  281                    "use 'draw_mouse' option with value 0 instead\n");
 
  288            "device: %s -> display: %s x: %d y: %d width: %d height: %d\n",
 
  291     dpy = XOpenDisplay(dpyname);
 
  306     screen = DefaultScreen(dpy);
 
  309         int screen_w, screen_h;
 
  312         screen_w = DisplayWidth(dpy, screen);
 
  313         screen_h = DisplayHeight(dpy, screen);
 
  314         XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off,
 
  316         x_off -= x11grab->
width / 2;
 
  317         y_off -= x11grab->
height / 2;
 
  318         x_off = av_clip(x_off, 0, screen_w - x11grab->
width);
 
  319         y_off = av_clip(y_off, 0, screen_h - x11grab->
height);
 
  321                "followmouse is enabled, resetting grabbing region to x: %d y: %d\n",
 
  326         use_shm = XShmQueryExtension(dpy);
 
  328                "shared memory extension %sfound\n", use_shm ? 
"" : 
"not ");
 
  331     if (use_shm && 
setup_shm(s1, dpy, &image) < 0) {
 
  337         image = XGetImage(dpy, RootWindow(dpy, screen),
 
  345                "XFixes not available, cannot draw the mouse cursor\n");
 
  353     x11grab->
x_off      = x_off;
 
  354     x11grab->
y_off      = y_off;
 
  355     x11grab->
image      = image;
 
  363         color_map = DefaultColormap(dpy, screen);
 
  364         for (i = 0; i < 256; ++i)
 
  366         XQueryColors(dpy, color_map, color, 256);
 
  367         for (i = 0; i < 256; ++i)
 
  368             x11grab->
palette[i] = (color[i].red   & 0xFF00) << 8 |
 
  369                                   (color[i].green & 0xFF00)      |
 
  370                                   (color[i].blue  & 0xFF00) >> 8;
 
  398     int x_off    = s->
x_off;
 
  399     int y_off    = s->
y_off;
 
  402     Display *dpy = s->
dpy;
 
  403     XFixesCursorImage *xcim;
 
  406     int to_line, to_column;
 
  407     int pixstride = image->bits_per_pixel >> 3;
 
  414     XSetWindowAttributes attr;
 
  417     if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)
 
  421         s->
c = XCreateFontCursor(dpy, XC_left_ptr);
 
  422     root = DefaultRootWindow(dpy);
 
  424     XChangeWindowAttributes(dpy, root, CWCursor, &attr);
 
  426     xcim = XFixesGetCursorImage(dpy);
 
  429                "XFixesGetCursorImage failed\n");
 
  433     x = xcim->x - xcim->xhot;
 
  434     y = xcim->y - xcim->yhot;
 
  436     to_line   = 
FFMIN((y + xcim->height), (height + y_off));
 
  437     to_column = 
FFMIN((x + xcim->width),  (width  + x_off));
 
  439     for (line = 
FFMAX(y, y_off); line < to_line; line++) {
 
  440         for (column = 
FFMAX(x, x_off); column < to_column; column++) {
 
  441             int xcim_addr  = (line  - y)     * xcim->width + column - x;
 
  442             int image_addr = ((line - y_off) * width       + column - x_off) * pixstride;
 
  443             int r          = (
uint8_t)(xcim->pixels[xcim_addr] >>  0);
 
  444             int g          = (
uint8_t)(xcim->pixels[xcim_addr] >>  8);
 
  445             int b          = (
uint8_t)(xcim->pixels[xcim_addr] >> 16);
 
  446             int a          = (
uint8_t)(xcim->pixels[xcim_addr] >> 24);
 
  449                 pix[image_addr + 0] = 
r;
 
  450                 pix[image_addr + 1] = 
g;
 
  451                 pix[image_addr + 2] = 
b;
 
  454                 pix[image_addr + 0] = r + (pix[image_addr + 0] * (255 - 
a) + 255 / 2) / 255;
 
  455                 pix[image_addr + 1] = g + (pix[image_addr + 1] * (255 - 
a) + 255 / 2) / 255;
 
  456                 pix[image_addr + 2] = b + (pix[image_addr + 2] * (255 - 
a) + 255 / 2) / 255;
 
  475 static int xget_zpixmap(Display *dpy, Drawable d, XImage *image, 
int x, 
int y)
 
  485     GetReq(GetImage, req);
 
  491     req->width     = image->width;
 
  492     req->height    = image->height;
 
  493     req->planeMask = (
unsigned int)AllPlanes;
 
  494     req->format    = ZPixmap;
 
  496     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
 
  502     nbytes = (long)rep.length << 2;
 
  503     _XReadPad(dpy, image->data, nbytes);
 
  520     Display *dpy      = s->
dpy;
 
  521     XImage *image     = s->
image;
 
  522     int x_off         = s->
x_off;
 
  523     int y_off         = s->
y_off;
 
  525     int screen, pointer_x, pointer_y, 
_, same_screen = 1;
 
  527     int64_t curtime, delay;
 
  537         ts.tv_sec  = delay / 1000000;
 
  538         ts.tv_nsec = (delay % 1000000) * 1000;
 
  539         nanosleep(&ts, 
NULL);
 
  547     pkt->
data = image->data;
 
  561     screen = DefaultScreen(dpy);
 
  562     root   = RootWindow(dpy, screen);
 
  565         same_screen = XQueryPointer(dpy, root, &w, &w,
 
  566                                     &pointer_x, &pointer_y, &_, &_, &_);
 
  568     if (follow_mouse && same_screen) {
 
  569         int screen_w, screen_h;
 
  571         screen_w = DisplayWidth(dpy, screen);
 
  572         screen_h = DisplayHeight(dpy, screen);
 
  573         if (follow_mouse == -1) {
 
  575             x_off += pointer_x - s->
width / 2 - x_off;
 
  576             y_off += pointer_y - s->
height / 2 - y_off;
 
  580             if (pointer_x > x_off + s->
width - follow_mouse)
 
  581                 x_off += pointer_x - (x_off + s->
width - follow_mouse);
 
  582             else if (pointer_x < x_off + follow_mouse)
 
  583                 x_off -= (x_off + follow_mouse) - pointer_x;
 
  584             if (pointer_y > y_off + s->
height - follow_mouse)
 
  585                 y_off += pointer_y - (y_off + s->
height - follow_mouse);
 
  586             else if (pointer_y < y_off + follow_mouse)
 
  587                 y_off -= (y_off + follow_mouse) - pointer_y;
 
  590         s->
x_off = x_off = av_clip(x_off, 0, screen_w - s->
width);
 
  591         s->
y_off = y_off = av_clip(y_off, 0, screen_h - s->
height);
 
  601             XEvent evt = { .type = NoEventMask };
 
  603             while (XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask,
 
  614         if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes))
 
  640         shmdt(x11grab->
shminfo.shmaddr);
 
  645     if (x11grab->
image) {
 
  646         XDestroyImage(x11grab->
image);
 
  654     XCloseDisplay(x11grab->
dpy);
 
  658 #define OFFSET(x) offsetof(X11GrabContext, x) 
  659 #define DEC AV_OPT_FLAG_DECODING_PARAM 
  665     { 
"follow_mouse", 
"move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region",
 
  667     { 
"centered",     
"keep the mouse pointer at the center of grabbing region when following",
 
  694     .priv_class     = &x11_class,
 
static int x11grab_read_header(AVFormatContext *s1)
Initialize the x11 grab device demuxer (public device demuxer API). 
static enum AVPixelFormat pix_fmt
static int setup_shm(AVFormatContext *s, Display *dpy, XImage **image)
AVInputFormat ff_x11grab_demuxer
x11 grabber device demuxer declaration 
#define AV_LOG_WARNING
Something somehow does not look correct. 
#define LIBAVUTIL_VERSION_INT
packed RGB 8:8:8, 24bpp, RGBRGB... 
#define REGION_WIN_BORDER
enum AVCodecID codec_id
Specific type of the encoded data (the codec used). 
int x_off
Horizontal top-left corner coordinate. 
int show_region
set by a private option. 
Window region_win
This is used by show_region option. 
static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
Grab a frame from x11 (public device demuxer API). 
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static void x11grab_draw_region_win(X11GrabContext *s)
Draw grabbing region window. 
8 bits with AV_PIX_FMT_RGB32 palette 
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file. 
static double av_q2d(AVRational a)
Convert an AVRational to a double. 
static av_cold int read_close(AVFormatContext *ctx)
static void x11grab_region_win_init(X11GrabContext *s)
Initialize grabbing region window. 
int64_t bit_rate
The average bitrate of the encoded data (in bits per second). 
Main libavdevice API header. 
static const AVOption options[]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered. 
static int pixfmt_from_image(AVFormatContext *s, XImage *image, int *pix_fmt)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers. 
enum AVMediaType codec_type
General type of the encoded data. 
static const AVClass x11_class
static const uint8_t offset[127][2]
static int x11grab_read_close(AVFormatContext *s1)
Close x11 frame grabber (public device demuxer API). 
AVRational avg_frame_rate
Average framerate. 
AVRational time_base
Time base. 
int64_t time_frame
Current time. 
common internal API header 
static int xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
Read new data in the image structure. 
char filename[1024]
input or output filename 
int height
Height of the grab frame. 
int use_shm
!0 when using XShm extension 
packed RGB 8:8:8, 24bpp, BGRBGR... 
static void paint_mouse_pointer(XImage *image, AVFormatContext *s1)
Paint a mouse pointer in an X11 image. 
static int read_header(FFV1Context *f)
int64_t av_gettime(void)
Get the current time in microseconds. 
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome. 
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
X11 device demuxer context. 
#define AV_LOG_INFO
Standard information. 
char * av_strdup(const char *s)
Duplicate a string. 
XShmSegmentInfo shminfo
When using XShm, keeps track of XShm info. 
static int setup_mouse(Display *dpy, int screen)
int frame_size
Size in bytes of a grabbed frame. 
Describe the class of an AVClass context structure. 
Rational number (pair of numerator and denominator). 
XImage * image
X11 image holding the grab. 
offset must point to AVRational 
int width
Width of the grab frame. 
offset must point to two consecutive integers 
int follow_mouse
Set by a private option. 
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational. 
#define AV_PIX_FMT_RGB555
int draw_mouse
Set by a private option. 
int y_off
Vertical top-left corner coordinate. 
Display * dpy
X11 display from which x11grab grabs frames. 
void * priv_data
Format private data. 
#define AV_PIX_FMT_RGB565
AVCodecParameters * codecpar
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size)
Allocate new information of a packet. 
AVRational framerate
Set by a private option. 
This structure stores compressed data. 
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_PIX_FMT_0RGB32