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