Mercurial > libavformat.hg
annotate x11grab.c @ 1960:c0289552590f libavformat
Change the vhook code to send real timestamps to the filters instead of the
current time of day, which is useless, and which the filters could just as
easily query for themselves.
patch by Bobby Bingham, uhmmmm gmail com
author | diego |
---|---|
date | Thu, 29 Mar 2007 05:24:35 +0000 |
parents | 62792a60f740 |
children | 06083249909c |
rev | line source |
---|---|
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
1 /* |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
2 * X11 video grab interface |
1581 | 3 * |
1583 | 4 * This file is part of FFmpeg. |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
5 * |
1583 | 6 * FFmpeg integration: |
7 * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org> | |
8 * Edouard Gomez <ed.gomez@free.fr> | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
9 * |
1583 | 10 * This file contains code from grab.c: |
1584 | 11 * Copyright (c) 2000-2001 Fabrice Bellard |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
12 * |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
13 * This file contains code from the xvidcap project: |
1583 | 14 * Copyright (C) 1997-1998 Rasca, Berlin |
15 * 2003-2004 Karl H. Beckers, Frankfurt | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
16 * |
1583 | 17 * FFmpeg is free software; you can redistribute it and/or modify |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
18 * it under the terms of the GNU General Public License as published by |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
19 * the Free Software Foundation; either version 2 of the License, or |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
20 * (at your option) any later version. |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
21 * |
1583 | 22 * FFmpeg is distributed in the hope that it will be useful, |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
25 * GNU General Public License for more details. |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
26 * |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
27 * You should have received a copy of the GNU General Public License along |
1586 | 28 * with FFmpeg; if not, write to the Free Software Foundation, Inc., |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
29 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
30 */ |
1581 | 31 |
1586 | 32 /** |
33 * @file x11grab.c | |
34 * X11 frame device demuxer by Clemens Fruhwirth <clemens@endorphin.org> | |
35 * and Edouard Gomez <ed.gomez@free.fr>. | |
36 */ | |
37 | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
38 #include "avformat.h" |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
39 #include <unistd.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
40 #include <fcntl.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
41 #include <sys/ioctl.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
42 #include <sys/mman.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
43 #include <sys/time.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
44 #define _LINUX_TIME_H 1 |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
45 #include <time.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
46 #include <X11/X.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
47 #include <X11/Xlib.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
48 #include <X11/Xlibint.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
49 #include <X11/Xproto.h> |
1583 | 50 #include <X11/Xutil.h> |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
51 #include <sys/ipc.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
52 #include <sys/shm.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
53 #include <X11/extensions/XShm.h> |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
54 |
1586 | 55 /** |
56 * X11 Device Demuxer context | |
57 */ | |
58 typedef struct x11_grab_s | |
1581 | 59 { |
1586 | 60 int frame_size; /**< Size in bytes of a grabbed frame */ |
61 AVRational time_base; /**< Time base */ | |
62 int64_t time_frame; /**< Current time */ | |
63 | |
64 int height; /**< Height of the grab frame */ | |
65 int width; /**< Width of the grab frame */ | |
66 int x_off; /**< Horizontal top-left corner coordinate */ | |
67 int y_off; /**< Vertical top-left corner coordinate */ | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
68 |
1586 | 69 Display *dpy; /**< X11 display from which x11grab grabs frames */ |
70 XImage *image; /**< X11 image holding the grab */ | |
71 int use_shm; /**< !0 when using XShm extension */ | |
72 XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */ | |
1753
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
73 int mouse_warning_shown; |
1586 | 74 } x11_grab_t; |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
75 |
1586 | 76 /** |
77 * Initializes the x11 grab device demuxer (public device demuxer API). | |
78 * | |
79 * @param s1 Context from avformat core | |
80 * @param ap Parameters from avformat core | |
81 * @return <ul> | |
82 * <li>ENOMEM no memory left</li> | |
83 * <li>AVERROR_IO other failure case</li> | |
84 * <li>0 success</li> | |
85 * </ul> | |
86 */ | |
1581 | 87 static int |
88 x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
89 { |
1586 | 90 x11_grab_t *x11grab = s1->priv_data; |
1584 | 91 Display *dpy; |
92 AVStream *st = NULL; | |
93 int input_pixfmt; | |
94 XImage *image; | |
1586 | 95 int x_off = 0; |
96 int y_off = 0; | |
1584 | 97 int use_shm; |
1591
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
98 char *param, *offset; |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
99 |
1795
62792a60f740
implement new grabbing interface, as described here:
gpoirier
parents:
1787
diff
changeset
|
100 param = av_strdup(s1->filename); |
1591
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
101 offset = strchr(param, '+'); |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
102 if (offset) { |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
103 sscanf(offset, "%d,%d", &x_off, &y_off); |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
104 *offset= 0; |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
105 } |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
106 |
1795
62792a60f740
implement new grabbing interface, as described here:
gpoirier
parents:
1787
diff
changeset
|
107 av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, param, x_off, y_off, ap->width, ap->height); |
1591
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
108 |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
109 dpy = XOpenDisplay(param); |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
110 if(!dpy) { |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
111 av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
112 return AVERROR_IO; |
5b46490d0435
Allow provision of displaynumber, screennumber, x-offset and y-offset parameters
takis
parents:
1590
diff
changeset
|
113 } |
1584 | 114 |
115 if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { | |
116 av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n"); | |
117 return AVERROR_IO; | |
118 } | |
119 | |
120 st = av_new_stream(s1, 0); | |
121 if (!st) { | |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1760
diff
changeset
|
122 return AVERROR(ENOMEM); |
1584 | 123 } |
124 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
125 |
1584 | 126 use_shm = XShmQueryExtension(dpy); |
1586 | 127 av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ? "" : "not"); |
1581 | 128 |
1584 | 129 if(use_shm) { |
130 int scr = XDefaultScreen(dpy); | |
131 image = XShmCreateImage(dpy, | |
132 DefaultVisual(dpy, scr), | |
133 DefaultDepth(dpy, scr), | |
134 ZPixmap, | |
135 NULL, | |
136 &x11grab->shminfo, | |
137 ap->width, ap->height); | |
138 x11grab->shminfo.shmid = shmget(IPC_PRIVATE, | |
139 image->bytes_per_line * image->height, | |
140 IPC_CREAT|0777); | |
141 if (x11grab->shminfo.shmid == -1) { | |
142 av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); | |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1760
diff
changeset
|
143 return AVERROR(ENOMEM); |
1584 | 144 } |
145 x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); | |
146 x11grab->shminfo.readOnly = False; | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
147 |
1584 | 148 if (!XShmAttach(dpy, &x11grab->shminfo)) { |
149 av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); | |
150 /* needs some better error subroutine :) */ | |
151 return AVERROR_IO; | |
152 } | |
153 } else { | |
154 image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), | |
155 x_off,y_off, | |
156 ap->width,ap->height, | |
157 AllPlanes, ZPixmap); | |
158 } | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
159 |
1584 | 160 switch (image->bits_per_pixel) { |
161 case 8: | |
1630 | 162 av_log (s1, AV_LOG_DEBUG, "8 bit palette\n"); |
1584 | 163 input_pixfmt = PIX_FMT_PAL8; |
164 break; | |
165 case 16: | |
1586 | 166 if ( image->red_mask == 0xf800 && |
167 image->green_mask == 0x07e0 && | |
168 image->blue_mask == 0x001f ) { | |
1584 | 169 av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); |
170 input_pixfmt = PIX_FMT_RGB565; | |
1586 | 171 } else if (image->red_mask == 0x7c00 && |
172 image->green_mask == 0x03e0 && | |
173 image->blue_mask == 0x001f ) { | |
1584 | 174 av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); |
175 input_pixfmt = PIX_FMT_RGB555; | |
176 } else { | |
177 av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); | |
178 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); | |
179 return AVERROR_IO; | |
180 } | |
181 break; | |
182 case 24: | |
1586 | 183 if ( image->red_mask == 0xff0000 && |
184 image->green_mask == 0x00ff00 && | |
185 image->blue_mask == 0x0000ff ) { | |
1584 | 186 input_pixfmt = PIX_FMT_BGR24; |
1586 | 187 } else if ( image->red_mask == 0x0000ff && |
188 image->green_mask == 0x00ff00 && | |
189 image->blue_mask == 0xff0000 ) { | |
1584 | 190 input_pixfmt = PIX_FMT_RGB24; |
191 } else { | |
192 av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); | |
193 av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); | |
194 return AVERROR_IO; | |
195 } | |
196 break; | |
197 case 32: | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
198 #if 0 |
1584 | 199 GetColorInfo (image, &c_info); |
1586 | 200 if ( c_info.alpha_mask == 0xff000000 && image->green_mask == 0x0000ff00) { |
1584 | 201 /* byte order is relevant here, not endianness |
202 * endianness is handled by avcodec, but atm no such thing | |
203 * as having ABGR, instead of ARGB in a word. Since we | |
204 * need this for Solaris/SPARC, but need to do the conversion | |
205 * for every frame we do it outside of this loop, cf. below | |
206 * this matches both ARGB32 and ABGR32 */ | |
207 input_pixfmt = PIX_FMT_ARGB32; | |
208 } else { | |
209 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); | |
210 return AVERROR_IO; | |
211 } | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
212 #endif |
1760
8cba5672faa4
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
1753
diff
changeset
|
213 input_pixfmt = PIX_FMT_RGB32; |
1584 | 214 break; |
215 default: | |
216 av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); | |
217 return -1; | |
218 } | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
219 |
1586 | 220 x11grab->frame_size = ap->width * ap->height * image->bits_per_pixel/8; |
1584 | 221 x11grab->dpy = dpy; |
222 x11grab->width = ap->width; | |
223 x11grab->height = ap->height; | |
1586 | 224 x11grab->time_base = ap->time_base; |
225 x11grab->time_frame = av_gettime() / av_q2d(ap->time_base); | |
1584 | 226 x11grab->x_off = x_off; |
227 x11grab->y_off = y_off; | |
228 x11grab->image = image; | |
229 x11grab->use_shm = use_shm; | |
1753
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
230 x11grab->mouse_warning_shown = 0; |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
231 |
1584 | 232 st->codec->codec_type = CODEC_TYPE_VIDEO; |
233 st->codec->codec_id = CODEC_ID_RAWVIDEO; | |
1586 | 234 st->codec->width = ap->width; |
235 st->codec->height = ap->height; | |
1584 | 236 st->codec->pix_fmt = input_pixfmt; |
1586 | 237 st->codec->time_base = ap->time_base; |
238 st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(ap->time_base) * 8; | |
1584 | 239 |
240 return 0; | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
241 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
242 |
1586 | 243 /** |
244 * Get pointer coordinates from X11. | |
245 * | |
246 * @param x Integer where horizontal coordinate will be returned | |
247 * @param y Integer where vertical coordinate will be returned | |
248 * @param dpy X11 display from where pointer coordinates are retrieved | |
249 * @param s1 Context used for logging errors if necessary | |
250 */ | |
1581 | 251 static void |
1586 | 252 get_pointer_coordinates(int *x, int *y, Display *dpy, AVFormatContext *s1) |
1581 | 253 { |
1584 | 254 Window mrootwindow, childwindow; |
255 int dummy; | |
256 | |
257 mrootwindow = DefaultRootWindow(dpy); | |
258 | |
259 if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, | |
260 x, y, &dummy, &dummy, (unsigned int*)&dummy)) { | |
261 } else { | |
1753
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
262 x11_grab_t *s = s1->priv_data; |
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
263 if (!s->mouse_warning_shown) { |
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
264 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); |
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
265 s->mouse_warning_shown = 1; |
d0a97c73ee97
Make x11grab output its warning that it couldn't find the mouse pointer only
takis
parents:
1630
diff
changeset
|
266 } |
1584 | 267 *x = -1; |
268 *y = -1; | |
269 } | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
270 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
271 |
1586 | 272 /** |
273 * Mouse painting helper function that applies an 'and' and 'or' mask pair to | |
274 * '*dst' pixel. It actually draws a mouse pointer pixel to grabbed frame. | |
275 * | |
276 * @param dst Destination pixel | |
277 * @param and Part of the mask that must be applied using a bitwise 'and' | |
278 * operator | |
279 * @param or Part of the mask that must be applied using a bitwise 'or' | |
280 * operator | |
281 * @param bits_per_pixel Bits per pixel used in the grabbed image | |
282 */ | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
283 static void inline |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
284 apply_masks(uint8_t *dst, int and, int or, int bits_per_pixel) |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
285 { |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
286 switch (bits_per_pixel) { |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
287 case 32: |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
288 *(uint32_t*)dst = (*(uint32_t*)dst & and) | or; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
289 break; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
290 case 16: |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
291 *(uint16_t*)dst = (*(uint16_t*)dst & and) | or; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
292 break; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
293 case 8: |
1586 | 294 *dst = !!or; |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
295 break; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
296 } |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
297 } |
1582
754781df8033
RFC 1 stage: Improve maintainability of the cursoir painting code
gpoirier
parents:
1581
diff
changeset
|
298 |
1586 | 299 /** |
300 * Paints a mouse pointer in an X11 image. | |
301 * | |
302 * @param image Image where to paint the mouse pointer | |
303 * @param s context used to retrieve original grabbing rectangle | |
304 * coordinates | |
305 * @param x Mouse pointer coordinate | |
306 * @param y Mouse pointer coordinate | |
307 */ | |
1581 | 308 static void |
1586 | 309 paint_mouse_pointer(XImage *image, x11_grab_t *s, int x, int y) |
1581 | 310 { |
1586 | 311 /* 16x20x1bpp bitmap for the black channel of the mouse pointer */ |
1584 | 312 static const uint16_t const mousePointerBlack[] = |
313 { | |
1587 | 314 0x0000, 0x0003, 0x0005, 0x0009, 0x0011, |
315 0x0021, 0x0041, 0x0081, 0x0101, 0x0201, | |
316 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120, | |
317 0x0120, 0x0240, 0x0240, 0x0380, 0x0000 | |
1584 | 318 }; |
1583 | 319 |
1586 | 320 /* 16x20x1bpp bitmap for the white channel of the mouse pointer */ |
1584 | 321 static const uint16_t const mousePointerWhite[] = |
322 { | |
1587 | 323 0x0000, 0x0000, 0x0002, 0x0006, 0x000e, |
324 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, | |
325 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, | |
326 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000 | |
1584 | 327 }; |
1583 | 328 |
1584 | 329 int x_off = s->x_off; |
330 int y_off = s->y_off; | |
331 int width = s->width; | |
332 int height = s->height; | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
333 |
1586 | 334 if ( x - x_off >= 0 && x < width + x_off |
335 && y - y_off >= 0 && y < height + y_off) { | |
336 uint8_t *im_data = (uint8_t*)image->data; | |
337 int bytes_per_pixel; | |
1584 | 338 int line; |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
339 int masks; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
340 |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
341 /* Select correct masks and pixel size */ |
1586 | 342 if (image->bits_per_pixel == 8) { |
343 masks = 1; | |
344 } else { | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
345 masks = (image->red_mask|image->green_mask|image->blue_mask); |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
346 } |
1586 | 347 bytes_per_pixel = image->bits_per_pixel>>3; |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
348 |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
349 /* Shift to right line */ |
1586 | 350 im_data += image->bytes_per_line * (y - y_off); |
351 /* Shift to right pixel in the line */ | |
352 im_data += bytes_per_pixel * (x - x_off); | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
353 |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
354 /* Draw the cursor - proper loop */ |
1586 | 355 for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) { |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
356 uint8_t *cursor = im_data; |
1586 | 357 int column; |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
358 uint16_t bm_b; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
359 uint16_t bm_w; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
360 |
1586 | 361 bm_b = mousePointerBlack[line]; |
362 bm_w = mousePointerWhite[line]; | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
363 |
1586 | 364 for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) { |
365 apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1), | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
366 image->bits_per_pixel); |
1586 | 367 cursor += bytes_per_pixel; |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
368 bm_b >>= 1; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
369 bm_w >>= 1; |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
370 } |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
371 im_data += image->bytes_per_line; |
1584 | 372 } |
373 } | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
374 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
375 |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
376 |
1586 | 377 /** |
378 * Reads new data in the image structure. | |
379 * | |
380 * @param dpy X11 display to grab from | |
1588 | 381 * @param d |
1586 | 382 * @param image Image where the grab will be put |
383 * @param x Top-Left grabbing rectangle horizontal coordinate | |
384 * @param y Top-Left grabbing rectangle vertical coordinate | |
385 * @return 0 if error, !0 if successful | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
386 */ |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
387 static int |
1586 | 388 xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y) |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
389 { |
1584 | 390 xGetImageReply rep; |
391 xGetImageReq *req; | |
392 long nbytes; | |
1581 | 393 |
1584 | 394 if (!image) { |
1586 | 395 return 0; |
1584 | 396 } |
397 | |
398 LockDisplay(dpy); | |
399 GetReq(GetImage, req); | |
1581 | 400 |
1584 | 401 /* First set up the standard stuff in the request */ |
402 req->drawable = d; | |
403 req->x = x; | |
404 req->y = y; | |
405 req->width = image->width; | |
406 req->height = image->height; | |
407 req->planeMask = (unsigned int)AllPlanes; | |
408 req->format = ZPixmap; | |
409 | |
1586 | 410 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) { |
1584 | 411 UnlockDisplay(dpy); |
412 SyncHandle(); | |
1586 | 413 return 0; |
1584 | 414 } |
415 | |
416 nbytes = (long)rep.length << 2; | |
417 _XReadPad(dpy, image->data, nbytes); | |
418 | |
419 UnlockDisplay(dpy); | |
420 SyncHandle(); | |
1586 | 421 return 1; |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
422 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
423 |
1586 | 424 /** |
425 * Grabs a frame from x11 (public device demuxer API). | |
426 * | |
427 * @param s1 Context from avformat core | |
428 * @param pkt Packet holding the brabbed frame | |
429 * @return frame size in bytes | |
430 */ | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
431 static int |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
432 x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
433 { |
1586 | 434 x11_grab_t *s = s1->priv_data; |
1584 | 435 Display *dpy = s->dpy; |
436 XImage *image = s->image; | |
437 int x_off = s->x_off; | |
438 int y_off = s->y_off; | |
439 | |
440 int64_t curtime, delay; | |
441 struct timespec ts; | |
442 | |
443 /* Calculate the time of the next frame */ | |
1589
d63bac8be31a
fix compilation, use the standard INT64_C macro
bcoudurier
parents:
1588
diff
changeset
|
444 s->time_frame += INT64_C(1000000); |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
445 |
1584 | 446 /* wait based on the frame rate */ |
447 for(;;) { | |
448 curtime = av_gettime(); | |
1586 | 449 delay = s->time_frame * av_q2d(s->time_base) - curtime; |
1584 | 450 if (delay <= 0) { |
1589
d63bac8be31a
fix compilation, use the standard INT64_C macro
bcoudurier
parents:
1588
diff
changeset
|
451 if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { |
d63bac8be31a
fix compilation, use the standard INT64_C macro
bcoudurier
parents:
1588
diff
changeset
|
452 s->time_frame += INT64_C(1000000); |
1584 | 453 } |
454 break; | |
455 } | |
456 ts.tv_sec = delay / 1000000; | |
457 ts.tv_nsec = (delay % 1000000) * 1000; | |
458 nanosleep(&ts, NULL); | |
459 } | |
1581 | 460 |
1584 | 461 if (av_new_packet(pkt, s->frame_size) < 0) { |
462 return AVERROR_IO; | |
463 } | |
464 | |
1586 | 465 pkt->pts = curtime; |
1584 | 466 |
467 if(s->use_shm) { | |
468 if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { | |
469 av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); | |
470 } | |
471 } else { | |
1586 | 472 if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { |
1584 | 473 av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); |
474 } | |
475 } | |
476 | |
477 { | |
478 int pointer_x, pointer_y; | |
1586 | 479 get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1); |
480 paint_mouse_pointer(image, s, pointer_x, pointer_y); | |
1584 | 481 } |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
482 |
1582
754781df8033
RFC 1 stage: Improve maintainability of the cursoir painting code
gpoirier
parents:
1581
diff
changeset
|
483 |
1584 | 484 /* XXX: avoid memcpy */ |
485 memcpy(pkt->data, image->data, s->frame_size); | |
486 return s->frame_size; | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
487 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
488 |
1586 | 489 /** |
490 * Closes x11 frame grabber (public device demuxer API). | |
491 * | |
492 * @param s1 Context from avformat core | |
493 * @return 0 success, !0 failure | |
494 */ | |
1585
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
495 static int |
14c185883eab
RFC 5: Mouse cursor painting reduc and more cleanups
gpoirier
parents:
1584
diff
changeset
|
496 x11grab_read_close(AVFormatContext *s1) |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
497 { |
1586 | 498 x11_grab_t *x11grab = s1->priv_data; |
1582
754781df8033
RFC 1 stage: Improve maintainability of the cursoir painting code
gpoirier
parents:
1581
diff
changeset
|
499 |
1584 | 500 /* Detach cleanly from shared mem */ |
501 if (x11grab->use_shm) { | |
502 XShmDetach(x11grab->dpy, &x11grab->shminfo); | |
503 shmdt(x11grab->shminfo.shmaddr); | |
504 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); | |
505 } | |
1582
754781df8033
RFC 1 stage: Improve maintainability of the cursoir painting code
gpoirier
parents:
1581
diff
changeset
|
506 |
1584 | 507 /* Destroy X11 image */ |
508 if (x11grab->image) { | |
509 XDestroyImage(x11grab->image); | |
510 x11grab->image = NULL; | |
511 } | |
1583 | 512 |
1584 | 513 /* Free X11 display */ |
514 XCloseDisplay(x11grab->dpy); | |
515 return 0; | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
516 } |
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
517 |
1586 | 518 /** x11 grabber device demuxer declaration */ |
1581 | 519 AVInputFormat x11_grab_device_demuxer = |
520 { | |
1584 | 521 "x11grab", |
522 "X11grab", | |
1586 | 523 sizeof(x11_grab_t), |
1584 | 524 NULL, |
525 x11grab_read_header, | |
526 x11grab_read_packet, | |
527 x11grab_read_close, | |
528 .flags = AVFMT_NOFILE, | |
1580
32bfc91cb541
Original X11 device demuxer patch from Clemens Fruhwirth
gpoirier
parents:
1579
diff
changeset
|
529 }; |