comparison x11grab.c @ 1584:33997fca4b0d libavformat

RFC 3&4 stage: FFmpeg style aint't my style - Tabs are 4 width - No tabs allowed (patch by Edouard Gomez)
author gpoirier
date Wed, 13 Dec 2006 08:48:56 +0000
parents 8c0065795c92
children 14c185883eab
comparison
equal deleted inserted replaced
1583:8c0065795c92 1584:33997fca4b0d
6 * FFmpeg integration: 6 * FFmpeg integration:
7 * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org> 7 * Copyright (C) 2006 Clemens Fruhwirth <clemens@endorphin.org>
8 * Edouard Gomez <ed.gomez@free.fr> 8 * Edouard Gomez <ed.gomez@free.fr>
9 * 9 *
10 * This file contains code from grab.c: 10 * This file contains code from grab.c:
11 * Copyright (c) 2000-2001 Fabrice Bellard 11 * Copyright (c) 2000-2001 Fabrice Bellard
12 * 12 *
13 * This file contains code from the xvidcap project: 13 * This file contains code from the xvidcap project:
14 * Copyright (C) 1997-1998 Rasca, Berlin 14 * Copyright (C) 1997-1998 Rasca, Berlin
15 * 2003-2004 Karl H. Beckers, Frankfurt 15 * 2003-2004 Karl H. Beckers, Frankfurt
16 * 16 *
46 #include <sys/shm.h> 46 #include <sys/shm.h>
47 #include <X11/extensions/XShm.h> 47 #include <X11/extensions/XShm.h>
48 48
49 typedef struct 49 typedef struct
50 { 50 {
51 Display *dpy; 51 Display *dpy;
52 int frame_format; 52 int frame_format;
53 int frame_size; 53 int frame_size;
54 int frame_rate; 54 int frame_rate;
55 int frame_rate_base; 55 int frame_rate_base;
56 int64_t time_frame; 56 int64_t time_frame;
57 57
58 int height; 58 int height;
59 int width; 59 int width;
60 int x_off; 60 int x_off;
61 int y_off; 61 int y_off;
62 XImage *image; 62 XImage *image;
63 int use_shm; 63 int use_shm;
64 XShmSegmentInfo shminfo; 64 XShmSegmentInfo shminfo;
65 int mouse_wanted; 65 int mouse_wanted;
66 } X11Grab; 66 } X11Grab;
67 67
68 static int 68 static int
69 x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) 69 x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
70 { 70 {
71 X11Grab *x11grab = s1->priv_data; 71 X11Grab *x11grab = s1->priv_data;
72 Display *dpy; 72 Display *dpy;
73 AVStream *st = NULL; 73 AVStream *st = NULL;
74 int width, height; 74 int width, height;
75 int frame_rate, frame_rate_base, frame_size; 75 int frame_rate, frame_rate_base, frame_size;
76 int input_pixfmt; 76 int input_pixfmt;
77 XImage *image; 77 XImage *image;
78 int x_off=0; int y_off = 0; 78 int x_off=0; int y_off = 0;
79 int use_shm; 79 int use_shm;
80 80
81 dpy = XOpenDisplay(NULL); 81 dpy = XOpenDisplay(NULL);
82 if(!dpy) { 82 if(!dpy) {
83 goto fail; 83 goto fail;
84 } 84 }
85 85
86 sscanf(ap->device, "x11:%d,%d", &x_off, &y_off); 86 sscanf(ap->device, "x11:%d,%d", &x_off, &y_off);
87 av_log(s1, AV_LOG_INFO, "device: %s -> x: %d y: %d width: %d height: %d\n", ap->device, x_off, y_off, ap->width, ap->height); 87 av_log(s1, AV_LOG_INFO, "device: %s -> x: %d y: %d width: %d height: %d\n", ap->device, x_off, y_off, ap->width, ap->height);
88 88
89 if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { 89 if (!ap || ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
90 av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n"); 90 av_log(s1, AV_LOG_ERROR, "AVParameters don't have any video size. Use -s.\n");
91 return AVERROR_IO; 91 return AVERROR_IO;
92 } 92 }
93 93
94 width = ap->width; 94 width = ap->width;
95 height = ap->height; 95 height = ap->height;
96 frame_rate = ap->time_base.den; 96 frame_rate = ap->time_base.den;
97 frame_rate_base = ap->time_base.num; 97 frame_rate_base = ap->time_base.num;
98 98
99 st = av_new_stream(s1, 0); 99 st = av_new_stream(s1, 0);
100 if (!st) { 100 if (!st) {
101 return -ENOMEM; 101 return -ENOMEM;
102 } 102 }
103 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ 103 av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
104 104
105 use_shm = XShmQueryExtension(dpy); 105 use_shm = XShmQueryExtension(dpy);
106 av_log(s1, AV_LOG_INFO, "shared memory extension %s\n", use_shm ? "found" : "not found"); 106 av_log(s1, AV_LOG_INFO, "shared memory extension %s\n", use_shm ? "found" : "not found");
107 107
108 if(use_shm) { 108 if(use_shm) {
109 int scr = XDefaultScreen(dpy); 109 int scr = XDefaultScreen(dpy);
110 image = XShmCreateImage(dpy, 110 image = XShmCreateImage(dpy,
111 DefaultVisual(dpy, scr), 111 DefaultVisual(dpy, scr),
112 DefaultDepth(dpy, scr), 112 DefaultDepth(dpy, scr),
113 ZPixmap, 113 ZPixmap,
114 NULL, 114 NULL,
115 &x11grab->shminfo, 115 &x11grab->shminfo,
116 ap->width, ap->height); 116 ap->width, ap->height);
117 x11grab->shminfo.shmid = shmget(IPC_PRIVATE, 117 x11grab->shminfo.shmid = shmget(IPC_PRIVATE,
118 image->bytes_per_line * image->height, 118 image->bytes_per_line * image->height,
119 IPC_CREAT|0777); 119 IPC_CREAT|0777);
120 if (x11grab->shminfo.shmid == -1) { 120 if (x11grab->shminfo.shmid == -1) {
121 av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); 121 av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n");
122 return -ENOMEM; 122 return -ENOMEM;
123 } 123 }
124 x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); 124 x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0);
125 x11grab->shminfo.readOnly = False; 125 x11grab->shminfo.readOnly = False;
126 126
127 if (!XShmAttach(dpy, &x11grab->shminfo)) { 127 if (!XShmAttach(dpy, &x11grab->shminfo)) {
128 av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); 128 av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n");
129 /* needs some better error subroutine :) */ 129 /* needs some better error subroutine :) */
130 return AVERROR_IO; 130 return AVERROR_IO;
131 } 131 }
132 } else { 132 } else {
133 image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), 133 image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)),
134 x_off,y_off, 134 x_off,y_off,
135 ap->width,ap->height, 135 ap->width,ap->height,
136 AllPlanes, ZPixmap); 136 AllPlanes, ZPixmap);
137 } 137 }
138 138
139 switch (image->bits_per_pixel) { 139 switch (image->bits_per_pixel) {
140 case 8: 140 case 8:
141 av_log (s1, AV_LOG_DEBUG, "8 bit pallete\n"); 141 av_log (s1, AV_LOG_DEBUG, "8 bit pallete\n");
142 input_pixfmt = PIX_FMT_PAL8; 142 input_pixfmt = PIX_FMT_PAL8;
143 break; 143 break;
144 case 16: 144 case 16:
145 if ( image->red_mask == 0xF800 && image->green_mask == 0x07E0 145 if ( image->red_mask == 0xF800 && image->green_mask == 0x07E0
146 && image->blue_mask == 0x1F ) { 146 && image->blue_mask == 0x1F ) {
147 av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); 147 av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n");
148 input_pixfmt = PIX_FMT_RGB565; 148 input_pixfmt = PIX_FMT_RGB565;
149 } else if ( image->red_mask == 0x7C00 && 149 } else if ( image->red_mask == 0x7C00 &&
150 image->green_mask == 0x03E0 && 150 image->green_mask == 0x03E0 &&
151 image->blue_mask == 0x1F ) { 151 image->blue_mask == 0x1F ) {
152 av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); 152 av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n");
153 input_pixfmt = PIX_FMT_RGB555; 153 input_pixfmt = PIX_FMT_RGB555;
154 } else { 154 } else {
155 av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); 155 av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
156 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); 156 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);
157 return AVERROR_IO; 157 return AVERROR_IO;
158 } 158 }
159 break; 159 break;
160 case 24: 160 case 24:
161 if ( image->red_mask == 0xFF0000 && 161 if ( image->red_mask == 0xFF0000 &&
162 image->green_mask == 0xFF00 162 image->green_mask == 0xFF00
163 && image->blue_mask == 0xFF ) { 163 && image->blue_mask == 0xFF ) {
164 input_pixfmt = PIX_FMT_BGR24; 164 input_pixfmt = PIX_FMT_BGR24;
165 } else if ( image->red_mask == 0xFF && image->green_mask == 0xFF00 165 } else if ( image->red_mask == 0xFF && image->green_mask == 0xFF00
166 && image->blue_mask == 0xFF0000 ) { 166 && image->blue_mask == 0xFF0000 ) {
167 input_pixfmt = PIX_FMT_RGB24; 167 input_pixfmt = PIX_FMT_RGB24;
168 } else { 168 } else {
169 av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); 169 av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel);
170 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); 170 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);
171 return AVERROR_IO; 171 return AVERROR_IO;
172 } 172 }
173 break; 173 break;
174 case 32: 174 case 32:
175 #if 0 175 #if 0
176 GetColorInfo (image, &c_info); 176 GetColorInfo (image, &c_info);
177 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) { 177 if ( c_info.alpha_mask == 0xFF000000 && image->green_mask == 0xFF00 ) {
178 /* byte order is relevant here, not endianness 178 /* byte order is relevant here, not endianness
179 * endianness is handled by avcodec, but atm no such thing 179 * endianness is handled by avcodec, but atm no such thing
180 * as having ABGR, instead of ARGB in a word. Since we 180 * as having ABGR, instead of ARGB in a word. Since we
181 * need this for Solaris/SPARC, but need to do the conversion 181 * need this for Solaris/SPARC, but need to do the conversion
182 * for every frame we do it outside of this loop, cf. below 182 * for every frame we do it outside of this loop, cf. below
183 * this matches both ARGB32 and ABGR32 */ 183 * this matches both ARGB32 and ABGR32 */
184 input_pixfmt = PIX_FMT_ARGB32; 184 input_pixfmt = PIX_FMT_ARGB32;
185 } else { 185 } else {
186 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); 186 av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel);
187 return AVERROR_IO; 187 return AVERROR_IO;
188 } 188 }
189 #endif 189 #endif
190 input_pixfmt = PIX_FMT_RGBA32; 190 input_pixfmt = PIX_FMT_RGBA32;
191 break; 191 break;
192 default: 192 default:
193 av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); 193 av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel);
194 return -1; 194 return -1;
195 } 195 }
196 196
197 frame_size = width * height * image->bits_per_pixel/8; 197 frame_size = width * height * image->bits_per_pixel/8;
198 x11grab->frame_size = frame_size; 198 x11grab->frame_size = frame_size;
199 x11grab->dpy = dpy; 199 x11grab->dpy = dpy;
200 x11grab->width = ap->width; 200 x11grab->width = ap->width;
201 x11grab->height = ap->height; 201 x11grab->height = ap->height;
202 x11grab->frame_rate = frame_rate; 202 x11grab->frame_rate = frame_rate;
203 x11grab->frame_rate_base = frame_rate_base; 203 x11grab->frame_rate_base = frame_rate_base;
204 x11grab->time_frame = av_gettime() * frame_rate / frame_rate_base; 204 x11grab->time_frame = av_gettime() * frame_rate / frame_rate_base;
205 x11grab->x_off = x_off; 205 x11grab->x_off = x_off;
206 x11grab->y_off = y_off; 206 x11grab->y_off = y_off;
207 x11grab->image = image; 207 x11grab->image = image;
208 x11grab->use_shm = use_shm; 208 x11grab->use_shm = use_shm;
209 x11grab->mouse_wanted = 1; 209 x11grab->mouse_wanted = 1;
210 210
211 st->codec->codec_type = CODEC_TYPE_VIDEO; 211 st->codec->codec_type = CODEC_TYPE_VIDEO;
212 st->codec->codec_id = CODEC_ID_RAWVIDEO; 212 st->codec->codec_id = CODEC_ID_RAWVIDEO;
213 st->codec->width = width; 213 st->codec->width = width;
214 st->codec->height = height; 214 st->codec->height = height;
215 st->codec->pix_fmt = input_pixfmt; 215 st->codec->pix_fmt = input_pixfmt;
216 st->codec->time_base.den = frame_rate; 216 st->codec->time_base.den = frame_rate;
217 st->codec->time_base.num = frame_rate_base; 217 st->codec->time_base.num = frame_rate_base;
218 st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8; 218 st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8;
219 219
220 return 0; 220 return 0;
221 fail: 221 fail:
222 av_free(st); 222 av_free(st);
223 return AVERROR_IO; 223 return AVERROR_IO;
224 } 224 }
225 225
226 static void 226 static void
227 getCurrentPointer(AVFormatContext *s1, X11Grab *s, int *x, int *y) 227 getCurrentPointer(AVFormatContext *s1, X11Grab *s, int *x, int *y)
228 { 228 {
229 Window mrootwindow, childwindow; 229 Window mrootwindow, childwindow;
230 int dummy; 230 int dummy;
231 Display *dpy = s->dpy; 231 Display *dpy = s->dpy;
232 232
233 mrootwindow = DefaultRootWindow(dpy); 233 mrootwindow = DefaultRootWindow(dpy);
234 234
235 if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, 235 if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow,
236 x, y, &dummy, &dummy, (unsigned int*)&dummy)) { 236 x, y, &dummy, &dummy, (unsigned int*)&dummy)) {
237 } else { 237 } else {
238 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); 238 av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n");
239 *x = -1; 239 *x = -1;
240 *y = -1; 240 *y = -1;
241 } 241 }
242 } 242 }
243 243
244 #define DRAW_CURSOR_TEMPLATE(type_t) \ 244 #define DRAW_CURSOR_TEMPLATE(type_t) \
245 do { \ 245 do { \
246 type_t *cursor; \ 246 type_t *cursor; \
247 int width_cursor; \ 247 int width_cursor; \
248 uint16_t bm_b, bm_w, mask; \ 248 uint16_t bm_b, bm_w, mask; \
249 \ 249 \
250 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { \ 250 for (line = 0; line < min(20, (y_off + height) - *y); line++ ) { \
251 if (s->mouse_wanted == 1) { \ 251 if (s->mouse_wanted == 1) { \
252 bm_b = mousePointerBlack[line]; \ 252 bm_b = mousePointerBlack[line]; \
253 bm_w = mousePointerWhite[line]; \ 253 bm_w = mousePointerWhite[line]; \
254 } else { \ 254 } else { \
255 bm_b = mousePointerWhite[line]; \ 255 bm_b = mousePointerWhite[line]; \
256 bm_w = mousePointerBlack[line]; \ 256 bm_w = mousePointerBlack[line]; \
257 } \ 257 } \
258 mask = ( 0x0001 << 15 ); \ 258 mask = ( 0x0001 << 15 ); \
259 \ 259 \
260 for (cursor = (type_t*) im_data, width_cursor = 0; \ 260 for (cursor = (type_t*) im_data, width_cursor = 0; \
261 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); \ 261 ((width_cursor + *x) < (width + x_off) && width_cursor < 16); \
262 cursor++, width_cursor++) { \ 262 cursor++, width_cursor++) { \
263 if ( ( bm_b & mask ) > 0 ) { \ 263 if ( ( bm_b & mask ) > 0 ) { \
264 *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~image->blue_mask )); \ 264 *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~image->blue_mask )); \
265 } else if ( ( bm_w & mask ) > 0 ) { \ 265 } else if ( ( bm_w & mask ) > 0 ) { \
266 *cursor |= (image->red_mask | image->green_mask | image->blue_mask ); \ 266 *cursor |= (image->red_mask | image->green_mask | image->blue_mask ); \
267 } \ 267 } \
268 mask >>= 1; \ 268 mask >>= 1; \
269 } \ 269 } \
270 im_data += image->bytes_per_line; \ 270 im_data += image->bytes_per_line; \
271 } \ 271 } \
272 } while (0) 272 } while (0)
273 273
274 static void 274 static void
275 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image) 275 paintMousePointer(AVFormatContext *s1, X11Grab *s, int *x, int *y, XImage *image)
276 { 276 {
277 static const uint16_t const mousePointerBlack[] = 277 static const uint16_t const mousePointerBlack[] =
278 { 278 {
279 0, 49152, 40960, 36864, 34816, 279 0, 49152, 40960, 36864, 34816,
280 33792, 33280, 33024, 32896, 32832, 280 33792, 33280, 33024, 32896, 32832,
281 33728, 37376, 43264, 51456, 1152, 281 33728, 37376, 43264, 51456, 1152,
282 1152, 576, 576, 448, 0 282 1152, 576, 576, 448, 0
283 }; 283 };
284 284
285 static const uint16_t const mousePointerWhite[] = 285 static const uint16_t const mousePointerWhite[] =
286 { 286 {
287 0, 0, 16384, 24576, 28672, 287 0, 0, 16384, 24576, 28672,
288 30720, 31744, 32256, 32512, 32640, 288 30720, 31744, 32256, 32512, 32640,
289 31744, 27648, 17920, 1536, 768, 289 31744, 27648, 17920, 1536, 768,
290 768, 384, 384, 0, 0 290 768, 384, 384, 0, 0
291 }; 291 };
292 292
293 int x_off = s->x_off; 293 int x_off = s->x_off;
294 int y_off = s->y_off; 294 int y_off = s->y_off;
295 int width = s->width; 295 int width = s->width;
296 int height = s->height; 296 int height = s->height;
297 297
298 if ( (*x - x_off) >= 0 && *x < (width + x_off) 298 if ( (*x - x_off) >= 0 && *x < (width + x_off)
299 && (*y - y_off) >= 0 && *y < (height + y_off) ) { 299 && (*y - y_off) >= 0 && *y < (height + y_off) ) {
300 int line; 300 int line;
301 uint8_t *im_data = (uint8_t*)image->data; 301 uint8_t *im_data = (uint8_t*)image->data;
302 302
303 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line 303 im_data += (image->bytes_per_line * (*y - y_off)); // shift to right line
304 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel 304 im_data += (image->bits_per_pixel / 8 * (*x - x_off)); // shift to right pixel
305 305
306 switch(image->bits_per_pixel) { 306 switch(image->bits_per_pixel) {
307 case 32: 307 case 32:
308 DRAW_CURSOR_TEMPLATE(uint32_t); 308 DRAW_CURSOR_TEMPLATE(uint32_t);
309 break; 309 break;
310 case 16: 310 case 16:
311 DRAW_CURSOR_TEMPLATE(uint16_t); 311 DRAW_CURSOR_TEMPLATE(uint16_t);
312 break; 312 break;
313 default: 313 default:
314 /* XXX: How do we deal with 24bit and 8bit modes ? */ 314 /* XXX: How do we deal with 24bit and 8bit modes ? */
315 break; 315 break;
316 } 316 }
317 } 317 }
318 } 318 }
319 319
320 320
321 /* 321 /*
322 * just read new data in the image structure, the image 322 * just read new data in the image structure, the image
323 * structure inclusive the data area must be allocated before 323 * structure inclusive the data area must be allocated before
324 */ 324 */
325 static int 325 static int
326 XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) 326 XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
327 { 327 {
328 xGetImageReply rep; 328 xGetImageReply rep;
329 xGetImageReq *req; 329 xGetImageReq *req;
330 long nbytes; 330 long nbytes;
331 331
332 if (!image) { 332 if (!image) {
333 return False; 333 return False;
334 } 334 }
335 335
336 LockDisplay(dpy); 336 LockDisplay(dpy);
337 GetReq(GetImage, req); 337 GetReq(GetImage, req);
338 338
339 /* First set up the standard stuff in the request */ 339 /* First set up the standard stuff in the request */
340 req->drawable = d; 340 req->drawable = d;
341 req->x = x; 341 req->x = x;
342 req->y = y; 342 req->y = y;
343 req->width = image->width; 343 req->width = image->width;
344 req->height = image->height; 344 req->height = image->height;
345 req->planeMask = (unsigned int)AllPlanes; 345 req->planeMask = (unsigned int)AllPlanes;
346 req->format = ZPixmap; 346 req->format = ZPixmap;
347 347
348 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.length) { 348 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.length) {
349 UnlockDisplay(dpy); 349 UnlockDisplay(dpy);
350 SyncHandle(); 350 SyncHandle();
351 return False; 351 return False;
352 } 352 }
353 353
354 nbytes = (long)rep.length << 2; 354 nbytes = (long)rep.length << 2;
355 _XReadPad(dpy, image->data, nbytes); 355 _XReadPad(dpy, image->data, nbytes);
356 356
357 UnlockDisplay(dpy); 357 UnlockDisplay(dpy);
358 SyncHandle(); 358 SyncHandle();
359 return True; 359 return True;
360 } 360 }
361 361
362 static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) 362 static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
363 { 363 {
364 X11Grab *s = s1->priv_data; 364 X11Grab *s = s1->priv_data;
365 Display *dpy = s->dpy; 365 Display *dpy = s->dpy;
366 XImage *image = s->image; 366 XImage *image = s->image;
367 int x_off = s->x_off; 367 int x_off = s->x_off;
368 int y_off = s->y_off; 368 int y_off = s->y_off;
369 369
370 int64_t curtime, delay; 370 int64_t curtime, delay;
371 struct timespec ts; 371 struct timespec ts;
372 372
373 /* Calculate the time of the next frame */ 373 /* Calculate the time of the next frame */
374 s->time_frame += int64_t_C(1000000); 374 s->time_frame += int64_t_C(1000000);
375 375
376 /* wait based on the frame rate */ 376 /* wait based on the frame rate */
377 for(;;) { 377 for(;;) {
378 curtime = av_gettime(); 378 curtime = av_gettime();
379 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; 379 delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime;
380 if (delay <= 0) { 380 if (delay <= 0) {
381 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { 381 if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) {
382 s->time_frame += int64_t_C(1000000); 382 s->time_frame += int64_t_C(1000000);
383 } 383 }
384 break; 384 break;
385 } 385 }
386 ts.tv_sec = delay / 1000000; 386 ts.tv_sec = delay / 1000000;
387 ts.tv_nsec = (delay % 1000000) * 1000; 387 ts.tv_nsec = (delay % 1000000) * 1000;
388 nanosleep(&ts, NULL); 388 nanosleep(&ts, NULL);
389 } 389 }
390 390
391 if (av_new_packet(pkt, s->frame_size) < 0) { 391 if (av_new_packet(pkt, s->frame_size) < 0) {
392 return AVERROR_IO; 392 return AVERROR_IO;
393 } 393 }
394 394
395 pkt->pts = curtime & ((1LL << 48) - 1); 395 pkt->pts = curtime & ((1LL << 48) - 1);
396 396
397 if(s->use_shm) { 397 if(s->use_shm) {
398 if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { 398 if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) {
399 av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); 399 av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n");
400 } 400 }
401 } else { 401 } else {
402 if (!XGetZPixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { 402 if (!XGetZPixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) {
403 av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); 403 av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n");
404 } 404 }
405 } 405 }
406 406
407 { 407 {
408 int pointer_x, pointer_y; 408 int pointer_x, pointer_y;
409 getCurrentPointer(s1, s, &pointer_x, &pointer_y); 409 getCurrentPointer(s1, s, &pointer_x, &pointer_y);
410 paintMousePointer(s1, s, &pointer_x, &pointer_y, image); 410 paintMousePointer(s1, s, &pointer_x, &pointer_y, image);
411 } 411 }
412 412
413 413
414 /* XXX: avoid memcpy */ 414 /* XXX: avoid memcpy */
415 memcpy(pkt->data, image->data, s->frame_size); 415 memcpy(pkt->data, image->data, s->frame_size);
416 return s->frame_size; 416 return s->frame_size;
417 } 417 }
418 418
419 static int x11grab_read_close(AVFormatContext *s1) 419 static int x11grab_read_close(AVFormatContext *s1)
420 { 420 {
421 X11Grab *x11grab = s1->priv_data; 421 X11Grab *x11grab = s1->priv_data;
422 422
423 /* Detach cleanly from shared mem */ 423 /* Detach cleanly from shared mem */
424 if (x11grab->use_shm) { 424 if (x11grab->use_shm) {
425 XShmDetach(x11grab->dpy, &x11grab->shminfo); 425 XShmDetach(x11grab->dpy, &x11grab->shminfo);
426 shmdt(x11grab->shminfo.shmaddr); 426 shmdt(x11grab->shminfo.shmaddr);
427 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL); 427 shmctl(x11grab->shminfo.shmid, IPC_RMID, NULL);
428 } 428 }
429 429
430 /* Destroy X11 image */ 430 /* Destroy X11 image */
431 if (x11grab->image) { 431 if (x11grab->image) {
432 XDestroyImage(x11grab->image); 432 XDestroyImage(x11grab->image);
433 x11grab->image = NULL; 433 x11grab->image = NULL;
434 } 434 }
435 435
436 /* Free X11 display */ 436 /* Free X11 display */
437 XCloseDisplay(x11grab->dpy); 437 XCloseDisplay(x11grab->dpy);
438 return 0; 438 return 0;
439 } 439 }
440 440
441 AVInputFormat x11_grab_device_demuxer = 441 AVInputFormat x11_grab_device_demuxer =
442 { 442 {
443 "x11grab", 443 "x11grab",
444 "X11grab", 444 "X11grab",
445 sizeof(X11Grab), 445 sizeof(X11Grab),
446 NULL, 446 NULL,
447 x11grab_read_header, 447 x11grab_read_header,
448 x11grab_read_packet, 448 x11grab_read_packet,
449 x11grab_read_close, 449 x11grab_read_close,
450 .flags = AVFMT_NOFILE, 450 .flags = AVFMT_NOFILE,
451 }; 451 };