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  xcb_window_t window_id;
64  int x, y;
65  int width, height;
67  int bpp;
68 
73  int centered;
75 
76  const char *framerate;
77 
78  int has_shm;
80 
81 #define FOLLOW_CENTER -1
82 
83 #define OFFSET(x) offsetof(XCBGrabContext, x)
84 #define D AV_OPT_FLAG_DECODING_PARAM
85 static const AVOption options[] = {
86  { "window_id", "Window to capture.", OFFSET(window_id), AV_OPT_TYPE_INT, { .i64 = XCB_NONE }, 0, UINT32_MAX, D },
87  { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
88  { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
89  { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
90  { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D },
91  { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, D },
92  { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D },
93  { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D },
94  { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
95  OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, FOLLOW_CENTER, INT_MAX, D, "follow_mouse" },
96  { "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" },
97  { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
98  { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D },
99  { "select_region", "Select the grabbing region graphically using the pointer.", OFFSET(select_region), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
100  { NULL },
101 };
102 
103 static const AVClass xcbgrab_class = {
104  .class_name = "xcbgrab indev",
105  .item_name = av_default_item_name,
106  .option = options,
107  .version = LIBAVUTIL_VERSION_INT,
109 };
110 
112  xcb_query_pointer_reply_t *p,
113  xcb_get_geometry_reply_t *geo)
114 {
115  XCBGrabContext *c = s->priv_data;
116  int x = c->x, y = c->y;
117  int w = c->width, h = c->height, f = c->follow_mouse;
118  int p_x, p_y;
119 
120  if (!p || !geo)
121  return AVERROR(EIO);
122 
123  p_x = p->win_x;
124  p_y = p->win_y;
125 
126  if (f == FOLLOW_CENTER) {
127  x = p_x - w / 2;
128  y = p_y - h / 2;
129  } else {
130  int left = x + f;
131  int right = x + w - f;
132  int top = y + f;
133  int bottom = y + h - f;
134  if (p_x > right) {
135  x += p_x - right;
136  } else if (p_x < left) {
137  x -= left - p_x;
138  }
139  if (p_y > bottom) {
140  y += p_y - bottom;
141  } else if (p_y < top) {
142  y -= top - p_y;
143  }
144  }
145 
146  c->x = FFMIN(FFMAX(0, x), geo->width - w);
147  c->y = FFMIN(FFMAX(0, y), geo->height - h);
148 
149  return 0;
150 }
151 
152 static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
153 {
154  free(opaque);
155 }
156 
158 {
159  XCBGrabContext *c = s->priv_data;
160  xcb_get_image_cookie_t iq;
161  xcb_get_image_reply_t *img;
162  xcb_drawable_t drawable = c->window_id;
163  xcb_generic_error_t *e = NULL;
164  uint8_t *data;
165  int length;
166 
167  iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
168  c->x, c->y, c->width, c->height, ~0);
169 
170  img = xcb_get_image_reply(c->conn, iq, &e);
171 
172  if (e) {
174  "Cannot get the image data "
175  "event_error: response_type:%u error_code:%u "
176  "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
177  e->response_type, e->error_code,
178  e->sequence, e->resource_id, e->minor_code, e->major_code);
179  free(e);
180  return AVERROR(EACCES);
181  }
182 
183  if (!img)
184  return AVERROR(EAGAIN);
185 
186  data = xcb_get_image_data(img);
187  length = xcb_get_image_data_length(img);
188 
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, size_t 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->window_id;
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)(uintptr_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) {
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  pkt->buf = buf;
305  pkt->data = buf->data;
306  pkt->size = c->frame_size;
307 
308  return 0;
309 }
310 #endif /* CONFIG_LIBXCB_SHM */
311 
312 #if CONFIG_LIBXCB_XFIXES
313 static int check_xfixes(xcb_connection_t *conn)
314 {
315  xcb_xfixes_query_version_cookie_t cookie;
316  xcb_xfixes_query_version_reply_t *reply;
317 
318  cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
319  XCB_XFIXES_MINOR_VERSION);
320  reply = xcb_xfixes_query_version_reply(conn, cookie, NULL);
321 
322  if (reply) {
323  free(reply);
324  return 1;
325  }
326  return 0;
327 }
328 
329 #define BLEND(target, source, alpha) \
330  (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
331 
332 static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt,
333  xcb_query_pointer_reply_t *p,
334  xcb_get_geometry_reply_t *geo,
335  int win_x, int win_y)
336 {
337  XCBGrabContext *gr = s->priv_data;
338  uint32_t *cursor;
339  uint8_t *image = pkt->data;
340  int stride = gr->bpp / 8;
341  xcb_xfixes_get_cursor_image_cookie_t cc;
342  xcb_xfixes_get_cursor_image_reply_t *ci;
343  int cx, cy, x, y, w, h, c_off, i_off;
344 
345  cc = xcb_xfixes_get_cursor_image(gr->conn);
346  ci = xcb_xfixes_get_cursor_image_reply(gr->conn, cc, NULL);
347  if (!ci)
348  return;
349 
350  cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
351  if (!cursor)
352  return;
353 
354  cx = ci->x - ci->xhot;
355  cy = ci->y - ci->yhot;
356 
357  x = FFMAX(cx, win_x + gr->x);
358  y = FFMAX(cy, win_y + gr->y);
359 
360  w = FFMIN(cx + ci->width, win_x + gr->x + gr->width) - x;
361  h = FFMIN(cy + ci->height, win_y + gr->y + gr->height) - y;
362 
363  c_off = x - cx;
364  i_off = x - gr->x - win_x;
365 
366  cursor += (y - cy) * ci->width;
367  image += (y - gr->y - win_y) * gr->width * stride;
368 
369  for (y = 0; y < h; y++) {
370  cursor += c_off;
371  image += i_off * stride;
372  for (x = 0; x < w; x++, cursor++, image += stride) {
373  int r, g, b, a;
374 
375  r = *cursor & 0xff;
376  g = (*cursor >> 8) & 0xff;
377  b = (*cursor >> 16) & 0xff;
378  a = (*cursor >> 24) & 0xff;
379 
380  if (!a)
381  continue;
382 
383  if (a == 255) {
384  image[0] = r;
385  image[1] = g;
386  image[2] = b;
387  } else {
388  image[0] = BLEND(r, image[0], a);
389  image[1] = BLEND(g, image[1], a);
390  image[2] = BLEND(b, image[2], a);
391  }
392 
393  }
394  cursor += ci->width - w - c_off;
395  image += (gr->width - w - i_off) * stride;
396  }
397 
398  free(ci);
399 }
400 #endif /* CONFIG_LIBXCB_XFIXES */
401 
402 static void xcbgrab_update_region(AVFormatContext *s, int win_x, int win_y)
403 {
404  XCBGrabContext *c = s->priv_data;
405  const uint32_t args[] = { win_x + c->x - c->region_border,
406  win_y + c->y - c->region_border };
407 
408  xcb_configure_window(c->conn,
409  c->window,
410  XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
411  args);
412 }
413 
415 {
416  XCBGrabContext *c = s->priv_data;
417  xcb_query_pointer_cookie_t pc;
418  xcb_get_geometry_cookie_t gc;
419  xcb_translate_coordinates_cookie_t tc;
420  xcb_query_pointer_reply_t *p = NULL;
421  xcb_get_geometry_reply_t *geo = NULL;
422  xcb_translate_coordinates_reply_t *translate = NULL;
423  int ret = 0;
424  int64_t pts;
425  int win_x = 0, win_y = 0;
426 
427  wait_frame(s, pkt);
428  pts = av_gettime();
429 
430  if (c->follow_mouse || c->draw_mouse) {
431  pc = xcb_query_pointer(c->conn, c->window_id);
432  gc = xcb_get_geometry(c->conn, c->window_id);
433  p = xcb_query_pointer_reply(c->conn, pc, NULL);
434  if (!p) {
435  av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n");
436  return AVERROR_EXTERNAL;
437  }
438  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
439  if (!geo) {
440  av_log(s, AV_LOG_ERROR, "Failed to get xcb geometry\n");
441  free(p);
442  return AVERROR_EXTERNAL;
443  }
444  }
445  if (c->window_id != c->screen->root) {
446  tc = xcb_translate_coordinates(c->conn, c->window_id, c->screen->root, 0, 0);
447  translate = xcb_translate_coordinates_reply(c->conn, tc, NULL);
448  if (!translate) {
449  free(p);
450  free(geo);
451  av_log(s, AV_LOG_ERROR, "Failed to translate xcb geometry\n");
452  return AVERROR_EXTERNAL;
453  }
454  win_x = translate->dst_x;
455  win_y = translate->dst_y;
456  free(translate);
457  }
458 
459  if (c->follow_mouse && p->same_screen)
460  xcbgrab_reposition(s, p, geo);
461 
462  if (c->show_region)
463  xcbgrab_update_region(s, win_x, win_y);
464 
465 #if CONFIG_LIBXCB_SHM
466  if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) {
467  av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n");
468  c->has_shm = 0;
469  }
470 #endif
471  if (!c->has_shm)
472  ret = xcbgrab_frame(s, pkt);
473  pkt->dts = pkt->pts = pts;
474  pkt->duration = c->frame_duration;
475 
476 #if CONFIG_LIBXCB_XFIXES
477  if (ret >= 0 && c->draw_mouse && p->same_screen)
478  xcbgrab_draw_mouse(s, pkt, p, geo, win_x, win_y);
479 #endif
480 
481  free(p);
482  free(geo);
483 
484  return ret;
485 }
486 
488 {
489  XCBGrabContext *ctx = s->priv_data;
490 
491 #if CONFIG_LIBXCB_SHM
492  av_buffer_pool_uninit(&ctx->shm_pool);
493 #endif
494 
495  xcb_disconnect(ctx->conn);
496 
497  return 0;
498 }
499 
500 static xcb_screen_t *get_screen(const xcb_setup_t *setup, int screen_num)
501 {
502  xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
503  xcb_screen_t *screen = NULL;
504 
505  for (; it.rem > 0; xcb_screen_next (&it)) {
506  if (!screen_num) {
507  screen = it.data;
508  break;
509  }
510 
511  screen_num--;
512  }
513 
514  return screen;
515 }
516 
518  int *pix_fmt, int *bpp)
519 {
520  XCBGrabContext *c = s->priv_data;
521  const xcb_setup_t *setup = xcb_get_setup(c->conn);
522  const xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
523  int length = xcb_setup_pixmap_formats_length(setup);
524 
525  *pix_fmt = 0;
526 
527  while (length--) {
528  if (fmt->depth == depth) {
529  switch (depth) {
530  case 32:
531  if (fmt->bits_per_pixel == 32)
532  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
534  break;
535  case 24:
536  if (fmt->bits_per_pixel == 32)
537  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
539  else if (fmt->bits_per_pixel == 24)
540  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
542  break;
543  case 16:
544  if (fmt->bits_per_pixel == 16)
545  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
547  break;
548  case 15:
549  if (fmt->bits_per_pixel == 16)
550  *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ?
552  break;
553  case 8:
554  if (fmt->bits_per_pixel == 8)
556  break;
557  }
558  }
559 
560  if (*pix_fmt) {
561  *bpp = fmt->bits_per_pixel;
562  return 0;
563  }
564 
565  fmt++;
566  }
567  avpriv_report_missing_feature(s, "Mapping this pixmap format");
568 
569  return AVERROR_PATCHWELCOME;
570 }
571 
573 {
574  XCBGrabContext *c = s->priv_data;
576  xcb_get_geometry_cookie_t gc;
577  xcb_get_geometry_reply_t *geo;
578  int64_t frame_size_bits;
579  int ret;
580 
581  if (!st)
582  return AVERROR(ENOMEM);
583 
584  ret = av_parse_video_rate(&st->avg_frame_rate, c->framerate);
585  if (ret < 0)
586  return ret;
587 
588  avpriv_set_pts_info(st, 64, 1, 1000000);
589 
590  gc = xcb_get_geometry(c->conn, c->window_id);
591  geo = xcb_get_geometry_reply(c->conn, gc, NULL);
592  if (!geo) {
593  av_log(s, AV_LOG_ERROR, "Can't find window '0x%x', aborting.\n", c->window_id);
594  return AVERROR_EXTERNAL;
595  }
596 
597  if (!c->width || !c->height) {
598  c->width = geo->width;
599  c->height = geo->height;
600  }
601 
602  if (c->x + c->width > geo->width ||
603  c->y + c->height > geo->height) {
605  "Capture area %dx%d at position %d.%d "
606  "outside the screen size %dx%d\n",
607  c->width, c->height,
608  c->x, c->y,
609  geo->width, geo->height);
610  free(geo);
611  return AVERROR(EINVAL);
612  }
613 
614  c->time_base = (AVRational){ st->avg_frame_rate.den,
615  st->avg_frame_rate.num };
616  c->frame_duration = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q);
617  c->time_frame = av_gettime_relative();
618 
619  ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp);
620  free(geo);
621  if (ret < 0)
622  return ret;
623 
624  frame_size_bits = (int64_t)c->width * c->height * c->bpp;
625  if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
626  av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
627  return AVERROR_PATCHWELCOME;
628  }
629  c->frame_size = frame_size_bits / 8;
630 
631 #if CONFIG_LIBXCB_SHM
632  c->shm_pool = av_buffer_pool_init2(c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE,
633  c->conn, allocate_shm_buffer, NULL);
634  if (!c->shm_pool)
635  return AVERROR(ENOMEM);
636 #endif
637 
640  st->codecpar->width = c->width;
641  st->codecpar->height = c->height;
642  st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
643 
644  return ret;
645 }
646 
648 {
649  XCBGrabContext *c = s->priv_data;
650  xcb_gcontext_t gc = xcb_generate_id(c->conn);
651  uint32_t mask = XCB_GC_FOREGROUND |
652  XCB_GC_BACKGROUND |
653  XCB_GC_LINE_WIDTH |
654  XCB_GC_LINE_STYLE |
655  XCB_GC_FILL_STYLE;
656  uint32_t values[] = { c->screen->black_pixel,
657  c->screen->white_pixel,
658  c->region_border,
659  XCB_LINE_STYLE_DOUBLE_DASH,
660  XCB_FILL_STYLE_SOLID };
661  xcb_rectangle_t r = { 1, 1,
662  c->width + c->region_border * 2 - 3,
663  c->height + c->region_border * 2 - 3 };
664 
665  xcb_create_gc(c->conn, gc, c->window, mask, values);
666 
667  xcb_poly_rectangle(c->conn, c->window, gc, 1, &r);
668 }
669 
671 {
672  XCBGrabContext *c = s->priv_data;
673  uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
674  uint32_t values[] = { 1,
675  XCB_EVENT_MASK_EXPOSURE |
676  XCB_EVENT_MASK_STRUCTURE_NOTIFY };
677  av_unused xcb_rectangle_t rect = { 0, 0, c->width, c->height };
678 
679  c->window = xcb_generate_id(c->conn);
680 
681  xcb_create_window(c->conn, XCB_COPY_FROM_PARENT,
682  c->window,
683  c->screen->root,
684  c->x - c->region_border,
685  c->y - c->region_border,
686  c->width + c->region_border * 2,
687  c->height + c->region_border * 2,
688  0,
689  XCB_WINDOW_CLASS_INPUT_OUTPUT,
690  XCB_COPY_FROM_PARENT,
691  mask, values);
692 
693 #if CONFIG_LIBXCB_SHAPE
694  xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
695  XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
696  c->window,
697  c->region_border, c->region_border,
698  1, &rect);
699 #endif
700 
701  xcb_map_window(c->conn, c->window);
702 
703  draw_rectangle(s);
704 }
705 
706 #define CROSSHAIR_CURSOR 34
707 
708 static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a,
709  xcb_point_t *corner_b)
710 {
711  xcb_rectangle_t rectangle;
712  rectangle.x = FFMIN(corner_a->x, corner_b->x);
713  rectangle.y = FFMIN(corner_a->y, corner_b->y);
714  rectangle.width = FFABS(corner_a->x - corner_b->x);
715  rectangle.height = FFABS(corner_a->y - corner_b->y);
716  return rectangle;
717 }
718 
720 {
721  XCBGrabContext *c = s->priv_data;
722  xcb_connection_t *conn = c->conn;
723  xcb_screen_t *screen = c->screen;
724 
725  int ret = 0, done = 0, was_pressed = 0;
726  xcb_cursor_t cursor;
727  xcb_font_t cursor_font;
728  xcb_point_t press_position;
729  xcb_generic_event_t *event;
730  xcb_rectangle_t rectangle = { 0 };
731  xcb_grab_pointer_reply_t *reply;
732  xcb_grab_pointer_cookie_t cookie;
733 
734  xcb_window_t root_window = screen->root;
735  xcb_gcontext_t gc = xcb_generate_id(conn);
736  uint32_t mask = XCB_GC_FUNCTION | XCB_GC_SUBWINDOW_MODE;
737  uint32_t values[] = { XCB_GX_INVERT, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS };
738  xcb_create_gc(conn, gc, root_window, mask, values);
739 
740  cursor_font = xcb_generate_id(conn);
741  xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor");
742  cursor = xcb_generate_id(conn);
743  xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font,
744  CROSSHAIR_CURSOR, CROSSHAIR_CURSOR + 1, 0, 0, 0,
745  0xFFFF, 0xFFFF, 0xFFFF);
746  cookie = xcb_grab_pointer(conn, 0, root_window,
747  XCB_EVENT_MASK_BUTTON_PRESS |
748  XCB_EVENT_MASK_BUTTON_RELEASE |
749  XCB_EVENT_MASK_BUTTON_MOTION,
750  XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
751  root_window, cursor, XCB_CURRENT_TIME);
752  reply = xcb_grab_pointer_reply(conn, cookie, NULL);
753  if (!reply || reply->status != XCB_GRAB_STATUS_SUCCESS) {
755  "Failed to select region. Could not grab pointer.\n");
756  ret = AVERROR(EIO);
757  free(reply);
758  goto fail;
759  }
760  free(reply);
761 
762  xcb_grab_server(conn);
763 
764  while (!done && (event = xcb_wait_for_event(conn))) {
765  switch (event->response_type & ~0x80) {
766  case XCB_BUTTON_PRESS: {
767  xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
768  press_position = (xcb_point_t){ press->event_x, press->event_y };
769  rectangle.x = press_position.x;
770  rectangle.y = press_position.y;
771  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
772  was_pressed = 1;
773  break;
774  }
775  case XCB_MOTION_NOTIFY: {
776  if (was_pressed) {
777  xcb_motion_notify_event_t *motion =
778  (xcb_motion_notify_event_t *)event;
779  xcb_point_t cursor_position = { motion->event_x, motion->event_y };
780  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
781  rectangle = rectangle_from_corners(&press_position, &cursor_position);
782  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
783  }
784  break;
785  }
786  case XCB_BUTTON_RELEASE: {
787  xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle);
788  done = 1;
789  break;
790  }
791  default:
792  break;
793  }
794  xcb_flush(conn);
795  free(event);
796  }
797  c->width = rectangle.width;
798  c->height = rectangle.height;
799  if (c->width && c->height) {
800  c->x = rectangle.x;
801  c->y = rectangle.y;
802  } else {
803  c->x = 0;
804  c->y = 0;
805  }
806  xcb_ungrab_server(conn);
807  xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
808  xcb_flush(conn);
809 
810 fail:
811  xcb_free_cursor(conn, cursor);
812  xcb_close_font(conn, cursor_font);
813  xcb_free_gc(conn, gc);
814  return ret;
815 }
816 
818 {
819  XCBGrabContext *c = s->priv_data;
820  int screen_num, ret;
821  const xcb_setup_t *setup;
822  char *display_name = av_strdup(s->url);
823 
824  if (!display_name)
825  return AVERROR(ENOMEM);
826 
827  if (!sscanf(s->url, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
828  *display_name = 0;
829  sscanf(s->url, "+%d,%d", &c->x, &c->y);
830  }
831 
832  c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num);
833  av_freep(&display_name);
834 
835  if ((ret = xcb_connection_has_error(c->conn))) {
836  av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
837  s->url[0] ? s->url : "default", ret);
838  return AVERROR(EIO);
839  }
840 
841  setup = xcb_get_setup(c->conn);
842 
843  c->screen = get_screen(setup, screen_num);
844  if (!c->screen) {
845  av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n",
846  screen_num);
848  return AVERROR(EIO);
849  }
850 
851  if (c->window_id == XCB_NONE)
852  c->window_id = c->screen->root;
853  else {
854  if (c->select_region) {
855  av_log(s, AV_LOG_WARNING, "select_region ignored with window_id.\n");
856  c->select_region = 0;
857  }
858  if (c->follow_mouse) {
859  av_log(s, AV_LOG_WARNING, "follow_mouse ignored with window_id.\n");
860  c->follow_mouse = 0;
861  }
862  }
863 
864  if (c->select_region) {
865  ret = select_region(s);
866  if (ret < 0) {
868  return ret;
869  }
870  }
871 
872  ret = create_stream(s);
873 
874  if (ret < 0) {
876  return ret;
877  }
878 
879 #if CONFIG_LIBXCB_SHM
880  c->has_shm = check_shm(c->conn);
881 #endif
882 
883 #if CONFIG_LIBXCB_XFIXES
884  if (c->draw_mouse) {
885  if (!(c->draw_mouse = check_xfixes(c->conn))) {
887  "XFixes not available, cannot draw the mouse.\n");
888  }
889  if (c->bpp < 24) {
890  avpriv_report_missing_feature(s, "%d bits per pixel screen",
891  c->bpp);
892  c->draw_mouse = 0;
893  }
894  }
895 #endif
896 
897  if (c->show_region)
898  setup_window(s);
899 
900  return 0;
901 }
902 
904  .name = "x11grab",
905  .long_name = NULL_IF_CONFIG_SMALL("X11 screen capture, using XCB"),
906  .priv_data_size = sizeof(XCBGrabContext),
910  .flags = AVFMT_NOFILE,
911  .priv_class = &xcbgrab_class,
912 };
XCBGrabContext::has_shm
int has_shm
Definition: xcbgrab.c:78
stride
int stride
Definition: mace.c:144
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:64
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:768
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
FOLLOW_CENTER
#define FOLLOW_CENTER
Definition: xcbgrab.c:81
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:89
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
XCBGrabContext::time_base
AVRational time_base
Definition: xcbgrab.c:60
rect
Definition: f_ebur128.c:77
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
XCBGrabContext::select_region
int select_region
Definition: xcbgrab.c:74
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:63
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:373
AVOption
AVOption.
Definition: opt.h:247
b
#define b
Definition: input.c:40
ff_xcbgrab_demuxer
const AVInputFormat ff_xcbgrab_demuxer
Definition: xcbgrab.c:903
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:1015
data
const char data[16]
Definition: mxf.c:143
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:391
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:107
create_stream
static int create_stream(AVFormatContext *s)
Definition: xcbgrab.c:572
framerate
int framerate
Definition: h264_levels.c:65
xcbgrab_class
static const AVClass xcbgrab_class
Definition: xcbgrab.c:103
fail
#define fail()
Definition: checkasm.h:127
xcbgrab_frame
static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:157
draw_rectangle
static void draw_rectangle(AVFormatContext *s)
Definition: xcbgrab.c:647
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:141
pts
static int64_t pts
Definition: transcode_aac.c:653
AVRational::num
int num
Numerator.
Definition: rational.h:59
CROSSHAIR_CURSOR
#define CROSSHAIR_CURSOR
Definition: xcbgrab.c:706
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
AVInputFormat
Definition: avformat.h:650
av_cold
#define av_cold
Definition: attributes.h:90
mask
static const uint16_t mask[17]
Definition: lzw.c:38
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:387
options
static const AVOption options[]
Definition: xcbgrab.c:85
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:517
s
#define s(width, name)
Definition: cbs_vp9.c:257
XCBGrabContext::frame_duration
int64_t frame_duration
Definition: xcbgrab.c:61
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:655
g
const char * g
Definition: vf_curves.c:117
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:126
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:141
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
f
#define f(width, name)
Definition: cbs_vp9.c:255
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:65
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1200
XCBGrabContext::region_border
int region_border
Definition: xcbgrab.c:72
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1095
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:356
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:106
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
AVClass
Describe the class of an AVClass context structure.
Definition: log.h: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:67
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:234
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
parseutils.h
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:322
XCBGrabContext::window
xcb_window_t window
Definition: xcbgrab.c:55
AV_PIX_FMT_RGB8
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:230
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:71
XCBGrabContext::follow_mouse
int follow_mouse
Definition: xcbgrab.c:70
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
AVPacket::size
int size
Definition: packet.h:374
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:117
id
enum AVCodecID id
Definition: extract_extradata_bsf.c:325
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:464
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:372
XCBGrabContext::window_id
xcb_window_t window_id
Definition: xcbgrab.c:63
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:116
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:414
rectangle_from_corners
static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a, xcb_point_t *corner_b)
Definition: xcbgrab.c:708
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:108
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:366
xcbgrab_image_reply_free
static void xcbgrab_image_reply_free(void *opaque, uint8_t *data)
Definition: xcbgrab.c:152
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:127
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
setup_window
static void setup_window(AVFormatContext *s)
Definition: xcbgrab.c:670
xcbgrab_update_region
static void xcbgrab_update_region(AVFormatContext *s, int win_x, int win_y)
Definition: xcbgrab.c:402
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:128
D
#define D
Definition: xcbgrab.c:84
XCBGrabContext::framerate
const char * framerate
Definition: xcbgrab.c:76
XCBGrabContext::screen
xcb_screen_t * screen
Definition: xcbgrab.c:54
xcbgrab_read_close
static av_cold int xcbgrab_read_close(AVFormatContext *s)
Definition: xcbgrab.c:487
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:935
xcbgrab_read_packet
static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: xcbgrab.c:414
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:201
avformat.h
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
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:719
XCBGrabContext::conn
xcb_connection_t * conn
Definition: xcbgrab.c:53
XCBGrabContext::frame_size
int frame_size
Definition: xcbgrab.c:66
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:111
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
values
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return values
Definition: filter_design.txt:263
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
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: utils.c:1196
segment
Definition: hls.c:71
AV_PIX_FMT_RGB565BE
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:105
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:279
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
XCBGrabContext::x
int x
Definition: xcbgrab.c:64
get_screen
static xcb_screen_t * get_screen(const xcb_setup_t *setup, int screen_num)
Definition: xcbgrab.c:500
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:817
it
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s it
Definition: writing_filters.txt:31
AVCodecParameters::format
int format
Definition: codec_par.h:84
XCBGrabContext::height
int height
Definition: xcbgrab.c:65
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVPacket
This structure stores compressed data.
Definition: packet.h:350
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:241
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:227
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
OFFSET
#define OFFSET(x)
Definition: xcbgrab.c:83
h
h
Definition: vp9dsp_template.c:2038
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
XCBGrabContext::draw_mouse
int draw_mouse
Definition: xcbgrab.c:69
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
XCBGrabContext::centered
int centered
Definition: xcbgrab.c:73
XCBGrabContext
Definition: xcbgrab.c:50
XCBGrabContext::time_frame
int64_t time_frame
Definition: xcbgrab.c:59
XCBGrabContext::width
int width
Definition: xcbgrab.c:65