Statistics
| Branch: | Revision:

ffmpeg / libavformat / x11grab.c @ 756fb7fe

History | View | Annotate | Download (16.5 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 cc58300e Ramiro Polla
    param = av_strdup(s1->filename);
101 0cd4faf9 Panagiotis Issaris
    offset = strchr(param, '+');
102
    if (offset) {
103
        sscanf(offset, "%d,%d", &x_off, &y_off);
104
        *offset= 0;
105
    }
106
107 cc58300e Ramiro Polla
    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);
108 0cd4faf9 Panagiotis Issaris
109
    dpy = XOpenDisplay(param);
110
    if(!dpy) {
111
        av_log(s1, AV_LOG_ERROR, "Could not open X display.\n");
112
        return AVERROR_IO;
113
    }
114 aac105fc Edouard Gomez
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) {
122 8fa36ae0 Fran├žois Revol
        return AVERROR(ENOMEM);
123 aac105fc Edouard Gomez
    }
124
    av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
125
126
    use_shm = XShmQueryExtension(dpy);
127 6e71a18e Edouard Gomez
    av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ? "" : "not");
128 aac105fc Edouard Gomez
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");
143 8fa36ae0 Fran├žois Revol
            return AVERROR(ENOMEM);
144 aac105fc Edouard Gomez
        }
145
        x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0);
146
        x11grab->shminfo.readOnly = False;
147
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
    }
159
160
    switch (image->bits_per_pixel) {
161
    case 8:
162 6187b8bd Diego Biurrun
        av_log (s1, AV_LOG_DEBUG, "8 bit palette\n");
163 aac105fc Edouard Gomez
        input_pixfmt = PIX_FMT_PAL8;
164
        break;
165
    case 16:
166 6e71a18e Edouard Gomez
        if (       image->red_mask   == 0xf800 &&
167
                   image->green_mask == 0x07e0 &&
168
                   image->blue_mask  == 0x001f ) {
169 aac105fc Edouard Gomez
            av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n");
170
            input_pixfmt = PIX_FMT_RGB565;
171 6e71a18e Edouard Gomez
        } else if (image->red_mask   == 0x7c00 &&
172
                   image->green_mask == 0x03e0 &&
173
                   image->blue_mask  == 0x001f ) {
174 aac105fc Edouard Gomez
            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:
183 6e71a18e Edouard Gomez
        if (        image->red_mask   == 0xff0000 &&
184
                    image->green_mask == 0x00ff00 &&
185
                    image->blue_mask  == 0x0000ff ) {
186 aac105fc Edouard Gomez
            input_pixfmt = PIX_FMT_BGR24;
187 6e71a18e Edouard Gomez
        } else if ( image->red_mask   == 0x0000ff &&
188
                    image->green_mask == 0x00ff00 &&
189
                    image->blue_mask  == 0xff0000 ) {
190 aac105fc Edouard Gomez
            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:
198 f58f4ce1 Guillaume Poirier
#if 0
199 aac105fc Edouard Gomez
        GetColorInfo (image, &c_info);
200 6e71a18e Edouard Gomez
        if ( c_info.alpha_mask == 0xff000000 && image->green_mask == 0x0000ff00) {
201 aac105fc Edouard Gomez
            /* 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
        }
212 f58f4ce1 Guillaume Poirier
#endif
213 71e445fc Diego Biurrun
        input_pixfmt = PIX_FMT_RGB32;
214 aac105fc Edouard Gomez
        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
    }
219
220 6e71a18e Edouard Gomez
    x11grab->frame_size = ap->width * ap->height * image->bits_per_pixel/8;
221 aac105fc Edouard Gomez
    x11grab->dpy = dpy;
222
    x11grab->width = ap->width;
223
    x11grab->height = ap->height;
224 6e71a18e Edouard Gomez
    x11grab->time_base  = ap->time_base;
225
    x11grab->time_frame = av_gettime() / av_q2d(ap->time_base);
226 aac105fc Edouard Gomez
    x11grab->x_off = x_off;
227
    x11grab->y_off = y_off;
228
    x11grab->image = image;
229
    x11grab->use_shm = use_shm;
230 ca454440 Panagiotis Issaris
    x11grab->mouse_warning_shown = 0;
231 aac105fc Edouard Gomez
232
    st->codec->codec_type = CODEC_TYPE_VIDEO;
233
    st->codec->codec_id = CODEC_ID_RAWVIDEO;
234 6e71a18e Edouard Gomez
    st->codec->width = ap->width;
235
    st->codec->height = ap->height;
236 aac105fc Edouard Gomez
    st->codec->pix_fmt = input_pixfmt;
237 6e71a18e Edouard Gomez
    st->codec->time_base = ap->time_base;
238
    st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(ap->time_base) * 8;
239 aac105fc Edouard Gomez
240
    return 0;
241 f58f4ce1 Guillaume Poirier
}
242
243 6e71a18e Edouard Gomez
/**
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
 */
251 2909f177 Edouard Gomez
static void
252 6e71a18e Edouard Gomez
get_pointer_coordinates(int *x, int *y, Display *dpy, AVFormatContext *s1)
253 2909f177 Edouard Gomez
{
254 aac105fc Edouard Gomez
    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 {
262 ca454440 Panagiotis Issaris
        x11_grab_t *s = s1->priv_data;
263
        if (!s->mouse_warning_shown) {
264
            av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n");
265
            s->mouse_warning_shown = 1;
266
        }
267 aac105fc Edouard Gomez
        *x = -1;
268
        *y = -1;
269
    }
270 f58f4ce1 Guillaume Poirier
}
271
272 6e71a18e Edouard Gomez
/**
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
 */
283 0235a311 Edouard Gomez
static void inline
284
apply_masks(uint8_t *dst, int and, int or, int bits_per_pixel)
285
{
286
    switch (bits_per_pixel) {
287
    case 32:
288
        *(uint32_t*)dst = (*(uint32_t*)dst & and) | or;
289
        break;
290
    case 16:
291
        *(uint16_t*)dst = (*(uint16_t*)dst & and) | or;
292
        break;
293
    case 8:
294 6e71a18e Edouard Gomez
        *dst = !!or;
295 0235a311 Edouard Gomez
        break;
296
    }
297
}
298 65a1c656 Edouard Gomez
299 6e71a18e Edouard Gomez
/**
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
 */
308 2909f177 Edouard Gomez
static void
309 6e71a18e Edouard Gomez
paint_mouse_pointer(XImage *image, x11_grab_t *s, int x, int y)
310 2909f177 Edouard Gomez
{
311 6e71a18e Edouard Gomez
    /* 16x20x1bpp bitmap for the black channel of the mouse pointer */
312 aac105fc Edouard Gomez
    static const uint16_t const mousePointerBlack[] =
313
        {
314 bd839338 Edouard Gomez
            0x0000, 0x0003, 0x0005, 0x0009, 0x0011,
315
            0x0021, 0x0041, 0x0081, 0x0101, 0x0201,
316
            0x03c1, 0x0049, 0x0095, 0x0093, 0x0120,
317
            0x0120, 0x0240, 0x0240, 0x0380, 0x0000
318 aac105fc Edouard Gomez
        };
319
320 6e71a18e Edouard Gomez
    /* 16x20x1bpp bitmap for the white channel of the mouse pointer */
321 aac105fc Edouard Gomez
    static const uint16_t const mousePointerWhite[] =
322
        {
323 bd839338 Edouard Gomez
            0x0000, 0x0000, 0x0002, 0x0006, 0x000e,
324
            0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe,
325
            0x003e, 0x0036, 0x0062, 0x0060, 0x00c0,
326
            0x00c0, 0x0180, 0x0180, 0x0000, 0x0000
327 aac105fc Edouard Gomez
        };
328
329
    int x_off = s->x_off;
330
    int y_off = s->y_off;
331
    int width = s->width;
332
    int height = s->height;
333
334 6e71a18e Edouard Gomez
    if (   x - x_off >= 0 && x < width + x_off
335
        && y - y_off >= 0 && y < height + y_off) {
336 aac105fc Edouard Gomez
        uint8_t *im_data = (uint8_t*)image->data;
337 6e71a18e Edouard Gomez
        int bytes_per_pixel;
338
        int line;
339 0235a311 Edouard Gomez
        int masks;
340 aac105fc Edouard Gomez
341 0235a311 Edouard Gomez
        /* Select correct masks and pixel size */
342 6e71a18e Edouard Gomez
        if (image->bits_per_pixel == 8) {
343 0235a311 Edouard Gomez
            masks = 1;
344 6e71a18e Edouard Gomez
        } else {
345
            masks = (image->red_mask|image->green_mask|image->blue_mask);
346 0235a311 Edouard Gomez
        }
347 6e71a18e Edouard Gomez
        bytes_per_pixel = image->bits_per_pixel>>3;
348 0235a311 Edouard Gomez
349
        /* Shift to right line */
350 6e71a18e Edouard Gomez
        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);
353 0235a311 Edouard Gomez
354
        /* Draw the cursor - proper loop */
355 6e71a18e Edouard Gomez
        for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) {
356 0235a311 Edouard Gomez
            uint8_t *cursor = im_data;
357 6e71a18e Edouard Gomez
            int column;
358 0235a311 Edouard Gomez
            uint16_t bm_b;
359
            uint16_t bm_w;
360
361 6e71a18e Edouard Gomez
            bm_b = mousePointerBlack[line];
362
            bm_w = mousePointerWhite[line];
363 0235a311 Edouard Gomez
364 6e71a18e Edouard Gomez
            for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) {
365
                apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1),
366 0235a311 Edouard Gomez
                            image->bits_per_pixel);
367 6e71a18e Edouard Gomez
                cursor += bytes_per_pixel;
368 0235a311 Edouard Gomez
                bm_b >>= 1;
369
                bm_w >>= 1;
370
            }
371
            im_data += image->bytes_per_line;
372 aac105fc Edouard Gomez
        }
373
    }
374 f58f4ce1 Guillaume Poirier
}
375
376
377 6e71a18e Edouard Gomez
/**
378
 * Reads new data in the image structure.
379
 *
380
 * @param dpy X11 display to grab from
381 05f3b6ab Guillaume Poirier
 * @param d
382 6e71a18e Edouard Gomez
 * @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
386 f58f4ce1 Guillaume Poirier
 */
387
static int
388 6e71a18e Edouard Gomez
xget_zpixmap(Display *dpy, Drawable d, XImage *image, int x, int y)
389 f58f4ce1 Guillaume Poirier
{
390 aac105fc Edouard Gomez
    xGetImageReply rep;
391
    xGetImageReq *req;
392
    long nbytes;
393
394
    if (!image) {
395 6e71a18e Edouard Gomez
        return 0;
396 aac105fc Edouard Gomez
    }
397
398
    LockDisplay(dpy);
399
    GetReq(GetImage, req);
400
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
410 6e71a18e Edouard Gomez
    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
411 aac105fc Edouard Gomez
        UnlockDisplay(dpy);
412
        SyncHandle();
413 6e71a18e Edouard Gomez
        return 0;
414 aac105fc Edouard Gomez
    }
415
416
    nbytes = (long)rep.length << 2;
417
    _XReadPad(dpy, image->data, nbytes);
418
419
    UnlockDisplay(dpy);
420
    SyncHandle();
421 6e71a18e Edouard Gomez
    return 1;
422 f58f4ce1 Guillaume Poirier
}
423
424 6e71a18e Edouard Gomez
/**
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
 */
431 0235a311 Edouard Gomez
static int
432
x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
433 f58f4ce1 Guillaume Poirier
{
434 6e71a18e Edouard Gomez
    x11_grab_t *s = s1->priv_data;
435 aac105fc Edouard Gomez
    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 */
444 ba78f9d4 Baptiste Coudurier
    s->time_frame += INT64_C(1000000);
445 aac105fc Edouard Gomez
446
    /* wait based on the frame rate */
447
    for(;;) {
448
        curtime = av_gettime();
449 6e71a18e Edouard Gomez
        delay = s->time_frame * av_q2d(s->time_base) - curtime;
450 aac105fc Edouard Gomez
        if (delay <= 0) {
451 ba78f9d4 Baptiste Coudurier
            if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) {
452
                s->time_frame += INT64_C(1000000);
453 aac105fc Edouard Gomez
            }
454
            break;
455
        }
456
        ts.tv_sec = delay / 1000000;
457
        ts.tv_nsec = (delay % 1000000) * 1000;
458
        nanosleep(&ts, NULL);
459
    }
460
461
    if (av_new_packet(pkt, s->frame_size) < 0) {
462
        return AVERROR_IO;
463
    }
464
465 6e71a18e Edouard Gomez
    pkt->pts = curtime;
466 aac105fc Edouard Gomez
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 {
472 6e71a18e Edouard Gomez
        if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) {
473 aac105fc Edouard Gomez
            av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n");
474
        }
475
    }
476
477
    {
478
        int pointer_x, pointer_y;
479 6e71a18e Edouard Gomez
        get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1);
480
        paint_mouse_pointer(image, s, pointer_x, pointer_y);
481 aac105fc Edouard Gomez
    }
482
483
484
    /* XXX: avoid memcpy */
485
    memcpy(pkt->data, image->data, s->frame_size);
486
    return s->frame_size;
487 f58f4ce1 Guillaume Poirier
}
488
489 6e71a18e Edouard Gomez
/**
490
 * Closes x11 frame grabber (public device demuxer API).
491
 *
492
 * @param s1 Context from avformat core
493
 * @return 0 success, !0 failure
494
 */
495 0235a311 Edouard Gomez
static int
496
x11grab_read_close(AVFormatContext *s1)
497 f58f4ce1 Guillaume Poirier
{
498 6e71a18e Edouard Gomez
    x11_grab_t *x11grab = s1->priv_data;
499 aac105fc Edouard Gomez
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
    }
506
507
    /* Destroy X11 image */
508
    if (x11grab->image) {
509
        XDestroyImage(x11grab->image);
510
        x11grab->image = NULL;
511
    }
512
513
    /* Free X11 display */
514
    XCloseDisplay(x11grab->dpy);
515
    return 0;
516 f58f4ce1 Guillaume Poirier
}
517
518 6e71a18e Edouard Gomez
/** x11 grabber device demuxer declaration */
519 2909f177 Edouard Gomez
AVInputFormat x11_grab_device_demuxer =
520
{
521 aac105fc Edouard Gomez
    "x11grab",
522
    "X11grab",
523 6e71a18e Edouard Gomez
    sizeof(x11_grab_t),
524 aac105fc Edouard Gomez
    NULL,
525
    x11grab_read_header,
526
    x11grab_read_packet,
527
    x11grab_read_close,
528
    .flags = AVFMT_NOFILE,
529 f58f4ce1 Guillaume Poirier
};