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 *****************************************************************************/
37 #include <vlc_interface.h>
41 #ifdef HAVE_MACHINE_PARAM_H
43 # include <machine/param.h>
44 # include <sys/types.h> /* typedef ushort */
49 # include <netinet/in.h> /* BSD: struct in_addr */
53 # include <sys/shm.h> /* shmget(), shmctl() */
58 #include <X11/Xutil.h>
59 #include <X11/keysym.h>
61 # include <X11/extensions/XShm.h>
63 #ifdef DPMSINFO_IN_DPMS_H
64 # include <X11/extensions/dpms.h>
67 #include <X11/extensions/Xv.h>
68 #include <X11/extensions/Xvlib.h>
69 #include <X11/extensions/vldXvMC.h>
71 #include "../../codec/xvmc/accel_xvmc.h"
73 #include "../../codec/spudec/spudec.h"
76 /* picture structure */
78 #define BOTTOM_FIELD 2
79 #define FRAME_PICTURE 3
81 /* picture coding type */
87 /*****************************************************************************
89 *****************************************************************************/
90 extern int E_(Activate) ( vlc_object_t * );
91 extern void E_(Deactivate) ( vlc_object_t * );
93 /*****************************************************************************
95 *****************************************************************************/
96 #define ADAPTOR_TEXT N_("XVMC adaptor number")
97 #define ADAPTOR_LONGTEXT N_( \
98 "If you graphics card provides several adaptors, this option allows you " \
99 "to choose which one will be used (you shouldn't have to change this).")
101 #define ALT_FS_TEXT N_("Alternate fullscreen method")
102 #define ALT_FS_LONGTEXT N_( \
103 "There are two ways to make a fullscreen window, unfortunately each one " \
104 "has its drawbacks.\n" \
105 "1) Let the window manager handle your fullscreen window (default), but " \
106 "things like taskbars will likely show on top of the video.\n" \
107 "2) Completely bypass the window manager, but then nothing will be able " \
108 "to show on top of the video.")
110 #define DISPLAY_TEXT N_("X11 display name")
111 #define DISPLAY_LONGTEXT N_( \
112 "Specify the X11 hardware display you want to use. By default VLC will " \
113 "use the value of the DISPLAY environment variable.")
115 #define CHROMA_TEXT N_("XVimage chroma format")
116 #define CHROMA_LONGTEXT N_( \
117 "Force the XVideo renderer to use a specific chroma format instead of " \
118 "trying to improve performances by using the most efficient one.")
120 #define SHM_TEXT N_("Use shared memory")
121 #define SHM_LONGTEXT N_( \
122 "Use shared memory to communicate between VLC and the X server.")
124 #define SCREEN_TEXT N_("Screen to be used for fullscreen mode.")
125 #define SCREEN_LONGTEXT N_( \
126 "Choose the screen you want to use in fullscreen mode. For instance " \
127 "set it to 0 for first screen, 1 for the second.")
129 #define MODE_TEXT N_("Deinterlace mode")
130 #define MODE_LONGTEXT N_("You can choose the default deinterlace mode")
132 #define CROP_TEXT N_("Crop")
133 #define CROP_LONGTEXT N_("You can choose the crop style to apply.")
136 set_shortname( "XVMC" );
137 add_string( "xvmc-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
138 add_integer( "xvmc-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT, VLC_TRUE );
139 add_bool( "xvmc-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, VLC_TRUE );
140 add_string( "xvmc-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, VLC_TRUE );
141 #ifdef HAVE_SYS_SHM_H
142 add_bool( "xvmc-shm", 1, NULL, SHM_TEXT, SHM_LONGTEXT, VLC_TRUE );
145 add_integer ( "xvmc-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, VLC_TRUE );
147 add_string( "xvmc-deinterlace-mode", "bob", NULL, MODE_TEXT, MODE_LONGTEXT, VLC_FALSE );
148 add_string( "xvmc-crop-style", "eq", NULL, CROP_TEXT, CROP_LONGTEXT, VLC_FALSE );
150 set_description( _("XVMC extension video output") );
151 set_capability( "video output", 10 );
152 set_callbacks( E_(Activate), E_(Deactivate) );
155 /* following functions are local */
157 static unsigned accel_priority[] = {
161 #define NUM_ACCEL_PRIORITY (sizeof(accel_priority)/sizeof(accel_priority[0]))
164 * Additional thread safety, since the plugin may decide to destroy a context
165 * while it's surfaces are still active in the video-out loop.
166 * When / If XvMC libs are reasonably thread-safe, the locks can be made
167 * more efficient by allowing multiple threads in that do not destroy
168 * the context or surfaces that may be active in other threads.
171 static void init_context_lock( context_lock_t *c )
173 pthread_cond_init(&c->cond,NULL);
174 pthread_mutex_init(&c->mutex,NULL);
178 void free_context_lock( context_lock_t *c )
180 pthread_mutex_destroy(&c->mutex);
181 pthread_cond_destroy(&c->cond);
184 void xvmc_context_reader_lock( context_lock_t *c )
186 pthread_mutex_lock(&c->mutex);
188 pthread_mutex_unlock(&c->mutex);
191 void xvmc_context_reader_unlock( context_lock_t *c )
193 pthread_mutex_lock(&c->mutex);
194 if (c->num_readers > 0) {
195 if (--(c->num_readers) == 0) {
196 pthread_cond_broadcast(&c->cond);
199 pthread_mutex_unlock(&c->mutex);
202 void xvmc_context_writer_lock( context_lock_t *c )
204 pthread_mutex_lock(&c->mutex);
205 while(c->num_readers) {
206 pthread_cond_wait( &c->cond, &c->mutex );
210 void xvmc_context_writer_unlock( context_lock_t *c )
212 pthread_mutex_unlock( &c->mutex );
215 void clear_xx44_palette( xx44_palette_t *p )
218 uint32_t *cluts = p->cluts;
219 int *ids = p->lookup_cache;
224 i = 2*OVL_PALETTE_SIZE;
230 static void init_xx44_palette( xx44_palette_t *p, unsigned num_entries )
232 p->size = (num_entries > XX44_PALETTE_SIZE) ?
233 XX44_PALETTE_SIZE : num_entries;
236 static void dispose_xx44_palette(xx44_palette_t *p)
241 static void colorToPalette( const uint32_t *icolor, unsigned char *palette_p,
242 unsigned num_xvmc_components, char *xvmc_components )
244 const clut_t *color = (const clut_t *) icolor;
247 for (i=0; i<num_xvmc_components; ++i)
249 switch(xvmc_components[i])
251 case 'V': *palette_p = color->cr; break;
252 case 'U': *palette_p = color->cb; break;
254 default: *palette_p = color->y; break;
261 void xx44_to_xvmc_palette( const xx44_palette_t *p,unsigned char *xvmc_palette,
262 unsigned first_xx44_entry, unsigned num_xx44_entries,
263 unsigned num_xvmc_components, char *xvmc_components )
266 const uint32_t *cluts = p->cluts + first_xx44_entry;
268 for( i=0; i<num_xx44_entries; ++i )
270 if( (cluts - p->cluts) < p->size )
272 colorToPalette( cluts++, xvmc_palette,
273 num_xvmc_components, xvmc_components );
274 xvmc_palette += num_xvmc_components;
279 static int xx44_paletteIndex( xx44_palette_t *p, int color, uint32_t clut )
282 uint32_t *cluts = p->cluts;
285 if( (tmp = p->lookup_cache[color]) >= 0 )
287 if (cluts[tmp] == clut)
290 for (i=0; i<p->max_used; ++i)
292 if (*cluts++ == clut) {
293 p->lookup_cache[color] = i;
294 return p->lookup_cache[color];
298 if( p->max_used == (p->size -1) )
300 //printf("video_out: Warning! Out of xx44 palette colors!\n");
303 p->cluts[p->max_used] = clut;
304 p->lookup_cache[color] = p->max_used++;
305 return p->lookup_cache[color];
308 static void memblend_xx44( uint8_t *mem, uint8_t val,
309 size_t size, uint8_t mask )
311 uint8_t masked_val = val & mask;
313 /* size_t is unsigned, therefore always positive
319 if( (*mem & mask) <= masked_val )
325 void blend_xx44( uint8_t *dst_img, subpicture_t *sub_img,
326 int dst_width, int dst_height, int dst_pitch,
327 xx44_palette_t *palette, int ia44 )
335 uint8_t norm_pixel,clip_pixel;
341 uint16_t *p_source = NULL;
346 src_width = sub_img->i_width;
347 src_height = sub_img->i_height;
348 x_off = sub_img->i_x;
349 y_off = sub_img->i_y;
350 alphamask = (ia44) ? 0x0F : 0xF0;
351 p_source = (uint16_t *)sub_img->p_sys->p_data;
353 dst_y = dst_img + dst_pitch*y_off + x_off;
355 if( (x_off + sub_img->i_width) <= dst_width )
356 clip_right = sub_img->i_width;
358 clip_right = dst_width - x_off;
360 if ((src_height + y_off) > dst_height)
361 src_height = dst_height - y_off;
363 for (y = 0; y < src_height; y++)
365 mask = !( (y < sub_img->p_sys->i_y_start) ||
366 (y >= sub_img->p_sys->i_y_end) );
369 for (x = 0; x < src_width;)
371 i_color = *p_source & 0x3;
372 i_len = *p_source++ >> 2;
374 if( (i_len > 0) && ((x+i_len) <= src_width) )
376 /* Get the RLE part, then draw the line */
377 uint32_t color = (sub_img->p_sys->pi_yuv[i_color][0] << 16) |
378 (sub_img->p_sys->pi_yuv[i_color][1] << 0) |
379 (sub_img->p_sys->pi_yuv[i_color][2] << 8);
381 norm_pixel = (uint8_t)(
382 (xx44_paletteIndex( palette,i_color, color ) << 4) |
383 (sub_img->p_sys->pi_alpha[i_color] & 0x0F) );
384 clip_pixel = (uint8_t)(
385 (xx44_paletteIndex( palette,i_color + OVL_PALETTE_SIZE,
386 sub_img->p_sys->pi_yuv[i_color][0] ) << 4) |
387 (sub_img->p_sys->pi_alpha[i_color] & 0x0F));
391 norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
392 clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
396 if( x < sub_img->p_sys->i_x_start )
398 if( (x + i_len) <= sub_img->p_sys->i_x_start )
400 memblend_xx44( dst, norm_pixel, i_len, alphamask );
405 memblend_xx44( dst, norm_pixel,
406 sub_img->p_sys->i_x_start - x,
408 dst += sub_img->p_sys->i_x_start - x;
409 i_len -= sub_img->p_sys->i_x_start - x;
410 if( i_len <= (sub_img->p_sys->i_x_end -
411 sub_img->p_sys->i_x_start) )
413 memblend_xx44( dst, clip_pixel,
419 memblend_xx44( dst, clip_pixel,
420 sub_img->p_sys->i_x_end -
421 sub_img->p_sys->i_x_start,
423 dst += (sub_img->p_sys->i_x_end -
424 sub_img->p_sys->i_x_start);
425 i_len -= (sub_img->p_sys->i_x_end -
426 sub_img->p_sys->i_x_start);
427 memblend_xx44( dst, norm_pixel,
433 else if( x < sub_img->p_sys->i_x_end )
435 if( i_len <= (sub_img->p_sys->i_x_end - x) )
437 memblend_xx44( dst, clip_pixel, i_len, alphamask);
442 memblend_xx44( dst, clip_pixel,
443 sub_img->p_sys->i_x_end - x,
445 dst += (sub_img->p_sys->i_x_end - x);
446 i_len -= (sub_img->p_sys->i_x_end - x);
447 memblend_xx44( dst, norm_pixel, i_len, alphamask);
453 memblend_xx44( dst, norm_pixel, i_len, alphamask );
459 memblend_xx44( dst, norm_pixel, i_len, alphamask );
474 int xxmc_xvmc_surface_valid( vout_thread_t *p_vout, XvMCSurface *surf )
476 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
477 unsigned long index = surf - handler->surfaces;
480 if( index >= XVMC_MAX_SURFACES )
482 pthread_mutex_lock(&handler->mutex);
483 ret = handler->surfValid[index];
484 pthread_mutex_unlock(&handler->mutex);
488 static void xxmc_xvmc_dump_subpictures( vout_thread_t *p_vout )
491 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
493 for( i=0; i < XVMC_MAX_SUBPICTURES; ++i )
495 msg_Dbg( p_vout, "handler in use %d, valid %d",
496 handler->subInUse[i],
497 handler->subValid[i]);
501 XvMCSubpicture *xxmc_xvmc_alloc_subpicture( vout_thread_t *p_vout,
502 XvMCContext *context, unsigned short width,
503 unsigned short height, int xvimage_id )
506 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
509 pthread_mutex_lock(&handler->mutex);
510 /* xxmc_xvmc_dump_subpictures(p_vout); */
511 for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
513 if( handler->subValid[i] && !handler->subInUse[i] )
515 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
516 if( XvMCGetSubpictureStatus( p_vout->p_sys->p_display,
517 handler->subpictures + i,
520 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
523 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
524 if( status & XVMC_DISPLAYING )
526 handler->subInUse[i] = 1;
527 /* xxmc_xvmc_dump_subpictures(p_vout); */
528 pthread_mutex_unlock(&handler->mutex);
529 return (handler->subpictures + i);
532 for (i=0; i<XVMC_MAX_SUBPICTURES; ++i)
534 if( !handler->subInUse[i] )
536 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
537 if( Success != XvMCCreateSubpicture( p_vout->p_sys->p_display,
539 handler->subpictures + i,
540 width, height, xvimage_id ) )
542 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
543 pthread_mutex_unlock( &handler->mutex );
546 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
547 msg_Dbg( p_vout, "video_out_xxmc: created subpicture %d\n", i );
548 handler->subInUse[i] = 1;
549 handler->subValid[i] = 1;
550 pthread_mutex_unlock( &handler->mutex );
551 return (handler->subpictures + i);
554 pthread_mutex_unlock( &handler->mutex );
558 void xxmc_xvmc_free_subpicture( vout_thread_t *p_vout, XvMCSubpicture *sub )
560 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
561 unsigned int index = sub - handler->subpictures;
563 if( index >= XVMC_MAX_SUBPICTURES )
566 pthread_mutex_lock( &handler->mutex );
567 handler->subInUse[index] = 0;
568 /* xxmc_xvmc_dump_subpictures(p_vout); */
569 pthread_mutex_unlock( &handler->mutex );
572 static void xxmc_xvmc_surface_handler_construct( vout_thread_t *p_vout )
575 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
577 pthread_mutex_init( &handler->mutex, NULL );
578 for( i=0; i<XVMC_MAX_SURFACES; ++i )
580 handler->surfInUse[i] = 0;
581 handler->surfValid[i] = 0;
583 for( i=0; i<XVMC_MAX_SUBPICTURES; ++i )
585 handler->subInUse[i] = 0;
586 handler->subValid[i] = 0;
590 static void xxmc_xvmc_dump_surfaces( vout_thread_t *p_vout )
593 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
595 for (i=0; i<XVMC_MAX_SURFACES; ++i)
597 msg_Dbg(p_vout, "surfaces in use %d, valid %d;",
598 handler->surfInUse[i],
599 handler->surfValid[i]);
603 void xxmc_xvmc_free_surface( vout_thread_t *p_vout, XvMCSurface *surf )
605 xvmc_surface_handler_t *handler = &p_vout->p_sys->xvmc_surf_handler;
606 unsigned int index = 0;
608 index = (surf - handler->surfaces);
610 if (index < XVMC_MAX_SURFACES)
612 pthread_mutex_lock(&handler->mutex);
613 msg_Dbg( p_vout,"free surface %d",index );
614 handler->surfInUse[index]--;
615 xxmc_xvmc_dump_surfaces(p_vout);
616 pthread_mutex_unlock(&handler->mutex);
620 int checkXvMCCap( vout_thread_t *p_vout )
626 XvMCSurfaceInfo *surfaceInfo =NULL;
627 XvMCSurfaceInfo *curInfo = NULL;
629 xvmc_capabilities_t *curCap = NULL;
630 XvImageFormatValues *formatValues = NULL;
632 i_xvport = p_vout->p_sys->i_xvport;
633 p_vout->p_sys->xvmc_cap = 0;
635 init_context_lock( &p_vout->p_sys->xvmc_lock );
636 xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
638 p_vout->p_sys->old_subpic = NULL;
639 p_vout->p_sys->new_subpic = NULL;
640 p_vout->p_sys->contextActive = 0;
641 p_vout->p_sys->subImage = NULL;
642 p_vout->p_sys->hwSubpictures = 0;
643 p_vout->p_sys->xvmc_palette = NULL;
645 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
647 if( !XvMCQueryExtension( p_vout->p_sys->p_display,
648 &p_vout->p_sys->xvmc_eventbase,
649 &p_vout->p_sys->xvmc_errbase ) )
651 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
652 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
655 msg_Dbg( p_vout,"XvMC extension found" );
657 surfaceInfo = XvMCListSurfaceTypes(p_vout->p_sys->p_display, i_xvport, &numSurf);
660 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
661 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
665 p_vout->p_sys->xvmc_cap =
666 (xvmc_capabilities_t *) malloc( numSurf *
667 sizeof(xvmc_capabilities_t) );
668 if( !p_vout->p_sys->xvmc_cap )
670 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
671 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
675 p_vout->p_sys->xvmc_num_cap = numSurf;
676 curInfo = surfaceInfo;
677 curCap = p_vout->p_sys->xvmc_cap;
679 msg_Dbg( p_vout,"found %d XvMC surface types", numSurf );
681 for( i=0; i< numSurf; ++i )
683 curCap->mpeg_flags = 0;
684 curCap->accel_flags = 0;
685 if( curInfo->chroma_format == XVMC_CHROMA_FORMAT_420 )
687 curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ?
688 VLC_XVMC_MPEG_1 : 0);
689 curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ?
690 VLC_XVMC_MPEG_2 : 0);
691 curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ?
692 VLC_XVMC_MPEG_4 : 0);
693 curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ?
694 VLC_XVMC_ACCEL_VLD : 0);
695 curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ?
696 VLC_XVMC_ACCEL_IDCT : 0);
697 curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ?
698 0 : VLC_XVMC_ACCEL_MOCOMP);
699 curCap->max_width = curInfo->max_width;
700 curCap->max_height = curInfo->max_height;
701 curCap->sub_max_width = curInfo->subpicture_max_width;
702 curCap->sub_max_height = curInfo->subpicture_max_height;
703 curCap->flags = curInfo->flags;
705 msg_Dbg (p_vout, "surface type %d: Max size: %d %d.",
706 i, curCap->max_width, curCap->max_height);
707 msg_Dbg (p_vout, "surface subtype %d: Max subpic size: %d %d.",
708 i, curCap->sub_max_width, curCap->sub_max_height);
710 curCap->type_id = curInfo->surface_type_id;
711 formatValues = XvMCListSubpictureTypes( p_vout->p_sys->p_display,
715 curCap->subPicType.id = 0;
718 msg_Dbg( p_vout, "surface type %d: found %d XvMC subpicture types",
720 for( j = 0; j<numSub; ++j )
722 if( formatValues[j].id == FOURCC_IA44 )
724 curCap->subPicType = formatValues[j];
726 "surface type %d: detected and using "
727 "IA44 subpicture type.", i );
731 else if( formatValues[j].id == FOURCC_AI44 )
733 curCap->subPicType = formatValues[j];
735 "surface type %d: detected AI44 "
736 "subpicture type.", i );
748 * Try to create a direct rendering context. This will fail if we are not
749 * on the displaying computer or an indirect context is not available.
751 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
752 curCap = p_vout->p_sys->xvmc_cap;
753 if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
759 msg_Dbg( p_vout, "using direct XVMC rendering context" );
760 p_vout->p_sys->context_flags = XVMC_DIRECT;
762 else if( Success == XvMCCreateContext( p_vout->p_sys->p_display, i_xvport,
768 msg_Dbg( p_vout, "using default XVMC rendering context" );
769 p_vout->p_sys->context_flags = 0;
773 if( p_vout->p_sys->xvmc_cap )
774 free( p_vout->p_sys->xvmc_cap );
775 p_vout->p_sys->xvmc_cap = NULL;
776 msg_Err( p_vout, "use of direct XvMC context on a remote display failed"
777 " falling back to XV." );
778 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
781 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
782 XvMCDestroyContext( p_vout->p_sys->p_display, &c );
783 xxmc_xvmc_surface_handler_construct( p_vout );
784 /* p_vout->p_sys->capabilities |= VO_CAP_XXMC; */
785 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
786 init_xx44_palette( &p_vout->p_sys->palette , 0 );
787 p_vout->p_sys->last_accel_request = 0xFFFFFFFF;
788 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
792 static int xxmc_setup_subpictures( vout_thread_t *p_vout,
793 unsigned int width, unsigned int height )
795 xvmc_capabilities_t *curCap = NULL;
796 XvMCSubpicture *sp = NULL;
798 if( p_vout->p_sys->contextActive )
800 curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
802 if( (width > curCap->sub_max_width) ||
803 (height > curCap->sub_max_height) )
806 if( (p_vout->p_sys->xvmc_backend_subpic =
807 (curCap->flags & XVMC_BACKEND_SUBPICTURE)) )
808 msg_Dbg( p_vout, "using backend subpictures." );
810 if (!p_vout->p_sys->subImage)
812 XLockDisplay( p_vout->p_sys->p_display );
813 msg_Dbg(p_vout, "xxmc_setup_subpictures");
814 #ifdef HAVE_SYS_SHM_H
815 if( p_vout->p_sys->i_shm_opcode )
817 /* Create image using XShm extension */
818 p_vout->p_sys->subImage = CreateShmImage( p_vout,
819 p_vout->p_sys->p_display,
820 p_vout->p_sys->i_xvport,
821 curCap->subPicType.id,
822 /* VLC2X11_FOURCC( p_vout->output. i_chroma ), */
823 &p_vout->p_sys->subShmInfo,
824 p_vout->output.i_width,
825 p_vout->output.i_height );
827 #endif /* HAVE_SYS_SHM_H */
828 XUnlockDisplay( p_vout->p_sys->p_display );
829 if( !p_vout->p_sys->subImage )
831 msg_Dbg(p_vout, "failed allocating XvImage for supbictures" );
836 sp = xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
838 curCap->subPicType.id );
841 init_xx44_palette( &p_vout->p_sys->palette, sp->num_palette_entries );
842 p_vout->p_sys->xvmc_palette = (char *) malloc( sp->num_palette_entries
844 xxmc_xvmc_free_subpicture( p_vout, sp);
845 if( !p_vout->p_sys->xvmc_palette )
847 p_vout->p_sys->hwSubpictures = 1;
853 static void xvmc_check_colorkey_properties( vout_thread_t *p_vout )
856 XvAttribute *xvmc_attributes = NULL;
860 * Determine if the context is of "Overlay" type. If so,
861 * check whether we can autopaint.
863 p_vout->p_sys->have_xvmc_autopaint = 0;
864 if( p_vout->p_sys->context_flags & XVMC_OVERLAID_SURFACE )
866 msg_Dbg( p_vout, "check colorkey properties" );
867 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
868 xvmc_attributes = XvMCQueryAttributes( p_vout->p_sys->p_display,
869 &p_vout->p_sys->context,
871 if( xvmc_attributes )
873 for( i = 0; i < num; ++i )
875 if( strncmp( "XV_AUTOPAINT_COLORKEY",
876 xvmc_attributes[i].name,
879 ap = XInternAtom( p_vout->p_sys->p_display,
880 "XV_AUTOPAINT_COLORKEY",
882 XvMCSetAttribute( p_vout->p_sys->p_display,
883 &p_vout->p_sys->context,
885 1 ); /* p_vout->p_sys->props[VO_PROP_AUTOPAINT_COLORKEY].value */
886 p_vout->p_sys->have_xvmc_autopaint = 1;
887 msg_Dbg( p_vout, "has xvmc autopaint" );
891 XFree( xvmc_attributes );
892 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
893 /* p_vout->p_sys->xvmc_xoverlay_type = X11OSD_COLORKEY; */
898 p_vout->p_sys->xvmc_xoverlay_type = X11OSD_SHAPED;
903 static void xxmc_xvmc_destroy_surfaces( vout_thread_t *p_vout )
906 xvmc_surface_handler_t *handler = NULL;
908 handler = &p_vout->p_sys->xvmc_surf_handler;
910 pthread_mutex_lock( &handler->mutex );
911 for( i = 0; i < XVMC_MAX_SURFACES; ++i )
913 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
914 if( handler->surfValid[i] )
916 XvMCFlushSurface( p_vout->p_sys->p_display , handler->surfaces+i);
917 XvMCSyncSurface( p_vout->p_sys->p_display, handler->surfaces+i );
918 XvMCHideSurface( p_vout->p_sys->p_display, handler->surfaces+i );
919 XvMCDestroySurface( p_vout->p_sys->p_display, handler->surfaces+i );
921 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
922 handler->surfValid[i] = 0;
924 pthread_mutex_unlock( &handler->mutex );
927 static void xxmc_xvmc_destroy_subpictures( vout_thread_t *p_vout )
930 xvmc_surface_handler_t *handler = NULL;
932 handler = &p_vout->p_sys->xvmc_surf_handler;
934 pthread_mutex_lock( &handler->mutex );
935 for( i = 0; i < XVMC_MAX_SUBPICTURES; ++i )
937 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
938 if( handler->subValid[i] )
940 XvMCFlushSubpicture( p_vout->p_sys->p_display , handler->subpictures+i);
941 XvMCSyncSubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
942 XvMCDestroySubpicture( p_vout->p_sys->p_display, handler->subpictures+i );
944 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
945 handler->subValid[i] = 0;
947 pthread_mutex_unlock( &handler->mutex );
950 static XvMCSurface *xxmc_xvmc_alloc_surface( vout_thread_t *p_vout,
951 XvMCContext *context )
953 xvmc_surface_handler_t *handler = NULL;
956 handler = &p_vout->p_sys->xvmc_surf_handler;
958 pthread_mutex_lock( &handler->mutex );
959 xxmc_xvmc_dump_surfaces( p_vout );
960 for( i = 0; i < XVMC_MAX_SURFACES; ++i )
962 if( handler->surfValid[i] && !handler->surfInUse[i] )
964 handler->surfInUse[i] = 1;
965 msg_Dbg( p_vout, "reusing surface %d", i );
966 xxmc_xvmc_dump_surfaces( p_vout );
967 pthread_mutex_unlock( &handler->mutex );
968 return (handler->surfaces + i);
971 for( i = 0; i < XVMC_MAX_SURFACES; ++i )
973 if( !handler->surfInUse[i] )
975 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
976 if( Success != XvMCCreateSurface( p_vout->p_sys->p_display,
978 handler->surfaces + i) )
980 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
981 pthread_mutex_unlock( &handler->mutex );
984 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
986 msg_Dbg( p_vout, "created surface %d", i );
987 handler->surfInUse[i] = 1;
988 handler->surfValid[i] = 1;
989 pthread_mutex_unlock( &handler->mutex );
990 return (handler->surfaces + i);
993 pthread_mutex_unlock( &handler->mutex );
997 void xxmc_dispose_context( vout_thread_t *p_vout )
999 if( p_vout->p_sys->contextActive )
1001 if( p_vout->p_sys->xvmc_accel &
1002 (VLC_XVMC_ACCEL_MOCOMP | VLC_XVMC_ACCEL_IDCT) )
1004 xvmc_macroblocks_t *macroblocks = NULL;
1006 macroblocks = &p_vout->p_sys->macroblocks;
1007 XvMCDestroyMacroBlocks( p_vout->p_sys->p_display,
1008 ¯oblocks->macro_blocks );
1009 XvMCDestroyBlocks( p_vout->p_sys->p_display,
1010 ¯oblocks->blocks );
1013 msg_Dbg( p_vout, "freeing up XvMC surfaces and subpictures" );
1014 if( p_vout->p_sys->xvmc_palette )
1015 free( p_vout->p_sys->xvmc_palette );
1016 dispose_xx44_palette( &p_vout->p_sys->palette );
1017 xxmc_xvmc_destroy_subpictures( p_vout );
1018 xxmc_xvmc_destroy_surfaces( p_vout );
1020 msg_Dbg(p_vout, "freeing up XvMC Context.");
1021 XLockDisplay( p_vout->p_sys->p_display );
1022 if( p_vout->p_sys->subImage )
1024 XFree( p_vout->p_sys->subImage );
1025 p_vout->p_sys->subImage = NULL;
1027 p_vout->p_sys->subImage = NULL;
1028 XUnlockDisplay( p_vout->p_sys->p_display );
1029 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1030 XvMCDestroyContext( p_vout->p_sys->p_display,
1031 &p_vout->p_sys->context );
1032 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1033 p_vout->p_sys->contextActive = 0;
1034 p_vout->p_sys->hwSubpictures = 0;
1035 p_vout->p_sys->xvmc_accel = 0;
1039 static int xxmc_find_context( vout_thread_t *p_vout, vlc_xxmc_t *xxmc,
1040 unsigned int width, unsigned int height )
1043 vlc_bool_t found = VLC_FALSE;
1044 xvmc_capabilities_t *curCap = NULL;
1045 unsigned int request_mpeg_flags, request_accel_flags;
1047 request_mpeg_flags = xxmc->mpeg;
1048 for( k = 0; k < NUM_ACCEL_PRIORITY; ++k )
1050 request_accel_flags = xxmc->acceleration & accel_priority[k];
1051 if( !request_accel_flags )
1054 curCap = p_vout->p_sys->xvmc_cap;
1055 for( i =0; i < p_vout->p_sys->xvmc_num_cap; ++i )
1057 msg_Dbg( p_vout, "surface type %d, capabilities 0x%8x 0x%8x",
1060 curCap->accel_flags );
1061 msg_Dbg( p_vout, "fequests: 0x%8x 0x%8x",
1063 request_accel_flags );
1064 if( ( (curCap->mpeg_flags & request_mpeg_flags) == request_mpeg_flags) &&
1065 (curCap->accel_flags & request_accel_flags) &&
1066 (width <= curCap->max_width) &&
1067 (height <= curCap->max_height) )
1076 p_vout->p_sys->xvmc_cur_cap = i;
1082 p_vout->p_sys->xvmc_accel = request_accel_flags;
1083 p_vout->p_sys->unsigned_intra = (curCap->flags & XVMC_INTRA_UNSIGNED);
1086 p_vout->p_sys->xvmc_accel = 0;
1090 static int xxmc_create_context( vout_thread_t *p_vout,
1091 unsigned int width, unsigned int height )
1093 xvmc_capabilities_t *curCap = NULL;
1095 curCap = p_vout->p_sys->xvmc_cap + p_vout->p_sys->xvmc_cur_cap;
1097 msg_Dbg( p_vout, "creating new XvMC context %d", curCap->type_id );
1099 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1100 if( Success == XvMCCreateContext( p_vout->p_sys->p_display,
1101 p_vout->p_sys->i_xvport,
1105 p_vout->p_sys->context_flags,
1106 &p_vout->p_sys->context ) )
1108 p_vout->p_sys->xvmc_mpeg = curCap->mpeg_flags;
1109 p_vout->p_sys->xvmc_width = width;
1110 p_vout->p_sys->xvmc_height = height;
1111 p_vout->p_sys->contextActive = 1;
1113 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1114 return p_vout->p_sys->contextActive;
1117 static void xvmc_flushsync(picture_t *picture)
1119 vout_thread_t *p_vout = picture->p_sys->p_vout;
1121 xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1123 if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1125 msg_Dbg(p_vout, "xvmc_flushsync 1 : %d", picture->p_sys->xxmc_data.result );
1126 picture->p_sys->xxmc_data.result = 128;
1127 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1131 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1132 picture->p_sys->xxmc_data.result =
1133 XvMCFlushSurface( p_vout->p_sys->p_display,
1134 picture->p_sys->xvmc_surf );
1135 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1136 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1139 static void xvmc_flush(picture_t *picture)
1141 vout_thread_t *p_vout = picture->p_sys->p_vout;
1143 xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1145 if ( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1147 msg_Dbg(p_vout, "xvmc flush 1 : %d", picture->p_sys->xxmc_data.result );
1148 picture->p_sys->xxmc_data.result = 128;
1149 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1153 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1154 picture->p_sys->xxmc_data.result =
1155 XvMCFlushSurface( p_vout->p_sys->p_display,
1156 picture->p_sys->xvmc_surf );
1157 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1158 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1161 static int xxmc_frame_updates( vout_thread_t *p_vout, picture_t *picture )
1163 vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
1166 * If we have changed context since the surface was updated, xvmc_surf
1167 * is either NULL or invalid. If it is invalid. Set it to NULL.
1168 * Also if there are other users of this surface, deregister our use of
1169 * it and later try to allocate a new, fresh one.
1172 if( picture->p_sys->xvmc_surf )
1174 if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1176 xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
1177 picture->p_sys->xvmc_surf = NULL;
1181 if( picture->p_sys->p_image )
1183 memset( picture->p_sys->p_image->data, 0,
1184 picture->p_sys->p_image->width
1185 * picture->p_sys->p_image->height );
1189 * If it is NULL create a new surface.
1191 if( !picture->p_sys->xvmc_surf )
1193 picture->p_sys->xvmc_surf = xxmc_xvmc_alloc_surface( p_vout,
1194 &p_vout->p_sys->context );
1195 if( !picture->p_sys->xvmc_surf )
1197 msg_Err( p_vout, "accelerated surface allocation failed.\n"
1198 " You are probably out of framebuffer memory.\n"
1199 " Falling back to software decoding." );
1200 p_vout->p_sys->xvmc_accel = 0;
1201 xxmc_dispose_context( p_vout );
1202 return VLC_EGENERIC;
1205 xxmc->acceleration = p_vout->p_sys->xvmc_accel;
1207 xxmc->proc_xxmc_flush = xvmc_flush;
1208 xxmc->proc_xxmc_flushsync = xvmc_flushsync;
1209 xxmc->xvmc.proc_macro_block = NULL;
1211 frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data;
1213 xxmc->proc_xxmc_begin = xvmc_vld_frame;
1214 xxmc->proc_xxmc_slice = xvmc_vld_slice;
1218 static int xxmc_xvmc_update_context( vout_thread_t *p_vout,
1219 picture_t *picture, uint32_t width, uint32_t height )
1221 vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
1224 * Are we at all capable of doing XvMC ?
1226 if( p_vout->p_sys->xvmc_cap == 0 )
1227 return VLC_EGENERIC;
1229 msg_Dbg( p_vout, "new format: need to change XvMC context. "
1230 "width: %d height: %d mpeg: %d acceleration: %d",
1232 xxmc->mpeg, xxmc->acceleration );
1234 if( picture->p_sys->xvmc_surf )
1235 xxmc_xvmc_free_surface( p_vout , picture->p_sys->xvmc_surf );
1236 picture->p_sys->xvmc_surf = NULL;
1238 xxmc_dispose_context( p_vout );
1240 if( xxmc_find_context( p_vout, xxmc, width, height ) )
1242 xxmc_create_context( p_vout, width, height);
1243 xvmc_check_colorkey_properties( p_vout );
1244 xxmc_setup_subpictures(p_vout, width, height);
1247 if( !p_vout->p_sys->contextActive )
1249 msg_Dbg( p_vout, "using software decoding for this stream" );
1250 p_vout->p_sys->xvmc_accel = 0;
1254 msg_Dbg(p_vout, "using hardware decoding for this stream." );
1257 p_vout->p_sys->xvmc_mpeg = xxmc->mpeg;
1258 p_vout->p_sys->xvmc_width = width;
1259 p_vout->p_sys->xvmc_height = height;
1260 return p_vout->p_sys->contextActive;
1264 void xxmc_do_update_frame( picture_t *picture, uint32_t width, uint32_t height,
1265 double ratio, int format, int flags)
1267 vout_thread_t *p_vout = picture->p_sys->p_vout;
1271 picture->p_sys->xxmc_data.decoded = 0;
1272 picture->p_sys->nb_display = 0;
1273 picture->b_force = 0;
1274 vlc_xxmc_t *xxmc = &picture->p_sys->xxmc_data;
1276 xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock);
1277 if( (p_vout->p_sys->last_accel_request != xxmc->acceleration) ||
1278 (p_vout->p_sys->xvmc_mpeg != xxmc->mpeg) ||
1279 (p_vout->p_sys->xvmc_width != width) ||
1280 (p_vout->p_sys->xvmc_height != height))
1282 p_vout->p_sys->last_accel_request = xxmc->acceleration;
1283 xxmc_xvmc_update_context( p_vout, picture, width, height );
1286 if( p_vout->p_sys->contextActive )
1287 xxmc_frame_updates( p_vout, picture );
1289 if( !p_vout->p_sys->contextActive )
1291 xxmc->acceleration = 0;
1292 xxmc->xvmc.macroblocks = 0;
1296 picture->format.i_chroma = format;
1298 xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock);
1300 XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
1301 picture->p_sys->xvmc_surf,
1303 /* Wait a little till frame is being displayed */
1304 while( status & XVMC_DISPLAYING )
1308 XvMCGetSurfaceStatus( p_vout->p_sys->p_display,
1309 picture->p_sys->xvmc_surf,
1319 /* called xlocked */
1320 static void dispose_ximage( vout_thread_t *p_vout, XShmSegmentInfo *shminfo,
1323 # ifdef HAVE_SYS_SHM_H
1324 if( p_vout->p_sys->i_shm_opcode )
1326 XShmDetach( p_vout->p_sys->p_display, shminfo );
1328 shmdt( shminfo->shmaddr );
1329 if( shminfo->shmid >= 0 )
1331 shmctl( shminfo->shmid, IPC_RMID, 0 );
1332 shminfo->shmid = -1;
1339 free(myimage->data);
1345 void xvmc_vld_frame( picture_t *picture )
1347 picture_sys_t *p_sys = picture->p_sys;
1348 vout_thread_t *p_vout = p_sys->p_vout;
1349 vlc_vld_frame_t *vft = &(p_sys->xxmc_data.vld_frame);
1350 picture_t *ff = (picture_t *) vft->forward_reference_picture;
1351 picture_t *bf = (picture_t *) vft->backward_reference_picture;
1352 XvMCMpegControl ctl;
1353 XvMCSurface *fs=0, *bs=0;
1356 ctl.BHMV_range = vft->mv_ranges[0][0];
1357 ctl.BVMV_range = vft->mv_ranges[0][1];
1358 ctl.FHMV_range = vft->mv_ranges[1][0];
1359 ctl.FVMV_range = vft->mv_ranges[1][1];
1360 ctl.picture_structure = vft->picture_structure;
1361 ctl.intra_dc_precision = vft->intra_dc_precision;
1362 ctl.picture_coding_type = vft->picture_coding_type;
1363 ctl.mpeg_coding = (vft->mpeg_coding == 0) ? XVMC_MPEG_1 : XVMC_MPEG_2;
1365 ctl.flags |= (vft->progressive_sequence) ? XVMC_PROGRESSIVE_SEQUENCE : 0;
1366 ctl.flags |= (vft->scan) ? XVMC_ALTERNATE_SCAN : XVMC_ZIG_ZAG_SCAN;
1367 ctl.flags |= (vft->pred_dct_frame) ?
1368 XVMC_PRED_DCT_FRAME : XVMC_PRED_DCT_FIELD;
1369 ctl.flags |= (picture->b_top_field_first) ?
1370 XVMC_TOP_FIELD_FIRST : XVMC_BOTTOM_FIELD_FIRST;
1371 ctl.flags |= (vft->concealment_motion_vectors) ?
1372 XVMC_CONCEALMENT_MOTION_VECTORS : 0;
1373 ctl.flags |= (vft->q_scale_type) ? XVMC_Q_SCALE_TYPE : 0;
1374 ctl.flags |= (vft->intra_vlc_format) ? XVMC_INTRA_VLC_FORMAT : 0;
1375 ctl.flags |= (vft->second_field) ? XVMC_SECOND_FIELD : 0;
1378 fs = ff->p_sys->xvmc_surf;
1380 bs = bf->p_sys->xvmc_surf;
1383 * Below is for interlaced streams and second_field.
1385 if( ctl.picture_coding_type == P_TYPE ) /* XVMC_P_PICTURE) */
1386 bs = picture->p_sys->xvmc_surf;
1388 if( (qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix) )
1390 memcpy( qmx.intra_quantiser_matrix, vft->intra_quantizer_matrix,
1391 sizeof(qmx.intra_quantiser_matrix) );
1393 if( (qmx.load_non_intra_quantiser_matrix =
1394 vft->load_non_intra_quantizer_matrix) )
1396 memcpy( qmx.non_intra_quantiser_matrix, vft->non_intra_quantizer_matrix,
1397 sizeof(qmx.non_intra_quantiser_matrix) );
1399 qmx.load_chroma_intra_quantiser_matrix = 0;
1400 qmx.load_chroma_non_intra_quantiser_matrix = 0;
1401 xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1403 if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1405 picture->p_sys->xxmc_data.result = 128;
1406 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1410 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1411 XvMCLoadQMatrix( p_vout->p_sys->p_display, &p_vout->p_sys->context, &qmx );
1413 picture->p_sys->xxmc_data.result =
1414 XvMCBeginSurface( p_vout->p_sys->p_display,
1415 &p_vout->p_sys->context,
1416 picture->p_sys->xvmc_surf,
1418 } while( !picture->p_sys->xxmc_data.result );
1419 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1420 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1423 void xvmc_vld_slice( picture_t *picture )
1425 picture_sys_t *p_sys = picture->p_sys;
1426 vout_thread_t *p_vout = p_sys->p_vout;
1428 xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
1429 if( !xxmc_xvmc_surface_valid( p_vout, picture->p_sys->xvmc_surf ) )
1431 picture->p_sys->xxmc_data.result = 128;
1432 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1433 msg_Err(p_vout, "vld slice error" );
1437 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
1438 picture->p_sys->xxmc_data.result =
1439 XvMCPutSlice2( p_vout->p_sys->p_display,
1440 &p_vout->p_sys->context,
1441 (char *)picture->p_sys->xxmc_data.slice_data,
1442 picture->p_sys->xxmc_data.slice_data_size,
1443 picture->p_sys->xxmc_data.slice_code );
1445 if( picture->p_sys->xxmc_data.result != 0 )
1446 msg_Err( p_vout, "vlc slice error %d",
1447 picture->p_sys->xxmc_data.result );
1449 * If CPU-saving mode is enabled, sleep after every xxmc->sleep slice. This will free
1450 * up the cpu while the decoder is working on the slice. The value of xxmc->sleep is calculated
1451 * so that the decoder thread sleeps at most 50% of the frame delay,
1452 * assuming a 2.6 kernel clock of 1000 Hz.
1454 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
1455 xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
1457 if( p_vout->p_sys->cpu_save_enabled )
1459 p_vout->p_sys->cpu_saver += 1.;
1460 if( p_vout->p_sys->cpu_saver >= picture->p_sys->xxmc_data.sleep )
1463 p_vout->p_sys->cpu_saver -= picture->p_sys->xxmc_data.sleep;