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/demux.h"
49 #include "libavformat/internal.h"
50 
51 typedef struct XCBGrabContext {
52  const AVClass *class;
53 
54  xcb_connection_t *conn;
55  xcb_screen_t *screen;
56  xcb_window_t window;
57 #if CONFIG_LIBXCB_SHM
58  AVBufferPool *shm_pool;
59 #endif
60  int64_t time_frame;
62  int64_t frame_duration;
63 
64  xcb_window_t window_id;
65  int x, y;
66  int width, height;
68  int bpp;
69 
74  int centered;
76 
77  const char *framerate;
78 
79  int has_shm;
81 
82 #define FOLLOW_CENTER -1
83 
84 #define OFFSET(x) offsetof(XCBGrabContext, x)
85 #define D AV_OPT_FLAG_DECODING_PARAM
86 static const AVOption options[] = {
87  { "window_id", "Window to capture.", OFFSET(window_id), AV_OPT_TYPE_INT, { .i64 = XCB_NONE }, 0, UINT32_MAX, D },
88  { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
89  { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
90  { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
91  { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
92  { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, D },
93  { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D },
94  { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D },
95  { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
96  OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, FOLLOW_CENTER, INT_MAX, D, .unit = "follow_mouse" },
97  { "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, .unit = "follow_mouse" },
98  { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
99  { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D },
100  { "select_region", "Select the grabbing region graphically using the pointer.", OFFSET(select_region), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
101  { NULL },
102 };
103 
104 static const AVClass xcbgrab_class = {
105  .class_name = "xcbgrab indev",
106  .item_name = av_default_item_name,
107  .option = options,
108  .version = LIBAVUTIL_VERSION_INT,
110 };
111 
113  xcb_query_pointer_reply_t *p,
114  xcb_get_geometry_reply_t *geo)
115 {
116  XCBGrabContext *c = s->priv_data;
117  int x = c->x, y = c->y;
118  int w = c->width, h = c->height, f = c->follow_mouse;
119  int p_x, p_y;
120 
121  if (!p || !geo)
122  return AVERROR(EIO);
123 
124  p_x = p->win_x;
125  p_y = p->win_y;
126 
127  if (f == FOLLOW_CENTER) {
128  x = p_x - w / 2;
129  y = p_y - h / 2;
130  } else {
131  int left = x + f;
132  int right = x + w - f;
133  int top = y + f;
134  int bottom = y + h - f;
135  if (p_x > right) {
136  x += p_x - right;
137  } else if (p_x < left) {
138  x -= left - p_x;
139  }
140  if (p_y > bottom) {
141  y += p_y - bottom;
142  } else if (p_y < top) {
143  y -= top - p_y;
144  }
145  }
146 
147  c->x = FFMIN(FFMAX(0, x), geo->width - w);
148  c->y = FFMIN(FFMAX(0, y), geo->height - h);
149 
150  return 0;
151 }
152 
153 static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
154 {
155  free(opaque);
156 }
157 
159 {
160  XCBGrabContext *c = s->priv_data;
161  xcb_get_image_cookie_t iq;
162  xcb_get_image_reply_t *img;
163  xcb_drawable_t drawable = c->window_id;
164  xcb_generic_error_t *e = NULL;
165  uint8_t *data;
166  int length;
167 
168  iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
169  c->x, c->y, c->width, c->height, ~0);
170 
171  img = xcb_get_image_reply(c->conn, iq, &e);
172 
173  if (e) {
175  "Cannot get the image data "
176  "event_error: response_type:%u error_code:%u "
177  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
178  e->response_type, e->error_code,
179  e->sequence, e->resource_id, e->minor_code, e->major_code);
180  free(e);
181  return AVERROR(EACCES);
182  }
183 
184  if (!img)
185  return AVERROR(EAGAIN);
186 
187  data = xcb_get_image_data(img);
188  length = xcb_get_image_data_length(img);
189 
191  if (!pkt->buf) {
192  free(img);
193  return AVERROR(ENOMEM);
194  }
195 
196  pkt->data = data;
197  pkt->size = length;
198 
199  return 0;
200 }
201 
203 {
204  XCBGrabContext *c = s->priv_data;
205  int64_t curtime, delay;
206 
207  c->time_frame += c->frame_duration;
208 
209  for (;;) {
210  curtime = av_gettime_relative();
211  delay = c->time_frame - curtime;
212  if (delay <= 0)
213  break;
214  av_usleep(delay);
215  }
216 
217  return curtime;
218 }
219 
220 #if CONFIG_LIBXCB_SHM
221 static int check_shm(xcb_connection_t *conn)
222 {
223  xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
224  xcb_shm_query_version_reply_t *reply;
225 
226  reply = xcb_shm_query_version_reply(conn, cookie, NULL);
227  if (reply) {
228  free(reply);
229  return 1;
230  }
231 
232  return 0;
233 }
234 
235 static void free_shm_buffer(void *opaque, uint8_t *data)
236 {
237  shmdt(data);
238 }
239 
240 static AVBufferRef *allocate_shm_buffer(void *opaque, size_t size)
241 {
242  xcb_connection_t *conn = opaque;
243  xcb_shm_seg_t segment;
244  AVBufferRef *ref;
245  uint8_t *data;
246  int id;
247 
248  id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
249  if (id == -1)
250  return NULL;
251 
252  segment = xcb_generate_id(conn);
253  xcb_shm_attach(conn, segment, id, 0);
254  data = shmat(id, NULL, 0);
255  shmctl(id, IPC_RMID, 0);
256  if ((intptr_t)data == -1 || !data)
257  return NULL;
258 
259  ref = av_buffer_create(data, size, free_shm_buffer, (void *)(ptrdiff_t)segment, 0);
260  if (!ref)
261  shmdt(data);
262 
263  return ref;
264 }
265 
266 static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt)
267 {
268  XCBGrabContext *c = s->priv_data;
269  xcb_shm_get_image_cookie_t iq;
270  xcb_shm_get_image_reply_t *img;
271  xcb_drawable_t drawable = c->window_id;
272  xcb_generic_error_t *e = NULL;
273  AVBufferRef *buf;
274  xcb_shm_seg_t segment;
275 
276  buf = av_buffer_pool_get(c->shm_pool);
277  if (!buf) {
278  av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n");
279  return AVERROR(ENOMEM);
280  }
281  segment = (xcb_shm_seg_t)(uintptr_t)av_buffer_pool_buffer_get_opaque(buf);
282 
283  iq = xcb_shm_get_image(c->conn, drawable,
284  c->x, c->y, c->width, c->height, ~0,
285  XCB_IMAGE_FORMAT_Z_PIXMAP, segment, 0);
286  img = xcb_shm_get_image_reply(c->conn, iq, &e);
287 
288  xcb_flush(c->conn);
289 
290  if (e) {
292  "Cannot get the image data "
293  "event_error: response_type:%u error_code:%u "
294  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
295  e->response_type, e->error_code,
296  e->sequence, e->resource_id, e->minor_code, e->major_code);
297 
298  free(e);
299  av_buffer_unref(&buf);
300  return AVERROR(EACCES);
301  }
302 
303  free(img);
304 
305  pkt->buf = buf;
306  pkt->data = buf->data;
307  pkt->size = c->frame_size;
308 
309  return 0;
310 }
311 #endif /* CONFIG_LIBXCB_SHM */
312 
313 #if CONFIG_LIBXCB_XFIXES
314 static int check_xfixes(xcb_connection_t *conn)
315 {
316  xcb_xfixes_query_version_cookie_t cookie;
317  xcb_xfixes_query_version_reply_t *reply;
318 
319  cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
320  XCB_XFIXES_MINOR_VERSION);
321  reply = xcb_xfixes_query_version_reply(conn, cookie, NULL);
322 
323  if (reply) {
324  free(reply);
325  return 1;
326  }
327  return 0;
328 }
329 
330 #define BLEND(target, source, alpha) \
331  (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
332 
333 static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt,
334  xcb_query_pointer_reply_t *p,
335  xcb_get_geometry_reply_t *geo,
336  int win_x, int win_y)
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, win_x + gr->x);
359  y = FFMAX(cy, win_y + gr->y);
360 
361  w = FFMIN(cx + ci->width, win_x + gr->x + gr->width) - x;
362  h = FFMIN(cy + ci->height, win_y + gr->y + gr->height) - y;
363 
364  c_off = x - cx;
365  i_off = x - gr->x - win_x;
366 
367  cursor += (y - cy) * ci->width;
368  image += (y - gr->y - win_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 
403 static void xcbgrab_update_region(AVFormatContext *s, int win_x, int win_y)
404 {
405  XCBGrabContext *c = s->priv_data;
406  const uint32_t args[] = { win_x + c->x - c->region_border,
407  win_y + 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_translate_coordinates_cookie_t tc;
421  xcb_query_pointer_reply_t *p = NULL;
422  xcb_get_geometry_reply_t *geo = NULL;
423  xcb_translate_coordinates_reply_t *translate = NULL;
424  int ret = 0;
425  int64_t pts;
426  int win_x = 0, win_y = 0;
427 
428  wait_frame(s, pkt);
429  pts = av_gettime();
430 
431  if (c->follow_mouse || c->draw_mouse) {
432  pc = xcb_query_pointer(c->conn, c->window_id);
433  gc = xcb_get_geometry(c->conn, c->window_id);
434  p = xcb_query_pointer_reply(c->conn, pc, NULL);
435  if (!p) {
436  av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n");
437  return AVERROR_EXTERNAL;
438  }
439  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
440  if (!geo) {
441  av_log(s, AV_LOG_ERROR, "Failed to get xcb geometry\n");
442  free(p);
443  return AVERROR_EXTERNAL;
444  }
445  }
446  if (c->window_id != c->screen->root) {
447  tc = xcb_translate_coordinates(c->conn, c->window_id, c->screen->root, 0, 0);
448  translate = xcb_translate_coordinates_reply(c->conn, tc, NULL);
449  if (!translate) {
450  free(p);
451  free(geo);
452  av_log(s, AV_LOG_ERROR, "Failed to translate xcb geometry\n");
453  return AVERROR_EXTERNAL;
454  }
455  win_x = translate->dst_x;
456  win_y = translate->dst_y;
457  free(translate);
458  }
459 
460  if (c->follow_mouse && p->same_screen)
461  xcbgrab_reposition(s, p, geo);
462 
463  if (c->show_region)
464  xcbgrab_update_region(s, win_x, win_y);
465 
466 #if CONFIG_LIBXCB_SHM
467  if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) {
468  av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n");
469  c->has_shm = 0;
470  }
471 #endif
472  if (!c->has_shm)
473  ret = xcbgrab_frame(s, pkt);
474  pkt->dts = pkt->pts = pts;
475  pkt->duration = c->frame_duration;
476 
477 #if CONFIG_LIBXCB_XFIXES
478  if (ret >= 0 && c->draw_mouse && p->same_screen)
479  xcbgrab_draw_mouse(s, pkt, p, geo, win_x, win_y);
480 #endif
481 
482  free(p);
483  free(geo);
484 
485  return ret;
486 }
487 
489 {
490  XCBGrabContext *ctx = s->priv_data;
491 
492 #if CONFIG_LIBXCB_SHM
493  av_buffer_pool_uninit(&ctx->shm_pool);
494 #endif
495 
496  xcb_disconnect(ctx->conn);
497 
498  return 0;
499 }
500 
501 static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num)
502 {
503  xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
504  xcb_screen_t *screen = NULL;
505 
506  for (; it.rem > 0; xcb_screen_next (&it)) {
507  if (!screen_num) {
508  screen = it.data;
509  break;
510  }
511 
512  screen_num--;
513  }
514 
515  return screen;
516 }
517 
519  int *pix_fmt, int *bpp)
520 {
521  XCBGrabContext *c = s->priv_data;
522  const xcb_setup_t *setup = xcb_get_setup(c->conn);
523  const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
524  int length = xcb_setup_pixmap_formats_length(setup);
525 
526  *pix_fmt = 0;
527 
528  while (length--) {
529  if (fmt->depth == depth) {
530  switch (depth) {
531  case 32:
532  if (fmt->bits_per_pixel == 32)
533  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
535  break;
536  case 24:
537  if (fmt->bits_per_pixel == 32)
538  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
540  else if (fmt->bits_per_pixel == 24)
541  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
543  break;
544  case 16:
545  if (fmt->bits_per_pixel == 16)
546  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
548  break;
549  case 15:
550  if (fmt->bits_per_pixel == 16)
551  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
553  break;
554  case 8:
555  if (fmt->bits_per_pixel == 8)
557  break;
558  }
559  }
560 
561  if (*pix_fmt) {
562  *bpp = fmt->bits_per_pixel;
563  return 0;
564  }
565 
566  fmt++;
567  }
568  avpriv_report_missing_feature(s, "Mapping this pixmap format");
569 
570  return AVERROR_PATCHWELCOME;
571 }
572 
574 {
575  XCBGrabContext *c = s->priv_data;
577  xcb_get_geometry_cookie_t gc;
578  xcb_get_geometry_reply_t *geo;
579  int64_t frame_size_bits;
580  int ret;
581 
582  if (!st)
583  return AVERROR(ENOMEM);
584 
585  ret = av_parse_video_rate(&st->avg_frame_rate, c->framerate);
586  if (ret < 0)
587  return ret;
588 
589  avpriv_set_pts_info(st, 64, 1, 1000000);
590 
591  gc = xcb_get_geometry(c->conn, c->window_id);
592  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
593  if (!geo) {
594  av_log(s, AV_LOG_ERROR, "Can't find window '0x%x', aborting.\n", c->window_id);
595  return AVERROR_EXTERNAL;
596  }
597 
598  if (!c->width || !c->height) {
599  c->width = geo->width;
600  c->height = geo->height;
601  }
602 
603  if (c->x + c->width > geo->width ||
604  c->y + c->height > geo->height) {
606  "Capture area %dx%d at position %d.%d "
607  "outside the screen size %dx%d\n",
608  c->width, c->height,
609  c->x, c->y,
610  geo->width, geo->height);
611  free(geo);
612  return AVERROR(EINVAL);
613  }
614 
615  c->time_base = (AVRational){ st->avg_frame_rate.den,
616  st->avg_frame_rate.num };
617  c->frame_duration = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q);
618  c->time_frame = av_gettime_relative();
619 
620  ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp);
621  free(geo);
622  if (ret < 0)
623  return ret;
624 
625  frame_size_bits = (int64_t)c->width * c->height * c->bpp;
626  if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
627  av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
628  return AVERROR_PATCHWELCOME;
629  }
630  c->frame_size = frame_size_bits / 8;
631 
632 #if CONFIG_LIBXCB_SHM
633  c->shm_pool = av_buffer_pool_init2(c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE,
634  c->conn, allocate_shm_buffer, NULL);
635  if (!c->shm_pool)
636  return AVERROR(ENOMEM);
637 #endif
638 
641  st->codecpar->width = c->width;
642  st->codecpar->height = c->height;
643  st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
644 
645  return ret;
646 }
647 
649 {
650  XCBGrabContext *c = s->priv_data;
651  xcb_gcontext_t gc = xcb_generate_id(c->conn);
652  uint32_t mask = XCB_GC_FOREGROUND |
653  XCB_GC_BACKGROUND |
654  XCB_GC_LINE_WIDTH |
655  XCB_GC_LINE_STYLE |
656  XCB_GC_FILL_STYLE;
657  uint32_t values[] = { c->screen->black_pixel,
658  c->screen->white_pixel,
659  c->region_border,
660  XCB_LINE_STYLE_DOUBLE_DASH,
661  XCB_FILL_STYLE_SOLID };
662  xcb_rectangle_t r = { 1, 1,
663  c->width + c->region_border * 2 - 3,
664  c->height + c->region_border * 2 - 3 };
665 
666  xcb_create_gc(c->conn, gc, c->window, mask, values);
667 
668  xcb_poly_rectangle(c->conn, c->window, gc, 1, &r);
669 }
670 
672 {
673  XCBGrabContext *c = s->priv_data;
674  uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
675  uint32_t values[] = { 1,
676  XCB_EVENT_MASK_EXPOSURE |
677  XCB_EVENT_MASK_STRUCTURE_NOTIFY };
678  av_unused xcb_rectangle_t rect = { 0, 0, c->width, c->height };
679 
680  c->window = xcb_generate_id(c->conn);
681 
682  xcb_create_window(c->conn, XCB_COPY_FROM_PARENT,
683  c->window,
684  c->screen->root,
685  c->x - c->region_border,
686  c->y - c->region_border,
687  c->width + c->region_border * 2,
688  c->height + c->region_border * 2,
689  0,
690  XCB_WINDOW_CLASS_INPUT_OUTPUT,
691  XCB_COPY_FROM_PARENT,
692  mask, values);
693 
694 #if CONFIG_LIBXCB_SHAPE
695  xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
696  XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
697  c->window,
698  c->region_border, c->region_border,
699  1, &rect);
700 #endif
701 
702  xcb_map_window(c->conn, c->window);
703 
704  draw_rectangle(s);
705 }
706 
707 #define CROSSHAIR_CURSOR 34
708 
709 static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a,
710  xcb_point_t *corner_b)
711 {
712  xcb_rectangle_t rectangle;
713  rectangle.x = FFMIN(corner_a->x, corner_b->x);
714  rectangle.y = FFMIN(corner_a->y, corner_b->y);
715  rectangle.width = FFABS(corner_a->x - corner_b->x);
716  rectangle.height = FFABS(corner_a->y - corner_b->y);
717  return rectangle;
718 }
719 
721 {
722  XCBGrabContext *c = s->priv_data;
723  xcb_connection_t *conn = c->conn;
724  xcb_screen_t *screen = c->screen;
725 
726  int ret = 0, done = 0, was_pressed = 0;
727  xcb_cursor_t cursor;
728  xcb_font_t cursor_font;
729  xcb_point_t press_position;
730  xcb_generic_event_t *event;
731  xcb_rectangle_t rectangle = { 0 };
732  xcb_grab_pointer_reply_t *reply;
733  xcb_grab_pointer_cookie_t cookie;
734 
735  xcb_window_t root_window = screen->root;
736  xcb_gcontext_t gc = xcb_generate_id(conn);
737  uint32_t mask = XCB_GC_FUNCTION | XCB_GC_SUBWINDOW_MODE;
738  uint32_t values[] = { XCB_GX_INVERT, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS };
739  xcb_create_gc(conn, gc, root_window, mask, values);
740 
741  cursor_font = xcb_generate_id(conn);
742  xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
743  cursor = xcb_generate_id(conn);
744  xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
745  CROSSHAIR_CURSOR, CROSSHAIR_CURSOR + 1, 0, 0, 0,
746  0xFFFF, 0xFFFF, 0xFFFF);
747  cookie = xcb_grab_pointer(conn, 0, root_window,
748  XCB_EVENT_MASK_BUTTON_PRESS |
749  XCB_EVENT_MASK_BUTTON_RELEASE |
750  XCB_EVENT_MASK_BUTTON_MOTION,
751  XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
752  root_window, cursor, XCB_CURRENT_TIME);
753  reply = xcb_grab_pointer_reply(conn, cookie, NULL);
754  if (!reply || reply->status != XCB_GRAB_STATUS_SUCCESS) {
756  "Failed to select region. Could not grab pointer.\n");
757  ret = AVERROR(EIO);
758  free(reply);
759  goto fail;
760  }
761  free(reply);
762 
763  xcb_grab_server(conn);
764 
765  while (!done && (event = xcb_wait_for_event(conn))) {
766  switch (event->response_type & ~0x80) {
767  case XCB_BUTTON_PRESS: {
768  xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
769  press_position = (xcb_point_t){ press->event_x, press->event_y };
770  rectangle.x = press_position.x;
771  rectangle.y = press_position.y;
772  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
773  was_pressed = 1;
774  break;
775  }
776  case XCB_MOTION_NOTIFY: {
777  if (was_pressed) {
778  xcb_motion_notify_event_t *motion =
779  (xcb_motion_notify_event_t *)event;
780  xcb_point_t cursor_position = { motion->event_x, motion->event_y };
781  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
782  rectangle = rectangle_from_corners(&press_position, &cursor_position);
783  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
784  }
785  break;
786  }
787  case XCB_BUTTON_RELEASE: {
788  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
789  done = 1;
790  break;
791  }
792  default:
793  break;
794  }
795  xcb_flush(conn);
796  free(event);
797  }
798  c->width = rectangle.width;
799  c->height = rectangle.height;
800  if (c->width && c->height) {
801  c->x = rectangle.x;
802  c->y = rectangle.y;
803  } else {
804  c->x = 0;
805  c->y = 0;
806  }
807  xcb_ungrab_server(conn);
808  xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
809  xcb_flush(conn);
810 
811 fail:
812  xcb_free_cursor(conn, cursor);
813  xcb_close_font(conn, cursor_font);
814  xcb_free_gc(conn, gc);
815  return ret;
816 }
817 
819 {
820  XCBGrabContext *c = s->priv_data;
821  int screen_num, ret;
822  const xcb_setup_t *setup;
823  char *display_name = av_strdup(s->url);
824 
825  if (!display_name)
826  return AVERROR(ENOMEM);
827 
828  if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
829  *display_name = 0;
830  sscanf(s->url, "+%d,%d", &c->x, &c->y);
831  }
832 
833  c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
834  av_freep(&display_name);
835 
836  if ((ret = xcb_connection_has_error(c->conn))) {
837  av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
838  s->url[0] ? s->url : "default", ret);
839  return AVERROR(EIO);
840  }
841 
842  setup = xcb_get_setup(c->conn);
843 
844  c->screen = get_screen(setup, screen_num);
845  if (!c->screen) {
846  av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n",
847  screen_num);
849  return AVERROR(EIO);
850  }
851 
852  if (c->window_id == XCB_NONE)
853  c->window_id = c->screen->root;
854  else {
855  if (c->select_region) {
856  av_log(s, AV_LOG_WARNING, "select_region ignored with window_id.\n");
857  c->select_region = 0;
858  }
859  if (c->follow_mouse) {
860  av_log(s, AV_LOG_WARNING, "follow_mouse ignored with window_id.\n");
861  c->follow_mouse = 0;
862  }
863  }
864 
865  if (c->select_region) {
866  ret = select_region(s);
867  if (ret < 0) {
869  return ret;
870  }
871  }
872 
873  ret = create_stream(s);
874 
875  if (ret < 0) {
877  return ret;
878  }
879 
880 #if CONFIG_LIBXCB_SHM
881  c->has_shm = check_shm(c->conn);
882 #endif
883 
884 #if CONFIG_LIBXCB_XFIXES
885  if (c->draw_mouse) {
886  if (!(c->draw_mouse = check_xfixes(c->conn))) {
888  "XFixes not available, cannot draw the mouse.\n");
889  }
890  if (c->bpp < 24) {
891  avpriv_report_missing_feature(s, "%d bits per pixel screen",
892  c->bpp);
893  c->draw_mouse = 0;
894  }
895  }
896 #endif
897 
898  if (c->show_region)
899  setup_window(s);
900 
901  return 0;
902 }
903 
905  .p.name = "x11grab",
906  .p.long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"),
907  .p.flags = AVFMT_NOFILE,
908  .p.priv_class = &xcbgrab_class,
909  .priv_data_size = sizeof(XCBGrabContext),
913 };
XCBGrabContext::has_shm
int has_shm
Definition: xcbgrab.c:79
av_gettime_relative
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
XCBGrabContext::y
int y
Definition: xcbgrab.c:65
r
const char * r
Definition: vf_curves.c:126
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
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
FOLLOW_CENTER
#define FOLLOW_CENTER
Definition: xcbgrab.c:82
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
XCBGrabContext::time_base
AVRational time_base
Definition: xcbgrab.c:61
rect
Definition: f_ebur128.c:78
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
XCBGrabContext::select_region
int select_region
Definition: xcbgrab.c:75
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:65
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:522
AVOption
AVOption.
Definition: opt.h:346
b
#define b
Definition: input.c:41
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:832
data
const char data[16]
Definition: mxf.c:148
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:540
mathematics.h
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AV_PIX_FMT_RGB555BE
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:114
create_stream
static int create_stream(AVFormatContext *s)
Definition: xcbgrab.c:573
xcbgrab_class
static const AVClass xcbgrab_class
Definition: xcbgrab.c:104
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:853
fail
#define fail()
Definition: checkasm.h:179
xcbgrab_frame
static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:158
draw_rectangle
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:648
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
pts
static int64_t pts
Definition: transcode_aac.c:643
AVRational::num
int num
Numerator.
Definition: rational.h:59
CROSSHAIR_CURSOR
#define CROSSHAIR_CURSOR
Definition: xcbgrab.c:707
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:41
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:384
options
static const AVOption options[]
Definition: xcbgrab.c:86
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:518
s
#define s(width, name)
Definition: cbs_vp9.c:198
XCBGrabContext::frame_duration
int64_t frame_duration
Definition: xcbgrab.c:62
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
g
const char * g
Definition: vf_curves.c:127
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:134
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
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
XCBGrabContext::region_border
int region_border
Definition: xcbgrab.c:73
ff_xcbgrab_demuxer
const FFInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:904
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:505
framerate
float framerate
Definition: av1_levels.c:29
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:113
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:550
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
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:139
XCBGrabContext::bpp
int bpp
Definition: xcbgrab.c:68
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:245
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
parseutils.h
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:322
XCBGrabContext::window
xcb_window_t window
Definition: xcbgrab.c:56
AV_PIX_FMT_RGB8
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb)
Definition: pixfmt.h:93
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
time.h
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:41
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
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
XCBGrabContext::show_region
int show_region
Definition: xcbgrab.c:72
XCBGrabContext::follow_mouse
int follow_mouse
Definition: xcbgrab.c:71
f
f
Definition: af_crystalizer.c:121
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
AVPacket::size
int size
Definition: packet.h:523
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:106
size
int size
Definition: twinvq_data.h:10344
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:468
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:35
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:521
XCBGrabContext::window_id
xcb_window_t window_id
Definition: xcbgrab.c:64
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
img
#define img
Definition: vf_colormatrix.c:114
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
av_buffer_pool_buffer_get_opaque
void * av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:411
rectangle_from_corners
static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a, xcb_point_t *corner_b)
Definition: xcbgrab.c:709
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:181
AV_PIX_FMT_RGB555LE
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition: pixfmt.h:115
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:515
xcbgrab_image_reply_free
static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
Definition: xcbgrab.c:153
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:135
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
setup_window
static void setup_window(AVFormatContext *s)
Definition: xcbgrab.c:671
demux.h
xcbgrab_update_region
static void xcbgrab_update_region(AVFormatContext *s, int win_x, int win_y)
Definition: xcbgrab.c:403
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:85
XCBGrabContext::framerate
const char * framerate
Definition: xcbgrab.c:77
stride
#define stride
Definition: h264pred_template.c:537
XCBGrabContext::screen
xcb_screen_t * screen
Definition: xcbgrab.c:55
xcbgrab_read_close
static av_cold int xcbgrab_read_close(AVFormatContext *s)
Definition: xcbgrab.c:488
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:743
xcbgrab_read_packet
static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:415
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:71
wait_frame
static int64_t wait_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:202
avformat.h
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:364
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
select_region
static int select_region(AVFormatContext *s)
Definition: xcbgrab.c:720
XCBGrabContext::conn
xcb_connection_t * conn
Definition: xcbgrab.c:54
XCBGrabContext::frame_size
int frame_size
Definition: xcbgrab.c:67
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:112
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
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:112
segment
Definition: hls.c:76
AV_PIX_FMT_RGB565BE
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:112
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
tc
#define tc
Definition: regdef.h:69
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
XCBGrabContext::x
int x
Definition: xcbgrab.c:65
get_screen
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:501
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
xcbgrab_read_header
static av_cold int xcbgrab_read_header(AVFormatContext *s)
Definition: xcbgrab.c:818
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:92
XCBGrabContext::height
int height
Definition: xcbgrab.c:66
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:499
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:251
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFInputFormat
Definition: demux.h:31
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:262
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:97
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
OFFSET
#define OFFSET(x)
Definition: xcbgrab.c:84
h
h
Definition: vp9dsp_template.c:2038
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
XCBGrabContext::draw_mouse
int draw_mouse
Definition: xcbgrab.c:70
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:244
XCBGrabContext::centered
int centered
Definition: xcbgrab.c:74
XCBGrabContext
Definition: xcbgrab.c:51
XCBGrabContext::time_frame
int64_t time_frame
Definition: xcbgrab.c:60
XCBGrabContext::width
int width
Definition: xcbgrab.c:66