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 <string.h>
26 #include <xcb/xcb.h>
27 
28 #if CONFIG_LIBXCB_XFIXES
29 #include <xcb/xfixes.h>
30 #endif
31 
32 #if CONFIG_LIBXCB_SHM
33 #include <sys/shm.h>
34 #include <xcb/shm.h>
35 #endif
36 
37 #if CONFIG_LIBXCB_SHAPE
38 #include <xcb/shape.h>
39 #endif
40 
41 #include "libavutil/internal.h"
42 #include "libavutil/mathematics.h"
43 #include "libavutil/opt.h"
44 #include "libavutil/parseutils.h"
45 #include "libavutil/time.h"
46 
47 #include "libavformat/avformat.h"
48 #include "libavformat/internal.h"
49 
50 typedef struct XCBGrabContext {
51  const AVClass *class;
52 
53  xcb_connection_t *conn;
54  xcb_screen_t *screen;
55  xcb_window_t window;
56 #if CONFIG_LIBXCB_SHM
57  AVBufferPool *shm_pool;
58 #endif
59  int64_t time_frame;
61  int64_t frame_duration;
62 
63  int x, y;
64  int width, height;
66  int bpp;
67 
72  int centered;
74 
75  const char *framerate;
76 
77  int has_shm;
79 
80 #define FOLLOW_CENTER -1
81 
82 #define OFFSET(x) offsetof(XCBGrabContext, x)
83 #define D AV_OPT_FLAG_DECODING_PARAM
84 static const AVOption options[] = {
85  { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
86  { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
87  { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
88  { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
89  { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, D },
90  { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D },
91  { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D },
92  { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
93  OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, FOLLOW_CENTER, INT_MAX, D, "follow_mouse" },
94  { "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" },
95  { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
96  { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D },
97  { "select_region", "Select the grabbing region graphically using the pointer.", OFFSET(select_region), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
98  { NULL },
99 };
100 
101 static const AVClass xcbgrab_class = {
102  .class_name = "xcbgrab indev",
103  .item_name = av_default_item_name,
104  .option = options,
105  .version = LIBAVUTIL_VERSION_INT,
107 };
108 
110  xcb_query_pointer_reply_t *p,
111  xcb_get_geometry_reply_t *geo)
112 {
113  XCBGrabContext *c = s->priv_data;
114  int x = c->x, y = c->y;
115  int w = c->width, h = c->height, f = c->follow_mouse;
116  int p_x, p_y;
117 
118  if (!p || !geo)
119  return AVERROR(EIO);
120 
121  p_x = p->win_x;
122  p_y = p->win_y;
123 
124  if (f == FOLLOW_CENTER) {
125  x = p_x - w / 2;
126  y = p_y - h / 2;
127  } else {
128  int left = x + f;
129  int right = x + w - f;
130  int top = y + f;
131  int bottom = y + h - f;
132  if (p_x > right) {
133  x += p_x - right;
134  } else if (p_x < left) {
135  x -= left - p_x;
136  }
137  if (p_y > bottom) {
138  y += p_y - bottom;
139  } else if (p_y < top) {
140  y -= top - p_y;
141  }
142  }
143 
144  c->x = FFMIN(FFMAX(0, x), geo->width - w);
145  c->y = FFMIN(FFMAX(0, y), geo->height - h);
146 
147  return 0;
148 }
149 
150 static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
151 {
152  free(opaque);
153 }
154 
156 {
157  XCBGrabContext *c = s->priv_data;
158  xcb_get_image_cookie_t iq;
159  xcb_get_image_reply_t *img;
160  xcb_drawable_t drawable = c->screen->root;
161  xcb_generic_error_t *e = NULL;
162  uint8_t *data;
163  int length;
164 
165  iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
166  c->x, c->y, c->width, c->height, ~0);
167 
168  img = xcb_get_image_reply(c->conn, iq, &e);
169 
170  if (e) {
171  av_log(s, AV_LOG_ERROR,
172  "Cannot get the image data "
173  "event_error: response_type:%u error_code:%u "
174  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
175  e->response_type, e->error_code,
176  e->sequence, e->resource_id, e->minor_code, e->major_code);
177  free(e);
178  return AVERROR(EACCES);
179  }
180 
181  if (!img)
182  return AVERROR(EAGAIN);
183 
184  data = xcb_get_image_data(img);
185  length = xcb_get_image_data_length(img);
186 
187  av_init_packet(pkt);
188 
189  pkt->buf = av_buffer_create(data, length, xcbgrab_image_reply_free, img, 0);
190  if (!pkt->buf) {
191  free(img);
192  return AVERROR(ENOMEM);
193  }
194 
195  pkt->data = data;
196  pkt->size = length;
197 
198  return 0;
199 }
200 
202 {
203  XCBGrabContext *c = s->priv_data;
204  int64_t curtime, delay;
205 
206  c->time_frame += c->frame_duration;
207 
208  for (;;) {
209  curtime = av_gettime_relative();
210  delay = c->time_frame - curtime;
211  if (delay <= 0)
212  break;
213  av_usleep(delay);
214  }
215 
216  return curtime;
217 }
218 
219 #if CONFIG_LIBXCB_SHM
220 static int check_shm(xcb_connection_t *conn)
221 {
222  xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
223  xcb_shm_query_version_reply_t *reply;
224 
225  reply = xcb_shm_query_version_reply(conn, cookie, NULL);
226  if (reply) {
227  free(reply);
228  return 1;
229  }
230 
231  return 0;
232 }
233 
234 static void free_shm_buffer(void *opaque, uint8_t *data)
235 {
236  shmdt(data);
237 }
238 
239 static AVBufferRef *allocate_shm_buffer(void *opaque, int size)
240 {
241  xcb_connection_t *conn = opaque;
242  xcb_shm_seg_t segment;
243  AVBufferRef *ref;
244  uint8_t *data;
245  int id;
246 
247  id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
248  if (id == -1)
249  return NULL;
250 
251  segment = xcb_generate_id(conn);
252  xcb_shm_attach(conn, segment, id, 0);
253  data = shmat(id, NULL, 0);
254  shmctl(id, IPC_RMID, 0);
255  if ((intptr_t)data == -1 || !data)
256  return NULL;
257 
258  ref = av_buffer_create(data, size, free_shm_buffer, (void *)(ptrdiff_t)segment, 0);
259  if (!ref)
260  shmdt(data);
261 
262  return ref;
263 }
264 
265 static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt)
266 {
267  XCBGrabContext *c = s->priv_data;
268  xcb_shm_get_image_cookie_t iq;
269  xcb_shm_get_image_reply_t *img;
270  xcb_drawable_t drawable = c->screen->root;
271  xcb_generic_error_t *e = NULL;
272  AVBufferRef *buf;
273  xcb_shm_seg_t segment;
274 
275  buf = av_buffer_pool_get(c->shm_pool);
276  if (!buf) {
277  av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n");
278  return AVERROR(ENOMEM);
279  }
280  segment = (xcb_shm_seg_t)av_buffer_pool_buffer_get_opaque(buf);
281 
282  iq = xcb_shm_get_image(c->conn, drawable,
283  c->x, c->y, c->width, c->height, ~0,
284  XCB_IMAGE_FORMAT_Z_PIXMAP, segment, 0);
285  img = xcb_shm_get_image_reply(c->conn, iq, &e);
286 
287  xcb_flush(c->conn);
288 
289  if (e) {
290  av_log(s, AV_LOG_ERROR,
291  "Cannot get the image data "
292  "event_error: response_type:%u error_code:%u "
293  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
294  e->response_type, e->error_code,
295  e->sequence, e->resource_id, e->minor_code, e->major_code);
296 
297  free(e);
298  av_buffer_unref(&buf);
299  return AVERROR(EACCES);
300  }
301 
302  free(img);
303 
304  av_init_packet(pkt);
305 
306  pkt->buf = buf;
307  pkt->data = buf->data;
308  pkt->size = c->frame_size;
309 
310  return 0;
311 }
312 #endif /* CONFIG_LIBXCB_SHM */
313 
314 #if CONFIG_LIBXCB_XFIXES
315 static int check_xfixes(xcb_connection_t *conn)
316 {
317  xcb_xfixes_query_version_cookie_t cookie;
318  xcb_xfixes_query_version_reply_t *reply;
319 
320  cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
321  XCB_XFIXES_MINOR_VERSION);
322  reply = xcb_xfixes_query_version_reply(conn, cookie, NULL);
323 
324  if (reply) {
325  free(reply);
326  return 1;
327  }
328  return 0;
329 }
330 
331 #define BLEND(target, source, alpha) \
332  (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
333 
334 static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt,
335  xcb_query_pointer_reply_t *p,
336  xcb_get_geometry_reply_t *geo)
337 {
338  XCBGrabContext *gr = s->priv_data;
339  uint32_t *cursor;
340  uint8_t *image = pkt->data;
341  int stride = gr->bpp / 8;
342  xcb_xfixes_get_cursor_image_cookie_t cc;
343  xcb_xfixes_get_cursor_image_reply_t *ci;
344  int cx, cy, x, y, w, h, c_off, i_off;
345 
346  cc = xcb_xfixes_get_cursor_image(gr->conn);
347  ci = xcb_xfixes_get_cursor_image_reply(gr->conn, cc, NULL);
348  if (!ci)
349  return;
350 
351  cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
352  if (!cursor)
353  return;
354 
355  cx = ci->x - ci->xhot;
356  cy = ci->y - ci->yhot;
357 
358  x = FFMAX(cx, gr->x);
359  y = FFMAX(cy, gr->y);
360 
361  w = FFMIN(cx + ci->width, gr->x + gr->width) - x;
362  h = FFMIN(cy + ci->height, gr->y + gr->height) - y;
363 
364  c_off = x - cx;
365  i_off = x - gr->x;
366 
367  cursor += (y - cy) * ci->width;
368  image += (y - gr->y) * gr->width * stride;
369 
370  for (y = 0; y < h; y++) {
371  cursor += c_off;
372  image += i_off * stride;
373  for (x = 0; x < w; x++, cursor++, image += stride) {
374  int r, g, b, a;
375 
376  r = *cursor & 0xff;
377  g = (*cursor >> 8) & 0xff;
378  b = (*cursor >> 16) & 0xff;
379  a = (*cursor >> 24) & 0xff;
380 
381  if (!a)
382  continue;
383 
384  if (a == 255) {
385  image[0] = r;
386  image[1] = g;
387  image[2] = b;
388  } else {
389  image[0] = BLEND(r, image[0], a);
390  image[1] = BLEND(g, image[1], a);
391  image[2] = BLEND(b, image[2], a);
392  }
393 
394  }
395  cursor += ci->width - w - c_off;
396  image += (gr->width - w - i_off) * stride;
397  }
398 
399  free(ci);
400 }
401 #endif /* CONFIG_LIBXCB_XFIXES */
402 
404 {
405  XCBGrabContext *c = s->priv_data;
406  const uint32_t args[] = { c->x - c->region_border,
407  c->y - c->region_border };
408 
409  xcb_configure_window(c->conn,
410  c->window,
411  XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
412  args);
413 }
414 
416 {
417  XCBGrabContext *c = s->priv_data;
418  xcb_query_pointer_cookie_t pc;
419  xcb_get_geometry_cookie_t gc;
420  xcb_query_pointer_reply_t *p = NULL;
421  xcb_get_geometry_reply_t *geo = NULL;
422  int ret = 0;
423  int64_t pts;
424 
425  wait_frame(s, pkt);
426  pts = av_gettime();
427 
428  if (c->follow_mouse || c->draw_mouse) {
429  pc = xcb_query_pointer(c->conn, c->screen->root);
430  gc = xcb_get_geometry(c->conn, c->screen->root);
431  p = xcb_query_pointer_reply(c->conn, pc, NULL);
432  if (!p) {
433  av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n");
434  return AVERROR_EXTERNAL;
435  }
436  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
437  if (!geo) {
438  av_log(s, AV_LOG_ERROR, "Failed to get xcb geometry\n");
439  free(p);
440  return AVERROR_EXTERNAL;
441  }
442  }
443 
444  if (c->follow_mouse && p->same_screen)
445  xcbgrab_reposition(s, p, geo);
446 
447  if (c->show_region)
449 
450 #if CONFIG_LIBXCB_SHM
451  if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) {
452  av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n");
453  c->has_shm = 0;
454  }
455 #endif
456  if (!c->has_shm)
457  ret = xcbgrab_frame(s, pkt);
458  pkt->dts = pkt->pts = pts;
459  pkt->duration = c->frame_duration;
460 
461 #if CONFIG_LIBXCB_XFIXES
462  if (ret >= 0 && c->draw_mouse && p->same_screen)
463  xcbgrab_draw_mouse(s, pkt, p, geo);
464 #endif
465 
466  free(p);
467  free(geo);
468 
469  return ret;
470 }
471 
473 {
475 
476 #if CONFIG_LIBXCB_SHM
477  av_buffer_pool_uninit(&ctx->shm_pool);
478 #endif
479 
480  xcb_disconnect(ctx->conn);
481 
482  return 0;
483 }
484 
485 static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num)
486 {
487  xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
488  xcb_screen_t *screen = NULL;
489 
490  for (; it.rem > 0; xcb_screen_next (&it)) {
491  if (!screen_num) {
492  screen = it.data;
493  break;
494  }
495 
496  screen_num--;
497  }
498 
499  return screen;
500 }
501 
503  int *pix_fmt, int *bpp)
504 {
505  XCBGrabContext *c = s->priv_data;
506  const xcb_setup_t *setup = xcb_get_setup(c->conn);
507  const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
508  int length = xcb_setup_pixmap_formats_length(setup);
509 
510  *pix_fmt = 0;
511 
512  while (length--) {
513  if (fmt->depth == depth) {
514  switch (depth) {
515  case 32:
516  if (fmt->bits_per_pixel == 32)
517  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
519  break;
520  case 24:
521  if (fmt->bits_per_pixel == 32)
522  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
524  else if (fmt->bits_per_pixel == 24)
525  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
527  break;
528  case 16:
529  if (fmt->bits_per_pixel == 16)
530  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
532  break;
533  case 15:
534  if (fmt->bits_per_pixel == 16)
535  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
537  break;
538  case 8:
539  if (fmt->bits_per_pixel == 8)
540  *pix_fmt = AV_PIX_FMT_RGB8;
541  break;
542  }
543  }
544 
545  if (*pix_fmt) {
546  *bpp = fmt->bits_per_pixel;
547  return 0;
548  }
549 
550  fmt++;
551  }
552  avpriv_report_missing_feature(s, "Mapping this pixmap format");
553 
554  return AVERROR_PATCHWELCOME;
555 }
556 
558 {
559  XCBGrabContext *c = s->priv_data;
561  xcb_get_geometry_cookie_t gc;
562  xcb_get_geometry_reply_t *geo;
563  int64_t frame_size_bits;
564  int ret;
565 
566  if (!st)
567  return AVERROR(ENOMEM);
568 
570  if (ret < 0)
571  return ret;
572 
573  avpriv_set_pts_info(st, 64, 1, 1000000);
574 
575  gc = xcb_get_geometry(c->conn, c->screen->root);
576  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
577  if (!geo)
578  return AVERROR_EXTERNAL;
579 
580  if (!c->width || !c->height) {
581  c->width = geo->width;
582  c->height = geo->height;
583  }
584 
585  if (c->x + c->width > geo->width ||
586  c->y + c->height > geo->height) {
587  av_log(s, AV_LOG_ERROR,
588  "Capture area %dx%d at position %d.%d "
589  "outside the screen size %dx%d\n",
590  c->width, c->height,
591  c->x, c->y,
592  geo->width, geo->height);
593  free(geo);
594  return AVERROR(EINVAL);
595  }
596 
598  st->avg_frame_rate.num };
601 
602  ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp);
603  free(geo);
604  if (ret < 0)
605  return ret;
606 
607  frame_size_bits = (int64_t)c->width * c->height * c->bpp;
608  if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
609  av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
610  return AVERROR_PATCHWELCOME;
611  }
612  c->frame_size = frame_size_bits / 8;
613 
614 #if CONFIG_LIBXCB_SHM
616  c->conn, allocate_shm_buffer, NULL);
617  if (!c->shm_pool)
618  return AVERROR(ENOMEM);
619 #endif
620 
623  st->codecpar->width = c->width;
624  st->codecpar->height = c->height;
625  st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
626 
627  return ret;
628 }
629 
631 {
632  XCBGrabContext *c = s->priv_data;
633  xcb_gcontext_t gc = xcb_generate_id(c->conn);
634  uint32_t mask = XCB_GC_FOREGROUND |
635  XCB_GC_BACKGROUND |
636  XCB_GC_LINE_WIDTH |
637  XCB_GC_LINE_STYLE |
638  XCB_GC_FILL_STYLE;
639  uint32_t values[] = { c->screen->black_pixel,
640  c->screen->white_pixel,
641  c->region_border,
642  XCB_LINE_STYLE_DOUBLE_DASH,
643  XCB_FILL_STYLE_SOLID };
644  xcb_rectangle_t r = { 1, 1,
645  c->width + c->region_border * 2 - 3,
646  c->height + c->region_border * 2 - 3 };
647 
648  xcb_create_gc(c->conn, gc, c->window, mask, values);
649 
650  xcb_poly_rectangle(c->conn, c->window, gc, 1, &r);
651 }
652 
654 {
655  XCBGrabContext *c = s->priv_data;
656  uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
657  uint32_t values[] = { 1,
658  XCB_EVENT_MASK_EXPOSURE |
659  XCB_EVENT_MASK_STRUCTURE_NOTIFY };
660  av_unused xcb_rectangle_t rect = { 0, 0, c->width, c->height };
661 
662  c->window = xcb_generate_id(c->conn);
663 
664  xcb_create_window(c->conn, XCB_COPY_FROM_PARENT,
665  c->window,
666  c->screen->root,
667  c->x - c->region_border,
668  c->y - c->region_border,
669  c->width + c->region_border * 2,
670  c->height + c->region_border * 2,
671  0,
672  XCB_WINDOW_CLASS_INPUT_OUTPUT,
673  XCB_COPY_FROM_PARENT,
674  mask, values);
675 
676 #if CONFIG_LIBXCB_SHAPE
677  xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
678  XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
679  c->window,
681  1, &rect);
682 #endif
683 
684  xcb_map_window(c->conn, c->window);
685 
686  draw_rectangle(s);
687 }
688 
689 #define CROSSHAIR_CURSOR 34
690 
691 static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a,
692  xcb_point_t *corner_b)
693 {
694  xcb_rectangle_t rectangle;
695  rectangle.x = FFMIN(corner_a->x, corner_b->x);
696  rectangle.y = FFMIN(corner_a->y, corner_b->y);
697  rectangle.width = FFABS(corner_a->x - corner_b->x);
698  rectangle.height = FFABS(corner_a->y - corner_b->y);
699  return rectangle;
700 }
701 
703 {
704  XCBGrabContext *c = s->priv_data;
705  xcb_connection_t *conn = c->conn;
706  xcb_screen_t *screen = c->screen;
707 
708  int ret = 0, done = 0, was_pressed = 0;
709  xcb_cursor_t cursor;
710  xcb_font_t cursor_font;
711  xcb_point_t press_position;
712  xcb_generic_event_t *event;
713  xcb_rectangle_t rectangle = { 0 };
714  xcb_grab_pointer_reply_t *reply;
715  xcb_grab_pointer_cookie_t cookie;
716 
717  xcb_window_t root_window = screen->root;
718  xcb_gcontext_t gc = xcb_generate_id(conn);
719  uint32_t mask = XCB_GC_FUNCTION | XCB_GC_SUBWINDOW_MODE;
720  uint32_t values[] = { XCB_GX_INVERT, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS };
721  xcb_create_gc(conn, gc, root_window, mask, values);
722 
723  cursor_font = xcb_generate_id(conn);
724  xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
725  cursor = xcb_generate_id(conn);
726  xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
727  CROSSHAIR_CURSOR, CROSSHAIR_CURSOR + 1, 0, 0, 0,
728  0xFFFF, 0xFFFF, 0xFFFF);
729  cookie = xcb_grab_pointer(conn, 0, root_window,
730  XCB_EVENT_MASK_BUTTON_PRESS |
731  XCB_EVENT_MASK_BUTTON_RELEASE |
732  XCB_EVENT_MASK_BUTTON_MOTION,
733  XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
734  root_window, cursor, XCB_CURRENT_TIME);
735  reply = xcb_grab_pointer_reply(conn, cookie, NULL);
736  if (!reply || reply->status != XCB_GRAB_STATUS_SUCCESS) {
737  av_log(s, AV_LOG_ERROR,
738  "Failed to select region. Could not grab pointer.\n");
739  ret = AVERROR(EIO);
740  free(reply);
741  goto fail;
742  }
743  free(reply);
744 
745  xcb_grab_server(conn);
746 
747  while (!done && (event = xcb_wait_for_event(conn))) {
748  switch (event->response_type & ~0x80) {
749  case XCB_BUTTON_PRESS: {
750  xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
751  press_position = (xcb_point_t){ press->event_x, press->event_y };
752  rectangle.x = press_position.x;
753  rectangle.y = press_position.y;
754  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
755  was_pressed = 1;
756  break;
757  }
758  case XCB_MOTION_NOTIFY: {
759  if (was_pressed) {
760  xcb_motion_notify_event_t *motion =
761  (xcb_motion_notify_event_t *)event;
762  xcb_point_t cursor_position = { motion->event_x, motion->event_y };
763  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
764  rectangle = rectangle_from_corners(&press_position, &cursor_position);
765  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
766  }
767  break;
768  }
769  case XCB_BUTTON_RELEASE: {
770  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
771  done = 1;
772  break;
773  }
774  default:
775  break;
776  }
777  xcb_flush(conn);
778  free(event);
779  }
780  c->width = rectangle.width;
781  c->height = rectangle.height;
782  if (c->width && c->height) {
783  c->x = rectangle.x;
784  c->y = rectangle.y;
785  } else {
786  c->x = 0;
787  c->y = 0;
788  }
789  xcb_ungrab_server(conn);
790  xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
791  xcb_flush(conn);
792 
793 fail:
794  xcb_free_cursor(conn, cursor);
795  xcb_close_font(conn, cursor_font);
796  xcb_free_gc(conn, gc);
797  return ret;
798 }
799 
801 {
802  XCBGrabContext *c = s->priv_data;
803  int screen_num, ret;
804  const xcb_setup_t *setup;
805  char *display_name = av_strdup(s->url);
806 
807  if (!display_name)
808  return AVERROR(ENOMEM);
809 
810  if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
811  *display_name = 0;
812  sscanf(s->url, "+%d,%d", &c->x, &c->y);
813  }
814 
815  c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
816  av_freep(&display_name);
817 
818  if ((ret = xcb_connection_has_error(c->conn))) {
819  av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
820  s->url[0] ? s->url : "default", ret);
821  return AVERROR(EIO);
822  }
823 
824  setup = xcb_get_setup(c->conn);
825 
826  c->screen = get_screen(setup, screen_num);
827  if (!c->screen) {
828  av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n",
829  screen_num);
831  return AVERROR(EIO);
832  }
833 
834  if (c->select_region) {
835  ret = select_region(s);
836  if (ret < 0) {
838  return ret;
839  }
840  }
841 
842  ret = create_stream(s);
843 
844  if (ret < 0) {
846  return ret;
847  }
848 
849 #if CONFIG_LIBXCB_SHM
850  c->has_shm = check_shm(c->conn);
851 #endif
852 
853 #if CONFIG_LIBXCB_XFIXES
854  if (c->draw_mouse) {
855  if (!(c->draw_mouse = check_xfixes(c->conn))) {
857  "XFixes not available, cannot draw the mouse.\n");
858  }
859  if (c->bpp < 24) {
860  avpriv_report_missing_feature(s, "%d bits per pixel screen",
861  c->bpp);
862  c->draw_mouse = 0;
863  }
864  }
865 #endif
866 
867  if (c->show_region)
868  setup_window(s);
869 
870  return 0;
871 }
872 
874  .name = "x11grab",
875  .long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"),
876  .priv_data_size = sizeof(XCBGrabContext),
880  .flags = AVFMT_NOFILE,
881  .priv_class = &xcbgrab_class,
882 };
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:485
AVInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:873
#define NULL
Definition: coverity.c:32
xcb_connection_t * conn
Definition: xcbgrab.c:53
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:398
static enum AVPixelFormat pix_fmt
static av_cold int xcbgrab_read_header(AVFormatContext *s)
Definition: xcbgrab.c:800
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:557
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:403
#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:4913
const char * g
Definition: vf_curves.c:117
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:630
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
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined ...
Definition: pixfmt.h:108
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:55
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:72
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:106
Format I/O context.
Definition: avformat.h:1243
#define img
int frame_size
Definition: xcbgrab.c:65
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:4489
static const AVClass xcbgrab_class
Definition: xcbgrab.c:101
xcb_screen_t * screen
Definition: xcbgrab.c:54
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:105
static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, int *pix_fmt, int *bpp)
Definition: xcbgrab.c:502
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:155
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
#define CROSSHAIR_CURSOR
Definition: xcbgrab.c:689
AVRational time_base
Definition: xcbgrab.c:60
#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:115
char * url
input or output URL.
Definition: avformat.h:1339
const char * r
Definition: vf_curves.c:116
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:957
#define FFMAX(a, b)
Definition: common.h:103
#define fail()
Definition: checkasm.h:133
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:105
static const AVOption options[]
Definition: xcbgrab.c:84
const char * framerate
Definition: xcbgrab.c:75
uint8_t w
Definition: llviddspenc.c:39
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 FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
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:884
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a, xcb_point_t *corner_b)
Definition: xcbgrab.c:691
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
int64_t time_frame
Definition: xcbgrab.c:59
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:201
#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 select_region
Definition: xcbgrab.c:73
int show_region
Definition: xcbgrab.c:70
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:308
static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:415
Rational number (pair of numerator and denominator).
Definition: rational.h:58
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
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:150
#define OFFSET(x)
Definition: xcbgrab.c:82
static void setup_window(AVFormatContext *s)
Definition: xcbgrab.c:653
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
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
#define flags(name, subs,...)
Definition: cbs_av1.c:561
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:107
static int xcbgrab_reposition(AVFormatContext *s, xcb_query_pointer_reply_t *p, xcb_get_geometry_reply_t *geo)
Definition: xcbgrab.c:109
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:83
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:71
static av_cold int xcbgrab_read_close(AVFormatContext *s)
Definition: xcbgrab.c:472
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
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:69
void * priv_data
Format private data.
Definition: avformat.h:1271
int64_t frame_duration
Definition: xcbgrab.c:61
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:68
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:654
#define FOLLOW_CENTER
Definition: xcbgrab.c:80
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1049
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:373
#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