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