Statistics
| Branch: | Revision:

ffmpeg / libavformat / x11grab.c @ 71e445fc

History | View | Annotate | Download (16.7 KB)

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