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  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 {
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)
504  *pix_fmt = AV_PIX_FMT_0RGB;
505  break;
506  case 24:
507  if (fmt->bits_per_pixel == 32)
508  *pix_fmt = AV_PIX_FMT_0RGB32;
509  else if (fmt->bits_per_pixel == 24)
510  *pix_fmt = AV_PIX_FMT_RGB24;
511  break;
512  case 16:
513  if (fmt->bits_per_pixel == 16)
514  *pix_fmt = AV_PIX_FMT_RGB565;
515  break;
516  case 15:
517  if (fmt->bits_per_pixel == 16)
518  *pix_fmt = AV_PIX_FMT_RGB555;
519  break;
520  case 8:
521  if (fmt->bits_per_pixel == 8)
522  *pix_fmt = AV_PIX_FMT_RGB8;
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 
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) {
569  av_log(s, AV_LOG_ERROR,
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 
580  st->avg_frame_rate.num };
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
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,
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 };
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:472
AVInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:736
#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:360
static enum AVPixelFormat pix_fmt
static av_cold int xcbgrab_read_header(AVFormatContext *s)
Definition: xcbgrab.c:671
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:126
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:539
AVOption.
Definition: opt.h:246
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:182
#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:4938
const char * g
Definition: vf_curves.c:115
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:612
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:356
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:1351
#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:373
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:4519
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:489
uint8_t * data
Definition: packet.h:355
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:176
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:186
char * url
input or output URL.
Definition: avformat.h:1447
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:338
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:949
#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:219
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:876
#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:276
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:233
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:635
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:564
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:459
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:385
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:34
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:1379
int64_t frame_duration
Definition: xcbgrab.c:60
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:384
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: packet.h:354
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:650
#define FOLLOW_CENTER
Definition: xcbgrab.c:78
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:335
#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:332
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
#define av_unused
Definition: attributes.h:131
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:374