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