FFmpeg
xcbgrab.c
Go to the documentation of this file.
1 /*
2  * XCB input grabber
3  * Copyright (C) 2014 Luca Barbato <lu_zero@gentoo.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config.h"
23 
24 #include <stdlib.h>
25 #include <xcb/xcb.h>
26 
27 #if CONFIG_LIBXCB_XFIXES
28 #include <xcb/xfixes.h>
29 #endif
30 
31 #if CONFIG_LIBXCB_SHM
32 #include <sys/shm.h>
33 #include <xcb/shm.h>
34 #endif
35 
36 #if CONFIG_LIBXCB_SHAPE
37 #include <xcb/shape.h>
38 #endif
39 
40 #include "libavutil/internal.h"
41 #include "libavutil/mathematics.h"
42 #include "libavutil/opt.h"
43 #include "libavutil/parseutils.h"
44 #include "libavutil/time.h"
45 
46 #include "libavformat/avformat.h"
47 #include "libavformat/internal.h"
48 
49 typedef struct XCBGrabContext {
50  const AVClass *class;
51 
52  xcb_connection_t *conn;
53  xcb_screen_t *screen;
54  xcb_window_t window;
55 #if CONFIG_LIBXCB_SHM
56  AVBufferPool *shm_pool;
57 #endif
58  int64_t time_frame;
60  int64_t frame_duration;
61 
62  int x, y;
63  int width, height;
65  int bpp;
66 
71  int centered;
72 
73  const char *framerate;
74 
75  int has_shm;
77 
78 #define FOLLOW_CENTER -1
79 
80 #define OFFSET(x) offsetof(XCBGrabContext, x)
81 #define D AV_OPT_FLAG_DECODING_PARAM
82 static const AVOption options[] = {
83  { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
84  { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
85  { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
86  { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
87  { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, D },
88  { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D },
89  { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D },
90  { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
91  OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, FOLLOW_CENTER, INT_MAX, D, "follow_mouse" },
92  { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, D, "follow_mouse" },
93  { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
94  { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D },
95  { NULL },
96 };
97 
98 static const AVClass xcbgrab_class = {
99  .class_name = "xcbgrab indev",
100  .item_name = av_default_item_name,
101  .option = options,
102  .version = LIBAVUTIL_VERSION_INT,
104 };
105 
107  xcb_query_pointer_reply_t *p,
108  xcb_get_geometry_reply_t *geo)
109 {
110  XCBGrabContext *c = s->priv_data;
111  int x = c->x, y = c->y;
112  int w = c->width, h = c->height, f = c->follow_mouse;
113  int p_x, p_y;
114 
115  if (!p || !geo)
116  return AVERROR(EIO);
117 
118  p_x = p->win_x;
119  p_y = p->win_y;
120 
121  if (f == FOLLOW_CENTER) {
122  x = p_x - w / 2;
123  y = p_y - h / 2;
124  } else {
125  int left = x + f;
126  int right = x + w - f;
127  int top = y + f;
128  int bottom = y + h - f;
129  if (p_x > right) {
130  x += p_x - right;
131  } else if (p_x < left) {
132  x -= left - p_x;
133  }
134  if (p_y > bottom) {
135  y += p_y - bottom;
136  } else if (p_y < top) {
137  y -= top - p_y;
138  }
139  }
140 
141  c->x = FFMIN(FFMAX(0, x), geo->width - w);
142  c->y = FFMIN(FFMAX(0, y), geo->height - h);
143 
144  return 0;
145 }
146 
147 static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
148 {
149  free(opaque);
150 }
151 
153 {
154  XCBGrabContext *c = s->priv_data;
155  xcb_get_image_cookie_t iq;
156  xcb_get_image_reply_t *img;
157  xcb_drawable_t drawable = c->screen->root;
158  xcb_generic_error_t *e = NULL;
159  uint8_t *data;
160  int length;
161 
162  iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
163  c->x, c->y, c->width, c->height, ~0);
164 
165  img = xcb_get_image_reply(c->conn, iq, &e);
166 
167  if (e) {
168  av_log(s, AV_LOG_ERROR,
169  "Cannot get the image data "
170  "event_error: response_type:%u error_code:%u "
171  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
172  e->response_type, e->error_code,
173  e->sequence, e->resource_id, e->minor_code, e->major_code);
174  free(e);
175  return AVERROR(EACCES);
176  }
177 
178  if (!img)
179  return AVERROR(EAGAIN);
180 
181  data = xcb_get_image_data(img);
182  length = xcb_get_image_data_length(img);
183 
184  av_init_packet(pkt);
185 
186  pkt->buf = av_buffer_create(data, length, xcbgrab_image_reply_free, img, 0);
187  if (!pkt->buf) {
188  free(img);
189  return AVERROR(ENOMEM);
190  }
191 
192  pkt->data = data;
193  pkt->size = length;
194 
195  return 0;
196 }
197 
199 {
200  XCBGrabContext *c = s->priv_data;
201  int64_t curtime, delay;
202 
203  c->time_frame += c->frame_duration;
204 
205  for (;;) {
206  curtime = av_gettime();
207  delay = c->time_frame - curtime;
208  if (delay <= 0)
209  break;
210  av_usleep(delay);
211  }
212 
213  return curtime;
214 }
215 
216 #if CONFIG_LIBXCB_SHM
217 static int check_shm(xcb_connection_t *conn)
218 {
219  xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
220  xcb_shm_query_version_reply_t *reply;
221 
222  reply = xcb_shm_query_version_reply(conn, cookie, NULL);
223  if (reply) {
224  free(reply);
225  return 1;
226  }
227 
228  return 0;
229 }
230 
231 static void free_shm_buffer(void *opaque, uint8_t *data)
232 {
233  shmdt(data);
234 }
235 
236 static AVBufferRef *allocate_shm_buffer(void *opaque, int size)
237 {
238  xcb_connection_t *conn = opaque;
239  xcb_shm_seg_t segment;
240  AVBufferRef *ref;
241  uint8_t *data;
242  int id;
243 
244  id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
245  if (id == -1)
246  return NULL;
247 
248  segment = xcb_generate_id(conn);
249  xcb_shm_attach(conn, segment, id, 0);
250  data = shmat(id, NULL, 0);
251  shmctl(id, IPC_RMID, 0);
252  if ((intptr_t)data == -1 || !data)
253  return NULL;
254 
255  ref = av_buffer_create(data, size, free_shm_buffer, (void *)(ptrdiff_t)segment, 0);
256  if (!ref)
257  shmdt(data);
258 
259  return ref;
260 }
261 
262 static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt)
263 {
264  XCBGrabContext *c = s->priv_data;
265  xcb_shm_get_image_cookie_t iq;
266  xcb_shm_get_image_reply_t *img;
267  xcb_drawable_t drawable = c->screen->root;
268  xcb_generic_error_t *e = NULL;
269  AVBufferRef *buf;
270  xcb_shm_seg_t segment;
271 
272  buf = av_buffer_pool_get(c->shm_pool);
273  if (!buf) {
274  av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n");
275  return AVERROR(ENOMEM);
276  }
277  segment = (xcb_shm_seg_t)av_buffer_pool_buffer_get_opaque(buf);
278 
279  iq = xcb_shm_get_image(c->conn, drawable,
280  c->x, c->y, c->width, c->height, ~0,
281  XCB_IMAGE_FORMAT_Z_PIXMAP, segment, 0);
282  img = xcb_shm_get_image_reply(c->conn, iq, &e);
283 
284  xcb_flush(c->conn);
285 
286  if (e) {
287  av_log(s, AV_LOG_ERROR,
288  "Cannot get the image data "
289  "event_error: response_type:%u error_code:%u "
290  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
291  e->response_type, e->error_code,
292  e->sequence, e->resource_id, e->minor_code, e->major_code);
293 
294  free(e);
295  av_buffer_unref(&buf);
296  return AVERROR(EACCES);
297  }
298 
299  free(img);
300 
301  av_init_packet(pkt);
302 
303  pkt->buf = buf;
304  pkt->data = buf->data;
305  pkt->size = c->frame_size;
306 
307  return 0;
308 }
309 #endif /* CONFIG_LIBXCB_SHM */
310 
311 #if CONFIG_LIBXCB_XFIXES
312 static int check_xfixes(xcb_connection_t *conn)
313 {
314  xcb_xfixes_query_version_cookie_t cookie;
315  xcb_xfixes_query_version_reply_t *reply;
316 
317  cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
318  XCB_XFIXES_MINOR_VERSION);
319  reply = xcb_xfixes_query_version_reply(conn, cookie, NULL);
320 
321  if (reply) {
322  free(reply);
323  return 1;
324  }
325  return 0;
326 }
327 
328 #define BLEND(target, source, alpha) \
329  (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
330 
331 static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt,
332  xcb_query_pointer_reply_t *p,
333  xcb_get_geometry_reply_t *geo)
334 {
335  XCBGrabContext *gr = s->priv_data;
336  uint32_t *cursor;
337  uint8_t *image = pkt->data;
338  int stride = gr->bpp / 8;
339  xcb_xfixes_get_cursor_image_cookie_t cc;
340  xcb_xfixes_get_cursor_image_reply_t *ci;
341  int cx, cy, x, y, w, h, c_off, i_off;
342 
343  cc = xcb_xfixes_get_cursor_image(gr->conn);
344  ci = xcb_xfixes_get_cursor_image_reply(gr->conn, cc, NULL);
345  if (!ci)
346  return;
347 
348  cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
349  if (!cursor)
350  return;
351 
352  cx = ci->x - ci->xhot;
353  cy = ci->y - ci->yhot;
354 
355  x = FFMAX(cx, gr->x);
356  y = FFMAX(cy, gr->y);
357 
358  w = FFMIN(cx + ci->width, gr->x + gr->width) - x;
359  h = FFMIN(cy + ci->height, gr->y + gr->height) - y;
360 
361  c_off = x - cx;
362  i_off = x - gr->x;
363 
364  cursor += (y - cy) * ci->width;
365  image += (y - gr->y) * gr->width * stride;
366 
367  for (y = 0; y < h; y++) {
368  cursor += c_off;
369  image += i_off * stride;
370  for (x = 0; x < w; x++, cursor++, image += stride) {
371  int r, g, b, a;
372 
373  r = *cursor & 0xff;
374  g = (*cursor >> 8) & 0xff;
375  b = (*cursor >> 16) & 0xff;
376  a = (*cursor >> 24) & 0xff;
377 
378  if (!a)
379  continue;
380 
381  if (a == 255) {
382  image[0] = r;
383  image[1] = g;
384  image[2] = b;
385  } else {
386  image[0] = BLEND(r, image[0], a);
387  image[1] = BLEND(g, image[1], a);
388  image[2] = BLEND(b, image[2], a);
389  }
390 
391  }
392  cursor += ci->width - w - c_off;
393  image += (gr->width - w - i_off) * stride;
394  }
395 
396  free(ci);
397 }
398 #endif /* CONFIG_LIBXCB_XFIXES */
399 
401 {
402  XCBGrabContext *c = s->priv_data;
403  const uint32_t args[] = { c->x - c->region_border,
404  c->y - c->region_border };
405 
406  xcb_configure_window(c->conn,
407  c->window,
408  XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
409  args);
410 }
411 
413 {
414  XCBGrabContext *c = s->priv_data;
415  xcb_query_pointer_cookie_t pc;
416  xcb_get_geometry_cookie_t gc;
417  xcb_query_pointer_reply_t *p = NULL;
418  xcb_get_geometry_reply_t *geo = NULL;
419  int ret = 0;
420  int64_t pts;
421 
422  pts = wait_frame(s, pkt);
423 
424  if (c->follow_mouse || c->draw_mouse) {
425  pc = xcb_query_pointer(c->conn, c->screen->root);
426  gc = xcb_get_geometry(c->conn, c->screen->root);
427  p = xcb_query_pointer_reply(c->conn, pc, NULL);
428  if (!p) {
429  av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n");
430  return AVERROR_EXTERNAL;
431  }
432  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
433  if (!geo) {
434  av_log(s, AV_LOG_ERROR, "Failed to get xcb geometry\n");
435  free(p);
436  return AVERROR_EXTERNAL;
437  }
438  }
439 
440  if (c->follow_mouse && p->same_screen)
441  xcbgrab_reposition(s, p, geo);
442 
443  if (c->show_region)
445 
446 #if CONFIG_LIBXCB_SHM
447  if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) {
448  av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n");
449  c->has_shm = 0;
450  }
451 #endif
452  if (!c->has_shm)
453  ret = xcbgrab_frame(s, pkt);
454  pkt->dts = pkt->pts = pts;
455  pkt->duration = c->frame_duration;
456 
457 #if CONFIG_LIBXCB_XFIXES
458  if (ret >= 0 && c->draw_mouse && p->same_screen)
459  xcbgrab_draw_mouse(s, pkt, p, geo);
460 #endif
461 
462  free(p);
463  free(geo);
464 
465  return ret;
466 }
467 
469 {
471 
472 #if CONFIG_LIBXCB_SHM
473  av_buffer_pool_uninit(&ctx->shm_pool);
474 #endif
475 
476  xcb_disconnect(ctx->conn);
477 
478  return 0;
479 }
480 
481 static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num)
482 {
483  xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
484  xcb_screen_t *screen = NULL;
485 
486  for (; it.rem > 0; xcb_screen_next (&it)) {
487  if (!screen_num) {
488  screen = it.data;
489  break;
490  }
491 
492  screen_num--;
493  }
494 
495  return screen;
496 }
497 
499  int *pix_fmt, int *bpp)
500 {
501  XCBGrabContext *c = s->priv_data;
502  const xcb_setup_t *setup = xcb_get_setup(c->conn);
503  const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
504  int length = xcb_setup_pixmap_formats_length(setup);
505 
506  *pix_fmt = 0;
507 
508  while (length--) {
509  if (fmt->depth == depth) {
510  switch (depth) {
511  case 32:
512  if (fmt->bits_per_pixel == 32)
513  *pix_fmt = AV_PIX_FMT_0RGB;
514  break;
515  case 24:
516  if (fmt->bits_per_pixel == 32)
517  *pix_fmt = AV_PIX_FMT_0RGB32;
518  else if (fmt->bits_per_pixel == 24)
519  *pix_fmt = AV_PIX_FMT_RGB24;
520  break;
521  case 16:
522  if (fmt->bits_per_pixel == 16)
523  *pix_fmt = AV_PIX_FMT_RGB565;
524  break;
525  case 15:
526  if (fmt->bits_per_pixel == 16)
527  *pix_fmt = AV_PIX_FMT_RGB555;
528  break;
529  case 8:
530  if (fmt->bits_per_pixel == 8)
531  *pix_fmt = AV_PIX_FMT_RGB8;
532  break;
533  }
534  }
535 
536  if (*pix_fmt) {
537  *bpp = fmt->bits_per_pixel;
538  return 0;
539  }
540 
541  fmt++;
542  }
543  avpriv_report_missing_feature(s, "Mapping this pixmap format");
544 
545  return AVERROR_PATCHWELCOME;
546 }
547 
549 {
550  XCBGrabContext *c = s->priv_data;
552  xcb_get_geometry_cookie_t gc;
553  xcb_get_geometry_reply_t *geo;
554  int64_t frame_size_bits;
555  int ret;
556 
557  if (!st)
558  return AVERROR(ENOMEM);
559 
561  if (ret < 0)
562  return ret;
563 
564  avpriv_set_pts_info(st, 64, 1, 1000000);
565 
566  gc = xcb_get_geometry(c->conn, c->screen->root);
567  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
568  if (!geo)
569  return AVERROR_EXTERNAL;
570 
571  if (!c->width || !c->height) {
572  c->width = geo->width;
573  c->height = geo->height;
574  }
575 
576  if (c->x + c->width > geo->width ||
577  c->y + c->height > geo->height) {
578  av_log(s, AV_LOG_ERROR,
579  "Capture area %dx%d at position %d.%d "
580  "outside the screen size %dx%d\n",
581  c->width, c->height,
582  c->x, c->y,
583  geo->width, geo->height);
584  free(geo);
585  return AVERROR(EINVAL);
586  }
587 
589  st->avg_frame_rate.num };
591  c->time_frame = av_gettime();
592 
593  ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp);
594  free(geo);
595  if (ret < 0)
596  return ret;
597 
598  frame_size_bits = (int64_t)c->width * c->height * c->bpp;
599  if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
600  av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
601  return AVERROR_PATCHWELCOME;
602  }
603  c->frame_size = frame_size_bits / 8;
604 
605 #if CONFIG_LIBXCB_SHM
607  c->conn, allocate_shm_buffer, NULL);
608  if (!c->shm_pool)
609  return AVERROR(ENOMEM);
610 #endif
611 
614  st->codecpar->width = c->width;
615  st->codecpar->height = c->height;
616  st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
617 
618  return ret;
619 }
620 
622 {
623  XCBGrabContext *c = s->priv_data;
624  xcb_gcontext_t gc = xcb_generate_id(c->conn);
625  uint32_t mask = XCB_GC_FOREGROUND |
626  XCB_GC_BACKGROUND |
627  XCB_GC_LINE_WIDTH |
628  XCB_GC_LINE_STYLE |
629  XCB_GC_FILL_STYLE;
630  uint32_t values[] = { c->screen->black_pixel,
631  c->screen->white_pixel,
632  c->region_border,
633  XCB_LINE_STYLE_DOUBLE_DASH,
634  XCB_FILL_STYLE_SOLID };
635  xcb_rectangle_t r = { 1, 1,
636  c->width + c->region_border * 2 - 3,
637  c->height + c->region_border * 2 - 3 };
638 
639  xcb_create_gc(c->conn, gc, c->window, mask, values);
640 
641  xcb_poly_rectangle(c->conn, c->window, gc, 1, &r);
642 }
643 
645 {
646  XCBGrabContext *c = s->priv_data;
647  uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
648  uint32_t values[] = { 1,
649  XCB_EVENT_MASK_EXPOSURE |
650  XCB_EVENT_MASK_STRUCTURE_NOTIFY };
651  av_unused xcb_rectangle_t rect = { 0, 0, c->width, c->height };
652 
653  c->window = xcb_generate_id(c->conn);
654 
655  xcb_create_window(c->conn, XCB_COPY_FROM_PARENT,
656  c->window,
657  c->screen->root,
658  c->x - c->region_border,
659  c->y - c->region_border,
660  c->width + c->region_border * 2,
661  c->height + c->region_border * 2,
662  0,
663  XCB_WINDOW_CLASS_INPUT_OUTPUT,
664  XCB_COPY_FROM_PARENT,
665  mask, values);
666 
667 #if CONFIG_LIBXCB_SHAPE
668  xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
669  XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
670  c->window,
672  1, &rect);
673 #endif
674 
675  xcb_map_window(c->conn, c->window);
676 
677  draw_rectangle(s);
678 }
679 
681 {
682  XCBGrabContext *c = s->priv_data;
683  int screen_num, ret;
684  const xcb_setup_t *setup;
685  char *display_name = av_strdup(s->url);
686 
687  if (!display_name)
688  return AVERROR(ENOMEM);
689 
690  if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
691  *display_name = 0;
692  sscanf(s->url, "+%d,%d", &c->x, &c->y);
693  }
694 
695  c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
696  av_freep(&display_name);
697 
698  if ((ret = xcb_connection_has_error(c->conn))) {
699  av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
700  s->url[0] ? s->url : "default", ret);
701  return AVERROR(EIO);
702  }
703 
704  setup = xcb_get_setup(c->conn);
705 
706  c->screen = get_screen(setup, screen_num);
707  if (!c->screen) {
708  av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n",
709  screen_num);
711  return AVERROR(EIO);
712  }
713 
714  ret = create_stream(s);
715 
716  if (ret < 0) {
718  return ret;
719  }
720 
721 #if CONFIG_LIBXCB_SHM
722  c->has_shm = check_shm(c->conn);
723 #endif
724 
725 #if CONFIG_LIBXCB_XFIXES
726  if (c->draw_mouse) {
727  if (!(c->draw_mouse = check_xfixes(c->conn))) {
729  "XFixes not available, cannot draw the mouse.\n");
730  }
731  if (c->bpp < 24) {
732  avpriv_report_missing_feature(s, "%d bits per pixel screen",
733  c->bpp);
734  c->draw_mouse = 0;
735  }
736  }
737 #endif
738 
739  if (c->show_region)
740  setup_window(s);
741 
742  return 0;
743 }
744 
746  .name = "x11grab",
747  .long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"),
748  .priv_data_size = sizeof(XCBGrabContext),
752  .flags = AVFMT_NOFILE,
753  .priv_class = &xcbgrab_class,
754 };
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:481
AVInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:745
#define NULL
Definition: coverity.c:32
xcb_connection_t * conn
Definition: xcbgrab.c:52
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:389
static enum AVPixelFormat pix_fmt
static av_cold int xcbgrab_read_header(AVFormatContext *s)
Definition: xcbgrab.c:680
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:179
static int create_stream(AVFormatContext *s)
Definition: xcbgrab.c:548
AVOption.
Definition: opt.h:248
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static void xcbgrab_update_region(AVFormatContext *s)
Definition: xcbgrab.c:400
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
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.
Definition: utils.c:4871
const char * g
Definition: vf_curves.c:115
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:621
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int num
Numerator.
Definition: rational.h:59
int size
Definition: packet.h:364
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
xcb_window_t window
Definition: xcbgrab.c:54
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:36
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
static AVPacket pkt
int centered
Definition: xcbgrab.c:71
Format I/O context.
Definition: avformat.h:1239
#define img
int frame_size
Definition: xcbgrab.c:64
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:72
uint8_t
#define av_cold
Definition: attributes.h:88
int width
Video only.
Definition: codec_par.h:126
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:381
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4453
static const AVClass xcbgrab_class
Definition: xcbgrab.c:98
xcb_screen_t * screen
Definition: xcbgrab.c:53
static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, int *pix_fmt, int *bpp)
Definition: xcbgrab.c:498
uint8_t * data
Definition: packet.h:363
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s it
static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:152
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
ptrdiff_t size
Definition: opengl_enc.c:100
#define av_log(a,...)
The buffer pool.
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVRational time_base
Definition: xcbgrab.c:59
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
static const uint16_t mask[17]
Definition: lzw.c:38
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
char * url
input or output URL.
Definition: avformat.h:1335
const char * r
Definition: vf_curves.c:114
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:346
GLsizei GLsizei * length
Definition: opengl_enc.c:114
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:953
#define FFMAX(a, b)
Definition: common.h:94
Definition: hls.c:68
common internal API header
#define b
Definition: input.c:41
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
#define FFMIN(a, b)
Definition: common.h:96
static const AVOption options[]
Definition: xcbgrab.c:82
const char * framerate
Definition: xcbgrab.c:73
uint8_t w
Definition: llviddspenc.c:38
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return values
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:245
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
if(ret)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:880
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
int64_t time_frame
Definition: xcbgrab.c:58
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
static int64_t wait_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:198
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
uint8_t * data
The data buffer.
Definition: buffer.h:89
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2]...the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so...,+,-,+,-,+,+,-,+,-,+,...hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32-hcoeff[1]-hcoeff[2]-...a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2}an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||.........intra?||||:Block01:yes no||||:Block02:.................||||:Block03::y DC::ref index:||||:Block04::cb DC::motion x:||||.........:cr DC::motion y:||||.................|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------------------------------|||Y subbands||Cb subbands||Cr subbands||||------||------||------|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||------||------||------||||------||------||------|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||------||------||------||||------||------||------|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||------||------||------||||------||------||------|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------------------------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction------------|\Dequantization-------------------\||Reference frames|\IDWT|--------------|Motion\|||Frame 0||Frame 1||Compensation.OBMC v-------|--------------|--------------.\------> Frame n output Frame Frame<----------------------------------/|...|-------------------Range Coder:============Binary Range Coder:-------------------The implemented range coder is an adapted version based upon"Range encoding: an algorithm for removing redundancy from a digitised message."by G.N.N.Martin.The symbols encoded by the Snow range coder are bits(0|1).The associated probabilities are not fix but change depending on the symbol mix seen so far.bit seen|new state---------+-----------------------------------------------0|256-state_transition_table[256-old_state];1|state_transition_table[old_state];state_transition_table={0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:-------------------------FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1.the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:206
int show_region
Definition: xcbgrab.c:69
Describe the class of an AVClass context structure.
Definition: log.h:67
Definition: f_ebur128.c:91
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:303
static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:412
Rational number (pair of numerator and denominator).
Definition: rational.h:58
offset must point to two consecutive integers
Definition: opt.h:235
misc parsing utilities
static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
Definition: xcbgrab.c:147
#define OFFSET(x)
Definition: xcbgrab.c:80
static void setup_window(AVFormatContext *s)
Definition: xcbgrab.c:644
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
static int64_t pts
#define flags(name, subs,...)
Definition: cbs_av1.c:560
static int xcbgrab_reposition(AVFormatContext *s, xcb_query_pointer_reply_t *p, xcb_get_geometry_reply_t *geo)
Definition: xcbgrab.c:106
A reference to a data buffer.
Definition: buffer.h:81
Main libavformat public API header.
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
#define D
Definition: xcbgrab.c:81
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
int region_border
Definition: xcbgrab.c:70
static av_cold int xcbgrab_read_close(AVFormatContext *s)
Definition: xcbgrab.c:468
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:387
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:35
int den
Denominator.
Definition: rational.h:60
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:215
int follow_mouse
Definition: xcbgrab.c:68
void * priv_data
Format private data.
Definition: avformat.h:1267
int64_t frame_duration
Definition: xcbgrab.c:60
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:386
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: packet.h:362
int draw_mouse
Definition: xcbgrab.c:67
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:652
#define FOLLOW_CENTER
Definition: xcbgrab.c:78
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1045
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:364
#define stride
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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.Frame references ownership and permissions
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
enum AVCodecID id
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
This structure stores compressed data.
Definition: packet.h:340
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:356
#define av_unused
Definition: attributes.h:131
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:376