Originally committed as revision 20631 to svn://svn.ffmpeg.org/ffmpeg/trunk
Roxis authored on 2009/11/28 02:58:48... | ... |
@@ -1249,7 +1249,7 @@ v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" |
1249 | 1249 |
vfwcap_indev_deps="capCreateCaptureWindow" |
1250 | 1250 |
vfwcap_indev_extralibs="-lvfw32" |
1251 | 1251 |
x11_grab_device_indev_deps="x11grab XShmCreateImage" |
1252 |
-x11_grab_device_indev_extralibs="-lX11 -lXext" |
|
1252 |
+x11_grab_device_indev_extralibs="-lX11 -lXext -lXfixes" |
|
1253 | 1253 |
|
1254 | 1254 |
# protocols |
1255 | 1255 |
gopher_protocol_deps="network" |
... | ... |
@@ -2477,7 +2477,8 @@ enabled x11grab && |
2477 | 2477 |
check_header X11/Xlib.h && |
2478 | 2478 |
check_header X11/extensions/XShm.h && |
2479 | 2479 |
check_func XOpenDisplay -lX11 && |
2480 |
-check_func XShmCreateImage -lX11 -lXext |
|
2480 |
+check_func XShmCreateImage -lX11 -lXext && |
|
2481 |
+check_func XFixesGetCursorImage -lX11 -lXext -lXfixes |
|
2481 | 2482 |
|
2482 | 2483 |
enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel" |
2483 | 2484 |
|
... | ... |
@@ -45,6 +45,7 @@ |
45 | 45 |
#include <X11/Xutil.h> |
46 | 46 |
#include <sys/shm.h> |
47 | 47 |
#include <X11/extensions/XShm.h> |
48 |
+#include <X11/extensions/Xfixes.h> |
|
48 | 49 |
|
49 | 50 |
/** |
50 | 51 |
* X11 Device Demuxer context |
... | ... |
@@ -235,35 +236,6 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
235 | 235 |
} |
236 | 236 |
|
237 | 237 |
/** |
238 |
- * Get pointer coordinates from X11. |
|
239 |
- * |
|
240 |
- * @param x Integer where horizontal coordinate will be returned |
|
241 |
- * @param y Integer where vertical coordinate will be returned |
|
242 |
- * @param dpy X11 display from where pointer coordinates are retrieved |
|
243 |
- * @param s1 Context used for logging errors if necessary |
|
244 |
- */ |
|
245 |
-static void |
|
246 |
-get_pointer_coordinates(int *x, int *y, Display *dpy, AVFormatContext *s1) |
|
247 |
-{ |
|
248 |
- Window mrootwindow, childwindow; |
|
249 |
- int dummy; |
|
250 |
- |
|
251 |
- mrootwindow = DefaultRootWindow(dpy); |
|
252 |
- |
|
253 |
- if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, |
|
254 |
- x, y, &dummy, &dummy, (unsigned int*)&dummy)) { |
|
255 |
- } else { |
|
256 |
- struct x11_grab *s = s1->priv_data; |
|
257 |
- if (!s->mouse_warning_shown) { |
|
258 |
- av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); |
|
259 |
- s->mouse_warning_shown = 1; |
|
260 |
- } |
|
261 |
- *x = -1; |
|
262 |
- *y = -1; |
|
263 |
- } |
|
264 |
-} |
|
265 |
- |
|
266 |
-/** |
|
267 | 238 |
* Mouse painting helper function that applies an 'and' and 'or' mask pair to |
268 | 239 |
* '*dst' pixel. It actually draws a mouse pointer pixel to grabbed frame. |
269 | 240 |
* |
... | ... |
@@ -300,71 +272,43 @@ apply_masks(uint8_t *dst, int and, int or, int bits_per_pixel) |
300 | 300 |
* @param y Mouse pointer coordinate |
301 | 301 |
*/ |
302 | 302 |
static void |
303 |
-paint_mouse_pointer(XImage *image, struct x11_grab *s, int x, int y) |
|
303 |
+paint_mouse_pointer(XImage *image, struct x11_grab *s) |
|
304 | 304 |
{ |
305 |
- /* 16x20x1bpp bitmap for the black channel of the mouse pointer */ |
|
306 |
- static const uint16_t const mousePointerBlack[] = |
|
307 |
- { |
|
308 |
- 0x0000, 0x0003, 0x0005, 0x0009, 0x0011, |
|
309 |
- 0x0021, 0x0041, 0x0081, 0x0101, 0x0201, |
|
310 |
- 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120, |
|
311 |
- 0x0120, 0x0240, 0x0240, 0x0380, 0x0000 |
|
312 |
- }; |
|
313 |
- |
|
314 |
- /* 16x20x1bpp bitmap for the white channel of the mouse pointer */ |
|
315 |
- static const uint16_t const mousePointerWhite[] = |
|
316 |
- { |
|
317 |
- 0x0000, 0x0000, 0x0002, 0x0006, 0x000e, |
|
318 |
- 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, |
|
319 |
- 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, |
|
320 |
- 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000 |
|
321 |
- }; |
|
322 |
- |
|
323 | 305 |
int x_off = s->x_off; |
324 | 306 |
int y_off = s->y_off; |
325 | 307 |
int width = s->width; |
326 | 308 |
int height = s->height; |
309 |
+ Display *dpy = s->dpy; |
|
310 |
+ XFixesCursorImage *xcim; |
|
311 |
+ int x, y; |
|
312 |
+ int line, column; |
|
313 |
+ int to_line, to_column; |
|
314 |
+ int image_addr, xcim_addr; |
|
327 | 315 |
|
328 |
- if ( x - x_off >= 0 && x < width + x_off |
|
329 |
- && y - y_off >= 0 && y < height + y_off) { |
|
330 |
- uint8_t *im_data = (uint8_t*)image->data; |
|
331 |
- int bytes_per_pixel; |
|
332 |
- int line; |
|
333 |
- int masks; |
|
316 |
+ xcim = XFixesGetCursorImage(dpy);; |
|
334 | 317 |
|
335 |
- /* Select correct masks and pixel size */ |
|
336 |
- if (image->bits_per_pixel == 8) { |
|
337 |
- masks = 1; |
|
338 |
- } else { |
|
339 |
- masks = (image->red_mask|image->green_mask|image->blue_mask); |
|
340 |
- } |
|
341 |
- bytes_per_pixel = image->bits_per_pixel>>3; |
|
342 |
- |
|
343 |
- /* Shift to right line */ |
|
344 |
- im_data += image->bytes_per_line * (y - y_off); |
|
345 |
- /* Shift to right pixel in the line */ |
|
346 |
- im_data += bytes_per_pixel * (x - x_off); |
|
347 |
- |
|
348 |
- /* Draw the cursor - proper loop */ |
|
349 |
- for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) { |
|
350 |
- uint8_t *cursor = im_data; |
|
351 |
- int column; |
|
352 |
- uint16_t bm_b; |
|
353 |
- uint16_t bm_w; |
|
354 |
- |
|
355 |
- bm_b = mousePointerBlack[line]; |
|
356 |
- bm_w = mousePointerWhite[line]; |
|
357 |
- |
|
358 |
- for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) { |
|
359 |
- apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1), |
|
360 |
- image->bits_per_pixel); |
|
361 |
- cursor += bytes_per_pixel; |
|
362 |
- bm_b >>= 1; |
|
363 |
- bm_w >>= 1; |
|
318 |
+ x = xcim->x - xcim->xhot; |
|
319 |
+ y = xcim->y - xcim->yhot; |
|
320 |
+ |
|
321 |
+ to_line = FFMIN((y + xcim->height), (height + y_off)); |
|
322 |
+ to_column = FFMIN((x + xcim->width), (width + x_off)); |
|
323 |
+ |
|
324 |
+ for (line = FFMAX(y, y_off); line < to_line; line++) { |
|
325 |
+ for (column = FFMAX(x, x_off); column < to_column; column++) { |
|
326 |
+ xcim_addr = (line - y) * xcim->width + column - x; |
|
327 |
+ |
|
328 |
+ if ((unsigned char)(xcim->pixels[xcim_addr] >> 24) != 0) { // skip fully transparent pixel |
|
329 |
+ image_addr = ((line - y_off) * width + column - x_off) * 4; |
|
330 |
+ |
|
331 |
+ image->data[image_addr] = (unsigned char)(xcim->pixels[xcim_addr] >> 0); |
|
332 |
+ image->data[image_addr+1] = (unsigned char)(xcim->pixels[xcim_addr] >> 8); |
|
333 |
+ image->data[image_addr+2] = (unsigned char)(xcim->pixels[xcim_addr] >> 16); |
|
364 | 334 |
} |
365 |
- im_data += image->bytes_per_line; |
|
366 | 335 |
} |
367 | 336 |
} |
337 |
+ |
|
338 |
+ XFree(xcim); |
|
339 |
+ xcim = NULL; |
|
368 | 340 |
} |
369 | 341 |
|
370 | 342 |
|
... | ... |
@@ -469,9 +413,7 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) |
469 | 469 |
} |
470 | 470 |
|
471 | 471 |
{ |
472 |
- int pointer_x, pointer_y; |
|
473 |
- get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1); |
|
474 |
- paint_mouse_pointer(image, s, pointer_x, pointer_y); |
|
472 |
+ paint_mouse_pointer(image, s); |
|
475 | 473 |
} |
476 | 474 |
|
477 | 475 |
|