xvmc.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:50k
源码类别:

midi

开发平台:

Unix_Linux

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