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