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) {
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 
185 
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) {
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 
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  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
429  }
430 
431  if (c->follow_mouse && p->same_screen)
432  xcbgrab_reposition(s, p, geo);
433 
434  if (c->show_region)
436 
437 #if CONFIG_LIBXCB_SHM
438  if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) {
439  av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n");
440  c->has_shm = 0;
441  }
442 #endif
443  if (!c->has_shm)
444  ret = xcbgrab_frame(s, pkt);
445  pkt->dts = pkt->pts = pts;
446  pkt->duration = c->frame_duration;
447 
448 #if CONFIG_LIBXCB_XFIXES
449  if (ret >= 0 && c->draw_mouse && p->same_screen)
450  xcbgrab_draw_mouse(s, pkt, p, geo);
451 #endif
452 
453  free(p);
454  free(geo);
455 
456  return ret;
457 }
458 
460 {
461  XCBGrabContext *ctx = s->priv_data;
462 
463 #if CONFIG_LIBXCB_SHM
464  av_buffer_pool_uninit(&ctx->shm_pool);
465 #endif
466 
467  xcb_disconnect(ctx->conn);
468 
469  return 0;
470 }
471 
472 static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num)
473 {
474  xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
475  xcb_screen_t *screen = NULL;
476 
477  for (; it.rem > 0; xcb_screen_next (&it)) {
478  if (!screen_num) {
479  screen = it.data;
480  break;
481  }
482 
483  screen_num--;
484  }
485 
486  return screen;
487 }
488 
490  int *pix_fmt, int *bpp)
491 {
492  XCBGrabContext *c = s->priv_data;
493  const xcb_setup_t *setup = xcb_get_setup(c->conn);
494  const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
495  int length = xcb_setup_pixmap_formats_length(setup);
496 
497  *pix_fmt = 0;
498 
499  while (length--) {
500  if (fmt->depth == depth) {
501  switch (depth) {
502  case 32:
503  if (fmt->bits_per_pixel == 32)
505  break;
506  case 24:
507  if (fmt->bits_per_pixel == 32)
509  else if (fmt->bits_per_pixel == 24)
511  break;
512  case 16:
513  if (fmt->bits_per_pixel == 16)
515  break;
516  case 15:
517  if (fmt->bits_per_pixel == 16)
519  break;
520  case 8:
521  if (fmt->bits_per_pixel == 8)
523  break;
524  }
525  }
526 
527  if (*pix_fmt) {
528  *bpp = fmt->bits_per_pixel;
529  return 0;
530  }
531 
532  fmt++;
533  }
534  avpriv_report_missing_feature(s, "Mapping this pixmap format");
535 
536  return AVERROR_PATCHWELCOME;
537 }
538 
540 {
541  XCBGrabContext *c = s->priv_data;
543  xcb_get_geometry_cookie_t gc;
544  xcb_get_geometry_reply_t *geo;
545  int64_t frame_size_bits;
546  int ret;
547 
548  if (!st)
549  return AVERROR(ENOMEM);
550 
551  ret = av_parse_video_rate(&st->avg_frame_rate, c->framerate);
552  if (ret < 0)
553  return ret;
554 
555  avpriv_set_pts_info(st, 64, 1, 1000000);
556 
557  gc = xcb_get_geometry(c->conn, c->screen->root);
558  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
559  if (!geo)
560  return AVERROR_EXTERNAL;
561 
562  if (!c->width || !c->height) {
563  c->width = geo->width;
564  c->height = geo->height;
565  }
566 
567  if (c->x + c->width > geo->width ||
568  c->y + c->height > geo->height) {
570  "Capture area %dx%d at position %d.%d "
571  "outside the screen size %dx%d\n",
572  c->width, c->height,
573  c->x, c->y,
574  geo->width, geo->height);
575  free(geo);
576  return AVERROR(EINVAL);
577  }
578 
579  c->time_base = (AVRational){ st->avg_frame_rate.den,
580  st->avg_frame_rate.num };
581  c->frame_duration = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q);
582  c->time_frame = av_gettime();
583 
584  ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp);
585  free(geo);
586  if (ret < 0)
587  return ret;
588 
589  frame_size_bits = (int64_t)c->width * c->height * c->bpp;
590  if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
591  av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
592  return AVERROR_PATCHWELCOME;
593  }
594  c->frame_size = frame_size_bits / 8;
595 
596 #if CONFIG_LIBXCB_SHM
597  c->shm_pool = av_buffer_pool_init2(c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE,
598  c->conn, allocate_shm_buffer, NULL);
599  if (!c->shm_pool)
600  return AVERROR(ENOMEM);
601 #endif
602 
605  st->codecpar->width = c->width;
606  st->codecpar->height = c->height;
607  st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
608 
609  return ret;
610 }
611 
613 {
614  XCBGrabContext *c = s->priv_data;
615  xcb_gcontext_t gc = xcb_generate_id(c->conn);
616  uint32_t mask = XCB_GC_FOREGROUND |
617  XCB_GC_BACKGROUND |
618  XCB_GC_LINE_WIDTH |
619  XCB_GC_LINE_STYLE |
620  XCB_GC_FILL_STYLE;
621  uint32_t values[] = { c->screen->black_pixel,
622  c->screen->white_pixel,
623  c->region_border,
624  XCB_LINE_STYLE_DOUBLE_DASH,
625  XCB_FILL_STYLE_SOLID };
626  xcb_rectangle_t r = { 1, 1,
627  c->width + c->region_border * 2 - 3,
628  c->height + c->region_border * 2 - 3 };
629 
630  xcb_create_gc(c->conn, gc, c->window, mask, values);
631 
632  xcb_poly_rectangle(c->conn, c->window, gc, 1, &r);
633 }
634 
636 {
637  XCBGrabContext *c = s->priv_data;
638  uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
639  uint32_t values[] = { 1,
640  XCB_EVENT_MASK_EXPOSURE |
641  XCB_EVENT_MASK_STRUCTURE_NOTIFY };
642  av_unused xcb_rectangle_t rect = { 0, 0, c->width, c->height };
643 
644  c->window = xcb_generate_id(c->conn);
645 
646  xcb_create_window(c->conn, XCB_COPY_FROM_PARENT,
647  c->window,
648  c->screen->root,
649  c->x - c->region_border,
650  c->y - c->region_border,
651  c->width + c->region_border * 2,
652  c->height + c->region_border * 2,
653  0,
654  XCB_WINDOW_CLASS_INPUT_OUTPUT,
655  XCB_COPY_FROM_PARENT,
656  mask, values);
657 
658 #if CONFIG_LIBXCB_SHAPE
659  xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
660  XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
661  c->window,
662  c->region_border, c->region_border,
663  1, &rect);
664 #endif
665 
666  xcb_map_window(c->conn, c->window);
667 
668  draw_rectangle(s);
669 }
670 
672 {
673  XCBGrabContext *c = s->priv_data;
674  int screen_num, ret;
675  const xcb_setup_t *setup;
676  char *display_name = av_strdup(s->url);
677 
678  if (!display_name)
679  return AVERROR(ENOMEM);
680 
681  if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
682  *display_name = 0;
683  sscanf(s->url, "+%d,%d", &c->x, &c->y);
684  }
685 
686  c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
687  av_freep(&display_name);
688 
689  if ((ret = xcb_connection_has_error(c->conn))) {
690  av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
691  s->url[0] ? s->url : "default", ret);
692  return AVERROR(EIO);
693  }
694 
695  setup = xcb_get_setup(c->conn);
696 
697  c->screen = get_screen(setup, screen_num);
698  if (!c->screen) {
699  av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n",
700  screen_num);
702  return AVERROR(EIO);
703  }
704 
705  ret = create_stream(s);
706 
707  if (ret < 0) {
709  return ret;
710  }
711 
712 #if CONFIG_LIBXCB_SHM
713  c->has_shm = check_shm(c->conn);
714 #endif
715 
716 #if CONFIG_LIBXCB_XFIXES
717  if (c->draw_mouse) {
718  if (!(c->draw_mouse = check_xfixes(c->conn))) {
720  "XFixes not available, cannot draw the mouse.\n");
721  }
722  if (c->bpp < 24) {
723  avpriv_report_missing_feature(s, "%d bits per pixel screen",
724  c->bpp);
725  c->draw_mouse = 0;
726  }
727  }
728 #endif
729 
730  if (c->show_region)
731  setup_window(s);
732 
733  return 0;
734 }
735 
737  .name = "x11grab",
738  .long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"),
739  .priv_data_size = sizeof(XCBGrabContext),
743  .flags = AVFMT_NOFILE,
744  .priv_class = &xcbgrab_class,
745 };
XCBGrabContext::has_shm
int has_shm
Definition: xcbgrab.c:75
stride
int stride
Definition: mace.c:144
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
xcbgrab_update_region
static void xcbgrab_update_region(AVFormatContext *s)
Definition: xcbgrab.c:400
XCBGrabContext::y
int y
Definition: xcbgrab.c:62
r
const char * r
Definition: vf_curves.c:114
AVERROR
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
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4526
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
FOLLOW_CENTER
#define FOLLOW_CENTER
Definition: xcbgrab.c:78
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:77
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:89
XCBGrabContext::time_base
AVRational time_base
Definition: xcbgrab.c:59
rect
Definition: f_ebur128.c:91
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:62
av_unused
#define av_unused
Definition: attributes.h:131
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:355
AVOption
AVOption.
Definition: opt.h:246
b
#define b
Definition: input.c:41
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:938
data
const char data[16]
Definition: mxf.c:91
av_buffer_create
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
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:373
mathematics.h
create_stream
static int create_stream(AVFormatContext *s)
Definition: xcbgrab.c:539
framerate
int framerate
Definition: h264_levels.c:65
xcbgrab_class
static const AVClass xcbgrab_class
Definition: xcbgrab.c:98
av_buffer_pool_buffer_get_opaque
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:362
xcbgrab_frame
static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:152
draw_rectangle
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:612
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
pts
static int64_t pts
Definition: transcode_aac.c:647
AVRational::num
int num
Numerator.
Definition: rational.h:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVInputFormat
Definition: avformat.h:636
av_cold
#define av_cold
Definition: attributes.h:90
mask
static const uint16_t mask[17]
Definition: lzw.c:38
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:337
options
static const AVOption options[]
Definition: xcbgrab.c:82
width
#define width
pixfmt_from_pixmap_format
static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, int *pix_fmt, int *bpp)
Definition: xcbgrab.c:489
s
#define s(width, name)
Definition: cbs_vp9.c:257
XCBGrabContext::frame_duration
int64_t frame_duration
Definition: xcbgrab.c:60
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:641
g
const char * g
Definition: vf_curves.c:115
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:126
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
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
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:40
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
f
#define f(width, name)
Definition: cbs_vp9.c:255
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1335
XCBGrabContext::region_border
int region_border
Definition: xcbgrab.c:70
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1012
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:338
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
av_buffer_unref
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
XCBGrabContext::bpp
int bpp
Definition: xcbgrab.c:65
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:233
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
parseutils.h
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:276
XCBGrabContext::window
xcb_window_t window
Definition: xcbgrab.c:54
AV_PIX_FMT_RGB8
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
time.h
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:42
c
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
XCBGrabContext::show_region
int show_region
Definition: xcbgrab.c:69
XCBGrabContext::follow_mouse
int follow_mouse
Definition: xcbgrab.c:68
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
AVPacket::size
int size
Definition: packet.h:356
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
id
enum AVCodecID id
Definition: extract_extradata_bsf.c:332
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
avpriv_set_pts_info
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:4948
size
int size
Definition: twinvq_data.h:11134
avpriv_report_missing_feature
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:354
a
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:41
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
img
#define img
Definition: vf_colormatrix.c:116
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
av_parse_video_rate
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:179
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
xcbgrab_image_reply_free
static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
Definition: xcbgrab.c:147
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:127
AV_PIX_FMT_RGB555
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:385
uint8_t
uint8_t
Definition: audio_convert.c:194
setup_window
static void setup_window(AVFormatContext *s)
Definition: xcbgrab.c:635
av_buffer_pool_init2
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:218
av_rescale
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
D
#define D
Definition: xcbgrab.c:81
XCBGrabContext::framerate
const char * framerate
Definition: xcbgrab.c:73
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:384
XCBGrabContext::screen
xcb_screen_t * screen
Definition: xcbgrab.c:53
xcbgrab_read_close
static av_cold int xcbgrab_read_close(AVFormatContext *s)
Definition: xcbgrab.c:459
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:865
xcbgrab_read_packet
static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:412
AVClass::class_name
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
AV_PIX_FMT_0RGB32
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:374
wait_frame
static int64_t wait_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:198
avformat.h
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: avcodec.h:215
left
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:386
XCBGrabContext::conn
xcb_connection_t * conn
Definition: xcbgrab.c:52
XCBGrabContext::frame_size
int frame_size
Definition: xcbgrab.c:64
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
AVRational::den
int den
Denominator.
Definition: rational.h:60
xcbgrab_reposition
static int xcbgrab_reposition(AVFormatContext *s, xcb_query_pointer_reply_t *p, xcb_get_geometry_reply_t *geo)
Definition: xcbgrab.c:106
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
values
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
Definition: filter_design.txt:263
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
segment
Definition: hls.c:68
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
XCBGrabContext::x
int x
Definition: xcbgrab.c:62
get_screen
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:472
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:81
xcbgrab_read_header
static av_cold int xcbgrab_read_header(AVFormatContext *s)
Definition: xcbgrab.c:671
it
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
Definition: writing_filters.txt:31
AVCodecParameters::format
int format
Definition: codec_par.h:84
XCBGrabContext::height
int height
Definition: xcbgrab.c:63
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVPacket
This structure stores compressed data.
Definition: packet.h:332
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
OFFSET
#define OFFSET(x)
Definition: xcbgrab.c:80
h
h
Definition: vp9dsp_template.c:2038
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
XCBGrabContext::draw_mouse
int draw_mouse
Definition: xcbgrab.c:67
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:232
XCBGrabContext::centered
int centered
Definition: xcbgrab.c:71
XCBGrabContext
Definition: xcbgrab.c:49
ff_xcbgrab_demuxer
AVInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:736
XCBGrabContext::time_frame
int64_t time_frame
Definition: xcbgrab.c:58
XCBGrabContext::width
int width
Definition: xcbgrab.c:63
av_init_packet
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:35