~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/video_output/x11/xvmc.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * xvmc.c : XVMC plugin for vlc
 
3
 *****************************************************************************
 
4
 * Copyright (C) 1998-2001 VideoLAN
 
5
 * $Id$
 
6
 *
 
7
 * Authors: Shane Harper <shanegh@optusnet.com.au>
 
8
 *          Vincent Seguin <seguin@via.ecp.fr>
 
9
 *          Samuel Hocevar <sam@zoy.org>
 
10
 *          David Kennedy <dkennedy@tinytoad.com>
 
11
 *          Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
 
12
 *
 
13
 * This program is free software; you can redistribute it and/or modify
 
14
 * it under the terms of the GNU General Public License as published by
 
15
 * the Free Software Foundation; either version 2 of the License, or
 
16
 * (at your option) any later version.
 
17
 *
 
18
 * This program is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this program; if not, write to the Free Software
 
25
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
26
 *****************************************************************************/
 
27
 
 
28
/*****************************************************************************
 
29
 * Preamble
 
30
 *****************************************************************************/
 
31
 
 
32
#ifdef HAVE_CONFIG_H
 
33
# include "config.h"
 
34
#endif
 
35
 
 
36
#include <vlc_common.h>
 
37
#include <vlc_plugin.h>
 
38
#include <vlc_interface.h>
 
39
#include <vlc_vout.h>
 
40
#include <vlc_keys.h>
 
41
 
 
42
#ifdef HAVE_MACHINE_PARAM_H
 
43
    /* BSD */
 
44
#   include <machine/param.h>
 
45
#   include <sys/types.h>                                  /* typedef ushort */
 
46
#   include <sys/ipc.h>
 
47
#endif
 
48
 
 
49
#ifndef WIN32
 
50
#   include <netinet/in.h>                            /* BSD: struct in_addr */
 
51
#endif
 
52
 
 
53
#ifdef HAVE_SYS_SHM_H
 
54
#   include <sys/shm.h>                                /* shmget(), shmctl() */
 
55
#endif
 
56
 
 
57
#include <X11/Xlib.h>
 
58
#include <X11/Xmd.h>
 
59
#include <X11/Xutil.h>
 
60
#include <X11/keysym.h>
 
61
#ifdef HAVE_SYS_SHM_H
 
62
#   include <X11/extensions/XShm.h>
 
63
#endif
 
64
#ifdef DPMSINFO_IN_DPMS_H
 
65
#   include <X11/extensions/dpms.h>
 
66
#endif
 
67
 
 
68
#include <X11/extensions/Xv.h>
 
69
#include <X11/extensions/Xvlib.h>
 
70
#include <X11/extensions/vldXvMC.h>
 
71
 
 
72
#include "../../codec/xvmc/accel_xvmc.h"
 
73
#include "xcommon.h"
 
74
#include "../../codec/spudec/spudec.h"
 
75
#include <unistd.h>
 
76
 
 
77
/* picture structure */
 
78
#define TOP_FIELD 1
 
79
#define BOTTOM_FIELD 2
 
80
#define FRAME_PICTURE 3
 
81
 
 
82
/* picture coding type */
 
83
#define I_TYPE 1
 
84
#define P_TYPE 2
 
85
#define B_TYPE 3
 
86
#define D_TYPE 4
 
87
 
 
88
/*****************************************************************************
 
89
 * Exported prototypes
 
90
 *****************************************************************************/
 
91
extern int  Activate   ( vlc_object_t * );
 
92
extern void Deactivate ( vlc_object_t * );
 
93
 
 
94
/*****************************************************************************
 
95
 * Module descriptor
 
96
 *****************************************************************************/
 
97
#define ADAPTOR_TEXT N_("XVMC adaptor number")
 
98
#define ADAPTOR_LONGTEXT N_( \
 
99
    "If you graphics card provides several adaptors, this option allows you " \
 
100
    "to choose which one will be used (you shouldn't have to change this).")
 
101
 
 
102
#define ALT_FS_TEXT N_("Alternate fullscreen method")
 
103
#define ALT_FS_LONGTEXT N_( \
 
104
    "There are two ways to make a fullscreen window, unfortunately each one " \
 
105
    "has its drawbacks.\n" \
 
106
    "1) Let the window manager handle your fullscreen window (default), but " \
 
107
    "things like taskbars will likely show on top of the video.\n" \
 
108
    "2) Completely bypass the window manager, but then nothing will be able " \
 
109
    "to show on top of the video.")
 
110
 
 
111
#define DISPLAY_TEXT N_("X11 display name")
 
112
#define DISPLAY_LONGTEXT N_( \
 
113
    "Specify the X11 hardware display you want to use. By default VLC will " \
 
114
    "use the value of the DISPLAY environment variable.")
 
115
 
 
116
#define CHROMA_TEXT N_("XVimage chroma format")
 
117
#define CHROMA_LONGTEXT N_( \
 
118
    "Force the XVideo renderer to use a specific chroma format instead of " \
 
119
    "trying to improve performances by using the most efficient one.")
 
120
 
 
121
#define SHM_TEXT N_("Use shared memory")
 
122
#define SHM_LONGTEXT N_( \
 
123
    "Use shared memory to communicate between VLC and the X server.")
 
124
 
 
125
#define SCREEN_TEXT N_("Screen to be used for fullscreen mode.")
 
126
#define SCREEN_LONGTEXT N_( \
 
127
    "Choose the screen you want to use in fullscreen mode. For instance " \
 
128
    "set it to 0 for first screen, 1 for the second.")
 
129
 
 
130
#define MODE_TEXT N_("Deinterlace mode")
 
131
#define MODE_LONGTEXT N_("You can choose the default deinterlace mode")
 
132
 
 
133
#define CROP_TEXT N_("Crop")
 
134
#define CROP_LONGTEXT N_("You can choose the crop style to apply.")
 
135
 
 
136
vlc_module_begin();
 
137
    set_shortname( "XVMC" );
 
138
    add_string( "xvmc-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, true );
 
139
    add_integer( "xvmc-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT, true );
 
140
    add_bool( "xvmc-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, true );
 
141
    add_string( "xvmc-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true );
 
142
#ifdef HAVE_SYS_SHM_H
 
143
    add_bool( "xvmc-shm", 1, NULL, SHM_TEXT, SHM_LONGTEXT, true );
 
144
#endif
 
145
#ifdef HAVE_XINERAMA
 
146
    add_integer ( "xvmc-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, true );
 
147
#endif
 
148
    add_string( "xvmc-deinterlace-mode", "bob", NULL, MODE_TEXT, MODE_LONGTEXT, false );
 
149
    add_string( "xvmc-crop-style", "eq", NULL, CROP_TEXT, CROP_LONGTEXT, false );
 
150
 
 
151
    set_description( N_("XVMC extension video output") );
 
152
    set_capability( "video output", 10 );
 
153
    set_callbacks( Activate, Deactivate );
 
154
vlc_module_end();
 
155
 
 
156
/* following functions are local */
 
157
 
 
158
static const unsigned accel_priority[] = {
 
159
    VLC_XVMC_ACCEL_VLD,
 
160
};
 
161
 
 
162
#define NUM_ACCEL_PRIORITY (sizeof(accel_priority)/sizeof(accel_priority[0]))
 
163
 
 
164
/*
 
165
 * Additional thread safety, since the plugin may decide to destroy a context
 
166
 * while it's surfaces are still active in the video-out loop.
 
167
 * When / If XvMC libs are reasonably thread-safe, the locks can be made
 
168
 * more efficient by allowing multiple threads in that do not destroy
 
169
 * the context or surfaces that may be active in other threads.
 
170
 */
 
171
 
 
172
static void init_context_lock( context_lock_t *c )
 
173
{
 
174
    pthread_cond_init(&c->cond,NULL);
 
175
    pthread_mutex_init(&c->mutex,NULL);
 
176
    c->num_readers = 0;
 
177
}
 
178
 
 
179
void free_context_lock( context_lock_t *c )
 
180
{
 
181
    pthread_mutex_destroy(&c->mutex);
 
182
    pthread_cond_destroy(&c->cond);
 
183
}
 
184
 
 
185
void xvmc_context_reader_lock( context_lock_t *c )
 
186
{
 
187
    pthread_mutex_lock(&c->mutex);
 
188
    c->num_readers++;
 
189
    pthread_mutex_unlock(&c->mutex);
 
190
}
 
191
 
 
192
void xvmc_context_reader_unlock( context_lock_t *c )
 
193
{
 
194
    pthread_mutex_lock(&c->mutex);
 
195
    if (c->num_readers > 0) {
 
196
        if (--(c->num_readers) == 0) {
 
197
        pthread_cond_broadcast(&c->cond);
 
198
        }
 
199
    }
 
200
    pthread_mutex_unlock(&c->mutex);
 
201
}
 
202
 
 
203
void xvmc_context_writer_lock( context_lock_t *c )
 
204
{
 
205
    pthread_mutex_lock(&c->mutex);
 
206
    while(c->num_readers) {
 
207
        pthread_cond_wait( &c->cond, &c->mutex );
 
208
    }
 
209
}
 
210
 
 
211
void xvmc_context_writer_unlock( context_lock_t *c )
 
212
{
 
213
    pthread_mutex_unlock( &c->mutex );
 
214
}
 
215
 
 
216
void clear_xx44_palette( xx44_palette_t *p )
 
217
{
 
218
    int i;
 
219
    uint32_t *cluts = p->cluts;
 
220
    int *ids = p->lookup_cache;
 
221
 
 
222
    i= p->size;
 
223
    while(i--)
 
224
        *cluts++ = 0;
 
225
    i = 2*OVL_PALETTE_SIZE;
 
226
    while(i--)
 
227
        *ids++ = -1;
 
228
    p->max_used=1;
 
229
}
 
230
 
 
231
static void init_xx44_palette( xx44_palette_t *p, unsigned num_entries )
 
232
{
 
233
    p->size = (num_entries > XX44_PALETTE_SIZE) ?
 
234
                    XX44_PALETTE_SIZE : num_entries;
 
235
}
 
236
 
 
237
static void dispose_xx44_palette(xx44_palette_t *p)
 
238
{
 
239
    /* Nothing to do */
 
240
}
 
241
 
 
242
static void colorToPalette( const uint32_t *icolor, unsigned char *palette_p,
 
243
                            unsigned num_xvmc_components, char *xvmc_components )
 
244
{
 
245
    const clut_t *color = (const clut_t *) icolor;
 
246
    unsigned int i;
 
247
 
 
248
    for (i=0; i<num_xvmc_components; ++i)
 
249
    {
 
250
        switch(xvmc_components[i])
 
251
        {
 
252
            case 'V': *palette_p = color->cr; break;
 
253
            case 'U': *palette_p = color->cb; break;
 
254
            case 'Y':
 
255
            default:  *palette_p = color->y; break;
 
256
        }
 
257
        *palette_p++;
 
258
    }
 
259
}
 
260
 
 
261
 
 
262
void xx44_to_xvmc_palette( const xx44_palette_t *p,unsigned char *xvmc_palette,
 
263
                           unsigned first_xx44_entry, unsigned num_xx44_entries,
 
264
                           unsigned num_xvmc_components, char *xvmc_components )
 
265
{
 
266
    unsigned int i;
 
267
    const uint32_t *cluts = p->cluts + first_xx44_entry;
 
268
 
 
269
    for( i=0; i<num_xx44_entries; ++i )
 
270
    {
 
271
        if( (cluts - p->cluts) < p->size )
 
272
        {
 
273
            colorToPalette( cluts++, xvmc_palette,
 
274
                            num_xvmc_components, xvmc_components );
 
275
            xvmc_palette += num_xvmc_components;
 
276
        }
 
277
    }
 
278
}
 
279
 
 
280
static int xx44_paletteIndex( xx44_palette_t *p, int color, uint32_t clut )
 
281
{
 
282
    unsigned int i;
 
283
    uint32_t *cluts = p->cluts;
 
284
    int tmp;
 
285
 
 
286
    if( (tmp = p->lookup_cache[color]) >= 0 )
 
287
    {
 
288
        if (cluts[tmp] == clut)
 
289
            return tmp;
 
290
    }
 
291
    for (i=0; i<p->max_used; ++i)
 
292
    {
 
293
        if (*cluts++ == clut) {
 
294
            p->lookup_cache[color] = i;
 
295
            return p->lookup_cache[color];
 
296
        }
 
297
    }
 
298
 
 
299
    if( p->max_used == (p->size -1) )
 
300
    {
 
301
        //printf("video_out: Warning! Out of xx44 palette colors!\n");
 
302
        return 1;
 
303
    }
 
304
    p->cluts[p->max_used] = clut;
 
305
    p->lookup_cache[color] = p->max_used++;
 
306
    return p->lookup_cache[color];
 
307
}
 
308
 
 
309
static void memblend_xx44( uint8_t *mem, uint8_t val,
 
310
                           size_t size, uint8_t mask )
 
311
{
 
312
    uint8_t masked_val = val & mask;
 
313
 
 
314
/* size_t is unsigned, therefore always positive
 
315
   if (size < 0)
 
316
        return;*/
 
317
 
 
318
    while(size--)
 
319
    {
 
320
        if( (*mem & mask) <= masked_val )
 
321
            *mem = val;
 
322
        mem++;
 
323
    }
 
324
}
 
325
 
 
326
void blend_xx44( uint8_t *dst_img, subpicture_t *sub_img,
 
327
                 int dst_width, int dst_height, int dst_pitch,
 
328
                 xx44_palette_t *palette, int ia44 )
 
329
{
 
330
    int src_width;
 
331
    int src_height;
 
332
    int mask;
 
333
    int x_off;
 
334
    int y_off;
 
335
    int x, y;
 
336
    uint8_t norm_pixel,clip_pixel;
 
337
    uint8_t *dst_y;
 
338
    uint8_t *dst;
 
339
    uint8_t alphamask;
 
340
    int clip_right;
 
341
    int i_len, i_color;
 
342
    uint16_t *p_source = NULL;
 
343
#if 0
 
344
    if (!sub_img)
 
345
        return;
 
346
 
 
347
    src_width  = sub_img->i_width;
 
348
    src_height = sub_img->i_height;
 
349
    x_off = sub_img->i_x;
 
350
    y_off = sub_img->i_y;
 
351
    alphamask = (ia44) ? 0x0F : 0xF0;
 
352
    p_source = (uint16_t *)sub_img->p_sys->p_data;
 
353
 
 
354
    dst_y = dst_img + dst_pitch*y_off + x_off;
 
355
 
 
356
    if( (x_off + sub_img->i_width) <= dst_width )
 
357
        clip_right = sub_img->i_width;
 
358
    else
 
359
        clip_right = dst_width - x_off;
 
360
 
 
361
    if ((src_height + y_off) > dst_height)
 
362
        src_height = dst_height - y_off;
 
363
 
 
364
    for (y = 0; y < src_height; y++)
 
365
    {
 
366
        mask = !( (y < sub_img->p_sys->i_y_start) ||
 
367
                  (y >= sub_img->p_sys->i_y_end) );
 
368
        dst = dst_y;
 
369
 
 
370
        for (x = 0; x < src_width;)
 
371
        {
 
372
            i_color = *p_source & 0x3;
 
373
            i_len = *p_source++ >> 2;
 
374
 
 
375
            if( (i_len > 0) && ((x+i_len) <= src_width) )
 
376
            {
 
377
                /* Get the RLE part, then draw the line */
 
378
                uint32_t color = (sub_img->p_sys->pi_yuv[i_color][0] << 16) |
 
379
                                 (sub_img->p_sys->pi_yuv[i_color][1] << 0) |
 
380
                                 (sub_img->p_sys->pi_yuv[i_color][2] << 8);
 
381
 
 
382
                norm_pixel = (uint8_t)(
 
383
                            (xx44_paletteIndex( palette,i_color, color ) << 4) |
 
384
                            (sub_img->p_sys->pi_alpha[i_color] & 0x0F) );
 
385
                clip_pixel = (uint8_t)(
 
386
                            (xx44_paletteIndex( palette,i_color + OVL_PALETTE_SIZE,
 
387
                                                sub_img->p_sys->pi_yuv[i_color][0] ) << 4) |
 
388
                            (sub_img->p_sys->pi_alpha[i_color] & 0x0F));
 
389
 
 
390
                if( !ia44 )
 
391
                {
 
392
                    norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
 
393
                    clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
 
394
                }
 
395
                if( mask )
 
396
                {
 
397
                    if( x < sub_img->p_sys->i_x_start )
 
398
                    {
 
399
                        if( (x + i_len) <= sub_img->p_sys->i_x_start )
 
400
                        {
 
401
                            memblend_xx44( dst, norm_pixel, i_len, alphamask );
 
402
                            dst += i_len;
 
403
                        }
 
404
                        else
 
405
                        {
 
406
                            memblend_xx44( dst, norm_pixel,
 
407
                                           sub_img->p_sys->i_x_start - x,
 
408
                                           alphamask );
 
409
                            dst += sub_img->p_sys->i_x_start - x;
 
410
                            i_len -= sub_img->p_sys->i_x_start - x;
 
411
                            if( i_len <= (sub_img->p_sys->i_x_end -
 
412
                                          sub_img->p_sys->i_x_start) )
 
413
                            {
 
414
                                memblend_xx44( dst, clip_pixel,
 
415
                                               i_len, alphamask);
 
416
                                dst += i_len;
 
417
                            }
 
418
                            else
 
419
                            {
 
420
                                memblend_xx44( dst, clip_pixel,
 
421
                                               sub_img->p_sys->i_x_end -
 
422
                                                    sub_img->p_sys->i_x_start,
 
423
                                               alphamask );
 
424
                                dst += (sub_img->p_sys->i_x_end -
 
425
                                        sub_img->p_sys->i_x_start);
 
426
                                i_len -= (sub_img->p_sys->i_x_end -
 
427
                                          sub_img->p_sys->i_x_start);
 
428
                                memblend_xx44( dst, norm_pixel,
 
429
                                               i_len, alphamask );
 
430
                                dst += i_len;
 
431
                            }
 
432
                        }
 
433
                    }
 
434
                    else if( x < sub_img->p_sys->i_x_end )
 
435
                    {
 
436
                        if( i_len <= (sub_img->p_sys->i_x_end - x) )
 
437
                        {
 
438
                            memblend_xx44( dst, clip_pixel, i_len, alphamask);
 
439
                            dst += i_len;
 
440
                        }
 
441
                        else
 
442
                        {
 
443
                            memblend_xx44( dst, clip_pixel,
 
444
                                           sub_img->p_sys->i_x_end - x,
 
445
                                           alphamask);
 
446
                            dst += (sub_img->p_sys->i_x_end - x);
 
447
                            i_len -= (sub_img->p_sys->i_x_end - x);
 
448
                            memblend_xx44( dst, norm_pixel, i_len, alphamask);
 
449
                            dst += i_len;
 
450
                        }
 
451
                    }
 
452
                    else
 
453
                    {
 
454
                        memblend_xx44( dst, norm_pixel, i_len, alphamask );
 
455
                        dst += i_len;
 
456
                    }
 
457
                }
 
458
                else
 
459
                {
 
460
                    memblend_xx44( dst, norm_pixel, i_len, alphamask );
 
461
                    dst += i_len;
 
462
                }
 
463
            }
 
464
            else
 
465
            {
 
466
                return;
 
467
            }
 
468
            x += i_len;
 
469
        }
 
470
        dst_y += dst_pitch;
 
471
    }
 
472
#endif
 
473
}
 
474
 
 
475
int xxmc_xvmc_surface_valid( vout_thread_t *p_vout, XvMCSurface *surf )
 
476
{
 
477
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
478
    unsigned long index = surf - handler->surfaces;
 
479
    int ret;
 
480
 
 
481
    if( index >= XVMC_MAX_SURFACES )
 
482
        return 0;
 
483
    pthread_mutex_lock(&handler->mutex);
 
484
    ret = handler->surfValid[index];
 
485
    pthread_mutex_unlock(&handler->mutex);
 
486
    return ret;
 
487
}
 
488
 
 
489
static void xxmc_xvmc_dump_subpictures( vout_thread_t *p_vout )
 
490
{
 
491
    int i;
 
492
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
493
 
 
494
    for( i=0; i < XVMC_MAX_SUBPICTURES; ++i )
 
495
    {
 
496
        msg_Dbg( p_vout, "handler in use %d, valid %d",
 
497
                         handler->subInUse[i],
 
498
                         handler->subValid[i]);
 
499
    }
 
500
}
 
501
 
 
502
XvMCSubpicture *xxmc_xvmc_alloc_subpicture( vout_thread_t *p_vout,
 
503
                    XvMCContext *context, unsigned short width,
 
504
                    unsigned short height, int xvimage_id )
 
505
{
 
506
    int i;
 
507
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
508
    int status;
 
509
 
 
510
    pthread_mutex_lock(&handler->mutex);
 
511
    /* xxmc_xvmc_dump_subpictures(p_vout); */
 
512
    for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
 
513
    {
 
514
        if( handler->subValid[i] && !handler->subInUse[i] )
 
515
        {
 
516
            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
517
            if( XvMCGetSubpictureStatus( p_vout->p_sys->p_display,
 
518
                                         handler->subpictures + i,
 
519
                                         &status ) )
 
520
            {
 
521
                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
522
                continue;
 
523
            }
 
524
            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
525
            if( status & XVMC_DISPLAYING )
 
526
                continue;
 
527
            handler->subInUse[i] = 1;
 
528
            /* xxmc_xvmc_dump_subpictures(p_vout); */
 
529
            pthread_mutex_unlock(&handler->mutex);
 
530
            return (handler->subpictures + i);
 
531
        }
 
532
    }
 
533
    for (i=0; i<XVMC_MAX_SUBPICTURES; ++i)
 
534
    {
 
535
        if( !handler->subInUse[i] )
 
536
        {
 
537
            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
538
            if( Success != XvMCCreateSubpicture( p_vout->p_sys->p_display,
 
539
                                                 context,
 
540
                                                 handler->subpictures + i,
 
541
                                                 width, height, xvimage_id ) )
 
542
            {
 
543
                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
544
                pthread_mutex_unlock( &handler->mutex );
 
545
                return NULL;
 
546
            }
 
547
            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
548
            msg_Dbg( p_vout, "video_out_xxmc: created subpicture %d\n", i );
 
549
            handler->subInUse[i] = 1;
 
550
            handler->subValid[i] = 1;
 
551
            pthread_mutex_unlock( &handler->mutex );
 
552
            return (handler->subpictures + i);
 
553
        }
 
554
    }
 
555
    pthread_mutex_unlock( &handler->mutex );
 
556
    return NULL;
 
557
}
 
558
 
 
559
void xxmc_xvmc_free_subpicture( vout_thread_t *p_vout, XvMCSubpicture *sub )
 
560
{
 
561
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
562
    unsigned int index = sub - handler->subpictures;
 
563
 
 
564
    if( index >= XVMC_MAX_SUBPICTURES )
 
565
        return;
 
566
 
 
567
    pthread_mutex_lock( &handler->mutex );
 
568
    handler->subInUse[index] = 0;
 
569
    /* xxmc_xvmc_dump_subpictures(p_vout); */
 
570
    pthread_mutex_unlock( &handler->mutex );
 
571
}
 
572
 
 
573
static void xxmc_xvmc_surface_handler_construct( vout_thread_t *p_vout )
 
574
{
 
575
    int i;
 
576
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
577
 
 
578
    pthread_mutex_init( &handler->mutex, NULL );
 
579
    for( i=0; i<XVMC_MAX_SURFACES; ++i )
 
580
    {
 
581
        handler->surfInUse[i] = 0;
 
582
        handler->surfValid[i] = 0;
 
583
    }
 
584
    for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
 
585
    {
 
586
        handler->subInUse[i] = 0;
 
587
        handler->subValid[i] = 0;
 
588
    }
 
589
}
 
590
 
 
591
static void xxmc_xvmc_dump_surfaces( vout_thread_t *p_vout )
 
592
{
 
593
    int i;
 
594
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
595
 
 
596
    for (i=0; i<XVMC_MAX_SURFACES; ++i)
 
597
    {
 
598
        msg_Dbg(p_vout, "surfaces in use %d, valid %d;",
 
599
                        handler->surfInUse[i],
 
600
                        handler->surfValid[i]);
 
601
    }
 
602
}
 
603
 
 
604
void xxmc_xvmc_free_surface( vout_thread_t *p_vout, XvMCSurface *surf )
 
605
{
 
606
    xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
 
607
    unsigned int index = 0;
 
608
 
 
609
    index = (surf - handler->surfaces);
 
610
 
 
611
    if (index < XVMC_MAX_SURFACES)
 
612
    {
 
613
        pthread_mutex_lock(&handler->mutex);
 
614
        msg_Dbg( p_vout,"free surface %d",index );
 
615
        handler->surfInUse[index]--;
 
616
        xxmc_xvmc_dump_surfaces(p_vout);
 
617
        pthread_mutex_unlock(&handler->mutex);
 
618
    }
 
619
}
 
620
 
 
621
int checkXvMCCap( vout_thread_t *p_vout )
 
622
{
 
623
    int i_xvport = 0;
 
624
    int numSurf = 0;
 
625
    int numSub = 0;
 
626
    int i,j;
 
627
    XvMCSurfaceInfo     *surfaceInfo =NULL;
 
628
    XvMCSurfaceInfo     *curInfo = NULL;
 
629
    XvMCContext         c;
 
630
    xvmc_capabilities_t *curCap = NULL;
 
631
    XvImageFormatValues *formatValues = NULL;
 
632
 
 
633
    i_xvport = p_vout->p_sys->i_xvport;
 
634
    p_vout->p_sys->xvmc_cap = 0;
 
635
 
 
636
    init_context_lock( &p_vout->p_sys->xvmc_lock );
 
637
    xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
 
638
 
 
639
    p_vout->p_sys->old_subpic = NULL;
 
640
    p_vout->p_sys->new_subpic = NULL;
 
641
    p_vout->p_sys->contextActive = 0;
 
642
    p_vout->p_sys->subImage = NULL;
 
643
    p_vout->p_sys->hwSubpictures = 0;
 
644
    p_vout->p_sys->xvmc_palette = NULL;
 
645
 
 
646
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
647
 
 
648
    if( !XvMCQueryExtension( p_vout->p_sys->p_display,
 
649
                             &p_vout->p_sys->xvmc_eventbase,
 
650
                             &p_vout->p_sys->xvmc_errbase ) )
 
651
    {
 
652
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
653
        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
 
654
        return VLC_EGENERIC;
 
655
    }
 
656
    msg_Dbg( p_vout,"XvMC extension found" );
 
657
 
 
658
    surfaceInfo = XvMCListSurfaceTypes(p_vout->p_sys->p_display, i_xvport, &numSurf);
 
659
    if( !surfaceInfo )
 
660
    {
 
661
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
662
        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
 
663
        return VLC_EGENERIC;
 
664
    }
 
665
 
 
666
    p_vout->p_sys->xvmc_cap =
 
667
            (xvmc_capabilities_t *) malloc( numSurf *
 
668
                                            sizeof(xvmc_capabilities_t) );
 
669
    if( !p_vout->p_sys->xvmc_cap )
 
670
    {
 
671
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
672
        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
 
673
        return VLC_EGENERIC;
 
674
    }
 
675
 
 
676
    p_vout->p_sys->xvmc_num_cap = numSurf;
 
677
    curInfo = surfaceInfo;
 
678
    curCap = p_vout->p_sys->xvmc_cap;
 
679
 
 
680
    msg_Dbg( p_vout,"found %d XvMC surface types", numSurf );
 
681
 
 
682
    for( i=0; i< numSurf; ++i )
 
683
    {
 
684
        curCap->mpeg_flags = 0;
 
685
        curCap->accel_flags = 0;
 
686
        if( curInfo->chroma_format == XVMC_CHROMA_FORMAT_420 )
 
687
        {
 
688
            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ?
 
689
                                                VLC_XVMC_MPEG_1 : 0);
 
690
            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ?
 
691
                                                VLC_XVMC_MPEG_2 : 0);
 
692
            curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ?
 
693
                                                VLC_XVMC_MPEG_4 : 0);
 
694
            curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ?
 
695
                                              VLC_XVMC_ACCEL_VLD : 0);
 
696
            curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ?
 
697
                                             VLC_XVMC_ACCEL_IDCT : 0);
 
698
            curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ?
 
699
                                            0 : VLC_XVMC_ACCEL_MOCOMP);
 
700
            curCap->max_width = curInfo->max_width;
 
701
            curCap->max_height = curInfo->max_height;
 
702
            curCap->sub_max_width = curInfo->subpicture_max_width;
 
703
            curCap->sub_max_height = curInfo->subpicture_max_height;
 
704
            curCap->flags = curInfo->flags;
 
705
 
 
706
            msg_Dbg (p_vout, "surface type %d: Max size: %d %d.",
 
707
                            i, curCap->max_width, curCap->max_height);
 
708
            msg_Dbg (p_vout, "surface subtype %d: Max subpic size: %d %d.",
 
709
                            i, curCap->sub_max_width, curCap->sub_max_height);
 
710
 
 
711
            curCap->type_id = curInfo->surface_type_id;
 
712
            formatValues = XvMCListSubpictureTypes( p_vout->p_sys->p_display,
 
713
                                                    i_xvport,
 
714
                                                    curCap->type_id,
 
715
                                                    &numSub );
 
716
            curCap->subPicType.id = 0;
 
717
            if( formatValues )
 
718
            {
 
719
                msg_Dbg( p_vout, "surface type %d: found %d XvMC subpicture types",
 
720
                                i, numSub);
 
721
                for( j = 0; j<numSub; ++j )
 
722
                {
 
723
                    if( formatValues[j].id == FOURCC_IA44 )
 
724
                    {
 
725
                        curCap->subPicType = formatValues[j];
 
726
                        msg_Dbg( p_vout,
 
727
                                    "surface type %d: detected and using "
 
728
                                    "IA44 subpicture type.", i );
 
729
                        /* Prefer IA44 */
 
730
                        break;
 
731
                    }
 
732
                    else if( formatValues[j].id == FOURCC_AI44 )
 
733
                    {
 
734
                        curCap->subPicType = formatValues[j];
 
735
                        msg_Dbg( p_vout,
 
736
                                 "surface type %d: detected AI44 "
 
737
                                 "subpicture type.", i );
 
738
                    }
 
739
                }
 
740
            }
 
741
            XFree(formatValues);
 
742
            curInfo++;
 
743
            curCap++;
 
744
        }
 
745
    }
 
746
    XFree(surfaceInfo);
 
747
 
 
748
    /*
 
749
     * Try to create a direct rendering context. This will fail if we are not
 
750
     * on the displaying computer or an indirect context is not available.
 
751
     */
 
752
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
753
    curCap = p_vout->p_sys->xvmc_cap;
 
754
    if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
 
755
                                      curCap->type_id,
 
756
                                      curCap->max_width,
 
757
                                      curCap->max_height,
 
758
                                      XVMC_DIRECT, &c ) )
 
759
    {
 
760
        msg_Dbg( p_vout, "using direct XVMC rendering context" );
 
761
        p_vout->p_sys->context_flags = XVMC_DIRECT;
 
762
    }
 
763
    else if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
 
764
                                           curCap->type_id,
 
765
                                           curCap->max_width,
 
766
                                           curCap->max_height,
 
767
                                           0, &c ) )
 
768
    {
 
769
        msg_Dbg( p_vout, "using default XVMC rendering context" );
 
770
        p_vout->p_sys->context_flags = 0;
 
771
    }
 
772
    else
 
773
    {
 
774
        if( p_vout->p_sys->xvmc_cap )
 
775
            free( p_vout->p_sys->xvmc_cap );
 
776
        p_vout->p_sys->xvmc_cap = NULL;
 
777
        msg_Err( p_vout, "use of direct XvMC context on a remote display failed"
 
778
                         " falling back to XV." );
 
779
        xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
 
780
        return VLC_SUCCESS;
 
781
    }
 
782
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
783
    XvMCDestroyContext( p_vout->p_sys->p_display, &c );
 
784
    xxmc_xvmc_surface_handler_construct( p_vout );
 
785
    /*  p_vout->p_sys->capabilities |= VO_CAP_XXMC; */
 
786
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
787
    init_xx44_palette( &p_vout->p_sys->palette , 0 );
 
788
    p_vout->p_sys->last_accel_request = 0xFFFFFFFF;
 
789
    xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
 
790
    return VLC_SUCCESS;
 
791
}
 
792
 
 
793
static int xxmc_setup_subpictures( vout_thread_t *p_vout,
 
794
        unsigned int width, unsigned int height )
 
795
{
 
796
    xvmc_capabilities_t *curCap = NULL;
 
797
    XvMCSubpicture *sp = NULL;
 
798
 
 
799
    if( p_vout->p_sys->contextActive )
 
800
    {
 
801
        curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
 
802
 
 
803
        if( (width > curCap->sub_max_width) ||
 
804
            (height > curCap->sub_max_height) )
 
805
            return VLC_EGENERIC;
 
806
 
 
807
        if( (p_vout->p_sys->xvmc_backend_subpic =
 
808
                (curCap->flags & XVMC_BACKEND_SUBPICTURE)) )
 
809
            msg_Dbg( p_vout, "using backend subpictures." );
 
810
 
 
811
        if (!p_vout->p_sys->subImage)
 
812
        {
 
813
            XLockDisplay( p_vout->p_sys->p_display );
 
814
            msg_Dbg(p_vout, "xxmc_setup_subpictures");
 
815
#ifdef HAVE_SYS_SHM_H
 
816
            if( p_vout->p_sys->i_shm_opcode )
 
817
            {
 
818
                /* Create image using XShm extension */
 
819
                p_vout->p_sys->subImage = CreateShmImage( p_vout,
 
820
                                            p_vout->p_sys->p_display,
 
821
                                            p_vout->p_sys->i_xvport,
 
822
                                            curCap->subPicType.id,
 
823
                                            /* VLC2X11_FOURCC( p_vout->output. i_chroma ), */
 
824
                                            &p_vout->p_sys->subShmInfo,
 
825
                                            p_vout->output.i_width,
 
826
                                            p_vout->output.i_height );
 
827
            }
 
828
#endif /* HAVE_SYS_SHM_H */
 
829
            XUnlockDisplay( p_vout->p_sys->p_display );
 
830
            if( !p_vout->p_sys->subImage )
 
831
            {
 
832
                msg_Dbg(p_vout, "failed allocating XvImage for supbictures" );
 
833
                return VLC_EGENERIC;
 
834
            }
 
835
        }
 
836
 
 
837
        sp = xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
 
838
                                         width, height,
 
839
                                         curCap->subPicType.id );
 
840
        if( sp )
 
841
        {
 
842
            init_xx44_palette( &p_vout->p_sys->palette, sp->num_palette_entries );
 
843
            p_vout->p_sys->xvmc_palette = (char *) malloc( sp->num_palette_entries
 
844
                    * sp->entry_bytes );
 
845
            xxmc_xvmc_free_subpicture( p_vout, sp);
 
846
            if( !p_vout->p_sys->xvmc_palette )
 
847
                return VLC_EGENERIC;
 
848
            p_vout->p_sys->hwSubpictures = 1;
 
849
        }
 
850
    }
 
851
    return VLC_SUCCESS;
 
852
}
 
853
 
 
854
static void xvmc_check_colorkey_properties( vout_thread_t *p_vout )
 
855
{
 
856
    int num,i;
 
857
    XvAttribute *xvmc_attributes = NULL;
 
858
    Atom ap;
 
859
 
 
860
    /*
 
861
    * Determine if the context is of "Overlay" type. If so,
 
862
    * check whether we can autopaint.
 
863
    */
 
864
    p_vout->p_sys->have_xvmc_autopaint = 0;
 
865
    if( p_vout->p_sys->context_flags & XVMC_OVERLAID_SURFACE )
 
866
    {
 
867
        msg_Dbg( p_vout, "check colorkey properties" );
 
868
        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
869
        xvmc_attributes = XvMCQueryAttributes( p_vout->p_sys->p_display,
 
870
                                               &p_vout->p_sys->context,
 
871
                                               &num );
 
872
        if( xvmc_attributes )
 
873
        {
 
874
            for( i = 0; i < num; ++i )
 
875
            {
 
876
                if( strncmp( "XV_AUTOPAINT_COLORKEY",
 
877
                             xvmc_attributes[i].name,
 
878
                             21) == 0)
 
879
                {
 
880
                    ap = XInternAtom( p_vout->p_sys->p_display,
 
881
                                      "XV_AUTOPAINT_COLORKEY",
 
882
                                       False );
 
883
                    XvMCSetAttribute( p_vout->p_sys->p_display,
 
884
                                      &p_vout->p_sys->context,
 
885
                                      ap,
 
886
                                      1 ); /* p_vout->p_sys->props[VO_PROP_AUTOPAINT_COLORKEY].value */
 
887
                    p_vout->p_sys->have_xvmc_autopaint = 1;
 
888
                    msg_Dbg( p_vout, "has xvmc autopaint" );
 
889
                }
 
890
            }
 
891
        }
 
892
        XFree( xvmc_attributes );
 
893
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
894
        /* p_vout->p_sys->xvmc_xoverlay_type = X11OSD_COLORKEY; */
 
895
    }
 
896
#if 0
 
897
    else
 
898
    {
 
899
        p_vout->p_sys->xvmc_xoverlay_type = X11OSD_SHAPED;
 
900
    }
 
901
#endif
 
902
}
 
903
 
 
904
static void xxmc_xvmc_destroy_surfaces( vout_thread_t *p_vout )
 
905
{
 
906
    int i;
 
907
    xvmc_surface_handler_t *handler = NULL;
 
908
 
 
909
    handler = &p_vout->p_sys->xvmc_surf_handler;
 
910
 
 
911
    pthread_mutex_lock( &handler->mutex );
 
912
    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
 
913
    {
 
914
        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
915
        if( handler->surfValid[i] )
 
916
        {
 
917
            XvMCFlushSurface( p_vout->p_sys->p_display , handler->surfaces+i);
 
918
            XvMCSyncSurface( p_vout->p_sys->p_display, handler->surfaces+i );
 
919
            XvMCHideSurface( p_vout->p_sys->p_display, handler->surfaces+i );
 
920
            XvMCDestroySurface( p_vout->p_sys->p_display, handler->surfaces+i );
 
921
        }
 
922
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
923
        handler->surfValid[i] = 0;
 
924
    }
 
925
    pthread_mutex_unlock( &handler->mutex );
 
926
}
 
927
 
 
928
static void xxmc_xvmc_destroy_subpictures( vout_thread_t *p_vout )
 
929
{
 
930
    int i;
 
931
    xvmc_surface_handler_t *handler = NULL;
 
932
 
 
933
    handler = &p_vout->p_sys->xvmc_surf_handler;
 
934
 
 
935
    pthread_mutex_lock( &handler->mutex );
 
936
    for( i = 0; i < XVMC_MAX_SUBPICTURES; ++i )
 
937
    {
 
938
        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
939
        if( handler->subValid[i] )
 
940
        {
 
941
            XvMCFlushSubpicture( p_vout->p_sys->p_display , handler->subpictures+i);
 
942
            XvMCSyncSubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
 
943
            XvMCDestroySubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
 
944
        }
 
945
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
946
        handler->subValid[i] = 0;
 
947
    }
 
948
    pthread_mutex_unlock( &handler->mutex );
 
949
}
 
950
 
 
951
static XvMCSurface *xxmc_xvmc_alloc_surface( vout_thread_t *p_vout,
 
952
        XvMCContext *context )
 
953
{
 
954
    xvmc_surface_handler_t *handler = NULL;
 
955
    int i;
 
956
 
 
957
    handler = &p_vout->p_sys->xvmc_surf_handler;
 
958
 
 
959
    pthread_mutex_lock( &handler->mutex );
 
960
    xxmc_xvmc_dump_surfaces( p_vout );
 
961
    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
 
962
    {
 
963
        if( handler->surfValid[i] && !handler->surfInUse[i] )
 
964
        {
 
965
            handler->surfInUse[i] = 1;
 
966
            msg_Dbg( p_vout, "reusing surface %d", i );
 
967
            xxmc_xvmc_dump_surfaces( p_vout );
 
968
            pthread_mutex_unlock( &handler->mutex );
 
969
            return (handler->surfaces + i);
 
970
        }
 
971
    }
 
972
    for( i = 0; i < XVMC_MAX_SURFACES; ++i )
 
973
    {
 
974
        if( !handler->surfInUse[i] )
 
975
        {
 
976
            XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
977
            if( Success != XvMCCreateSurface( p_vout->p_sys->p_display,
 
978
                                              context,
 
979
                                              handler->surfaces + i) )
 
980
            {
 
981
                XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
982
                pthread_mutex_unlock( &handler->mutex );
 
983
                return NULL;
 
984
            }
 
985
            XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
986
 
 
987
            msg_Dbg( p_vout, "created surface %d", i );
 
988
            handler->surfInUse[i] = 1;
 
989
            handler->surfValid[i] = 1;
 
990
            pthread_mutex_unlock( &handler->mutex );
 
991
            return (handler->surfaces + i);
 
992
        }
 
993
    }
 
994
    pthread_mutex_unlock( &handler->mutex );
 
995
    return NULL;
 
996
}
 
997
 
 
998
void xxmc_dispose_context( vout_thread_t *p_vout )
 
999
{
 
1000
    if( p_vout->p_sys->contextActive )
 
1001
    {
 
1002
        if( p_vout->p_sys->xvmc_accel &
 
1003
            (VLC_XVMC_ACCEL_MOCOMP | VLC_XVMC_ACCEL_IDCT) )
 
1004
        {
 
1005
            xvmc_macroblocks_t *macroblocks = NULL;
 
1006
 
 
1007
            macroblocks = &p_vout->p_sys->macroblocks;
 
1008
            XvMCDestroyMacroBlocks( p_vout->p_sys->p_display,
 
1009
                                    &macroblocks->macro_blocks );
 
1010
            XvMCDestroyBlocks( p_vout->p_sys->p_display,
 
1011
                               &macroblocks->blocks );
 
1012
        }
 
1013
 
 
1014
        msg_Dbg( p_vout, "freeing up XvMC surfaces and subpictures" );
 
1015
        if( p_vout->p_sys->xvmc_palette )
 
1016
            free( p_vout->p_sys->xvmc_palette );
 
1017
        dispose_xx44_palette( &p_vout->p_sys->palette );
 
1018
        xxmc_xvmc_destroy_subpictures( p_vout );
 
1019
        xxmc_xvmc_destroy_surfaces( p_vout );
 
1020
 
 
1021
        msg_Dbg(p_vout, "freeing up XvMC Context.");
 
1022
        XLockDisplay( p_vout->p_sys->p_display );
 
1023
        if( p_vout->p_sys->subImage )
 
1024
        {
 
1025
            XFree( p_vout->p_sys->subImage );
 
1026
            p_vout->p_sys->subImage = NULL;
 
1027
        }
 
1028
        p_vout->p_sys->subImage = NULL;
 
1029
        XUnlockDisplay( p_vout->p_sys->p_display );
 
1030
        XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1031
        XvMCDestroyContext( p_vout->p_sys->p_display,
 
1032
                            &p_vout->p_sys->context );
 
1033
        XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1034
        p_vout->p_sys->contextActive = 0;
 
1035
        p_vout->p_sys->hwSubpictures = 0;
 
1036
        p_vout->p_sys->xvmc_accel = 0;
 
1037
    }
 
1038
}
 
1039
 
 
1040
static int xxmc_find_context( vout_thread_t *p_vout, vlc_xxmc_t *xxmc,
 
1041
        unsigned int width, unsigned int height )
 
1042
{
 
1043
    unsigned int i, k;
 
1044
    bool found = false;
 
1045
    xvmc_capabilities_t *curCap = NULL;
 
1046
    unsigned int request_mpeg_flags, request_accel_flags;
 
1047
 
 
1048
    request_mpeg_flags = xxmc->mpeg;
 
1049
    for( k = 0; k < NUM_ACCEL_PRIORITY; ++k )
 
1050
    {
 
1051
        request_accel_flags = xxmc->acceleration & accel_priority[k];
 
1052
        if( !request_accel_flags )
 
1053
            continue;
 
1054
 
 
1055
        curCap = p_vout->p_sys->xvmc_cap;
 
1056
        for( i =0; i < p_vout->p_sys->xvmc_num_cap; ++i )
 
1057
        {
 
1058
            msg_Dbg( p_vout, "surface type %d, capabilities 0x%8x 0x%8x",
 
1059
                             i,
 
1060
                             curCap->mpeg_flags,
 
1061
                             curCap->accel_flags );
 
1062
            msg_Dbg( p_vout, "fequests: 0x%8x 0x%8x",
 
1063
                             request_mpeg_flags,
 
1064
                             request_accel_flags );
 
1065
            if( ( (curCap->mpeg_flags & request_mpeg_flags) == request_mpeg_flags) &&
 
1066
                  (curCap->accel_flags & request_accel_flags) &&
 
1067
                  (width <= curCap->max_width) &&
 
1068
                  (height <= curCap->max_height) )
 
1069
            {
 
1070
                found = true;
 
1071
                break;
 
1072
            }
 
1073
            curCap++;
 
1074
        }
 
1075
        if( found )
 
1076
        {
 
1077
            p_vout->p_sys->xvmc_cur_cap = i;
 
1078
            break;
 
1079
        }
 
1080
    }
 
1081
    if( found )
 
1082
    {
 
1083
        p_vout->p_sys->xvmc_accel = request_accel_flags;
 
1084
        p_vout->p_sys->unsigned_intra = (curCap->flags & XVMC_INTRA_UNSIGNED);
 
1085
        return 1;
 
1086
    }
 
1087
    p_vout->p_sys->xvmc_accel = 0;
 
1088
    return 0;
 
1089
}
 
1090
 
 
1091
static int xxmc_create_context( vout_thread_t *p_vout,
 
1092
        unsigned int width, unsigned int height )
 
1093
{
 
1094
    xvmc_capabilities_t *curCap = NULL;
 
1095
 
 
1096
    curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
 
1097
 
 
1098
    msg_Dbg( p_vout, "creating new XvMC context %d", curCap->type_id );
 
1099
 
 
1100
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1101
    if( Success == XvMCCreateContext( p_vout->p_sys->p_display,
 
1102
                                      p_vout->p_sys->i_xvport,
 
1103
                                      curCap->type_id,
 
1104
                                      width,
 
1105
                                      height,
 
1106
                                      p_vout->p_sys->context_flags,
 
1107
                                      &p_vout->p_sys->context ) )
 
1108
    {
 
1109
        p_vout->p_sys->xvmc_mpeg = curCap->mpeg_flags;
 
1110
        p_vout->p_sys->xvmc_width = width;
 
1111
        p_vout->p_sys->xvmc_height = height;
 
1112
        p_vout->p_sys->contextActive = 1;
 
1113
    }
 
1114
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1115
    return p_vout->p_sys->contextActive;
 
1116
}
 
1117
 
 
1118
static void xvmc_flushsync(picture_t *picture)
 
1119
{
 
1120
    vout_thread_t *p_vout = picture->p_sys->p_vout;
 
1121
 
 
1122
    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
 
1123
 
 
1124
    if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
 
1125
    {
 
1126
        msg_Dbg(p_vout, "xvmc_flushsync 1 : %d", picture->p_sys->xxmc_data.result );
 
1127
        picture->p_sys->xxmc_data.result = 128;
 
1128
        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1129
        return;
 
1130
    }
 
1131
 
 
1132
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1133
    picture->p_sys->xxmc_data.result =
 
1134
            XvMCFlushSurface( p_vout->p_sys->p_display,
 
1135
                              picture->p_sys->xvmc_surf );
 
1136
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1137
    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1138
}
 
1139
 
 
1140
static void xvmc_flush(picture_t *picture)
 
1141
{
 
1142
    vout_thread_t *p_vout = picture->p_sys->p_vout;
 
1143
 
 
1144
    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
 
1145
 
 
1146
    if ( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
 
1147
    {
 
1148
        msg_Dbg(p_vout, "xvmc flush 1 : %d", picture->p_sys->xxmc_data.result );
 
1149
        picture->p_sys->xxmc_data.result = 128;
 
1150
        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1151
        return;
 
1152
    }
 
1153
 
 
1154
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1155
    picture->p_sys->xxmc_data.result =
 
1156
            XvMCFlushSurface( p_vout->p_sys->p_display,
 
1157
                              picture->p_sys->xvmc_surf );
 
1158
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1159
    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1160
}
 
1161
 
 
1162
static int xxmc_frame_updates( vout_thread_t *p_vout, picture_t *picture )
 
1163
{
 
1164
    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
 
1165
 
 
1166
    /*
 
1167
     * If we have changed context since the surface was updated, xvmc_surf
 
1168
     * is either NULL or invalid. If it is invalid. Set it to NULL.
 
1169
     * Also if there are other users of this surface, deregister our use of
 
1170
     * it and later try to allocate a new, fresh one.
 
1171
     */
 
1172
 
 
1173
    if( picture->p_sys->xvmc_surf )
 
1174
    {
 
1175
        if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
 
1176
        {
 
1177
            xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
 
1178
            picture->p_sys->xvmc_surf = NULL;
 
1179
        }
 
1180
    }
 
1181
#if 0
 
1182
    if( picture->p_sys->p_image )
 
1183
    {
 
1184
        memset( picture->p_sys->p_image->data, 0,
 
1185
                picture->p_sys->p_image->width
 
1186
                    * picture->p_sys->p_image->height );
 
1187
    }
 
1188
#endif
 
1189
    /*
 
1190
     * If it is NULL create a new surface.
 
1191
     */
 
1192
    if( !picture->p_sys->xvmc_surf )
 
1193
    {
 
1194
        picture->p_sys->xvmc_surf = xxmc_xvmc_alloc_surface( p_vout,
 
1195
                                                    &p_vout->p_sys->context );
 
1196
        if( !picture->p_sys->xvmc_surf )
 
1197
        {
 
1198
            msg_Err( p_vout, "accelerated surface allocation failed.\n"
 
1199
                            " You are probably out of framebuffer memory.\n"
 
1200
                            " Falling back to software decoding." );
 
1201
            p_vout->p_sys->xvmc_accel = 0;
 
1202
            xxmc_dispose_context( p_vout );
 
1203
            return VLC_EGENERIC;
 
1204
        }
 
1205
    }
 
1206
    xxmc->acceleration = p_vout->p_sys->xvmc_accel;
 
1207
 
 
1208
    xxmc->proc_xxmc_flush = xvmc_flush;
 
1209
    xxmc->proc_xxmc_flushsync = xvmc_flushsync;
 
1210
    xxmc->xvmc.proc_macro_block = NULL;
 
1211
#if 0
 
1212
    frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data;
 
1213
#endif
 
1214
    xxmc->proc_xxmc_begin = xvmc_vld_frame;
 
1215
    xxmc->proc_xxmc_slice = xvmc_vld_slice;
 
1216
    return VLC_SUCCESS;
 
1217
}
 
1218
 
 
1219
static int xxmc_xvmc_update_context( vout_thread_t *p_vout,
 
1220
    picture_t *picture, uint32_t width, uint32_t height )
 
1221
{
 
1222
    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
 
1223
 
 
1224
    /*
 
1225
     * Are we at all capable of doing XvMC ?
 
1226
     */
 
1227
    if( p_vout->p_sys->xvmc_cap == 0 )
 
1228
        return VLC_EGENERIC;
 
1229
 
 
1230
    msg_Dbg( p_vout, "new format: need to change XvMC context. "
 
1231
                     "width: %d height: %d mpeg: %d acceleration: %d",
 
1232
                     width, height,
 
1233
                     xxmc->mpeg, xxmc->acceleration );
 
1234
 
 
1235
    if( picture->p_sys->xvmc_surf )
 
1236
        xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
 
1237
    picture->p_sys->xvmc_surf = NULL;
 
1238
 
 
1239
    xxmc_dispose_context( p_vout );
 
1240
 
 
1241
    if( xxmc_find_context( p_vout, xxmc, width, height ) )
 
1242
    {
 
1243
        xxmc_create_context( p_vout, width, height);
 
1244
        xvmc_check_colorkey_properties( p_vout );
 
1245
        xxmc_setup_subpictures(p_vout, width, height);
 
1246
    }
 
1247
 
 
1248
    if( !p_vout->p_sys->contextActive )
 
1249
    {
 
1250
        msg_Dbg( p_vout, "using software decoding for this stream" );
 
1251
        p_vout->p_sys->xvmc_accel = 0;
 
1252
    }
 
1253
    else
 
1254
    {
 
1255
        msg_Dbg(p_vout, "using hardware decoding for this stream." );
 
1256
    }
 
1257
 
 
1258
    p_vout->p_sys->xvmc_mpeg = xxmc->mpeg;
 
1259
    p_vout->p_sys->xvmc_width = width;
 
1260
    p_vout->p_sys->xvmc_height = height;
 
1261
    return p_vout->p_sys->contextActive;
 
1262
}
 
1263
 
 
1264
 
 
1265
void xxmc_do_update_frame( picture_t *picture, uint32_t width, uint32_t height,
 
1266
        double ratio, int format, int flags)
 
1267
{
 
1268
    vout_thread_t *p_vout = picture->p_sys->p_vout;
 
1269
    int indextime = 0;
 
1270
    int status = 0;
 
1271
 
 
1272
    picture->p_sys->xxmc_data.decoded = 0;
 
1273
    picture->p_sys->nb_display = 0;
 
1274
    picture->b_force = 0;
 
1275
    vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
 
1276
 
 
1277
    xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock);
 
1278
    if( (p_vout->p_sys->last_accel_request != xxmc->acceleration) ||
 
1279
        (p_vout->p_sys->xvmc_mpeg != xxmc->mpeg) ||
 
1280
        (p_vout->p_sys->xvmc_width != width) ||
 
1281
        (p_vout->p_sys->xvmc_height != height))
 
1282
    {
 
1283
        p_vout->p_sys->last_accel_request = xxmc->acceleration;
 
1284
        xxmc_xvmc_update_context( p_vout, picture, width, height );
 
1285
    }
 
1286
 
 
1287
    if( p_vout->p_sys->contextActive )
 
1288
        xxmc_frame_updates( p_vout, picture );
 
1289
 
 
1290
    if( !p_vout->p_sys->contextActive )
 
1291
    {
 
1292
        xxmc->acceleration = 0;
 
1293
        xxmc->xvmc.macroblocks = 0;
 
1294
    }
 
1295
    else
 
1296
    {
 
1297
        picture->format.i_chroma = format;
 
1298
    }
 
1299
    xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock);
 
1300
 
 
1301
    XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
 
1302
                          picture->p_sys->xvmc_surf,
 
1303
                          &status );
 
1304
    /* Wait a little till frame is being displayed */
 
1305
    while( status & XVMC_DISPLAYING )
 
1306
    {
 
1307
        msleep(1);
 
1308
 
 
1309
        XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
 
1310
                              picture->p_sys->xvmc_surf,
 
1311
                              &status );
 
1312
 
 
1313
        indextime++;
 
1314
        if( indextime > 4 )
 
1315
            break;
 
1316
    }
 
1317
}
 
1318
 
 
1319
#if 0
 
1320
/* called xlocked */
 
1321
static void dispose_ximage( vout_thread_t *p_vout, XShmSegmentInfo *shminfo,
 
1322
                XvImage *myimage )
 
1323
{
 
1324
# ifdef HAVE_SYS_SHM_H
 
1325
    if( p_vout->p_sys->i_shm_opcode )
 
1326
    {
 
1327
        XShmDetach( p_vout->p_sys->p_display, shminfo );
 
1328
        XFree( myimage );
 
1329
        shmdt( shminfo->shmaddr );
 
1330
        if( shminfo->shmid >= 0 )
 
1331
        {
 
1332
            shmctl( shminfo->shmid, IPC_RMID, 0 );
 
1333
            shminfo->shmid = -1;
 
1334
        }
 
1335
    }
 
1336
    else
 
1337
#endif
 
1338
    {
 
1339
        if( myimage->data )
 
1340
            free(myimage->data);
 
1341
        XFree (myimage);
 
1342
    }
 
1343
}
 
1344
#endif
 
1345
 
 
1346
void xvmc_vld_frame( picture_t *picture )
 
1347
{
 
1348
    picture_sys_t *p_sys  = picture->p_sys;
 
1349
    vout_thread_t *p_vout = p_sys->p_vout;
 
1350
    vlc_vld_frame_t *vft  = &(p_sys->xxmc_data.vld_frame);
 
1351
    picture_t *ff         = (picture_t *) vft->forward_reference_picture;
 
1352
    picture_t *bf         = (picture_t *) vft->backward_reference_picture;
 
1353
    XvMCMpegControl ctl;
 
1354
    XvMCSurface *fs=0, *bs=0;
 
1355
    XvMCQMatrix qmx;
 
1356
 
 
1357
    ctl.BHMV_range = vft->mv_ranges[0][0];
 
1358
    ctl.BVMV_range = vft->mv_ranges[0][1];
 
1359
    ctl.FHMV_range = vft->mv_ranges[1][0];
 
1360
    ctl.FVMV_range = vft->mv_ranges[1][1];
 
1361
    ctl.picture_structure = vft->picture_structure;
 
1362
    ctl.intra_dc_precision = vft->intra_dc_precision;
 
1363
    ctl.picture_coding_type = vft->picture_coding_type;
 
1364
    ctl.mpeg_coding = (vft->mpeg_coding == 0) ? XVMC_MPEG_1 : XVMC_MPEG_2;
 
1365
    ctl.flags = 0;
 
1366
    ctl.flags |= (vft->progressive_sequence) ? XVMC_PROGRESSIVE_SEQUENCE : 0;
 
1367
    ctl.flags |= (vft->scan) ? XVMC_ALTERNATE_SCAN : XVMC_ZIG_ZAG_SCAN;
 
1368
    ctl.flags |= (vft->pred_dct_frame) ?
 
1369
                    XVMC_PRED_DCT_FRAME : XVMC_PRED_DCT_FIELD;
 
1370
    ctl.flags |= (picture->b_top_field_first) ?
 
1371
                    XVMC_TOP_FIELD_FIRST : XVMC_BOTTOM_FIELD_FIRST;
 
1372
    ctl.flags |= (vft->concealment_motion_vectors) ?
 
1373
                    XVMC_CONCEALMENT_MOTION_VECTORS : 0;
 
1374
    ctl.flags |= (vft->q_scale_type) ? XVMC_Q_SCALE_TYPE : 0;
 
1375
    ctl.flags |= (vft->intra_vlc_format) ? XVMC_INTRA_VLC_FORMAT : 0;
 
1376
    ctl.flags |= (vft->second_field) ? XVMC_SECOND_FIELD : 0;
 
1377
 
 
1378
    if( ff )
 
1379
        fs = ff->p_sys->xvmc_surf;
 
1380
    if( bf )
 
1381
        bs = bf->p_sys->xvmc_surf;
 
1382
 
 
1383
    /*
 
1384
     * Below is for interlaced streams and second_field.
 
1385
     */
 
1386
    if( ctl.picture_coding_type == P_TYPE ) /* XVMC_P_PICTURE) */
 
1387
        bs = picture->p_sys->xvmc_surf;
 
1388
 
 
1389
    if( (qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix) )
 
1390
    {
 
1391
        memcpy( qmx.intra_quantiser_matrix, vft->intra_quantizer_matrix,
 
1392
                sizeof(qmx.intra_quantiser_matrix) );
 
1393
    }
 
1394
    if( (qmx.load_non_intra_quantiser_matrix =
 
1395
                vft->load_non_intra_quantizer_matrix) )
 
1396
    {
 
1397
        memcpy( qmx.non_intra_quantiser_matrix, vft->non_intra_quantizer_matrix,
 
1398
               sizeof(qmx.non_intra_quantiser_matrix) );
 
1399
    }
 
1400
    qmx.load_chroma_intra_quantiser_matrix = 0;
 
1401
    qmx.load_chroma_non_intra_quantiser_matrix = 0;
 
1402
    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
 
1403
 
 
1404
    if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
 
1405
    {
 
1406
        picture->p_sys->xxmc_data.result = 128;
 
1407
        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1408
        return;
 
1409
    }
 
1410
 
 
1411
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1412
    XvMCLoadQMatrix( p_vout->p_sys->p_display, &p_vout->p_sys->context, &qmx );
 
1413
    do {
 
1414
        picture->p_sys->xxmc_data.result =
 
1415
                XvMCBeginSurface( p_vout->p_sys->p_display,
 
1416
                                  &p_vout->p_sys->context,
 
1417
                                  picture->p_sys->xvmc_surf,
 
1418
                                  fs, bs, &ctl );
 
1419
    } while( !picture->p_sys->xxmc_data.result );
 
1420
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1421
    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1422
}
 
1423
 
 
1424
void xvmc_vld_slice( picture_t *picture )
 
1425
{
 
1426
    picture_sys_t *p_sys  = picture->p_sys;
 
1427
    vout_thread_t *p_vout = p_sys->p_vout;
 
1428
 
 
1429
    xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
 
1430
    if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
 
1431
    {
 
1432
        picture->p_sys->xxmc_data.result = 128;
 
1433
        xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1434
        msg_Err(p_vout, "vld slice error" );
 
1435
        return;
 
1436
    }
 
1437
 
 
1438
    XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
 
1439
    picture->p_sys->xxmc_data.result =
 
1440
            XvMCPutSlice2( p_vout->p_sys->p_display,
 
1441
                           &p_vout->p_sys->context,
 
1442
                            (char *)picture->p_sys->xxmc_data.slice_data,
 
1443
                            picture->p_sys->xxmc_data.slice_data_size,
 
1444
                            picture->p_sys->xxmc_data.slice_code );
 
1445
 
 
1446
    if( picture->p_sys->xxmc_data.result != 0 )
 
1447
        msg_Err( p_vout, "vlc slice error %d",
 
1448
                 picture->p_sys->xxmc_data.result );
 
1449
    /*
 
1450
     * If CPU-saving mode is enabled, sleep after every xxmc->sleep slice. This will free
 
1451
     * up the cpu while the decoder is working on the slice. The value of xxmc->sleep is calculated
 
1452
     * so that the decoder thread sleeps at most 50% of the frame delay,
 
1453
     * assuming a 2.6 kernel clock of 1000 Hz.
 
1454
     */
 
1455
    XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
 
1456
    xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
 
1457
#if 0
 
1458
    if( p_vout->p_sys->cpu_save_enabled )
 
1459
    {
 
1460
        p_vout->p_sys->cpu_saver += 1.;
 
1461
        if( p_vout->p_sys->cpu_saver >= picture->p_sys->xxmc_data.sleep )
 
1462
        {
 
1463
            usleep(1);
 
1464
            p_vout->p_sys->cpu_saver -= picture->p_sys->xxmc_data.sleep;
 
1465
        }
 
1466
    }
 
1467
#endif
 
1468
}