x11grab.c
Go to the documentation of this file.
1 /*
2  * X11 video grab interface
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg integration:
7  * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org>
8  * Edouard Gomez <ed.gomez@free.fr>
9  *
10  * This file contains code from grab.c:
11  * Copyright (c) 2000-2001 Fabrice Bellard
12  *
13  * This file contains code from the xvidcap project:
14  * Copyright (C) 1997-1998 Rasca, Berlin
15  * 2003-2004 Karl H. Beckers, Frankfurt
16  *
17  * FFmpeg is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 2 of the License, or
20  * (at your option) any later version.
21  *
22  * FFmpeg is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with FFmpeg; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 
32 /**
33  * @file
34  * X11 frame device demuxer
35  * @author Clemens Fruhwirth <clemens@endorphin.org>
36  * @author Edouard Gomez <ed.gomez@free.fr>
37  */
38 
39 #include "config.h"
40 #include "libavformat/internal.h"
41 #include "libavutil/log.h"
42 #include "libavutil/opt.h"
43 #include "libavutil/parseutils.h"
44 #include "libavutil/time.h"
45 #include <time.h>
46 #include <X11/cursorfont.h>
47 #include <X11/X.h>
48 #include <X11/Xlib.h>
49 #include <X11/Xlibint.h>
50 #include <X11/Xproto.h>
51 #include <X11/Xutil.h>
52 #include <sys/shm.h>
53 #include <X11/extensions/shape.h>
54 #include <X11/extensions/XShm.h>
55 #include <X11/extensions/Xfixes.h>
56 #include "avdevice.h"
57 
58 /**
59  * X11 Device Demuxer context
60  */
61 struct x11grab {
62  const AVClass *class; /**< Class for private options. */
63  int frame_size; /**< Size in bytes of a grabbed frame */
64  AVRational time_base; /**< Time base */
65  int64_t time_frame; /**< Current time */
66 
67  int width; /**< Width of the grab frame */
68  int height; /**< Height of the grab frame */
69  int x_off; /**< Horizontal top-left corner coordinate */
70  int y_off; /**< Vertical top-left corner coordinate */
71 
72  Display *dpy; /**< X11 display from which x11grab grabs frames */
73  XImage *image; /**< X11 image holding the grab */
74  int use_shm; /**< !0 when using XShm extension */
75  XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */
76  int draw_mouse; /**< Set by a private option. */
77  int follow_mouse; /**< Set by a private option. */
78  int show_region; /**< set by a private option. */
79  char *framerate; /**< Set by a private option. */
80 
81  Window region_win; /**< This is used by show_region option. */
82 };
83 
84 #define REGION_WIN_BORDER 3
85 /**
86  * Draw grabbing region window
87  *
88  * @param s x11grab context
89  */
90 static void
92 {
93  Display *dpy = s->dpy;
94  int screen;
95  Window win = s->region_win;
96  GC gc;
97 
98  screen = DefaultScreen(dpy);
99  gc = XCreateGC(dpy, win, 0, 0);
100  XSetForeground(dpy, gc, WhitePixel(dpy, screen));
101  XSetBackground(dpy, gc, BlackPixel(dpy, screen));
102  XSetLineAttributes(dpy, gc, REGION_WIN_BORDER, LineDoubleDash, 0, 0);
103  XDrawRectangle(dpy, win, gc,
104  1, 1,
105  (s->width + REGION_WIN_BORDER * 2) - 1 * 2 - 1,
106  (s->height + REGION_WIN_BORDER * 2) - 1 * 2 - 1);
107  XFreeGC(dpy, gc);
108 }
109 
110 /**
111  * Initialize grabbing region window
112  *
113  * @param s x11grab context
114  */
115 static void
117 {
118  Display *dpy = s->dpy;
119  int screen;
120  XSetWindowAttributes attribs;
121  XRectangle rect;
122 
123  screen = DefaultScreen(dpy);
124  attribs.override_redirect = True;
125  s->region_win = XCreateWindow(dpy, RootWindow(dpy, screen),
128  s->width + REGION_WIN_BORDER * 2,
129  s->height + REGION_WIN_BORDER * 2,
130  0, CopyFromParent,
131  InputOutput, CopyFromParent,
132  CWOverrideRedirect, &attribs);
133  rect.x = 0;
134  rect.y = 0;
135  rect.width = s->width;
136  rect.height = s->height;
137  XShapeCombineRectangles(dpy, s->region_win,
138  ShapeBounding, REGION_WIN_BORDER, REGION_WIN_BORDER,
139  &rect, 1, ShapeSubtract, 0);
140  XMapWindow(dpy, s->region_win);
141  XSelectInput(dpy, s->region_win, ExposureMask | StructureNotifyMask);
143 }
144 
145 /**
146  * Initialize the x11 grab device demuxer (public device demuxer API).
147  *
148  * @param s1 Context from avformat core
149  * @return <ul>
150  * <li>AVERROR(ENOMEM) no memory left</li>
151  * <li>AVERROR(EIO) other failure case</li>
152  * <li>0 success</li>
153  * </ul>
154  */
155 static int
157 {
158  struct x11grab *x11grab = s1->priv_data;
159  Display *dpy;
160  AVStream *st = NULL;
161  enum AVPixelFormat input_pixfmt;
162  XImage *image;
163  int x_off = 0;
164  int y_off = 0;
165  int screen;
166  int use_shm;
167  char *dpyname, *offset;
168  int ret = 0;
170 
171  dpyname = av_strdup(s1->filename);
172  if (!dpyname)
173  goto out;
174 
175  offset = strchr(dpyname, '+');
176  if (offset) {
177  sscanf(offset, "%d,%d", &x_off, &y_off);
178  if (strstr(offset, "nomouse")) {
180  "'nomouse' specification in argument is deprecated: "
181  "use 'draw_mouse' option with value 0 instead\n");
182  x11grab->draw_mouse = 0;
183  }
184  *offset= 0;
185  }
186 
187  if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) {
188  av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate);
189  goto out;
190  }
191  av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n",
192  s1->filename, dpyname, x_off, y_off, x11grab->width, x11grab->height);
193 
194  dpy = XOpenDisplay(dpyname);
195  av_freep(&dpyname);
196  if(!dpy) {
197  av_log(s1, AV_LOG_ERROR, "Could not open X display.\n");
198  ret = AVERROR(EIO);
199  goto out;
200  }
201 
202  st = avformat_new_stream(s1, NULL);
203  if (!st) {
204  ret = AVERROR(ENOMEM);
205  goto out;
206  }
207  avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
208 
209  screen = DefaultScreen(dpy);
210 
211  if (x11grab->follow_mouse) {
212  int screen_w, screen_h;
213  Window w;
214 
215  screen_w = DisplayWidth(dpy, screen);
216  screen_h = DisplayHeight(dpy, screen);
217  XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret);
218  x_off -= x11grab->width / 2;
219  y_off -= x11grab->height / 2;
220  x_off = FFMIN(FFMAX(x_off, 0), screen_w - x11grab->width);
221  y_off = FFMIN(FFMAX(y_off, 0), screen_h - x11grab->height);
222  av_log(s1, AV_LOG_INFO, "followmouse is enabled, resetting grabbing region to x: %d y: %d\n", x_off, y_off);
223  }
224 
225  use_shm = XShmQueryExtension(dpy);
226  av_log(s1, AV_LOG_INFO, "shared memory extension%s found\n", use_shm ? "" : " not");
227 
228  if(use_shm) {
229  int scr = XDefaultScreen(dpy);
230  image = XShmCreateImage(dpy,
231  DefaultVisual(dpy, scr),
232  DefaultDepth(dpy, scr),
233  ZPixmap,
234  NULL,
235  &x11grab->shminfo,
236  x11grab->width, x11grab->height);
237  x11grab->shminfo.shmid = shmget(IPC_PRIVATE,
238  image->bytes_per_line * image->height,
239  IPC_CREAT|0777);
240  if (x11grab->shminfo.shmid == -1) {
241  av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n");
242  ret = AVERROR(ENOMEM);
243  goto out;
244  }
245  x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0);
246  x11grab->shminfo.readOnly = False;
247 
248  if (!XShmAttach(dpy, &x11grab->shminfo)) {
249  av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n");
250  /* needs some better error subroutine :) */
251  ret = AVERROR(EIO);
252  goto out;
253  }
254  } else {
255  image = XGetImage(dpy, RootWindow(dpy, screen),
256  x_off,y_off,
257  x11grab->width, x11grab->height,
258  AllPlanes, ZPixmap);
259  }
260 
261  switch (image->bits_per_pixel) {
262  case 8:
263  av_log (s1, AV_LOG_DEBUG, "8 bit palette\n");
264  input_pixfmt = AV_PIX_FMT_PAL8;
265  break;
266  case 16:
267  if ( image->red_mask == 0xf800 &&
268  image->green_mask == 0x07e0 &&
269  image->blue_mask == 0x001f ) {
270  av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n");
271  input_pixfmt = AV_PIX_FMT_RGB565;
272  } else if (image->red_mask == 0x7c00 &&
273  image->green_mask == 0x03e0 &&
274  image->blue_mask == 0x001f ) {
275  av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n");
276  input_pixfmt = AV_PIX_FMT_RGB555;
277  } else {
278  av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
279  av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
280  ret = AVERROR(EIO);
281  goto out;
282  }
283  break;
284  case 24:
285  if ( image->red_mask == 0xff0000 &&
286  image->green_mask == 0x00ff00 &&
287  image->blue_mask == 0x0000ff ) {
288  input_pixfmt = AV_PIX_FMT_BGR24;
289  } else if ( image->red_mask == 0x0000ff &&
290  image->green_mask == 0x00ff00 &&
291  image->blue_mask == 0xff0000 ) {
292  input_pixfmt = AV_PIX_FMT_RGB24;
293  } else {
294  av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
295  av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask);
296  ret = AVERROR(EIO);
297  goto out;
298  }
299  break;
300  case 32:
301  input_pixfmt = AV_PIX_FMT_0RGB32;
302  break;
303  default:
304  av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel);
305  ret = AVERROR(EINVAL);
306  goto out;
307  }
308 
309  x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8;
310  x11grab->dpy = dpy;
311  x11grab->time_base = av_inv_q(framerate);
312  x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base);
313  x11grab->x_off = x_off;
314  x11grab->y_off = y_off;
315  x11grab->image = image;
316  x11grab->use_shm = use_shm;
317 
320  st->codec->width = x11grab->width;
321  st->codec->height = x11grab->height;
322  st->codec->pix_fmt = input_pixfmt;
323  st->codec->time_base = x11grab->time_base;
324  st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8;
325 
326 out:
327  av_free(dpyname);
328  return ret;
329 }
330 
331 /**
332  * Paint a mouse pointer in an X11 image.
333  *
334  * @param image image to paint the mouse pointer to
335  * @param s context used to retrieve original grabbing rectangle
336  * coordinates
337  */
338 static void
340 {
341  int x_off = s->x_off;
342  int y_off = s->y_off;
343  int width = s->width;
344  int height = s->height;
345  Display *dpy = s->dpy;
346  XFixesCursorImage *xcim;
347  int x, y;
348  int line, column;
349  int to_line, to_column;
350  int pixstride = image->bits_per_pixel >> 3;
351  /* Warning: in its insanity, xlib provides unsigned image data through a
352  * char* pointer, so we have to make it uint8_t to make things not break.
353  * Anyone who performs further investigation of the xlib API likely risks
354  * permanent brain damage. */
355  uint8_t *pix = image->data;
356  Cursor c;
357  Window w;
358  XSetWindowAttributes attr;
359 
360  /* Code doesn't currently support 16-bit or PAL8 */
361  if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)
362  return;
363 
364  c = XCreateFontCursor(dpy, XC_left_ptr);
365  w = DefaultRootWindow(dpy);
366  attr.cursor = c;
367  XChangeWindowAttributes(dpy, w, CWCursor, &attr);
368 
369  xcim = XFixesGetCursorImage(dpy);
370 
371  x = xcim->x - xcim->xhot;
372  y = xcim->y - xcim->yhot;
373 
374  to_line = FFMIN((y + xcim->height), (height + y_off));
375  to_column = FFMIN((x + xcim->width), (width + x_off));
376 
377  for (line = FFMAX(y, y_off); line < to_line; line++) {
378  for (column = FFMAX(x, x_off); column < to_column; column++) {
379  int xcim_addr = (line - y) * xcim->width + column - x;
380  int image_addr = ((line - y_off) * width + column - x_off) * pixstride;
381  int r = (uint8_t)(xcim->pixels[xcim_addr] >> 0);
382  int g = (uint8_t)(xcim->pixels[xcim_addr] >> 8);
383  int b = (uint8_t)(xcim->pixels[xcim_addr] >> 16);
384  int a = (uint8_t)(xcim->pixels[xcim_addr] >> 24);
385 
386  if (a == 255) {
387  pix[image_addr+0] = r;
388  pix[image_addr+1] = g;
389  pix[image_addr+2] = b;
390  } else if (a) {
391  /* pixel values from XFixesGetCursorImage come premultiplied by alpha */
392  pix[image_addr+0] = r + (pix[image_addr+0]*(255-a) + 255/2) / 255;
393  pix[image_addr+1] = g + (pix[image_addr+1]*(255-a) + 255/2) / 255;
394  pix[image_addr+2] = b + (pix[image_addr+2]*(255-a) + 255/2) / 255;
395  }
396  }
397  }
398 
399  XFree(xcim);
400  xcim = NULL;
401 }
402 
403 
404 /**
405  * Read new data in the image structure.
406  *
407  * @param dpy X11 display to grab from
408  * @param d
409  * @param image Image where the grab will be put
410  * @param x Top-Left grabbing rectangle horizontal coordinate
411  * @param y Top-Left grabbing rectangle vertical coordinate
412  * @return 0 if error, !0 if successful
413  */
414 static int
415 xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
416 {
417  xGetImageReply rep;
418  xGetImageReq *req;
419  long nbytes;
420 
421  if (!image) {
422  return 0;
423  }
424 
425  LockDisplay(dpy);
426  GetReq(GetImage, req);
427 
428  /* First set up the standard stuff in the request */
429  req->drawable = d;
430  req->x = x;
431  req->y = y;
432  req->width = image->width;
433  req->height = image->height;
434  req->planeMask = (unsigned int)AllPlanes;
435  req->format = ZPixmap;
436 
437  if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
438  UnlockDisplay(dpy);
439  SyncHandle();
440  return 0;
441  }
442 
443  nbytes = (long)rep.length << 2;
444  _XReadPad(dpy, image->data, nbytes);
445 
446  UnlockDisplay(dpy);
447  SyncHandle();
448  return 1;
449 }
450 
451 /**
452  * Grab a frame from x11 (public device demuxer API).
453  *
454  * @param s1 Context from avformat core
455  * @param pkt Packet holding the brabbed frame
456  * @return frame size in bytes
457  */
458 static int
460 {
461  struct x11grab *s = s1->priv_data;
462  Display *dpy = s->dpy;
463  XImage *image = s->image;
464  int x_off = s->x_off;
465  int y_off = s->y_off;
466 
467  int screen;
468  Window root;
469  int follow_mouse = s->follow_mouse;
470 
471  int64_t curtime, delay;
472  struct timespec ts;
473 
474  /* Calculate the time of the next frame */
475  s->time_frame += INT64_C(1000000);
476 
477  /* wait based on the frame rate */
478  for(;;) {
479  curtime = av_gettime();
480  delay = s->time_frame * av_q2d(s->time_base) - curtime;
481  if (delay <= 0) {
482  if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) {
483  s->time_frame += INT64_C(1000000);
484  }
485  break;
486  }
487  ts.tv_sec = delay / 1000000;
488  ts.tv_nsec = (delay % 1000000) * 1000;
489  nanosleep(&ts, NULL);
490  }
491 
492  av_init_packet(pkt);
493  pkt->data = image->data;
494  pkt->size = s->frame_size;
495  pkt->pts = curtime;
496 
497  screen = DefaultScreen(dpy);
498  root = RootWindow(dpy, screen);
499  if (follow_mouse) {
500  int screen_w, screen_h;
501  int pointer_x, pointer_y, _;
502  Window w;
503 
504  screen_w = DisplayWidth(dpy, screen);
505  screen_h = DisplayHeight(dpy, screen);
506  XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_);
507  if (follow_mouse == -1) {
508  // follow the mouse, put it at center of grabbing region
509  x_off += pointer_x - s->width / 2 - x_off;
510  y_off += pointer_y - s->height / 2 - y_off;
511  } else {
512  // follow the mouse, but only move the grabbing region when mouse
513  // reaches within certain pixels to the edge.
514  if (pointer_x > x_off + s->width - follow_mouse) {
515  x_off += pointer_x - (x_off + s->width - follow_mouse);
516  } else if (pointer_x < x_off + follow_mouse)
517  x_off -= (x_off + follow_mouse) - pointer_x;
518  if (pointer_y > y_off + s->height - follow_mouse) {
519  y_off += pointer_y - (y_off + s->height - follow_mouse);
520  } else if (pointer_y < y_off + follow_mouse)
521  y_off -= (y_off + follow_mouse) - pointer_y;
522  }
523  // adjust grabbing region position if it goes out of screen.
524  s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width);
525  s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height);
526 
527  if (s->show_region && s->region_win)
528  XMoveWindow(dpy, s->region_win,
530  s->y_off - REGION_WIN_BORDER);
531  }
532 
533  if (s->show_region) {
534  if (s->region_win) {
535  XEvent evt;
536  // clean up the events, and do the initinal draw or redraw.
537  for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); );
538  if (evt.type)
540  } else {
542  }
543  }
544 
545  if(s->use_shm) {
546  if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) {
547  av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n");
548  }
549  } else {
550  if (!xget_zpixmap(dpy, root, image, x_off, y_off)) {
551  av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n");
552  }
553  }
554 
555  if (s->draw_mouse) {
556  paint_mouse_pointer(image, s);
557  }
558 
559  return s->frame_size;
560 }
561 
562 /**
563  * Close x11 frame grabber (public device demuxer API).
564  *
565  * @param s1 Context from avformat core
566  * @return 0 success, !0 failure
567  */
568 static int
570 {
571  struct x11grab *x11grab = s1->priv_data;
572 
573  /* Detach cleanly from shared mem */
574  if (x11grab->use_shm) {
575  XShmDetach(x11grab->dpy, &x11grab->shminfo);
576  shmdt(x11grab->shminfo.shmaddr);
577  shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL);
578  }
579 
580  /* Destroy X11 image */
581  if (x11grab->image) {
582  XDestroyImage(x11grab->image);
583  x11grab->image = NULL;
584  }
585 
586  if (x11grab->region_win) {
587  XDestroyWindow(x11grab->dpy, x11grab->region_win);
588  }
589 
590  /* Free X11 display */
591  XCloseDisplay(x11grab->dpy);
592  return 0;
593 }
594 
595 #define OFFSET(x) offsetof(struct x11grab, x)
596 #define DEC AV_OPT_FLAG_DECODING_PARAM
597 static const AVOption options[] = {
598  { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, DEC },
599 
600  { "follow_mouse", "move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region",
601  OFFSET(follow_mouse), AV_OPT_TYPE_INT, {.i64 = 0}, -1, INT_MAX, DEC, "follow_mouse" },
602  { "centered", "keep the mouse pointer at the center of grabbing region when following",
603  0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "follow_mouse" },
604 
605  { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC },
606  { "show_region", "show the grabbing region", OFFSET(show_region), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
607  { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = "vga"}, 0, 0, DEC },
608  { NULL },
609 };
610 
611 static const AVClass x11_class = {
612  .class_name = "X11grab indev",
613  .item_name = av_default_item_name,
614  .option = options,
615  .version = LIBAVUTIL_VERSION_INT,
616 };
617 
618 /** x11 grabber device demuxer declaration */
620  .name = "x11grab",
621  .long_name = NULL_IF_CONFIG_SMALL("X11grab"),
622  .priv_data_size = sizeof(struct x11grab),
623  .read_header = x11grab_read_header,
624  .read_packet = x11grab_read_packet,
625  .read_close = x11grab_read_close,
626  .flags = AVFMT_NOFILE,
627  .priv_class = &x11_class,
628 };
this is essentially always true and is there for self documentation without modifying the data in between WRITE and PRESERVE permissions are about sharing the same buffer between several filters to avoid expensive copies without them doing conflicting changes on the data The REUSE and REUSE2 permissions are about special memory for direct rendering For example a buffer directly allocated in video memory must not modified once it is displayed on screen
static int x11grab_read_header(AVFormatContext *s1)
Initialize the x11 grab device demuxer (public device demuxer API).
Definition: x11grab.c:156
const char * s
Definition: avisynth_c.h:668
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:162
AVOption.
Definition: opt.h:251
int y_off
Vertical top-left corner coordinate.
Definition: x11grab.c:70
AVInputFormat ff_x11grab_demuxer
x11 grabber device demuxer declaration
Definition: x11grab.c:619
av_default_item_name
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:70
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
#define REGION_WIN_BORDER
Definition: x11grab.c:84
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int show_region
set by a private option.
Definition: x11grab.c:78
output residual component w
static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
Grab a frame from x11 (public device demuxer API).
Definition: x11grab.c:459
#define _(x)
int height
Height of the grab frame.
Definition: x11grab.c:68
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
set threshold d
Format I/O context.
Definition: avformat.h:944
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:55
uint8_t
XShmSegmentInfo shminfo
When using XShm, keeps track of XShm infos.
Definition: x11grab.c:75
static void x11grab_region_win_init(struct x11grab *s)
Initialize grabbing region window.
Definition: x11grab.c:116
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
AVOptions.
static AVPacket pkt
Definition: demuxing.c:56
#define b
Definition: input.c:42
#define OFFSET(x)
Definition: x11grab.c:595
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
static double av_q2d(AVRational a)
Convert rational to double.
Definition: rational.h:69
uint8_t * data
#define DEC
Definition: x11grab.c:596
AVRational time_base
Time base.
Definition: x11grab.c:64
Discrete Time axis x
Main libavdevice API header.
static const AVOption options[]
Definition: x11grab.c:597
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
const char * r
Definition: vf_curves.c:94
static const AVClass x11_class
Definition: x11grab.c:611
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int draw_mouse
Set by a private option.
Definition: x11grab.c:76
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
static int x11grab_read_close(AVFormatContext *s1)
Close x11 frame grabber (public device demuxer API).
Definition: x11grab.c:569
#define FFMAX(a, b)
Definition: common.h:56
XImage * image
X11 image holding the grab.
Definition: x11grab.c:73
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int follow_mouse
Set by a private option.
Definition: x11grab.c:77
static int xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
Read new data in the image structure.
Definition: x11grab.c:415
FFT buffer for g
Definition: stft_peak.m:17
int bit_rate
the average bitrate
char filename[1024]
input or output filename
Definition: avformat.h:994
#define FFMIN(a, b)
Definition: common.h:58
ret
Definition: avfilter.c:821
int width
picture width / height.
static void paint_mouse_pointer(XImage *image, struct x11grab *s)
Paint a mouse pointer in an X11 image.
Definition: x11grab.c:339
int use_shm
!0 when using XShm extension
Definition: x11grab.c:74
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:71
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
int frame_size
Size in bytes of a grabbed frame.
Definition: x11grab.c:63
enum AVMediaType codec_type
enum AVCodecID codec_id
static void x11grab_draw_region_win(struct x11grab *s)
Draw grabbing region window.
Definition: x11grab.c:91
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
char * framerate
Set by a private option.
Definition: x11grab.c:79
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
Describe the class of an AVClass context structure.
Definition: log.h:50
Definition: f_ebur128.c:90
rational number numerator/denominator
Definition: rational.h:43
int x_off
Horizontal top-left corner coordinate.
Definition: x11grab.c:69
#define s1
Definition: regdef.h:38
offset must point to two consecutive integers
Definition: opt.h:230
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
misc parsing utilities
Window region_win
This is used by show_region option.
Definition: x11grab.c:81
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:122
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:345
static double c[64]
int64_t time_frame
Current time.
Definition: x11grab.c:65
X11 Device Demuxer context.
Definition: x11grab.c:61
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:269
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:56
function y
Definition: D.m:1
void * priv_data
Format private data.
Definition: avformat.h:964
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip please avoid problems through this extra level of scrutiny For cosmetics only commits you should e g by running git config global user name My Name git config global user email my email which is either set in your personal configuration file through git config core editor or set by one of the following environment VISUAL or EDITOR Log messages should be concise but descriptive Explain why you made a what you did will be obvious from the changes themselves most of the time Saying just bug fix or is bad Remember that people of varying skill levels look at and educate themselves while reading through your code Don t include filenames in log Git provides that information Possibly make the commit message have a descriptive first line
Definition: git-howto.txt:153
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:268
#define AV_LOG_INFO
Definition: log.h:156
int width
Width of the grab frame.
Definition: x11grab.c:67
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
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
Definition: pixfmt.h:263
Display * dpy
X11 display from which x11grab grabs frames.
Definition: x11grab.c:72