~ubuntu-branches/ubuntu/precise/vlc/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/bp-xvideo-color-key-automatic-painting.patch/modules/video_output/xcb/xvideo.c

  • Committer: Package Import Robot
  • Author(s): Benjamin Drung
  • Date: 2011-12-31 13:42:26 UTC
  • mfrom: (3.5.31 sid)
  • Revision ID: package-import@ubuntu.com-20111231134226-nwo5aheq7d03wooa
* New upstream release (Closes: #604687).
* Drop backported patches and patches that were accepted by upstream.
* Refresh remaining patches.
* Add mailcap entry for Ogg Video (Closes: #651662).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * @file xvideo.c
3
 
 * @brief X C Bindings video output module for VLC media player
4
 
 */
5
 
/*****************************************************************************
6
 
 * Copyright © 2009 Rémi Denis-Courmont
7
 
 *
8
 
 * This library is free software; you can redistribute it and/or
9
 
 * modify it under the terms of the GNU General Public License
10
 
 * as published by the Free Software Foundation; either version 2
11
 
 * of the License, or (at your option) any later version.
12
 
 *
13
 
 * This library is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 * GNU General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU General Public
19
 
 * License along with this library; if not, write to the Free Software
20
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
 
 ****************************************************************************/
22
 
 
23
 
#ifdef HAVE_CONFIG_H
24
 
# include <config.h>
25
 
#endif
26
 
 
27
 
#include <stdlib.h>
28
 
#include <assert.h>
29
 
 
30
 
#include <xcb/xcb.h>
31
 
#include <xcb/shm.h>
32
 
#include <xcb/xv.h>
33
 
 
34
 
#include <vlc_common.h>
35
 
#include <vlc_plugin.h>
36
 
#include <vlc_vout_display.h>
37
 
#include <vlc_picture_pool.h>
38
 
#include <vlc_dialog.h>
39
 
 
40
 
#include "xcb_vlc.h"
41
 
 
42
 
#define ADAPTOR_TEXT N_("XVideo adaptor number")
43
 
#define ADAPTOR_LONGTEXT N_( \
44
 
    "XVideo hardware adaptor to use. By default, VLC will " \
45
 
    "use the first functional adaptor.")
46
 
 
47
 
#define SHM_TEXT N_("Use shared memory")
48
 
#define SHM_LONGTEXT N_( \
49
 
    "Use shared memory to communicate between VLC and the X server.")
50
 
 
51
 
static int  Open (vlc_object_t *);
52
 
static void Close (vlc_object_t *);
53
 
 
54
 
/*
55
 
 * Module descriptor
56
 
 */
57
 
vlc_module_begin ()
58
 
    set_shortname (N_("XVideo"))
59
 
    set_description (N_("XVideo output (XCB)"))
60
 
    set_category (CAT_VIDEO)
61
 
    set_subcategory (SUBCAT_VIDEO_VOUT)
62
 
    set_capability ("vout display", 155)
63
 
    set_callbacks (Open, Close)
64
 
 
65
 
    add_integer ("xvideo-adaptor", -1, NULL,
66
 
                 ADAPTOR_TEXT, ADAPTOR_LONGTEXT, true)
67
 
    add_bool ("x11-shm", true, NULL, SHM_TEXT, SHM_LONGTEXT, true)
68
 
        add_deprecated_alias ("xvideo-shm")
69
 
    add_shortcut ("xcb-xv")
70
 
    add_shortcut ("xv")
71
 
    add_shortcut ("xvideo")
72
 
vlc_module_end ()
73
 
 
74
 
#define MAX_PICTURES (VOUT_MAX_PICTURES)
75
 
 
76
 
struct vout_display_sys_t
77
 
{
78
 
    xcb_connection_t *conn;
79
 
    vout_window_t *embed;/* VLC window */
80
 
 
81
 
    xcb_cursor_t cursor; /* blank cursor */
82
 
    xcb_window_t window; /* drawable X window */
83
 
    xcb_gcontext_t gc;   /* context to put images */
84
 
    xcb_xv_port_t port;  /* XVideo port */
85
 
    uint32_t id;         /* XVideo format */
86
 
    uint16_t width;      /* display width */
87
 
    uint16_t height;     /* display height */
88
 
    uint32_t data_size;  /* picture byte size (for non-SHM) */
89
 
    bool     swap_uv;    /* U/V pointer must be swapped in a picture */
90
 
    bool shm;            /* whether to use MIT-SHM */
91
 
    bool visible;        /* whether it makes sense to draw at all */
92
 
 
93
 
    xcb_xv_query_image_attributes_reply_t *att;
94
 
    picture_pool_t *pool; /* picture pool */
95
 
    picture_resource_t resource[MAX_PICTURES];
96
 
};
97
 
 
98
 
static picture_pool_t *Pool (vout_display_t *, unsigned);
99
 
static void Display (vout_display_t *, picture_t *);
100
 
static int Control (vout_display_t *, int, va_list);
101
 
static void Manage (vout_display_t *);
102
 
 
103
 
/**
104
 
 * Check that the X server supports the XVideo extension.
105
 
 */
106
 
static bool CheckXVideo (vout_display_t *vd, xcb_connection_t *conn)
107
 
{
108
 
    xcb_xv_query_extension_reply_t *r;
109
 
    xcb_xv_query_extension_cookie_t ck = xcb_xv_query_extension (conn);
110
 
    bool ok = false;
111
 
 
112
 
    /* We need XVideo 2.2 for PutImage */
113
 
    r = xcb_xv_query_extension_reply (conn, ck, NULL);
114
 
    if (r == NULL)
115
 
        msg_Dbg (vd, "XVideo extension not available");
116
 
    else
117
 
    if (r->major != 2)
118
 
        msg_Dbg (vd, "XVideo extension v%"PRIu8".%"PRIu8" unknown",
119
 
                 r->major, r->minor);
120
 
    else
121
 
    if (r->minor < 2)
122
 
        msg_Dbg (vd, "XVideo extension v%"PRIu8".%"PRIu8" too old",
123
 
                 r->major, r->minor);
124
 
    else
125
 
    {
126
 
        msg_Dbg (vd, "using XVideo extension v%"PRIu8".%"PRIu8,
127
 
                 r->major, r->minor);
128
 
        ok = true;
129
 
    }
130
 
    free (r);
131
 
    return ok;
132
 
}
133
 
 
134
 
static vlc_fourcc_t ParseFormat (vout_display_t *vd,
135
 
                                 const xcb_xv_image_format_info_t *restrict f)
136
 
{
137
 
    if (f->byte_order != ORDER && f->bpp != 8)
138
 
        return 0; /* Argh! */
139
 
 
140
 
    switch (f->type)
141
 
    {
142
 
      case XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB:
143
 
        switch (f->num_planes)
144
 
        {
145
 
          case 1:
146
 
            switch (f->bpp)
147
 
            {
148
 
              case 32:
149
 
                if (f->depth == 24)
150
 
                    return VLC_CODEC_RGB32;
151
 
                if (f->depth == 32)
152
 
                    return 0; /* ARGB -> VLC cannot do that currently */
153
 
                break;
154
 
              case 24:
155
 
                if (f->depth == 24)
156
 
                    return VLC_CODEC_RGB24;
157
 
                break;
158
 
              case 16:
159
 
                if (f->depth == 16)
160
 
                    return VLC_CODEC_RGB16;
161
 
                if (f->depth == 15)
162
 
                    return VLC_CODEC_RGB15;
163
 
                break;
164
 
              case 8:
165
 
                if (f->depth == 8)
166
 
                    return VLC_CODEC_RGB8;
167
 
                break;
168
 
            }
169
 
            break;
170
 
        }
171
 
        msg_Err (vd, "unknown XVideo RGB format %"PRIx32" (%.4s)",
172
 
                 f->id, f->guid);
173
 
        msg_Dbg (vd, " %"PRIu8" planes, %"PRIu8" bits/pixel, "
174
 
                 "depth %"PRIu8, f->num_planes, f->bpp, f->depth);
175
 
        break;
176
 
 
177
 
      case XCB_XV_IMAGE_FORMAT_INFO_TYPE_YUV:
178
 
        if (f->u_sample_bits != f->v_sample_bits
179
 
         || f->vhorz_u_period != f->vhorz_v_period
180
 
         || f->vvert_u_period != f->vvert_v_period
181
 
         || f->y_sample_bits != 8 || f->u_sample_bits != 8
182
 
         || f->vhorz_y_period != 1 || f->vvert_y_period != 1)
183
 
            goto bad;
184
 
        switch (f->num_planes)
185
 
        {
186
 
          case 1:
187
 
            switch (f->bpp)
188
 
            {
189
 
              /*untested: case 24:
190
 
                if (f->vhorz_u_period == 1 && f->vvert_u_period == 1)
191
 
                    return VLC_CODEC_I444;
192
 
                break;*/
193
 
              case 16:
194
 
                if (f->vhorz_u_period == 2 && f->vvert_u_period == 1)
195
 
                {
196
 
                    if (!strcmp ((const char *)f->vcomp_order, "YUYV"))
197
 
                        return VLC_CODEC_YUYV;
198
 
                    if (!strcmp ((const char *)f->vcomp_order, "UYVY"))
199
 
                        return VLC_CODEC_UYVY;
200
 
                }
201
 
                break;
202
 
            }
203
 
            break;
204
 
          case 3:
205
 
            switch (f->bpp)
206
 
            {
207
 
              case 12:
208
 
                if (f->vhorz_u_period == 2 && f->vvert_u_period == 2)
209
 
                {
210
 
                    if (!strcmp ((const char *)f->vcomp_order, "YVU"))
211
 
                        return VLC_CODEC_YV12;
212
 
                    if (!strcmp ((const char *)f->vcomp_order, "YUV"))
213
 
                        return VLC_CODEC_I420;
214
 
                }
215
 
            }
216
 
            break;
217
 
        }
218
 
    bad:
219
 
        msg_Err (vd, "unknown XVideo YUV format %"PRIx32" (%.4s)", f->id,
220
 
                 f->guid);
221
 
        msg_Dbg (vd, " %"PRIu8" planes, %"PRIu32" bits/pixel, "
222
 
                 "%"PRIu32"/%"PRIu32"/%"PRIu32" bits/sample", f->num_planes,
223
 
                 f->bpp, f->y_sample_bits, f->u_sample_bits, f->v_sample_bits);
224
 
        msg_Dbg (vd, " period: %"PRIu32"/%"PRIu32"/%"PRIu32"x"
225
 
                 "%"PRIu32"/%"PRIu32"/%"PRIu32,
226
 
                 f->vhorz_y_period, f->vhorz_u_period, f->vhorz_v_period,
227
 
                 f->vvert_y_period, f->vvert_u_period, f->vvert_v_period);
228
 
        msg_Warn (vd, " order: %.32s", f->vcomp_order);
229
 
        break;
230
 
    }
231
 
    return 0;
232
 
}
233
 
 
234
 
 
235
 
static const xcb_xv_image_format_info_t *
236
 
FindFormat (vout_display_t *vd,
237
 
            vlc_fourcc_t chroma, const video_format_t *fmt,
238
 
            xcb_xv_port_t port,
239
 
            const xcb_xv_list_image_formats_reply_t *list,
240
 
            xcb_xv_query_image_attributes_reply_t **restrict pa)
241
 
{
242
 
    xcb_connection_t *conn = vd->sys->conn;
243
 
    const xcb_xv_image_format_info_t *f, *end;
244
 
 
245
 
#ifndef XCB_XV_OLD
246
 
    f = xcb_xv_list_image_formats_format (list);
247
 
#else
248
 
    f = (xcb_xv_image_format_info_t *) (list + 1);
249
 
#endif
250
 
    end = f + xcb_xv_list_image_formats_format_length (list);
251
 
    for (; f < end; f++)
252
 
    {
253
 
        if (chroma != ParseFormat (vd, f))
254
 
            continue;
255
 
 
256
 
        /* VLC pads scanline to 16 pixels internally */
257
 
        unsigned width = fmt->i_width;
258
 
        unsigned height = fmt->i_height;
259
 
        xcb_xv_query_image_attributes_reply_t *i;
260
 
        i = xcb_xv_query_image_attributes_reply (conn,
261
 
            xcb_xv_query_image_attributes (conn, port, f->id,
262
 
                                           width, height), NULL);
263
 
        if (i == NULL)
264
 
            continue;
265
 
 
266
 
        if (i->width != width || i->height != height)
267
 
        {
268
 
            msg_Warn (vd, "incompatible size %ux%u -> %"PRIu32"x%"PRIu32,
269
 
                      fmt->i_width, fmt->i_height,
270
 
                      i->width, i->height);
271
 
            var_Create (vd->p_libvlc, "xvideo-resolution-error", VLC_VAR_BOOL);
272
 
            if (!var_GetBool (vd->p_libvlc, "xvideo-resolution-error"))
273
 
            {
274
 
                dialog_FatalWait (vd, _("Video acceleration not available"),
275
 
                    _("Your video output acceleration driver does not support "
276
 
                      "the required resolution: %ux%u pixels. The maximum "
277
 
                      "supported resolution is %"PRIu32"x%"PRIu32".\n"
278
 
                      "Video output acceleration will be disabled. However, "
279
 
                      "rendering videos with overly large resolution "
280
 
                      "may cause severe performance degration."),
281
 
                                  width, height, i->width, i->height);
282
 
                var_SetBool (vd->p_libvlc, "xvideo-resolution-error", true);
283
 
            }
284
 
            free (i);
285
 
            continue;
286
 
        }
287
 
        *pa = i;
288
 
        return f;
289
 
    }
290
 
    return NULL;
291
 
}
292
 
 
293
 
 
294
 
/**
295
 
 * Probe the X server.
296
 
 */
297
 
static int Open (vlc_object_t *obj)
298
 
{
299
 
    vout_display_t *vd = (vout_display_t *)obj;
300
 
    vout_display_sys_t *p_sys;
301
 
 
302
 
    if (!var_CreateGetBool (obj, "overlay"))
303
 
        return VLC_EGENERIC;
304
 
    p_sys = malloc (sizeof (*p_sys));
305
 
    if (p_sys == NULL)
306
 
        return VLC_ENOMEM;
307
 
 
308
 
    vd->sys = p_sys;
309
 
 
310
 
    /* Connect to X */
311
 
    xcb_connection_t *conn;
312
 
    const xcb_screen_t *screen;
313
 
    uint8_t depth;
314
 
    p_sys->embed = GetWindow (vd, &conn, &screen, &depth);
315
 
    if (p_sys->embed == NULL)
316
 
    {
317
 
        free (p_sys);
318
 
        return VLC_EGENERIC;
319
 
    }
320
 
 
321
 
    p_sys->conn = conn;
322
 
    p_sys->att = NULL;
323
 
    p_sys->pool = NULL;
324
 
    p_sys->swap_uv = false;
325
 
 
326
 
    if (!CheckXVideo (vd, conn))
327
 
    {
328
 
        msg_Warn (vd, "Please enable XVideo 2.2 for faster video display");
329
 
        goto error;
330
 
    }
331
 
 
332
 
    p_sys->window = xcb_generate_id (conn);
333
 
    xcb_pixmap_t pixmap = xcb_generate_id (conn);
334
 
 
335
 
    /* Cache adaptors infos */
336
 
    xcb_xv_query_adaptors_reply_t *adaptors =
337
 
        xcb_xv_query_adaptors_reply (conn,
338
 
            xcb_xv_query_adaptors (conn, p_sys->embed->handle.xid), NULL);
339
 
    if (adaptors == NULL)
340
 
        goto error;
341
 
 
342
 
    int forced_adaptor = var_CreateGetInteger (obj, "xvideo-adaptor");
343
 
 
344
 
    /* */
345
 
    video_format_t fmt = vd->fmt;
346
 
    bool found_adaptor = false;
347
 
 
348
 
    xcb_xv_adaptor_info_iterator_t it;
349
 
    for (it = xcb_xv_query_adaptors_info_iterator (adaptors);
350
 
         it.rem > 0 && !found_adaptor;
351
 
         xcb_xv_adaptor_info_next (&it))
352
 
    {
353
 
        const xcb_xv_adaptor_info_t *a = it.data;
354
 
        char *name;
355
 
 
356
 
        if (forced_adaptor != -1 && forced_adaptor != 0)
357
 
        {
358
 
            forced_adaptor--;
359
 
            continue;
360
 
        }
361
 
 
362
 
        if (!(a->type & XCB_XV_TYPE_INPUT_MASK)
363
 
         || !(a->type & XCB_XV_TYPE_IMAGE_MASK))
364
 
            continue;
365
 
 
366
 
        xcb_xv_list_image_formats_reply_t *r =
367
 
            xcb_xv_list_image_formats_reply (conn,
368
 
                xcb_xv_list_image_formats (conn, a->base_id), NULL);
369
 
        if (r == NULL)
370
 
            continue;
371
 
 
372
 
        /* Look for an image format */
373
 
        const xcb_xv_image_format_info_t *xfmt = NULL;
374
 
        const vlc_fourcc_t *chromas, chromas_default[] = {
375
 
            fmt.i_chroma,
376
 
            VLC_CODEC_RGB32,
377
 
            VLC_CODEC_RGB24,
378
 
            VLC_CODEC_RGB16,
379
 
            VLC_CODEC_RGB15,
380
 
            VLC_CODEC_YUYV,
381
 
            0
382
 
        };
383
 
        if (vlc_fourcc_IsYUV (fmt.i_chroma))
384
 
            chromas = vlc_fourcc_GetYUVFallback (fmt.i_chroma);
385
 
        else
386
 
            chromas = chromas_default;
387
 
 
388
 
        vlc_fourcc_t chroma;
389
 
        for (size_t i = 0; chromas[i]; i++)
390
 
        {
391
 
            chroma = chromas[i];
392
 
 
393
 
            /* Oink oink! */
394
 
            if ((chroma == VLC_CODEC_I420 || chroma == VLC_CODEC_YV12)
395
 
             && a->name_size >= 4
396
 
             && !memcmp ("OMAP", xcb_xv_adaptor_info_name (a), 4))
397
 
            {
398
 
                msg_Dbg (vd, "skipping slow I420 format");
399
 
                continue; /* OMAP framebuffer sucks at YUV 4:2:0 */
400
 
            }
401
 
 
402
 
            xfmt = FindFormat (vd, chroma, &fmt, a->base_id, r, &p_sys->att);
403
 
            if (xfmt != NULL)
404
 
            {
405
 
                p_sys->id = xfmt->id;
406
 
                p_sys->swap_uv = vlc_fourcc_AreUVPlanesSwapped (fmt.i_chroma,
407
 
                                                                chroma);
408
 
                if (!p_sys->swap_uv)
409
 
                    fmt.i_chroma = chroma;
410
 
                if (xfmt->type == XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB)
411
 
                {
412
 
                    fmt.i_rmask = xfmt->red_mask;
413
 
                    fmt.i_gmask = xfmt->green_mask;
414
 
                    fmt.i_bmask = xfmt->blue_mask;
415
 
                }
416
 
                break;
417
 
            }
418
 
        }
419
 
        free (r);
420
 
        if (xfmt == NULL) /* No acceptable image formats */
421
 
            continue;
422
 
 
423
 
        /* Grab a port */
424
 
        for (unsigned i = 0; i < a->num_ports; i++)
425
 
        {
426
 
             xcb_xv_port_t port = a->base_id + i;
427
 
             xcb_xv_grab_port_reply_t *gr =
428
 
                 xcb_xv_grab_port_reply (conn,
429
 
                     xcb_xv_grab_port (conn, port, XCB_CURRENT_TIME), NULL);
430
 
             uint8_t result = gr ? gr->result : 0xff;
431
 
 
432
 
             free (gr);
433
 
             if (result == 0)
434
 
             {
435
 
                 p_sys->port = port;
436
 
                 goto grabbed_port;
437
 
             }
438
 
             msg_Dbg (vd, "cannot grab port %"PRIu32": Xv error %"PRIu8, port,
439
 
                      result);
440
 
        }
441
 
        continue; /* No usable port */
442
 
 
443
 
    grabbed_port:
444
 
        /* Found port - initialize selected format */
445
 
        name = strndup (xcb_xv_adaptor_info_name (a), a->name_size);
446
 
        if (name != NULL)
447
 
        {
448
 
            msg_Dbg (vd, "using adaptor %s", name);
449
 
            free (name);
450
 
        }
451
 
        msg_Dbg (vd, "using port %"PRIu32, p_sys->port);
452
 
        msg_Dbg (vd, "using image format 0x%"PRIx32, p_sys->id);
453
 
 
454
 
        /* Look for an X11 visual, create a window */
455
 
        xcb_xv_format_t *f = xcb_xv_adaptor_info_formats (a);
456
 
        for (uint_fast16_t i = a->num_formats; i > 0; i--, f++)
457
 
        {
458
 
            if (f->depth != screen->root_depth)
459
 
                continue; /* this would fail anyway */
460
 
 
461
 
            uint32_t mask =
462
 
                XCB_CW_BACK_PIXMAP |
463
 
                XCB_CW_BACK_PIXEL |
464
 
                XCB_CW_BORDER_PIXMAP |
465
 
                XCB_CW_BORDER_PIXEL |
466
 
                XCB_CW_EVENT_MASK |
467
 
                XCB_CW_COLORMAP;
468
 
            const uint32_t list[] = {
469
 
                /* XCB_CW_BACK_PIXMAP */
470
 
                pixmap,
471
 
                /* XCB_CW_BACK_PIXEL */
472
 
                screen->black_pixel,
473
 
                /* XCB_CW_BORDER_PIXMAP */
474
 
                pixmap,
475
 
                /* XCB_CW_BORDER_PIXEL */
476
 
                screen->black_pixel,
477
 
                /* XCB_CW_EVENT_MASK */
478
 
                XCB_EVENT_MASK_VISIBILITY_CHANGE,
479
 
                /* XCB_CW_COLORMAP */
480
 
                screen->default_colormap,
481
 
            };
482
 
 
483
 
            xcb_void_cookie_t c;
484
 
 
485
 
            xcb_create_pixmap (conn, f->depth, pixmap, screen->root, 1, 1);
486
 
            c = xcb_create_window_checked (conn, f->depth, p_sys->window,
487
 
                 p_sys->embed->handle.xid, 0, 0, 1, 1, 0,
488
 
                 XCB_WINDOW_CLASS_INPUT_OUTPUT, f->visual, mask, list);
489
 
 
490
 
            if (!CheckError (vd, conn, "cannot create X11 window", c))
491
 
            {
492
 
                msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32
493
 
                         " (depth: %"PRIu8")", f->visual, f->depth);
494
 
                msg_Dbg (vd, "using X11 window 0x%08"PRIx32, p_sys->window);
495
 
                goto created_window;
496
 
            }
497
 
        }
498
 
        xcb_xv_ungrab_port (conn, p_sys->port, XCB_CURRENT_TIME);
499
 
        msg_Dbg (vd, "no usable X11 visual");
500
 
        continue; /* No workable XVideo format (visual/depth) */
501
 
 
502
 
    created_window:
503
 
        found_adaptor = true;
504
 
        break;
505
 
    }
506
 
    free (adaptors);
507
 
    if (!found_adaptor)
508
 
    {
509
 
        msg_Err (vd, "no available XVideo adaptor");
510
 
        goto error;
511
 
    }
512
 
    else
513
 
    {
514
 
        xcb_map_window (conn, p_sys->window);
515
 
 
516
 
        vout_display_place_t place;
517
 
 
518
 
        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
519
 
        p_sys->width  = place.width;
520
 
        p_sys->height = place.height;
521
 
 
522
 
        /* */
523
 
        const uint32_t values[] = {
524
 
            place.x, place.y, place.width, place.height };
525
 
        xcb_configure_window (conn, p_sys->window,
526
 
                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
527
 
                              XCB_CONFIG_WINDOW_WIDTH |
528
 
                              XCB_CONFIG_WINDOW_HEIGHT,
529
 
                              values);
530
 
    }
531
 
    p_sys->visible = false;
532
 
 
533
 
    /* Create graphic context */
534
 
    p_sys->gc = xcb_generate_id (conn);
535
 
    xcb_create_gc (conn, p_sys->gc, p_sys->window, 0, NULL);
536
 
    msg_Dbg (vd, "using X11 graphic context 0x%08"PRIx32, p_sys->gc);
537
 
 
538
 
    /* Create cursor */
539
 
    p_sys->cursor = CreateBlankCursor (conn, screen);
540
 
 
541
 
    CheckSHM (obj, conn, &p_sys->shm);
542
 
 
543
 
    /* */
544
 
    vout_display_info_t info = vd->info;
545
 
    info.has_pictures_invalid = false;
546
 
 
547
 
    /* Setup vout_display_t once everything is fine */
548
 
    vd->fmt = fmt;
549
 
    vd->info = info;
550
 
 
551
 
    vd->pool = Pool;
552
 
    vd->prepare = NULL;
553
 
    vd->display = Display;
554
 
    vd->control = Control;
555
 
    vd->manage = Manage;
556
 
 
557
 
    /* */
558
 
    vout_display_SendEventFullscreen (vd, false);
559
 
    unsigned width, height;
560
 
    if (!GetWindowSize (p_sys->embed, conn, &width, &height))
561
 
        vout_display_SendEventDisplaySize (vd, width, height, false);
562
 
 
563
 
    return VLC_SUCCESS;
564
 
 
565
 
error:
566
 
    Close (obj);
567
 
    return VLC_EGENERIC;
568
 
}
569
 
 
570
 
 
571
 
/**
572
 
 * Disconnect from the X server.
573
 
 */
574
 
static void Close (vlc_object_t *obj)
575
 
{
576
 
    vout_display_t *vd = (vout_display_t *)obj;
577
 
    vout_display_sys_t *p_sys = vd->sys;
578
 
 
579
 
    if (p_sys->pool)
580
 
    {
581
 
        for (unsigned i = 0; i < MAX_PICTURES; i++)
582
 
        {
583
 
            picture_resource_t *res = &p_sys->resource[i];
584
 
 
585
 
            if (!res->p->p_pixels)
586
 
                break;
587
 
            PictureResourceFree (res, NULL);
588
 
        }
589
 
        picture_pool_Delete (p_sys->pool);
590
 
    }
591
 
 
592
 
    /* show the default cursor */
593
 
    xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid, XCB_CW_CURSOR,
594
 
                                  &(uint32_t) { XCB_CURSOR_NONE });
595
 
    xcb_flush (p_sys->conn);
596
 
 
597
 
    free (p_sys->att);
598
 
    xcb_disconnect (p_sys->conn);
599
 
    vout_display_DeleteWindow (vd, p_sys->embed);
600
 
    free (p_sys);
601
 
}
602
 
 
603
 
/**
604
 
 * Return a direct buffer
605
 
 */
606
 
static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
607
 
{
608
 
    vout_display_sys_t *p_sys = vd->sys;
609
 
    (void)requested_count;
610
 
 
611
 
    if (!p_sys->pool)
612
 
    {
613
 
        memset (p_sys->resource, 0, sizeof(p_sys->resource));
614
 
 
615
 
        const uint32_t *pitches =
616
 
            xcb_xv_query_image_attributes_pitches (p_sys->att);
617
 
        const uint32_t *offsets =
618
 
            xcb_xv_query_image_attributes_offsets (p_sys->att);
619
 
        p_sys->data_size = p_sys->att->data_size;
620
 
 
621
 
        unsigned count;
622
 
        picture_t *pic_array[MAX_PICTURES];
623
 
        for (count = 0; count < MAX_PICTURES; count++)
624
 
        {
625
 
            picture_resource_t *res = &p_sys->resource[count];
626
 
 
627
 
            for (int i = 0; i < __MIN (p_sys->att->num_planes, PICTURE_PLANE_MAX); i++)
628
 
            {
629
 
                res->p[i].i_lines =
630
 
                    ((i + 1 < p_sys->att->num_planes ? offsets[i+1] :
631
 
                                                       p_sys->data_size) - offsets[i]) / pitches[i];
632
 
                res->p[i].i_pitch = pitches[i];
633
 
            }
634
 
            if (PictureResourceAlloc (vd, res, p_sys->att->data_size,
635
 
                                      p_sys->conn, p_sys->shm))
636
 
                break;
637
 
 
638
 
            /* Allocate further planes as specified by XVideo */
639
 
            /* We assume that offsets[0] is zero */
640
 
            for (int i = 1; i < __MIN (p_sys->att->num_planes, PICTURE_PLANE_MAX); i++)
641
 
                res->p[i].p_pixels = res->p[0].p_pixels + offsets[i];
642
 
            if (p_sys->swap_uv)
643
 
            {   /* YVU: swap U and V planes */
644
 
                uint8_t *buf = res->p[2].p_pixels;
645
 
                res->p[2].p_pixels = res->p[1].p_pixels;
646
 
                res->p[1].p_pixels = buf;
647
 
            }
648
 
 
649
 
            pic_array[count] = picture_NewFromResource (&vd->fmt, res);
650
 
            if (!pic_array[count])
651
 
            {
652
 
                PictureResourceFree (res, p_sys->conn);
653
 
                memset (res, 0, sizeof(*res));
654
 
                break;
655
 
            }
656
 
        }
657
 
 
658
 
        if (count == 0)
659
 
            return NULL;
660
 
 
661
 
        p_sys->pool = picture_pool_New (count, pic_array);
662
 
        /* TODO release picture resources if NULL */
663
 
        xcb_flush (p_sys->conn);
664
 
    }
665
 
 
666
 
    return p_sys->pool;
667
 
}
668
 
 
669
 
/**
670
 
 * Sends an image to the X server.
671
 
 */
672
 
static void Display (vout_display_t *vd, picture_t *pic)
673
 
{
674
 
    vout_display_sys_t *p_sys = vd->sys;
675
 
    xcb_shm_seg_t segment = pic->p_sys->segment;
676
 
    xcb_void_cookie_t ck;
677
 
 
678
 
    if (!p_sys->visible)
679
 
        goto out;
680
 
    if (segment)
681
 
        ck = xcb_xv_shm_put_image_checked (p_sys->conn, p_sys->port,
682
 
                              p_sys->window, p_sys->gc, segment, p_sys->id, 0,
683
 
                   /* Src: */ vd->source.i_x_offset,
684
 
                              vd->source.i_y_offset,
685
 
                              vd->source.i_visible_width,
686
 
                              vd->source.i_visible_height,
687
 
                   /* Dst: */ 0, 0, p_sys->width, p_sys->height,
688
 
                /* Memory: */ pic->p->i_pitch / pic->p->i_pixel_pitch,
689
 
                              pic->p->i_lines, false);
690
 
    else
691
 
        ck = xcb_xv_put_image_checked (p_sys->conn, p_sys->port, p_sys->window,
692
 
                          p_sys->gc, p_sys->id,
693
 
                          vd->source.i_x_offset,
694
 
                          vd->source.i_y_offset,
695
 
                          vd->source.i_visible_width,
696
 
                          vd->source.i_visible_height,
697
 
                          0, 0, p_sys->width, p_sys->height,
698
 
                          pic->p->i_pitch / pic->p->i_pixel_pitch,
699
 
                          pic->p->i_lines,
700
 
                          p_sys->data_size, pic->p->p_pixels);
701
 
 
702
 
    /* Wait for reply. See x11.c for rationale. */
703
 
    xcb_generic_error_t *e = xcb_request_check (p_sys->conn, ck);
704
 
    if (e != NULL)
705
 
    {
706
 
        msg_Dbg (vd, "%s: X11 error %d", "cannot put image", e->error_code);
707
 
        free (e);
708
 
    }
709
 
out:
710
 
    picture_Release (pic);
711
 
}
712
 
 
713
 
static int Control (vout_display_t *vd, int query, va_list ap)
714
 
{
715
 
    vout_display_sys_t *p_sys = vd->sys;
716
 
 
717
 
    switch (query)
718
 
    {
719
 
    case VOUT_DISPLAY_CHANGE_FULLSCREEN:
720
 
    {
721
 
        const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
722
 
        return vout_window_SetFullScreen (p_sys->embed, c->is_fullscreen);
723
 
    }
724
 
 
725
 
    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
726
 
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
727
 
    case VOUT_DISPLAY_CHANGE_ZOOM:
728
 
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
729
 
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
730
 
    {
731
 
        const vout_display_cfg_t *cfg;
732
 
        const video_format_t *source;
733
 
        bool is_forced = false;
734
 
 
735
 
        if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
736
 
         || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP)
737
 
        {
738
 
            source = (const video_format_t *)va_arg (ap, const video_format_t *);
739
 
            cfg = vd->cfg;
740
 
        }
741
 
        else
742
 
        {
743
 
            source = &vd->source;
744
 
            cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
745
 
            if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
746
 
                is_forced = (bool)va_arg (ap, int);
747
 
        }
748
 
 
749
 
        /* */
750
 
        if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
751
 
         && is_forced
752
 
         && (cfg->display.width  != vd->cfg->display.width
753
 
           ||cfg->display.height != vd->cfg->display.height)
754
 
         && vout_window_SetSize (p_sys->embed,
755
 
                                  cfg->display.width,
756
 
                                  cfg->display.height))
757
 
            return VLC_EGENERIC;
758
 
 
759
 
        vout_display_place_t place;
760
 
        vout_display_PlacePicture (&place, source, cfg, false);
761
 
        p_sys->width  = place.width;
762
 
        p_sys->height = place.height;
763
 
 
764
 
        /* Move the picture within the window */
765
 
        const uint32_t values[] = { place.x, place.y,
766
 
                                    place.width, place.height, };
767
 
        xcb_configure_window (p_sys->conn, p_sys->window,
768
 
                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
769
 
                            | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
770
 
                              values);
771
 
        xcb_flush (p_sys->conn);
772
 
        return VLC_SUCCESS;
773
 
    }
774
 
    case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
775
 
    {
776
 
        unsigned state = va_arg (ap, unsigned);
777
 
        return vout_window_SetState (p_sys->embed, state);
778
 
    }
779
 
 
780
 
    /* Hide the mouse. It will be send when
781
 
     * vout_display_t::info.b_hide_mouse is false */
782
 
    case VOUT_DISPLAY_HIDE_MOUSE:
783
 
        xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid,
784
 
                                  XCB_CW_CURSOR, &(uint32_t){ p_sys->cursor });
785
 
        xcb_flush (p_sys->conn);
786
 
        return VLC_SUCCESS;
787
 
    case VOUT_DISPLAY_RESET_PICTURES:
788
 
        assert(0);
789
 
    default:
790
 
        msg_Err (vd, "Unknown request in XCB vout display");
791
 
        return VLC_EGENERIC;
792
 
    }
793
 
}
794
 
 
795
 
static void Manage (vout_display_t *vd)
796
 
{
797
 
    vout_display_sys_t *p_sys = vd->sys;
798
 
 
799
 
    ManageEvent (vd, p_sys->conn, &p_sys->visible);
800
 
}
801