1
/*****************************************************************************
2
* xvmc.c : XVMC plugin for vlc
3
*****************************************************************************
4
* Copyright (C) 1998-2001 VideoLAN
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>
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.
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.
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
*****************************************************************************/
28
/*****************************************************************************
30
*****************************************************************************/
36
#include <vlc_common.h>
37
#include <vlc_plugin.h>
38
#include <vlc_interface.h>
42
#ifdef HAVE_MACHINE_PARAM_H
44
# include <machine/param.h>
45
# include <sys/types.h> /* typedef ushort */
50
# include <netinet/in.h> /* BSD: struct in_addr */
54
# include <sys/shm.h> /* shmget(), shmctl() */
59
#include <X11/Xutil.h>
60
#include <X11/keysym.h>
62
# include <X11/extensions/XShm.h>
64
#ifdef DPMSINFO_IN_DPMS_H
65
# include <X11/extensions/dpms.h>
68
#include <X11/extensions/Xv.h>
69
#include <X11/extensions/Xvlib.h>
70
#include <X11/extensions/vldXvMC.h>
72
#include "../../codec/xvmc/accel_xvmc.h"
74
#include "../../codec/spudec/spudec.h"
77
/* picture structure */
79
#define BOTTOM_FIELD 2
80
#define FRAME_PICTURE 3
82
/* picture coding type */
88
/*****************************************************************************
90
*****************************************************************************/
91
extern int Activate ( vlc_object_t * );
92
extern void Deactivate ( vlc_object_t * );
94
/*****************************************************************************
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).")
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.")
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.")
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.")
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.")
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.")
130
#define MODE_TEXT N_("Deinterlace mode")
131
#define MODE_LONGTEXT N_("You can choose the default deinterlace mode")
133
#define CROP_TEXT N_("Crop")
134
#define CROP_LONGTEXT N_("You can choose the crop style to apply.")
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 );
146
add_integer ( "xvmc-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, true );
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 );
151
set_description( N_("XVMC extension video output") );
152
set_capability( "video output", 10 );
153
set_callbacks( Activate, Deactivate );
156
/* following functions are local */
158
static const unsigned accel_priority[] = {
162
#define NUM_ACCEL_PRIORITY (sizeof(accel_priority)/sizeof(accel_priority[0]))
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.
172
static void init_context_lock( context_lock_t *c )
174
pthread_cond_init(&c->cond,NULL);
175
pthread_mutex_init(&c->mutex,NULL);
179
void free_context_lock( context_lock_t *c )
181
pthread_mutex_destroy(&c->mutex);
182
pthread_cond_destroy(&c->cond);
185
void xvmc_context_reader_lock( context_lock_t *c )
187
pthread_mutex_lock(&c->mutex);
189
pthread_mutex_unlock(&c->mutex);
192
void xvmc_context_reader_unlock( context_lock_t *c )
194
pthread_mutex_lock(&c->mutex);
195
if (c->num_readers > 0) {
196
if (--(c->num_readers) == 0) {
197
pthread_cond_broadcast(&c->cond);
200
pthread_mutex_unlock(&c->mutex);
203
void xvmc_context_writer_lock( context_lock_t *c )
205
pthread_mutex_lock(&c->mutex);
206
while(c->num_readers) {
207
pthread_cond_wait( &c->cond, &c->mutex );
211
void xvmc_context_writer_unlock( context_lock_t *c )
213
pthread_mutex_unlock( &c->mutex );
216
void clear_xx44_palette( xx44_palette_t *p )
219
uint32_t *cluts = p->cluts;
220
int *ids = p->lookup_cache;
225
i = 2*OVL_PALETTE_SIZE;
231
static void init_xx44_palette( xx44_palette_t *p, unsigned num_entries )
233
p->size = (num_entries > XX44_PALETTE_SIZE) ?
234
XX44_PALETTE_SIZE : num_entries;
237
static void dispose_xx44_palette(xx44_palette_t *p)
242
static void colorToPalette( const uint32_t *icolor, unsigned char *palette_p,
243
unsigned num_xvmc_components, char *xvmc_components )
245
const clut_t *color = (const clut_t *) icolor;
248
for (i=0; i<num_xvmc_components; ++i)
250
switch(xvmc_components[i])
252
case 'V': *palette_p = color->cr; break;
253
case 'U': *palette_p = color->cb; break;
255
default: *palette_p = color->y; break;
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 )
267
const uint32_t *cluts = p->cluts + first_xx44_entry;
269
for( i=0; i<num_xx44_entries; ++i )
271
if( (cluts - p->cluts) < p->size )
273
colorToPalette( cluts++, xvmc_palette,
274
num_xvmc_components, xvmc_components );
275
xvmc_palette += num_xvmc_components;
280
static int xx44_paletteIndex( xx44_palette_t *p, int color, uint32_t clut )
283
uint32_t *cluts = p->cluts;
286
if( (tmp = p->lookup_cache[color]) >= 0 )
288
if (cluts[tmp] == clut)
291
for (i=0; i<p->max_used; ++i)
293
if (*cluts++ == clut) {
294
p->lookup_cache[color] = i;
295
return p->lookup_cache[color];
299
if( p->max_used == (p->size -1) )
301
//printf("video_out: Warning! Out of xx44 palette colors!\n");
304
p->cluts[p->max_used] = clut;
305
p->lookup_cache[color] = p->max_used++;
306
return p->lookup_cache[color];
309
static void memblend_xx44( uint8_t *mem, uint8_t val,
310
size_t size, uint8_t mask )
312
uint8_t masked_val = val & mask;
314
/* size_t is unsigned, therefore always positive
320
if( (*mem & mask) <= masked_val )
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 )
336
uint8_t norm_pixel,clip_pixel;
342
uint16_t *p_source = NULL;
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;
354
dst_y = dst_img + dst_pitch*y_off + x_off;
356
if( (x_off + sub_img->i_width) <= dst_width )
357
clip_right = sub_img->i_width;
359
clip_right = dst_width - x_off;
361
if ((src_height + y_off) > dst_height)
362
src_height = dst_height - y_off;
364
for (y = 0; y < src_height; y++)
366
mask = !( (y < sub_img->p_sys->i_y_start) ||
367
(y >= sub_img->p_sys->i_y_end) );
370
for (x = 0; x < src_width;)
372
i_color = *p_source & 0x3;
373
i_len = *p_source++ >> 2;
375
if( (i_len > 0) && ((x+i_len) <= src_width) )
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);
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));
392
norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
393
clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
397
if( x < sub_img->p_sys->i_x_start )
399
if( (x + i_len) <= sub_img->p_sys->i_x_start )
401
memblend_xx44( dst, norm_pixel, i_len, alphamask );
406
memblend_xx44( dst, norm_pixel,
407
sub_img->p_sys->i_x_start - x,
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) )
414
memblend_xx44( dst, clip_pixel,
420
memblend_xx44( dst, clip_pixel,
421
sub_img->p_sys->i_x_end -
422
sub_img->p_sys->i_x_start,
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,
434
else if( x < sub_img->p_sys->i_x_end )
436
if( i_len <= (sub_img->p_sys->i_x_end - x) )
438
memblend_xx44( dst, clip_pixel, i_len, alphamask);
443
memblend_xx44( dst, clip_pixel,
444
sub_img->p_sys->i_x_end - x,
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);
454
memblend_xx44( dst, norm_pixel, i_len, alphamask );
460
memblend_xx44( dst, norm_pixel, i_len, alphamask );
475
int xxmc_xvmc_surface_valid( vout_thread_t *p_vout, XvMCSurface *surf )
477
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
478
unsigned long index = surf - handler->surfaces;
481
if( index >= XVMC_MAX_SURFACES )
483
pthread_mutex_lock(&handler->mutex);
484
ret = handler->surfValid[index];
485
pthread_mutex_unlock(&handler->mutex);
489
static void xxmc_xvmc_dump_subpictures( vout_thread_t *p_vout )
492
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
494
for( i=0; i < XVMC_MAX_SUBPICTURES; ++i )
496
msg_Dbg( p_vout, "handler in use %d, valid %d",
497
handler->subInUse[i],
498
handler->subValid[i]);
502
XvMCSubpicture *xxmc_xvmc_alloc_subpicture( vout_thread_t *p_vout,
503
XvMCContext *context, unsigned short width,
504
unsigned short height, int xvimage_id )
507
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
510
pthread_mutex_lock(&handler->mutex);
511
/* xxmc_xvmc_dump_subpictures(p_vout); */
512
for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
514
if( handler->subValid[i] && !handler->subInUse[i] )
516
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
517
if( XvMCGetSubpictureStatus( p_vout->p_sys->p_display,
518
handler->subpictures + i,
521
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
524
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
525
if( status & XVMC_DISPLAYING )
527
handler->subInUse[i] = 1;
528
/* xxmc_xvmc_dump_subpictures(p_vout); */
529
pthread_mutex_unlock(&handler->mutex);
530
return (handler->subpictures + i);
533
for (i=0; i<XVMC_MAX_SUBPICTURES; ++i)
535
if( !handler->subInUse[i] )
537
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
538
if( Success != XvMCCreateSubpicture( p_vout->p_sys->p_display,
540
handler->subpictures + i,
541
width, height, xvimage_id ) )
543
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
544
pthread_mutex_unlock( &handler->mutex );
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);
555
pthread_mutex_unlock( &handler->mutex );
559
void xxmc_xvmc_free_subpicture( vout_thread_t *p_vout, XvMCSubpicture *sub )
561
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
562
unsigned int index = sub - handler->subpictures;
564
if( index >= XVMC_MAX_SUBPICTURES )
567
pthread_mutex_lock( &handler->mutex );
568
handler->subInUse[index] = 0;
569
/* xxmc_xvmc_dump_subpictures(p_vout); */
570
pthread_mutex_unlock( &handler->mutex );
573
static void xxmc_xvmc_surface_handler_construct( vout_thread_t *p_vout )
576
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
578
pthread_mutex_init( &handler->mutex, NULL );
579
for( i=0; i<XVMC_MAX_SURFACES; ++i )
581
handler->surfInUse[i] = 0;
582
handler->surfValid[i] = 0;
584
for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
586
handler->subInUse[i] = 0;
587
handler->subValid[i] = 0;
591
static void xxmc_xvmc_dump_surfaces( vout_thread_t *p_vout )
594
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
596
for (i=0; i<XVMC_MAX_SURFACES; ++i)
598
msg_Dbg(p_vout, "surfaces in use %d, valid %d;",
599
handler->surfInUse[i],
600
handler->surfValid[i]);
604
void xxmc_xvmc_free_surface( vout_thread_t *p_vout, XvMCSurface *surf )
606
xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
607
unsigned int index = 0;
609
index = (surf - handler->surfaces);
611
if (index < XVMC_MAX_SURFACES)
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);
621
int checkXvMCCap( vout_thread_t *p_vout )
627
XvMCSurfaceInfo *surfaceInfo =NULL;
628
XvMCSurfaceInfo *curInfo = NULL;
630
xvmc_capabilities_t *curCap = NULL;
631
XvImageFormatValues *formatValues = NULL;
633
i_xvport = p_vout->p_sys->i_xvport;
634
p_vout->p_sys->xvmc_cap = 0;
636
init_context_lock( &p_vout->p_sys->xvmc_lock );
637
xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
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;
646
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
648
if( !XvMCQueryExtension( p_vout->p_sys->p_display,
649
&p_vout->p_sys->xvmc_eventbase,
650
&p_vout->p_sys->xvmc_errbase ) )
652
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
653
xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
656
msg_Dbg( p_vout,"XvMC extension found" );
658
surfaceInfo = XvMCListSurfaceTypes(p_vout->p_sys->p_display, i_xvport, &numSurf);
661
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
662
xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
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 )
671
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
672
xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
676
p_vout->p_sys->xvmc_num_cap = numSurf;
677
curInfo = surfaceInfo;
678
curCap = p_vout->p_sys->xvmc_cap;
680
msg_Dbg( p_vout,"found %d XvMC surface types", numSurf );
682
for( i=0; i< numSurf; ++i )
684
curCap->mpeg_flags = 0;
685
curCap->accel_flags = 0;
686
if( curInfo->chroma_format == XVMC_CHROMA_FORMAT_420 )
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;
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);
711
curCap->type_id = curInfo->surface_type_id;
712
formatValues = XvMCListSubpictureTypes( p_vout->p_sys->p_display,
716
curCap->subPicType.id = 0;
719
msg_Dbg( p_vout, "surface type %d: found %d XvMC subpicture types",
721
for( j = 0; j<numSub; ++j )
723
if( formatValues[j].id == FOURCC_IA44 )
725
curCap->subPicType = formatValues[j];
727
"surface type %d: detected and using "
728
"IA44 subpicture type.", i );
732
else if( formatValues[j].id == FOURCC_AI44 )
734
curCap->subPicType = formatValues[j];
736
"surface type %d: detected AI44 "
737
"subpicture type.", i );
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.
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,
760
msg_Dbg( p_vout, "using direct XVMC rendering context" );
761
p_vout->p_sys->context_flags = XVMC_DIRECT;
763
else if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
769
msg_Dbg( p_vout, "using default XVMC rendering context" );
770
p_vout->p_sys->context_flags = 0;
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 );
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 );
793
static int xxmc_setup_subpictures( vout_thread_t *p_vout,
794
unsigned int width, unsigned int height )
796
xvmc_capabilities_t *curCap = NULL;
797
XvMCSubpicture *sp = NULL;
799
if( p_vout->p_sys->contextActive )
801
curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
803
if( (width > curCap->sub_max_width) ||
804
(height > curCap->sub_max_height) )
807
if( (p_vout->p_sys->xvmc_backend_subpic =
808
(curCap->flags & XVMC_BACKEND_SUBPICTURE)) )
809
msg_Dbg( p_vout, "using backend subpictures." );
811
if (!p_vout->p_sys->subImage)
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 )
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 );
828
#endif /* HAVE_SYS_SHM_H */
829
XUnlockDisplay( p_vout->p_sys->p_display );
830
if( !p_vout->p_sys->subImage )
832
msg_Dbg(p_vout, "failed allocating XvImage for supbictures" );
837
sp = xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
839
curCap->subPicType.id );
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
845
xxmc_xvmc_free_subpicture( p_vout, sp);
846
if( !p_vout->p_sys->xvmc_palette )
848
p_vout->p_sys->hwSubpictures = 1;
854
static void xvmc_check_colorkey_properties( vout_thread_t *p_vout )
857
XvAttribute *xvmc_attributes = NULL;
861
* Determine if the context is of "Overlay" type. If so,
862
* check whether we can autopaint.
864
p_vout->p_sys->have_xvmc_autopaint = 0;
865
if( p_vout->p_sys->context_flags & XVMC_OVERLAID_SURFACE )
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,
872
if( xvmc_attributes )
874
for( i = 0; i < num; ++i )
876
if( strncmp( "XV_AUTOPAINT_COLORKEY",
877
xvmc_attributes[i].name,
880
ap = XInternAtom( p_vout->p_sys->p_display,
881
"XV_AUTOPAINT_COLORKEY",
883
XvMCSetAttribute( p_vout->p_sys->p_display,
884
&p_vout->p_sys->context,
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" );
892
XFree( xvmc_attributes );
893
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
894
/* p_vout->p_sys->xvmc_xoverlay_type = X11OSD_COLORKEY; */
899
p_vout->p_sys->xvmc_xoverlay_type = X11OSD_SHAPED;
904
static void xxmc_xvmc_destroy_surfaces( vout_thread_t *p_vout )
907
xvmc_surface_handler_t *handler = NULL;
909
handler = &p_vout->p_sys->xvmc_surf_handler;
911
pthread_mutex_lock( &handler->mutex );
912
for( i = 0; i < XVMC_MAX_SURFACES; ++i )
914
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
915
if( handler->surfValid[i] )
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 );
922
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
923
handler->surfValid[i] = 0;
925
pthread_mutex_unlock( &handler->mutex );
928
static void xxmc_xvmc_destroy_subpictures( vout_thread_t *p_vout )
931
xvmc_surface_handler_t *handler = NULL;
933
handler = &p_vout->p_sys->xvmc_surf_handler;
935
pthread_mutex_lock( &handler->mutex );
936
for( i = 0; i < XVMC_MAX_SUBPICTURES; ++i )
938
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
939
if( handler->subValid[i] )
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 );
945
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
946
handler->subValid[i] = 0;
948
pthread_mutex_unlock( &handler->mutex );
951
static XvMCSurface *xxmc_xvmc_alloc_surface( vout_thread_t *p_vout,
952
XvMCContext *context )
954
xvmc_surface_handler_t *handler = NULL;
957
handler = &p_vout->p_sys->xvmc_surf_handler;
959
pthread_mutex_lock( &handler->mutex );
960
xxmc_xvmc_dump_surfaces( p_vout );
961
for( i = 0; i < XVMC_MAX_SURFACES; ++i )
963
if( handler->surfValid[i] && !handler->surfInUse[i] )
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);
972
for( i = 0; i < XVMC_MAX_SURFACES; ++i )
974
if( !handler->surfInUse[i] )
976
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
977
if( Success != XvMCCreateSurface( p_vout->p_sys->p_display,
979
handler->surfaces + i) )
981
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
982
pthread_mutex_unlock( &handler->mutex );
985
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
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);
994
pthread_mutex_unlock( &handler->mutex );
998
void xxmc_dispose_context( vout_thread_t *p_vout )
1000
if( p_vout->p_sys->contextActive )
1002
if( p_vout->p_sys->xvmc_accel &
1003
(VLC_XVMC_ACCEL_MOCOMP | VLC_XVMC_ACCEL_IDCT) )
1005
xvmc_macroblocks_t *macroblocks = NULL;
1007
macroblocks = &p_vout->p_sys->macroblocks;
1008
XvMCDestroyMacroBlocks( p_vout->p_sys->p_display,
1009
¯oblocks->macro_blocks );
1010
XvMCDestroyBlocks( p_vout->p_sys->p_display,
1011
¯oblocks->blocks );
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 );
1021
msg_Dbg(p_vout, "freeing up XvMC Context.");
1022
XLockDisplay( p_vout->p_sys->p_display );
1023
if( p_vout->p_sys->subImage )
1025
XFree( p_vout->p_sys->subImage );
1026
p_vout->p_sys->subImage = NULL;
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;
1040
static int xxmc_find_context( vout_thread_t *p_vout, vlc_xxmc_t *xxmc,
1041
unsigned int width, unsigned int height )
1045
xvmc_capabilities_t *curCap = NULL;
1046
unsigned int request_mpeg_flags, request_accel_flags;
1048
request_mpeg_flags = xxmc->mpeg;
1049
for( k = 0; k < NUM_ACCEL_PRIORITY; ++k )
1051
request_accel_flags = xxmc->acceleration & accel_priority[k];
1052
if( !request_accel_flags )
1055
curCap = p_vout->p_sys->xvmc_cap;
1056
for( i =0; i < p_vout->p_sys->xvmc_num_cap; ++i )
1058
msg_Dbg( p_vout, "surface type %d, capabilities 0x%8x 0x%8x",
1061
curCap->accel_flags );
1062
msg_Dbg( p_vout, "fequests: 0x%8x 0x%8x",
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) )
1077
p_vout->p_sys->xvmc_cur_cap = i;
1083
p_vout->p_sys->xvmc_accel = request_accel_flags;
1084
p_vout->p_sys->unsigned_intra = (curCap->flags & XVMC_INTRA_UNSIGNED);
1087
p_vout->p_sys->xvmc_accel = 0;
1091
static int xxmc_create_context( vout_thread_t *p_vout,
1092
unsigned int width, unsigned int height )
1094
xvmc_capabilities_t *curCap = NULL;
1096
curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
1098
msg_Dbg( p_vout, "creating new XvMC context %d", curCap->type_id );
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,
1106
p_vout->p_sys->context_flags,
1107
&p_vout->p_sys->context ) )
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;
1114
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1115
return p_vout->p_sys->contextActive;
1118
static void xvmc_flushsync(picture_t *picture)
1120
vout_thread_t *p_vout = picture->p_sys->p_vout;
1122
xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1124
if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
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 );
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 );
1140
static void xvmc_flush(picture_t *picture)
1142
vout_thread_t *p_vout = picture->p_sys->p_vout;
1144
xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1146
if ( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
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 );
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 );
1162
static int xxmc_frame_updates( vout_thread_t *p_vout, picture_t *picture )
1164
vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
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.
1173
if( picture->p_sys->xvmc_surf )
1175
if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1177
xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
1178
picture->p_sys->xvmc_surf = NULL;
1182
if( picture->p_sys->p_image )
1184
memset( picture->p_sys->p_image->data, 0,
1185
picture->p_sys->p_image->width
1186
* picture->p_sys->p_image->height );
1190
* If it is NULL create a new surface.
1192
if( !picture->p_sys->xvmc_surf )
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 )
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;
1206
xxmc->acceleration = p_vout->p_sys->xvmc_accel;
1208
xxmc->proc_xxmc_flush = xvmc_flush;
1209
xxmc->proc_xxmc_flushsync = xvmc_flushsync;
1210
xxmc->xvmc.proc_macro_block = NULL;
1212
frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data;
1214
xxmc->proc_xxmc_begin = xvmc_vld_frame;
1215
xxmc->proc_xxmc_slice = xvmc_vld_slice;
1219
static int xxmc_xvmc_update_context( vout_thread_t *p_vout,
1220
picture_t *picture, uint32_t width, uint32_t height )
1222
vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
1225
* Are we at all capable of doing XvMC ?
1227
if( p_vout->p_sys->xvmc_cap == 0 )
1228
return VLC_EGENERIC;
1230
msg_Dbg( p_vout, "new format: need to change XvMC context. "
1231
"width: %d height: %d mpeg: %d acceleration: %d",
1233
xxmc->mpeg, xxmc->acceleration );
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;
1239
xxmc_dispose_context( p_vout );
1241
if( xxmc_find_context( p_vout, xxmc, width, height ) )
1243
xxmc_create_context( p_vout, width, height);
1244
xvmc_check_colorkey_properties( p_vout );
1245
xxmc_setup_subpictures(p_vout, width, height);
1248
if( !p_vout->p_sys->contextActive )
1250
msg_Dbg( p_vout, "using software decoding for this stream" );
1251
p_vout->p_sys->xvmc_accel = 0;
1255
msg_Dbg(p_vout, "using hardware decoding for this stream." );
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;
1265
void xxmc_do_update_frame( picture_t *picture, uint32_t width, uint32_t height,
1266
double ratio, int format, int flags)
1268
vout_thread_t *p_vout = picture->p_sys->p_vout;
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;
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))
1283
p_vout->p_sys->last_accel_request = xxmc->acceleration;
1284
xxmc_xvmc_update_context( p_vout, picture, width, height );
1287
if( p_vout->p_sys->contextActive )
1288
xxmc_frame_updates( p_vout, picture );
1290
if( !p_vout->p_sys->contextActive )
1292
xxmc->acceleration = 0;
1293
xxmc->xvmc.macroblocks = 0;
1297
picture->format.i_chroma = format;
1299
xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock);
1301
XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
1302
picture->p_sys->xvmc_surf,
1304
/* Wait a little till frame is being displayed */
1305
while( status & XVMC_DISPLAYING )
1309
XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
1310
picture->p_sys->xvmc_surf,
1320
/* called xlocked */
1321
static void dispose_ximage( vout_thread_t *p_vout, XShmSegmentInfo *shminfo,
1324
# ifdef HAVE_SYS_SHM_H
1325
if( p_vout->p_sys->i_shm_opcode )
1327
XShmDetach( p_vout->p_sys->p_display, shminfo );
1329
shmdt( shminfo->shmaddr );
1330
if( shminfo->shmid >= 0 )
1332
shmctl( shminfo->shmid, IPC_RMID, 0 );
1333
shminfo->shmid = -1;
1340
free(myimage->data);
1346
void xvmc_vld_frame( picture_t *picture )
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;
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;
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;
1379
fs = ff->p_sys->xvmc_surf;
1381
bs = bf->p_sys->xvmc_surf;
1384
* Below is for interlaced streams and second_field.
1386
if( ctl.picture_coding_type == P_TYPE ) /* XVMC_P_PICTURE) */
1387
bs = picture->p_sys->xvmc_surf;
1389
if( (qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix) )
1391
memcpy( qmx.intra_quantiser_matrix, vft->intra_quantizer_matrix,
1392
sizeof(qmx.intra_quantiser_matrix) );
1394
if( (qmx.load_non_intra_quantiser_matrix =
1395
vft->load_non_intra_quantizer_matrix) )
1397
memcpy( qmx.non_intra_quantiser_matrix, vft->non_intra_quantizer_matrix,
1398
sizeof(qmx.non_intra_quantiser_matrix) );
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 );
1404
if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1406
picture->p_sys->xxmc_data.result = 128;
1407
xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1411
XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1412
XvMCLoadQMatrix( p_vout->p_sys->p_display, &p_vout->p_sys->context, &qmx );
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,
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 );
1424
void xvmc_vld_slice( picture_t *picture )
1426
picture_sys_t *p_sys = picture->p_sys;
1427
vout_thread_t *p_vout = p_sys->p_vout;
1429
xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1430
if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
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" );
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 );
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 );
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.
1455
XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1456
xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1458
if( p_vout->p_sys->cpu_save_enabled )
1460
p_vout->p_sys->cpu_saver += 1.;
1461
if( p_vout->p_sys->cpu_saver >= picture->p_sys->xxmc_data.sleep )
1464
p_vout->p_sys->cpu_saver -= picture->p_sys->xxmc_data.sleep;