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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * panoramix.c : Wall panoramic video with edge blending plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000, 2001, 2002, 2003 VideoLAN
  5.  * $Id: 73c92814fbbafb454b33f6cafdfe91fd6845aa51 $
  6.  *
  7.  * Authors: Cedric Cocquebert <cedric.cocquebert@supelec.fr>
  8.  *          based on Samuel Hocevar <sam@zoy.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_vout.h>
  33. #include <assert.h>
  34. #include "filter_common.h"
  35. // add by cedric.cocquebert@supelec.fr
  36. #define OVERLAP        2350
  37. #ifdef OVERLAP
  38.     #include <math.h>
  39.     // OS CODE DEPENDENT to get display dimensions
  40.     #ifdef WIN32
  41.         #include <windows.h>
  42.     #else
  43.         #include <X11/Xlib.h>
  44.     #endif
  45.     #define GAMMA        1
  46. //  #define PACKED_YUV    1
  47.     #define F2(a) ((a)*(a))
  48.     #define F4(a,b,x) ((a)*(F2(x))+((b)*(x)))
  49.     #define ACCURACY 1000
  50.     #define RATIO_MAX 2500
  51.     #define CLIP_01(a) (a < 0.0 ? 0.0 : (a > 1.0 ? 1.0 : a))
  52. //    #define CLIP_0A(a) (a < 0.0 ? 0.0 : (a > ACCURACY ? ACCURACY : a))
  53. #endif
  54. /*****************************************************************************
  55.  * Local prototypes
  56.  *****************************************************************************/
  57. static int  Create    ( vlc_object_t * );
  58. static void Destroy   ( vlc_object_t * );
  59. static int  Init      ( vout_thread_t * );
  60. static void End       ( vout_thread_t * );
  61. #ifdef PACKED_YUV
  62. static void RenderPackedYUV   ( vout_thread_t *, picture_t * );
  63. #endif
  64. static void RenderPlanarYUV   ( vout_thread_t *, picture_t * );
  65. static void RenderPackedRGB   ( vout_thread_t *, picture_t * );
  66. static void RemoveAllVout  ( vout_thread_t *p_vout );
  67. static int  MouseEvent( vlc_object_t *, char const *,
  68.                         vlc_value_t, vlc_value_t, void * );
  69. static int  FullscreenEventUp( vlc_object_t *, char const *,
  70.                                vlc_value_t, vlc_value_t, void * );
  71. static int  FullscreenEventDown( vlc_object_t *, char const *,
  72.                                  vlc_value_t, vlc_value_t, void * );
  73. /*****************************************************************************
  74.  * Module descriptor
  75.  *****************************************************************************/
  76. #define COLS_TEXT N_("Number of columns")
  77. #define COLS_LONGTEXT N_("Select the number of horizontal video windows in " 
  78.     "which to split the video")
  79. #define ROWS_TEXT N_("Number of rows")
  80. #define ROWS_LONGTEXT N_("Select the number of vertical video windows in " 
  81.     "which to split the video")
  82. #define ACTIVE_TEXT N_("Active windows")
  83. #define ACTIVE_LONGTEXT N_("Comma separated list of active windows, " 
  84.     "defaults to all")
  85. #define CFG_PREFIX "panoramix-"
  86. vlc_module_begin ()
  87.     set_description( N_("Panoramix: wall with overlap video filter") )
  88.     set_shortname( N_("Panoramix" ))
  89.     set_capability( "video filter", 0 )
  90.     set_category( CAT_VIDEO )
  91.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  92.     add_integer( CFG_PREFIX "cols", -1, NULL,
  93.                  COLS_TEXT, COLS_LONGTEXT, true )
  94.     add_integer( CFG_PREFIX "rows", -1, NULL,
  95.                  ROWS_TEXT, ROWS_LONGTEXT, true )
  96. #ifdef OVERLAP
  97. #define OFFSET_X_TEXT N_("Offset X offset (automatic compensation)")
  98. #define OFFSET_X_LONGTEXT N_("Select if you want an automatic offset in horizontal (in case of misalignment due to autoratio control)")
  99.     add_bool( CFG_PREFIX "offset-x", 1, NULL, OFFSET_X_TEXT, OFFSET_X_LONGTEXT, true )
  100. #define LENGTH_TEXT N_("length of the overlapping area (in %)")
  101. #define LENGTH_LONGTEXT N_("Select in percent the length of the blended zone")
  102.     add_integer_with_range( CFG_PREFIX "bz-length", 100, 0, 100, NULL, LENGTH_TEXT, LENGTH_LONGTEXT, true )
  103. #define HEIGHT_TEXT N_("height of the overlapping area (in %)")
  104. #define HEIGHT_LONGTEXT N_("Select in percent the height of the blended zone (case of 2x2 wall)")
  105.     add_integer_with_range( CFG_PREFIX "bz-height", 100, 0, 100, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT, true )
  106. #define ATTENUATION_TEXT N_("Attenuation")
  107. #define ATTENUATION_LONGTEXT N_("Check this option if you want attenuate blended zone by this plug-in (if option is unchecked, attenuate is made by opengl)")
  108.     add_bool( CFG_PREFIX "attenuate", 1, NULL, ATTENUATION_TEXT, ATTENUATION_LONGTEXT, false )
  109. #define BEGIN_TEXT N_("Attenuation, begin (in %)")
  110. #define BEGIN_LONGTEXT N_("Select in percent the Lagrange coeff of the beginning blended zone")
  111.     add_integer_with_range( CFG_PREFIX "bz-begin", 0, 0, 100, NULL, BEGIN_TEXT, BEGIN_LONGTEXT, true )
  112. #define MIDDLE_TEXT N_("Attenuation, middle (in %)")
  113. #define MIDDLE_LONGTEXT N_("Select in percent the Lagrange coeff of the middle of blended zone")
  114.     add_integer_with_range( CFG_PREFIX "bz-middle", 50, 0, 100, NULL, MIDDLE_TEXT, MIDDLE_LONGTEXT, false )
  115. #define END_TEXT N_("Attenuation, end (in %)")
  116. #define END_LONGTEXT N_("Select in percent the Lagrange coeff of the end of blended zone")
  117.     add_integer_with_range( CFG_PREFIX "bz-end", 100, 0, 100, NULL, END_TEXT, END_LONGTEXT, true )
  118. #define MIDDLE_POS_TEXT N_("middle position (in %)")
  119. #define MIDDLE_POS_LONGTEXT N_("Select in percent (50 is center) the position of the middle point (Lagrange) of blended zone")
  120.     add_integer_with_range( CFG_PREFIX "bz-middle-pos", 50, 1, 99, NULL, MIDDLE_POS_TEXT, MIDDLE_POS_LONGTEXT, false )
  121. #ifdef GAMMA
  122. #define RGAMMA_TEXT N_("Gamma (Red) correction")
  123. #define RGAMMA_LONGTEXT N_("Select the gamma for the correction of blended zone (Red or Y component)")
  124.     add_float_with_range( CFG_PREFIX "bz-gamma-red", 1, 0, 5, NULL, RGAMMA_TEXT, RGAMMA_LONGTEXT, true )
  125. #define GGAMMA_TEXT N_("Gamma (Green) correction")
  126. #define GGAMMA_LONGTEXT N_("Select the gamma for the correction of blended zone (Green or U component)")
  127.     add_float_with_range( CFG_PREFIX "bz-gamma-green", 1, 0, 5, NULL, GGAMMA_TEXT, GGAMMA_LONGTEXT, true )
  128. #define BGAMMA_TEXT N_("Gamma (Blue) correction")
  129. #define BGAMMA_LONGTEXT N_("Select the gamma for the correction of blended zone (Blue or V component)")
  130.     add_float_with_range( CFG_PREFIX "bz-gamma-blue", 1, 0, 5, NULL, BGAMMA_TEXT, BGAMMA_LONGTEXT, true )
  131. #endif
  132. #define RGAMMA_BC_TEXT N_("Black Crush for Red")
  133. #define RGAMMA_BC_LONGTEXT N_("Select the Black Crush of blended zone (Red or Y component)")
  134. #define GGAMMA_BC_TEXT N_("Black Crush for Green")
  135. #define GGAMMA_BC_LONGTEXT N_("Select the Black Crush of blended zone (Green or U component)")
  136. #define BGAMMA_BC_TEXT N_("Black Crush for Blue")
  137. #define BGAMMA_BC_LONGTEXT N_("Select the Black Crush of blended zone (Blue or V component)")
  138. #define RGAMMA_WC_TEXT N_("White Crush for Red")
  139. #define RGAMMA_WC_LONGTEXT N_("Select the White Crush of blended zone (Red or Y component)")
  140. #define GGAMMA_WC_TEXT N_("White Crush for Green")
  141. #define GGAMMA_WC_LONGTEXT N_("Select the White Crush of blended zone (Green or U component)")
  142. #define BGAMMA_WC_TEXT N_("White Crush for Blue")
  143. #define BGAMMA_WC_LONGTEXT N_("Select the White Crush of blended zone (Blue or V component)")
  144. #define RGAMMA_BL_TEXT N_("Black Level for Red")
  145. #define RGAMMA_BL_LONGTEXT N_("Select the Black Level of blended zone (Red or Y component)")
  146. #define GGAMMA_BL_TEXT N_("Black Level for Green")
  147. #define GGAMMA_BL_LONGTEXT N_("Select the Black Level of blended zone (Green or U component)")
  148. #define BGAMMA_BL_TEXT N_("Black Level for Blue")
  149. #define BGAMMA_BL_LONGTEXT N_("Select the Black Level of blended zone (Blue or V component)")
  150. #define RGAMMA_WL_TEXT N_("White Level for Red")
  151. #define RGAMMA_WL_LONGTEXT N_("Select the White Level of blended zone (Red or Y component)")
  152. #define GGAMMA_WL_TEXT N_("White Level for Green")
  153. #define GGAMMA_WL_LONGTEXT N_("Select the White Level of blended zone (Green or U component)")
  154. #define BGAMMA_WL_TEXT N_("White Level for Blue")
  155. #define BGAMMA_WL_LONGTEXT N_("Select the White Level of blended zone (Blue or V component)")
  156.     add_integer_with_range( CFG_PREFIX "bz-blackcrush-red", 140, 0, 255, NULL, RGAMMA_BC_TEXT, RGAMMA_BC_LONGTEXT, true )
  157.     add_integer_with_range( CFG_PREFIX "bz-blackcrush-green", 140, 0, 255, NULL, GGAMMA_BC_TEXT, GGAMMA_BC_LONGTEXT, true )
  158.     add_integer_with_range( CFG_PREFIX "bz-blackcrush-blue", 140, 0, 255, NULL, BGAMMA_BC_TEXT, BGAMMA_BC_LONGTEXT, true )
  159.     add_integer_with_range( CFG_PREFIX "bz-whitecrush-red", 200, 0, 255, NULL, RGAMMA_WC_TEXT, RGAMMA_WC_LONGTEXT, true )
  160.     add_integer_with_range( CFG_PREFIX "bz-whitecrush-green", 200, 0, 255, NULL, GGAMMA_WC_TEXT, GGAMMA_WC_LONGTEXT, true )
  161.     add_integer_with_range( CFG_PREFIX "bz-whitecrush-blue", 200, 0, 255, NULL, BGAMMA_WC_TEXT, BGAMMA_WC_LONGTEXT, true )
  162.     add_integer_with_range( CFG_PREFIX "bz-blacklevel-red", 150, 0, 255, NULL, RGAMMA_BL_TEXT, RGAMMA_BL_LONGTEXT, true )
  163.     add_integer_with_range( CFG_PREFIX "bz-blacklevel-green", 150, 0, 255, NULL, GGAMMA_BL_TEXT, GGAMMA_BL_LONGTEXT, true )
  164.     add_integer_with_range( CFG_PREFIX "bz-blacklevel-blue", 150, 0, 255, NULL, BGAMMA_BL_TEXT, BGAMMA_BL_LONGTEXT, true )
  165.     add_integer_with_range( CFG_PREFIX "bz-whitelevel-red", 0, 0, 255, NULL, RGAMMA_WL_TEXT, RGAMMA_WL_LONGTEXT, true )
  166.     add_integer_with_range( CFG_PREFIX "bz-whitelevel-green", 0, 0, 255, NULL, GGAMMA_WL_TEXT, GGAMMA_WL_LONGTEXT, true )
  167.     add_integer_with_range( CFG_PREFIX "bz-whitelevel-blue", 0, 0, 255, NULL, BGAMMA_WL_TEXT, BGAMMA_WL_LONGTEXT, true )
  168. #ifndef WIN32
  169. #define XINERAMA_TEXT N_("Xinerama option")
  170. #define XINERAMA_LONGTEXT N_("Uncheck if you have not used xinerama")
  171.     add_bool( CFG_PREFIX "xinerama", 1, NULL, XINERAMA_TEXT, XINERAMA_LONGTEXT, true )
  172. #endif
  173. #endif
  174.     add_string( CFG_PREFIX "active", NULL, NULL, ACTIVE_TEXT, ACTIVE_LONGTEXT, true )
  175.     add_shortcut( "panoramix" )
  176.     set_callbacks( Create, Destroy )
  177. vlc_module_end ()
  178. static const char *const ppsz_filter_options[] = {
  179.     "cols", "rows", "offset-x", "bz-length", "bz-height", "attenuate",
  180.     "bz-begin", "bz-middle", "bz-end", "bz-middle-pos", "bz-gamma-red",
  181.     "bz-gamma-green", "bz-gamma-blue", "bz-blackcrush-red",
  182.     "bz-blackcrush-green", "bz-blackcrush-blue", "bz-whitecrush-red",
  183.     "bz-whitecrush-green", "bz-whitecrush-blue", "bz-blacklevel-red",
  184.     "bz-blacklevel-green", "bz-blacklevel-blue", "bz-whitelevel-red",
  185.     "bz-whitelevel-green", "bz-whitelevel-blue", "xinerama", "active",
  186.     NULL
  187. };
  188. /*****************************************************************************
  189.  * vout_sys_t: Wall video output method descriptor
  190.  *****************************************************************************
  191.  * This structure is part of the video output thread descriptor.
  192.  * It describes the Wall specific properties of an output thread.
  193.  *****************************************************************************/
  194. struct vout_sys_t
  195. {
  196. #ifdef OVERLAP
  197.     bool   b_autocrop;
  198.     bool   b_attenuate;
  199.     unsigned int bz_length, bz_height, bz_begin, bz_middle, bz_end, bz_middle_pos;
  200.     unsigned int i_ratio_max;
  201.     unsigned int i_ratio;
  202.     unsigned int a_0, a_1, a_2;
  203.     bool     b_has_changed;
  204.     int lambda[2][VOUT_MAX_PLANES][500];
  205.     int cstYUV[2][VOUT_MAX_PLANES][500];
  206.     int lambda2[2][VOUT_MAX_PLANES][500];
  207.     int cstYUV2[2][VOUT_MAX_PLANES][500];
  208.     unsigned int i_halfLength;
  209.     unsigned int i_halfHeight;
  210.     int i_offset_x;
  211.     int i_offset_y;
  212. #ifdef GAMMA
  213.     float        f_gamma_red, f_gamma_green, f_gamma_blue;
  214.     float         f_gamma[VOUT_MAX_PLANES];
  215.     uint8_t         LUT[VOUT_MAX_PLANES][ACCURACY + 1][256];
  216. #ifdef PACKED_YUV
  217.     uint8_t         LUT2[VOUT_MAX_PLANES][256][500];
  218. #endif
  219. #endif
  220. #ifndef WIN32
  221.     bool   b_xinerama;
  222. #endif
  223. #endif
  224.     int    i_col;
  225.     int    i_row;
  226.     int    i_vout;
  227.     struct vout_list_t
  228.     {
  229.         bool b_active;
  230.         int i_width;
  231.         int i_height;
  232.         vout_thread_t *p_vout;
  233.     } *pp_vout;
  234. };
  235. /*****************************************************************************
  236.  * Control: control facility for the vout (forwards to child vout)
  237.  *****************************************************************************/
  238. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  239. {
  240.     int i_row, i_col, i_vout = 0;
  241.     for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
  242.     {
  243.         for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++ )
  244.         {
  245.             vout_vaControl( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  246.                             i_query, args );
  247.             i_vout++;
  248.         }
  249.     }
  250.     return VLC_SUCCESS;
  251. }
  252. /*****************************************************************************
  253.  * Create: allocates Wall video thread output method
  254.  *****************************************************************************
  255.  * This function allocates and initializes a Wall vout method.
  256.  *****************************************************************************/
  257. static int Create( vlc_object_t *p_this )
  258. {
  259.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  260.     char *psz_method, *psz_tmp, *psz_method_tmp;
  261.     int i_vout;
  262.     /* Allocate structure */
  263.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  264.     if( p_vout->p_sys == NULL )
  265.         return VLC_ENOMEM;
  266.     p_vout->pf_init = Init;
  267.     p_vout->pf_end = End;
  268.     p_vout->pf_manage = NULL;
  269. /* Color Format not supported
  270. // Planar Y, packed UV
  271. case VLC_FOURCC('Y','M','G','A'):
  272. // Packed YUV 4:2:2, U:Y:V:Y, interlaced
  273. case VLC_FOURCC('I','U','Y','V'):    // packed by 2
  274. // Packed YUV 2:1:1, Y:U:Y:V
  275. case VLC_FOURCC('Y','2','1','1'):     // packed by 4
  276. // Packed YUV Reverted
  277. case VLC_FOURCC('c','y','u','v'):    // packed by 2
  278. */
  279.     switch (p_vout->render.i_chroma)
  280.     {
  281.     // planar YUV
  282.         case VLC_FOURCC('I','4','4','4'):
  283.         case VLC_FOURCC('I','4','2','2'):
  284.         case VLC_FOURCC('I','4','2','0'):
  285.         case VLC_FOURCC('Y','V','1','2'):
  286.         case VLC_FOURCC('I','Y','U','V'):
  287.         case VLC_FOURCC('I','4','1','1'):
  288.         case VLC_FOURCC('I','4','1','0'):
  289.         case VLC_FOURCC('Y','V','U','9'):
  290.         case VLC_FOURCC('Y','U','V','A'):
  291.             p_vout->pf_render = RenderPlanarYUV;
  292.             break;
  293.     // packed RGB
  294.         case VLC_FOURCC('R','G','B','2'):    // packed by 1
  295.         case VLC_FOURCC('R','V','1','5'):    // packed by 2
  296.         case VLC_FOURCC('R','V','1','6'):    // packed by 2
  297.         case VLC_FOURCC('R','V','2','4'):    // packed by 3
  298.         case VLC_FOURCC('R','V','3','2'):    // packed by 4
  299.             p_vout->pf_render = RenderPackedRGB;
  300.             break;
  301. #ifdef PACKED_YUV
  302.     // packed YUV
  303.         case VLC_FOURCC('Y','U','Y','2'):    // packed by 2
  304.         case VLC_FOURCC('Y','U','N','V'):    // packed by 2
  305.         case VLC_FOURCC('U','Y','V','Y'):    // packed by 2
  306.         case VLC_FOURCC('U','Y','N','V'):    // packed by 2
  307.         case VLC_FOURCC('Y','4','2','2'):    // packed by 2
  308.             p_vout->pf_render = RenderPackedYUV;
  309.             break;
  310. #endif
  311.         default:
  312.             msg_Err( p_vout, "colorspace not supported by plug-in !!!");
  313.             free( p_vout->p_sys );
  314.             return VLC_ENOMEM;
  315.     }
  316.     p_vout->pf_display = NULL;
  317.     p_vout->pf_control = Control;
  318.     config_ChainParse( p_vout, CFG_PREFIX, ppsz_filter_options,
  319.                        p_vout->p_cfg );
  320.     /* Look what method was requested */
  321.     p_vout->p_sys->i_col = var_CreateGetInteger( p_vout, CFG_PREFIX "cols" );
  322.     p_vout->p_sys->i_row = var_CreateGetInteger( p_vout, CFG_PREFIX "rows" );
  323. // OS dependent code :  Autodetect number of displays in wall
  324. #ifdef WIN32
  325.     if ((p_vout->p_sys->i_col < 0) || (p_vout->p_sys->i_row < 0) )
  326.     {
  327.         int nbMonitors = GetSystemMetrics(SM_CMONITORS);
  328.         if (nbMonitors == 1)
  329.         {
  330.             nbMonitors = 5; // 1 display => 5x1 simulation
  331.             p_vout->p_sys->i_col = nbMonitors;
  332.             p_vout->p_sys->i_row = 1;
  333.         }
  334.         else
  335.         {
  336.             p_vout->p_sys->i_col = GetSystemMetrics( SM_CXVIRTUALSCREEN ) / GetSystemMetrics( SM_CXSCREEN );
  337.             p_vout->p_sys->i_row = GetSystemMetrics( SM_CYVIRTUALSCREEN ) / GetSystemMetrics( SM_CYSCREEN );
  338.             if (p_vout->p_sys->i_col * p_vout->p_sys->i_row != nbMonitors)
  339.             {
  340.                 p_vout->p_sys->i_col = nbMonitors;
  341.                 p_vout->p_sys->i_row = 1;
  342.             }
  343.         }
  344.         var_SetInteger( p_vout, CFG_PREFIX "cols", p_vout->p_sys->i_col);
  345.         var_SetInteger( p_vout, CFG_PREFIX "rows", p_vout->p_sys->i_row);
  346.     }
  347. #endif
  348. #ifdef OVERLAP
  349.     p_vout->p_sys->i_offset_x = var_CreateGetBool( p_vout, CFG_PREFIX "offset-x" );
  350.     if (p_vout->p_sys->i_col > 2) p_vout->p_sys->i_offset_x = 0; // offset-x is used in case of 2x1 wall & autocrop
  351.     p_vout->p_sys->b_autocrop = !(var_CreateGetInteger( p_vout, "crop-ratio" ) == 0);
  352.     if (!p_vout->p_sys->b_autocrop) p_vout->p_sys->b_autocrop = var_CreateGetInteger( p_vout, "autocrop" );
  353.     p_vout->p_sys->b_attenuate = var_CreateGetBool( p_vout, CFG_PREFIX "attenuate");
  354.     p_vout->p_sys->bz_length = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-length" );
  355.     if (p_vout->p_sys->i_row > 1)
  356.         p_vout->p_sys->bz_height = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-height" );
  357.     else
  358.         p_vout->p_sys->bz_height = 100;
  359.     p_vout->p_sys->bz_begin = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-begin" );
  360.     p_vout->p_sys->bz_middle = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-middle" );
  361.     p_vout->p_sys->bz_end = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-end" );
  362.     p_vout->p_sys->bz_middle_pos = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-middle-pos" );
  363.     double d_p = 100.0 / p_vout->p_sys->bz_middle_pos;
  364.     p_vout->p_sys->i_ratio_max = var_CreateGetInteger( p_vout, "autocrop-ratio-max" ); // in crop module with autocrop ...
  365.     p_vout->p_sys->i_ratio = var_CreateGetInteger( p_vout, "crop-ratio" ); // in crop module with manual ratio ...
  366.     p_vout->p_sys->a_2 = d_p * p_vout->p_sys->bz_begin - (double)(d_p * d_p / (d_p - 1)) * p_vout->p_sys->bz_middle + (double)(d_p / (d_p - 1)) * p_vout->p_sys->bz_end;
  367.     p_vout->p_sys->a_1 = -(d_p + 1) * p_vout->p_sys->bz_begin + (double)(d_p * d_p / (d_p - 1)) * p_vout->p_sys->bz_middle - (double)(1 / (d_p - 1)) * p_vout->p_sys->bz_end;
  368.     p_vout->p_sys->a_0 =  p_vout->p_sys->bz_begin;
  369. #ifdef GAMMA
  370.     p_vout->p_sys->f_gamma_red = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-red" );
  371.     p_vout->p_sys->f_gamma_green = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-green" );
  372.     p_vout->p_sys->f_gamma_blue = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-blue" );
  373. #endif
  374. #ifndef WIN32
  375.     p_vout->p_sys->b_xinerama = var_CreateGetBool( p_vout, CFG_PREFIX "xinerama" );
  376. #endif
  377. #else
  378.     p_vout->p_sys->i_col = __MAX( 1, __MIN( 15, p_vout->p_sys->i_col ) );
  379.     p_vout->p_sys->i_row = __MAX( 1, __MIN( 15, p_vout->p_sys->i_row ) );
  380. #endif
  381.     msg_Dbg( p_vout, "opening a %i x %i wall",
  382.              p_vout->p_sys->i_col, p_vout->p_sys->i_row );
  383.     p_vout->p_sys->pp_vout = calloc( p_vout->p_sys->i_row *
  384.                                      p_vout->p_sys->i_col,
  385.                                      sizeof(struct vout_list_t) );
  386.     if( p_vout->p_sys->pp_vout == NULL )
  387.     {
  388.         free( p_vout->p_sys );
  389.         return VLC_ENOMEM;
  390.     }
  391.     psz_method_tmp =
  392.     psz_method = var_CreateGetNonEmptyString( p_vout, CFG_PREFIX "active" );
  393.     /* If no trailing vout are specified, take them all */
  394.     if( psz_method == NULL )
  395.     {
  396.         for( i_vout = p_vout->p_sys->i_row * p_vout->p_sys->i_col;
  397.              i_vout--; )
  398.         {
  399.             p_vout->p_sys->pp_vout[i_vout].b_active = 1;
  400.         }
  401.     }
  402.     /* If trailing vout are specified, activate only the requested ones */
  403.     else
  404.     {
  405.         for( i_vout = p_vout->p_sys->i_row * p_vout->p_sys->i_col;
  406.              i_vout--; )
  407.         {
  408.             p_vout->p_sys->pp_vout[i_vout].b_active = 0;
  409.         }
  410.         while( *psz_method )
  411.         {
  412.             psz_tmp = psz_method;
  413.             while( *psz_tmp && *psz_tmp != ',' )
  414.             {
  415.                 psz_tmp++;
  416.             }
  417.             if( *psz_tmp )
  418.             {
  419.                 *psz_tmp = '';
  420.                 i_vout = atoi( psz_method );
  421.                 psz_method = psz_tmp + 1;
  422.             }
  423.             else
  424.             {
  425.                 i_vout = atoi( psz_method );
  426.                 psz_method = psz_tmp;
  427.             }
  428.             if( i_vout >= 0 &&
  429.                 i_vout < p_vout->p_sys->i_row * p_vout->p_sys->i_col )
  430.             {
  431.                 p_vout->p_sys->pp_vout[i_vout].b_active = 1;
  432.             }
  433.         }
  434.     }
  435.     free( psz_method_tmp );
  436.     return VLC_SUCCESS;
  437. }
  438. #ifdef OVERLAP
  439. /*****************************************************************************
  440.  * CLIP_0A: clip between 0 and ACCURACY
  441.  *****************************************************************************/
  442. inline static int CLIP_0A( int a )
  443. {
  444.     return (a > ACCURACY) ? ACCURACY : (a < 0) ? 0 : a;
  445. }
  446. #ifdef GAMMA
  447. /*****************************************************************************
  448.  *  Gamma: Gamma correction
  449.  *****************************************************************************/
  450. static double Gamma_Correction(int i_plane, float f_component, float f_BlackCrush[VOUT_MAX_PLANES], float f_WhiteCrush[VOUT_MAX_PLANES], float f_BlackLevel[VOUT_MAX_PLANES], float f_WhiteLevel[VOUT_MAX_PLANES], float f_Gamma[VOUT_MAX_PLANES])
  451. {
  452.     float f_Input;
  453.     f_Input = (f_component * f_BlackLevel[i_plane]) / (f_BlackCrush[i_plane]) + (1.0 - f_BlackLevel[i_plane]);
  454.     if (f_component <= f_BlackCrush[i_plane])
  455.     {
  456.         return pow(f_Input, 1.0 / f_Gamma[i_plane]);
  457.     }
  458.     else if (f_component >= f_WhiteCrush[i_plane])
  459.     {
  460.         f_Input = (f_component * (1.0 - (f_WhiteLevel[i_plane] + 1.0)) + (f_WhiteLevel[i_plane] + 1.0) * f_WhiteCrush[i_plane] - 1.0) / (f_WhiteCrush[i_plane] - 1.0);
  461.         return pow(f_Input, 1.0 / f_Gamma[i_plane]);
  462.     }
  463.     else
  464.     {
  465.         return 1.0;
  466.     }
  467. }
  468. #ifdef PACKED_YUV
  469. /*****************************************************************************
  470.  * F: Function to calculate Gamma correction
  471.  *****************************************************************************/
  472. static uint8_t F(uint8_t i, float gamma)
  473. {
  474.     double input = (double) i / 255.0;
  475.     // return clip(255 * pow(input, 1.0 / gamma));
  476.     if (input < 0.5)
  477.         return clip_uint8((255 * pow(2 * input, gamma)) / 2);
  478.     else
  479.         return clip_uint8(255 * (1 - pow(2 * (1 - input), gamma) / 2));
  480. }
  481. #endif
  482. #endif
  483. /*****************************************************************************
  484.  * AdjustHeight: ajust p_sys->i_height to have same BZ width for any ratio
  485.  *****************************************************************************/
  486. static int AdjustHeight( vout_thread_t *p_vout )
  487. {
  488.     bool b_fullscreen = p_vout->b_fullscreen;
  489.     int i_window_width = p_vout->i_window_width;
  490.     int i_window_height = p_vout->i_window_height;
  491.     double d_halfLength = 0;
  492.     double d_halfLength_crop;
  493.     double d_halfLength_calculated;
  494.     int    i_offset = 0;
  495.     // OS DEPENDENT CODE to get display dimensions
  496.     if (b_fullscreen )
  497.     {
  498. #ifdef WIN32
  499.         i_window_width  = GetSystemMetrics(SM_CXSCREEN);
  500.         i_window_height = GetSystemMetrics(SM_CYSCREEN);
  501. #else
  502.         char *psz_display = var_CreateGetNonEmptyString( p_vout,
  503.                                                         "x11-display" );
  504.         Display *p_display = XOpenDisplay( psz_display );
  505.         free( psz_display );
  506.         if (p_vout->p_sys->b_xinerama)
  507.         {
  508.             i_window_width = DisplayWidth(p_display, 0) / p_vout->p_sys->i_col;
  509.             i_window_height = DisplayHeight(p_display, 0) / p_vout->p_sys->i_row;
  510.         }
  511.         else
  512.         {
  513.             i_window_width = DisplayWidth(p_display, 0);
  514.             i_window_height = DisplayHeight(p_display, 0);
  515.         }
  516.         XCloseDisplay( p_display );
  517. #endif
  518.         var_SetInteger( p_vout, "width", i_window_width);
  519.         var_SetInteger( p_vout, "height", i_window_height);
  520.         p_vout->i_window_width = i_window_width;
  521.         p_vout->i_window_height = i_window_height;
  522.     }
  523.     if( p_vout->p_sys->bz_length)
  524.         if ((!p_vout->p_sys->b_autocrop) && (!p_vout->p_sys->i_ratio))
  525.         {
  526.             if ((p_vout->p_sys->i_row > 1) || (p_vout->p_sys->i_col > 1))
  527.             {
  528.                 while ((d_halfLength <= 0) || (d_halfLength > p_vout->render.i_width / (2 * p_vout->p_sys->i_col)))
  529.                 {
  530.                     if (p_vout->p_sys->bz_length >= 50)
  531.                     {
  532.                         d_halfLength = i_window_width * p_vout->render.i_height / (2 * i_window_height * p_vout->p_sys->i_row) - p_vout->render.i_width / (2 * p_vout->p_sys->i_col);
  533.                     }
  534.                     else
  535.                     {
  536.                         d_halfLength = (p_vout->render.i_width * p_vout->p_sys->bz_length) / (100.0 * p_vout->p_sys->i_col);
  537.                         d_halfLength = __MAX(i_window_width * p_vout->render.i_height / (2 * i_window_height * p_vout->p_sys->i_row) - p_vout->render.i_width / (2 * p_vout->p_sys->i_col), d_halfLength);
  538.                     }
  539.                     if ((d_halfLength <= 0) || (d_halfLength > p_vout->render.i_width / (2 * p_vout->p_sys->i_col)))
  540.                         p_vout->p_sys->i_row--;
  541.                     if (p_vout->p_sys->i_row < 1 )
  542.                     {
  543.                         p_vout->p_sys->i_row = 1;
  544.                         break;
  545.                     }
  546.                 }
  547.                 p_vout->p_sys->i_halfLength = (d_halfLength + 0.5);
  548.                 p_vout->p_sys->bz_length = (p_vout->p_sys->i_halfLength * 100.0 * p_vout->p_sys->i_col) / p_vout->render.i_width;
  549.                 var_SetInteger( p_vout, "bz-length", p_vout->p_sys->bz_length);
  550.                 var_SetInteger( p_vout, "panoramix-rows", p_vout->p_sys->i_row);
  551.             }
  552.         }
  553.         else
  554.         {
  555.             d_halfLength = ((2 * (double)i_window_width - (double)(p_vout->p_sys->i_ratio_max * i_window_height) / 1000.0 ) * (double)p_vout->p_sys->bz_length) / 200.0;
  556.             d_halfLength_crop = d_halfLength * VOUT_ASPECT_FACTOR * (double)p_vout->output.i_width
  557.                         / (double)i_window_height / (double)p_vout->render.i_aspect;
  558.             p_vout->p_sys->i_halfLength = (d_halfLength_crop + 0.5);
  559.             d_halfLength_calculated = p_vout->p_sys->i_halfLength * (double)i_window_height *
  560.                                 (double)p_vout->render.i_aspect  /     VOUT_ASPECT_FACTOR / (double)p_vout->output.i_width;
  561.             if (!p_vout->p_sys->b_attenuate)
  562.             {
  563.                 double d_bz_length = (p_vout->p_sys->i_halfLength * p_vout->p_sys->i_col * 100.0) / p_vout->render.i_width;
  564.                 // F(2x) != 2F(x) in opengl module
  565.                 if (p_vout->p_sys->i_col == 2) d_bz_length = (100.0 * d_bz_length) / (100.0 - d_bz_length) ;
  566.                 var_SetInteger( p_vout, "bz-length", (int)(d_bz_length + 0.5));
  567.             }
  568.             i_offset =  (int)d_halfLength - (int)
  569.                         (p_vout->p_sys->i_halfLength * (double)i_window_height *
  570.                         (double)p_vout->render.i_aspect  /     VOUT_ASPECT_FACTOR / (double)p_vout->output.i_width);
  571.         }
  572.     else
  573.         p_vout->p_sys->i_halfLength = 0;
  574.     return i_offset;
  575. }
  576. #endif
  577. /*****************************************************************************
  578.  * Init: initialize Wall video thread output method
  579.  *****************************************************************************/
  580. #define VLC_XCHG( type, a, b ) do { type __tmp = (b); (b) = (a); (a) = __tmp; } while(0)
  581. static int Init( vout_thread_t *p_vout )
  582. {
  583.     int i_index, i_row, i_col;
  584.     I_OUTPUTPICTURES = 0;
  585.     /* Initialize the output structure */
  586.     p_vout->output.i_chroma = p_vout->render.i_chroma;
  587.     p_vout->output.i_width  = p_vout->render.i_width;
  588.     p_vout->output.i_height = p_vout->render.i_height;
  589.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  590. #ifdef OVERLAP
  591.     p_vout->p_sys->b_has_changed = p_vout->p_sys->b_attenuate;
  592.     int i_video_x = var_GetInteger( p_vout, "video-x");
  593.     int i_video_y = var_GetInteger( p_vout, "video-y");
  594. #ifdef GAMMA
  595.     if (p_vout->p_sys->b_attenuate)
  596.     {
  597.         int i_index2, i_plane;
  598.         int constantYUV[3] = {0,128,128};
  599.         float    f_BlackCrush[VOUT_MAX_PLANES];
  600.         float    f_BlackLevel[VOUT_MAX_PLANES];
  601.         float    f_WhiteCrush[VOUT_MAX_PLANES];
  602.         float    f_WhiteLevel[VOUT_MAX_PLANES];
  603.         p_vout->p_sys->f_gamma[0] = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-red" );
  604.         p_vout->p_sys->f_gamma[1] = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-green" );
  605.         p_vout->p_sys->f_gamma[2] = var_CreateGetFloat( p_vout, CFG_PREFIX "bz-gamma-blue" );
  606.         f_BlackCrush[0] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blackcrush-red" ) / 255.0;
  607.         f_BlackCrush[1] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blackcrush-green" ) / 255.0;
  608.         f_BlackCrush[2] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blackcrush-blue" ) / 255.0;
  609.         f_WhiteCrush[0] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitecrush-red" ) / 255.0;
  610.         f_WhiteCrush[1] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitecrush-green" ) / 255.0;
  611.         f_WhiteCrush[2] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitecrush-blue" ) / 255.0;
  612.         f_BlackLevel[0] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blacklevel-red" ) / 255.0;
  613.         f_BlackLevel[1] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blacklevel-green" ) / 255.0;
  614.         f_BlackLevel[2] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-blacklevel-blue" ) / 255.0;
  615.         f_WhiteLevel[0] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitelevel-red" ) / 255.0;
  616.         f_WhiteLevel[1] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitelevel-green" ) / 255.0;
  617.         f_WhiteLevel[2] = var_CreateGetInteger( p_vout, CFG_PREFIX "bz-whitelevel-blue" ) / 255.0;
  618.         for( int i = 3; i < VOUT_MAX_PLANES; i++ )
  619.         {
  620.             /* Initialize unsupported planes */
  621.             f_BlackCrush[i] = 140.0/255.0;
  622.             f_WhiteCrush[i] = 200.0/255.0;
  623.             f_BlackLevel[i] = 150.0/255.0;
  624.             f_WhiteLevel[i] = 0.0/255.0;
  625.             p_vout->p_sys->f_gamma[i] = 1.0;
  626.         }
  627.         switch (p_vout->render.i_chroma)
  628.         {
  629.         // planar YVU
  630.             case VLC_FOURCC('Y','V','1','2'):
  631.             case VLC_FOURCC('Y','V','U','9'):
  632.         // packed UYV
  633.             case VLC_FOURCC('U','Y','V','Y'):    // packed by 2
  634.             case VLC_FOURCC('U','Y','N','V'):    // packed by 2
  635.             case VLC_FOURCC('Y','4','2','2'):    // packed by 2
  636.     //        case VLC_FOURCC('c','y','u','v'):    // packed by 2
  637.                 VLC_XCHG( float, p_vout->p_sys->f_gamma[1], p_vout->p_sys->f_gamma[2] );
  638.                 VLC_XCHG( float, f_BlackCrush[1], f_BlackCrush[2] );
  639.                 VLC_XCHG( float, f_WhiteCrush[1], f_WhiteCrush[2] );
  640.                 VLC_XCHG( float, f_BlackLevel[1], f_BlackLevel[2] );
  641.                 VLC_XCHG( float, f_WhiteLevel[1], f_WhiteLevel[2] );
  642.         // planar YUV
  643.             case VLC_FOURCC('I','4','4','4'):
  644.             case VLC_FOURCC('I','4','2','2'):
  645.             case VLC_FOURCC('I','4','2','0'):
  646.             case VLC_FOURCC('I','4','1','1'):
  647.             case VLC_FOURCC('I','4','1','0'):
  648.             case VLC_FOURCC('I','Y','U','V'):
  649.             case VLC_FOURCC('Y','U','V','A'):
  650.         // packed YUV
  651.             case VLC_FOURCC('Y','U','Y','2'):    // packed by 2
  652.             case VLC_FOURCC('Y','U','N','V'):    // packed by 2
  653.                 for (i_index = 0; i_index < 256; i_index++)
  654.                     for (i_index2 = 0; i_index2 <= ACCURACY; i_index2++)
  655.                         for (i_plane = 0; i_plane < VOUT_MAX_PLANES; i_plane++)
  656.                         {
  657.                             float f_lut = CLIP_01(1.0 -
  658.                                      ((ACCURACY - (float)i_index2)
  659.                                      * Gamma_Correction(i_plane, (float)i_index / 255.0, f_BlackCrush, f_WhiteCrush, f_BlackLevel, f_WhiteLevel, p_vout->p_sys->f_gamma)
  660.                                      / (ACCURACY - 1)));
  661.                             p_vout->p_sys->LUT[i_plane][i_index2][i_index] = f_lut * i_index + (int)((1.0 - f_lut) * (float)constantYUV[i_plane]);
  662.                         }
  663.                 break;
  664.         // packed RGB
  665.             case VLC_FOURCC('R','G','B','2'):    // packed by 1
  666.             case VLC_FOURCC('R','V','1','5'):    // packed by 2
  667.             case VLC_FOURCC('R','V','1','6'):    // packed by 2
  668.             case VLC_FOURCC('R','V','2','4'):    // packed by 3
  669.             case VLC_FOURCC('R','V','3','2'):    // packed by 4
  670.             for (i_index = 0; i_index < 256; i_index++)
  671.                     for (i_index2 = 0; i_index2 <= ACCURACY; i_index2++)
  672.                         for (i_plane = 0; i_plane < VOUT_MAX_PLANES; i_plane++)
  673.                         {
  674.                             float f_lut = CLIP_01(1.0 -
  675.                                      ((ACCURACY - (float)i_index2)
  676.                                      * Gamma_Correction(i_plane, (float)i_index / 255.0, f_BlackCrush, f_WhiteCrush, f_BlackLevel, f_WhiteLevel, p_vout->p_sys->f_gamma)
  677.                                      / (ACCURACY - 1)));
  678.                             p_vout->p_sys->LUT[i_plane][i_index2][i_index] = f_lut * i_index;
  679.                         }
  680.                 break;
  681.             default:
  682.                 msg_Err( p_vout, "colorspace not supported by plug-in !!!");
  683.                 free( p_vout->p_sys );
  684.                 return VLC_ENOMEM;
  685.         }
  686.     }
  687. #endif
  688.     if (p_vout->p_sys->i_offset_x)
  689.         p_vout->p_sys->i_offset_x = AdjustHeight(p_vout);
  690.     else
  691.         AdjustHeight(p_vout);
  692.     if (p_vout->p_sys->i_row >= 2)
  693.     {
  694.         p_vout->p_sys->i_halfHeight = (p_vout->p_sys->i_halfLength * p_vout->p_sys->bz_height) / 100;
  695.         p_vout->p_sys->i_halfHeight -= (p_vout->p_sys->i_halfHeight % 2);
  696.     }
  697. #endif
  698.     /* Try to open the real video output */
  699.     msg_Dbg( p_vout, "spawning the real video outputs" );
  700.     /* FIXME: use bresenham instead of those ugly divisions */
  701.     p_vout->p_sys->i_vout = 0;
  702.     for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
  703.     {
  704.         for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++, p_vout->p_sys->i_vout++ )
  705.         {
  706.             struct vout_list_t *p_entry = &p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ];
  707.             video_format_t fmt;
  708.             int i_width, i_height;
  709.             /* */
  710.             i_width = ( p_vout->render.i_width / p_vout->p_sys->i_col ) & ~0x1;
  711.             if( i_col + 1 == p_vout->p_sys->i_col )
  712.                 i_width = p_vout->render.i_width - i_col * i_width;
  713. #ifdef OVERLAP
  714.             i_width += p_vout->p_sys->i_halfLength;
  715.             if (p_vout->p_sys->i_col > 2 )
  716.                 i_width += p_vout->p_sys->i_halfLength;
  717.             i_width &= ~0x1;
  718. #endif
  719.             /* */
  720.             i_height = ( p_vout->render.i_height / p_vout->p_sys->i_row ) & ~0x3;
  721.             if( i_row + 1 == p_vout->p_sys->i_row )
  722.                 i_height = p_vout->render.i_height - i_row * i_height;
  723. #ifdef OVERLAP
  724.             if(p_vout->p_sys->i_row >= 2 )
  725.             {
  726.                 i_height += p_vout->p_sys->i_halfHeight;
  727.                 if( p_vout->p_sys->i_row > 2 )
  728.                     i_height += p_vout->p_sys->i_halfHeight;
  729.             }
  730.             i_height &= ~0x1;
  731. #endif
  732.             p_entry->i_width = i_width;
  733.             p_entry->i_height = i_height;
  734.             if( !p_entry->b_active )
  735.                 continue;
  736.             /* */
  737.             memset( &fmt, 0, sizeof(video_format_t) );
  738.             fmt.i_width = fmt.i_visible_width = p_vout->render.i_width;
  739.             fmt.i_height = fmt.i_visible_height = p_vout->render.i_height;
  740.             fmt.i_x_offset = fmt.i_y_offset = 0;
  741.             fmt.i_chroma = p_vout->render.i_chroma;
  742.             fmt.i_aspect = p_vout->render.i_aspect;
  743.             fmt.i_sar_num = p_vout->render.i_aspect * fmt.i_height / fmt.i_width;
  744.             fmt.i_sar_den = VOUT_ASPECT_FACTOR;
  745.             fmt.i_width = fmt.i_visible_width = i_width;
  746.             fmt.i_height = fmt.i_visible_height = i_height;
  747.             fmt.i_aspect = p_vout->render.i_aspect
  748.                               * p_vout->render.i_height / i_height
  749.                               * i_width / p_vout->render.i_width;
  750. #ifdef OVERLAP
  751.             if (p_vout->p_sys->i_offset_x < 0)
  752.             {
  753.                 var_SetInteger(p_vout, "video-x", -p_vout->p_sys->i_offset_x);
  754.                 p_vout->p_sys->i_offset_x = 0;
  755.             }
  756. #endif
  757.             p_entry->p_vout = vout_Create( p_vout, &fmt);
  758.             if( p_entry->p_vout == NULL )
  759.             {
  760.                 msg_Err( p_vout, "failed to get %ix%i vout threads",
  761.                                  p_vout->p_sys->i_col, p_vout->p_sys->i_row );
  762.                 RemoveAllVout( p_vout );
  763.                 return VLC_EGENERIC;
  764.             }
  765.             vout_filter_SetupChild( p_vout, p_entry->p_vout,
  766.                                     MouseEvent, FullscreenEventUp, FullscreenEventDown, true );
  767. #ifdef OVERLAP
  768.             p_entry->p_vout->i_alignment = 0;
  769.             if (i_col == 0)
  770.                 p_entry->p_vout->i_alignment |= VOUT_ALIGN_RIGHT;
  771.             else if (i_col == p_vout->p_sys->i_col -1)
  772.                 p_entry->p_vout->i_alignment |= VOUT_ALIGN_LEFT;
  773.             if (p_vout->p_sys->i_row > 1)
  774.             {
  775.                 if (i_row == 0)
  776.                     p_entry->p_vout->i_alignment |= VOUT_ALIGN_BOTTOM;
  777.                 else if (i_row == p_vout->p_sys->i_row -1)
  778.                     p_entry->p_vout->i_alignment |= VOUT_ALIGN_TOP;
  779.             }
  780.             // i_active : number of active pp_vout
  781.             int i_active = 0;
  782.             for( int i = 0; i <= p_vout->p_sys->i_vout; i++ )
  783.             {
  784.                 if( p_vout->p_sys->pp_vout[i].b_active )
  785.                     i_active++;
  786.             }
  787.             var_SetInteger( p_vout, "align", p_entry->p_vout->i_alignment );
  788.             var_SetInteger( p_vout, "video-x", i_video_x + p_vout->p_sys->i_offset_x + (i_active % p_vout->p_sys->i_col) * p_vout->i_window_width);
  789.             var_SetInteger( p_vout, "video-y", i_video_y +                             (i_active / p_vout->p_sys->i_col) * p_vout->i_window_height);
  790. #endif
  791.         }
  792.     }
  793.     vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
  794.     return VLC_SUCCESS;
  795. }
  796. /*****************************************************************************
  797.  * End: terminate Wall video thread output method
  798.  *****************************************************************************/
  799. static void End( vout_thread_t *p_vout )
  800. {
  801.     RemoveAllVout( p_vout );
  802.     vout_filter_ReleaseDirectBuffers( p_vout );
  803. #ifdef OVERLAP
  804.     var_SetInteger( p_vout, "bz-length", p_vout->p_sys->bz_length);
  805. #endif
  806. }
  807. /*****************************************************************************
  808.  * Destroy: destroy Wall video thread output method
  809.  *****************************************************************************
  810.  * Terminate an output method created by WallCreateOutputMethod
  811.  *****************************************************************************/
  812. static void Destroy( vlc_object_t *p_this )
  813. {
  814.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  815.     free( p_vout->p_sys->pp_vout );
  816.     free( p_vout->p_sys );
  817. }
  818. /*****************************************************************************
  819.  * RenderPlanarYUV: displays previously rendered output
  820.  *****************************************************************************
  821.  * This function send the currently rendered image to Wall image, waits
  822.  * until it is displayed and switch the two rendering buffers, preparing next
  823.  * frame.
  824.  *****************************************************************************/
  825. static void RenderPlanarYUV( vout_thread_t *p_vout, picture_t *p_pic )
  826. {
  827.     picture_t *p_outpic = NULL;
  828.     int i_col, i_row, i_vout, i_plane;
  829.     int pi_left_skip[VOUT_MAX_PLANES], pi_top_skip[VOUT_MAX_PLANES];
  830. #ifdef OVERLAP
  831.     int TopOffset;
  832.     int constantYUV[3] = {0,128,128};
  833.     int Denom;
  834.     int a_2;
  835.     int a_1;
  836.     int a_0;
  837.     int i_index, i_index2;
  838. #endif
  839.     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  840.         pi_top_skip[i_plane] = 0;
  841.     for( i_vout = 0, i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
  842.     {
  843.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  844.             pi_left_skip[i_plane] = 0;
  845.         for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++, i_vout++ )
  846.         {
  847.             struct vout_list_t *p_entry = &p_vout->p_sys->pp_vout[ i_vout ];
  848.             if( !p_entry->b_active )
  849.             {
  850.                 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  851.                 {
  852.                     pi_left_skip[i_plane] += p_entry->i_width * p_pic->p[i_plane].i_pitch / p_vout->output.i_width;
  853.                 }
  854.                 continue;
  855.             }
  856.             while( ( p_outpic = vout_CreatePicture( p_entry->p_vout, 0, 0, 0 )) == NULL )
  857.             {
  858.                 if( !vlc_object_alive(p_vout) || p_vout->b_error )
  859.                 {
  860.                     vout_DestroyPicture( p_entry->p_vout, p_outpic );
  861.                     return;
  862.                 }
  863.                 msleep( VOUT_OUTMEM_SLEEP );
  864.             }
  865.             p_outpic->date = p_pic->date;
  866.             vout_LinkPicture( p_entry->p_vout, p_outpic );
  867.             for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  868.             {
  869.                 uint8_t *p_in, *p_in_end, *p_out;
  870.                 int i_in_pitch = p_pic->p[i_plane].i_pitch;
  871.                 int i_out_pitch = p_outpic->p[i_plane].i_pitch;
  872.                 int i_copy_pitch = p_outpic->p[i_plane].i_visible_pitch;
  873.                 int i_lines = p_outpic->p[i_plane].i_visible_lines;
  874.                 const int i_div = p_entry->i_width / i_copy_pitch;
  875.                 const bool b_row_first = i_row == 0;
  876.                 const bool b_row_last = i_row + 1 == p_vout->p_sys->i_row;
  877.                 const bool b_col_first = i_col == 0;
  878.                 const bool b_col_last = i_col + 1 == p_vout->p_sys->i_col;
  879. #ifdef OVERLAP
  880.                 if( !b_col_first )
  881.                     pi_left_skip[i_plane] -= (2 * p_vout->p_sys->i_halfLength ) / i_div;
  882.                 if( p_vout->p_sys->i_row >= 2 )
  883.                 {
  884.                     if( !b_row_first && b_col_first )
  885.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch) / i_div;
  886.                     if( p_vout->p_sys->i_row > 2 && i_row == 1 && b_col_first )
  887.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch) / i_div;
  888.                     if( !p_vout->p_sys->pp_vout[p_vout->p_sys->i_col-1].b_active )
  889.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * i_row * p_pic->p[i_plane].i_pitch) / i_div;
  890.                 }
  891. // i_n : previous inactive pp_vout
  892.                 int i_n=0;
  893.                 while( (i_col - i_n > 1) && (!p_vout->p_sys->pp_vout[i_row * p_vout->p_sys->i_col + i_col - 1 - i_n].b_active) ) i_n++;
  894.                 if( i_col > 1 && i_n )
  895.                     pi_left_skip[i_plane] -= i_n * (2 * p_vout->p_sys->i_halfLength ) / i_div;
  896.                 if( p_vout->p_sys->i_row > 2 && ( b_row_first || b_row_last ) )
  897.                     i_lines -= (2 * p_vout->p_sys->i_halfHeight) / i_div;
  898. // 1088 lines bug in a mpeg2 stream of 1080 lines
  899.                 if( b_row_last && p_pic->p[i_plane].i_lines == 1088 )
  900.                     i_lines -= 8 / i_div;
  901. #endif
  902.                 /* */
  903.                 p_in = &p_pic->p[i_plane].p_pixels[ pi_top_skip[i_plane] + pi_left_skip[i_plane] ]; /* Wall proprities */
  904.                 p_in_end = &p_in[i_lines * p_pic->p[i_plane].i_pitch];
  905.                 p_out = p_outpic->p[i_plane].p_pixels;
  906. #ifdef OVERLAP
  907.                 if( p_vout->p_sys->i_row > 2 && b_row_first )
  908.                     p_out += p_outpic->p[i_plane].i_pitch * (2 * p_vout->p_sys->i_halfHeight) / i_div;
  909.                 int i_col_mod;
  910.                 int length = 2 * p_vout->p_sys->i_halfLength / i_div;
  911.                 if( p_vout->p_sys->b_has_changed )
  912.                 {
  913.                     Denom = F2(length);
  914.                     a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  915.                     a_1 = p_vout->p_sys->a_1 * length * (ACCURACY / 100);
  916.                     a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  917.                     for( i_col_mod = 0; i_col_mod < 2; i_col_mod++ )
  918.                     {
  919.                         for( i_index = 0; i_index < length; i_index++ )
  920.                         {
  921.                             p_vout->p_sys->lambda[i_col_mod][i_plane][i_index] = CLIP_0A(!i_col_mod ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,length - i_index) + a_0) / Denom);
  922.                             p_vout->p_sys->cstYUV[i_col_mod][i_plane][i_index] = ((ACCURACY - p_vout->p_sys->lambda[i_col_mod][i_plane][i_index]) * constantYUV[i_plane]) / ACCURACY;
  923.                         }
  924.                     }
  925.                 }
  926. #endif
  927.                 while( p_in < p_in_end )
  928.                 {
  929. #ifndef OVERLAP
  930.                     vlc_memcpy( p_out, p_in, i_copy_pitch);
  931. #else
  932.                     if( p_vout->p_sys->i_col > 2 )
  933.                     {
  934.                         const int halfl = length / 2;
  935.                         if( b_col_first)
  936.                             vlc_memcpy( &p_out[halfl], &p_in[0], i_copy_pitch - halfl );
  937.                         else if( b_col_last )
  938.                             vlc_memcpy( &p_out[    0], &p_in[-halfl], i_copy_pitch - halfl );
  939.                         else
  940.                             vlc_memcpy( &p_out[    0], &p_in[-halfl], i_copy_pitch);
  941.                         // black bar
  942.                         if( b_col_first )
  943.                             memset( &p_out[0], constantYUV[i_plane], halfl);
  944.                         else if( b_col_last )
  945.                             memset( &p_out[i_copy_pitch - halfl], constantYUV[i_plane], halfl );
  946.                     }
  947.                     else
  948.                     {
  949.                         vlc_memcpy( p_out , p_in, i_copy_pitch );
  950.                     }
  951.                     if( p_vout->p_sys->b_attenuate )
  952.                     {
  953.                         // vertical blend
  954.                         // first blended zone
  955.                         if( !b_col_first )
  956.                         {
  957.                             uint8_t *p_dst = &p_out[0];
  958.                             for (i_index = 0; i_index < length; i_index++)
  959.                             {
  960. #ifndef GAMMA
  961.                                 p_dst[i_index] = (p_vout->p_sys->lambda[1][i_plane][i_index] * p_dst[i_index]) / ACCURACY +
  962.                                                         p_vout->p_sys->cstYUV[1][i_plane][i_index];
  963. #else
  964.                                 p_dst[i_index] = p_vout->p_sys->LUT[i_plane][p_vout->p_sys->lambda[1][i_plane][i_index]][p_dst[i_index]];
  965. #endif
  966.                             }
  967.                         }
  968.                         // second blended zone
  969.                         if( !b_col_last )
  970.                         {
  971.                             uint8_t *p_dst = &p_out[i_copy_pitch - length];
  972.                             for (i_index = 0; i_index < length; i_index++)
  973.                             {
  974. #ifndef GAMMA
  975.                                 p_dst[i_index] = (p_vout->p_sys->lambda[0][i_plane][i_index] * p_dst[i_index]) / ACCURACY +
  976.                                                         p_vout->p_sys->cstYUV[0][i_plane][i_index];
  977. #else
  978.                                p_dst[i_index] = p_vout->p_sys->LUT[i_plane][p_vout->p_sys->lambda[0][i_plane][i_index]][p_dst[i_index]];
  979. #endif
  980.                             }
  981.                         }
  982.                         // end blended zone
  983.                     }
  984. #endif
  985.                     p_in += i_in_pitch;
  986.                     p_out += i_out_pitch;
  987.                 }
  988. #ifdef OVERLAP
  989.        // horizontal blend
  990.         if ( p_vout->p_sys->i_row >= 2 )
  991.         {
  992.            // black bar
  993.            if (( p_vout->p_sys->i_row > 2 ) && (( b_row_first ) || ( b_row_last )))
  994.            {
  995.                int height = 2 * p_vout->p_sys->i_halfHeight / i_div;
  996.                if ( b_row_first )
  997.                {
  998.                     TopOffset = i_lines + (2 * p_vout->p_sys->i_halfHeight) / i_div;
  999.                }
  1000.                else
  1001.                 {
  1002.                    TopOffset = height - (2 * p_vout->p_sys->i_halfHeight) / i_div;
  1003.                 }
  1004.                 uint8_t *p_dst = p_out - TopOffset * i_out_pitch;
  1005.                 for (i_index = 0; i_index < height; i_index++)
  1006.                    for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1007.                        p_dst[i_index * i_out_pitch + i_index2] = constantYUV[i_plane];
  1008.            }
  1009.            if( p_vout->p_sys->b_attenuate )
  1010.            {
  1011.                length = 2 * p_vout->p_sys->i_halfHeight / (p_vout->p_sys->pp_vout[i_vout].i_width / i_copy_pitch);
  1012.                if (p_vout->p_sys->b_has_changed)
  1013.                {
  1014.                    Denom = F2(length);
  1015.                    a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1016.                    a_1 = p_vout->p_sys->a_1 * length * (ACCURACY / 100);
  1017.                    a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1018.                    for(i_col_mod = 0; i_col_mod < 2; i_col_mod++)
  1019.                        for (i_index = 0; i_index < length; i_index++)
  1020.                        {
  1021.                            p_vout->p_sys->lambda2[i_col_mod][i_plane][i_index] = CLIP_0A(!i_col_mod ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,length - i_index) + a_0) / Denom);
  1022.                            p_vout->p_sys->cstYUV2[i_col_mod][i_plane][i_index] = ((ACCURACY - p_vout->p_sys->lambda2[i_col_mod][i_plane][i_index]) * constantYUV[i_plane]) / ACCURACY;
  1023.                        }
  1024.                }
  1025.                // first blended zone
  1026.                if ( !b_row_first )
  1027.                {
  1028.                         TopOffset = i_lines;
  1029.                         uint8_t *p_dst = p_out - TopOffset * i_out_pitch;
  1030.                         for (i_index = 0; i_index < length; i_index++)
  1031.                         {
  1032.                             for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1033.                             {
  1034. #ifndef GAMMA
  1035.                                 p_dst[i_index * i_out_pitch + i_index2] = ( p_vout->p_sys->lambda2[1][i_plane][i_index] *
  1036.                                              p_dst[i_index * i_out_pitch + i_index2] ) / ACCURACY +
  1037.                                              p_vout->p_sys->cstYUV2[1][i_plane][i_index];
  1038. #else
  1039.                                 p_dst[i_index * i_out_pitch + i_index2] = p_vout->p_sys->LUT[i_plane][p_vout->p_sys->lambda2[1][i_plane][i_index]][p_dst[i_index * i_out_pitch + i_index2]];
  1040. #endif
  1041.                             }
  1042.                         }
  1043.                }
  1044.                // second blended zone
  1045.                if ( !b_row_last )
  1046.                {
  1047.                         TopOffset = length;
  1048.                         uint8_t *p_dst = p_out - TopOffset * p_outpic->p[i_plane].i_pitch;
  1049.                         for (i_index = 0; i_index < length; i_index++)
  1050.                         {
  1051.                             for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1052.                             {
  1053. #ifndef GAMMA
  1054.                                 p_dst[i_index * i_out_pitch + i_index2] = (p_vout->p_sys->lambda2[0][i_plane][i_index] *
  1055.                                              p_dst[i_index * i_out_pitch + i_index2]) / ACCURACY +
  1056.                                              p_vout->p_sys->cstYUV2[0][i_plane][i_index];
  1057. #else
  1058.                                 p_dst[i_index * i_out_pitch + i_index2] = p_vout->p_sys->LUT[i_plane][p_vout->p_sys->lambda2[0][i_plane][i_index]][p_dst[i_index * i_out_pitch + i_index2]];
  1059. #endif
  1060.                             }
  1061.                         }
  1062.                }
  1063.            }
  1064.         }
  1065.        // end blended zone
  1066. #endif
  1067.                 // bug for wall filter : fix by CC
  1068.                 //            pi_left_skip[i_plane] += i_out_pitch;
  1069.                 pi_left_skip[i_plane] += i_copy_pitch;
  1070.             }
  1071.             vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1072.                                 p_outpic );
  1073.             vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1074.                                  p_outpic );
  1075.         }
  1076.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1077.         {
  1078.             pi_top_skip[i_plane] += p_vout->p_sys->pp_vout[ i_vout-1 ].i_height
  1079.                                              * p_pic->p[i_plane].i_lines
  1080.                                              / p_vout->output.i_height
  1081.                                              * p_pic->p[i_plane].i_pitch;
  1082.         }
  1083.     }
  1084. #ifdef OVERLAP
  1085.     if (p_vout->p_sys->b_has_changed)
  1086.         p_vout->p_sys->b_has_changed = false;
  1087. #endif
  1088. }
  1089. /*****************************************************************************
  1090.  * RenderPackedRGB: displays previously rendered output
  1091.  *****************************************************************************
  1092.  * This function send the currently rendered image to Wall image, waits
  1093.  * until it is displayed and switch the two rendering buffers, preparing next
  1094.  * frame.
  1095.  *****************************************************************************/
  1096. static void RenderPackedRGB( vout_thread_t *p_vout, picture_t *p_pic )
  1097. {
  1098.     picture_t *p_outpic = NULL;
  1099.     int i_col, i_row, i_vout, i_plane;
  1100.     int pi_left_skip[VOUT_MAX_PLANES], pi_top_skip[VOUT_MAX_PLANES];
  1101. #ifdef OVERLAP
  1102.     int LeftOffset, TopOffset;
  1103.     int Denom;
  1104.     int a_2;
  1105.     int a_1;
  1106.     int a_0;
  1107.     int i_index, i_index2;
  1108. #endif
  1109.     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1110.         pi_top_skip[i_plane] = 0;
  1111.     for( i_vout = 0, i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
  1112.     {
  1113.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1114.             pi_left_skip[i_plane] = 0;
  1115.         for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++, i_vout++ )
  1116.         {
  1117.             if( !p_vout->p_sys->pp_vout[ i_vout ].b_active )
  1118.             {
  1119.                 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1120.                 {
  1121.                     pi_left_skip[i_plane] +=
  1122.                         p_vout->p_sys->pp_vout[ i_vout ].i_width * p_pic->p->i_pixel_pitch;
  1123.                 }
  1124.                 continue;
  1125.             }
  1126.             while( ( p_outpic =
  1127.                 vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1128.                                     0, 0, 0 )
  1129.                    ) == NULL )
  1130.             {
  1131.                 if( !vlc_object_alive (p_vout) || p_vout->b_error )
  1132.                 {
  1133.                     vout_DestroyPicture(
  1134.                         p_vout->p_sys->pp_vout[ i_vout ].p_vout, p_outpic );
  1135.                     return;
  1136.                 }
  1137.                 msleep( VOUT_OUTMEM_SLEEP );
  1138.             }
  1139.             p_outpic->date = p_pic->date;
  1140.             vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1141.                               p_outpic );
  1142.             for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1143.             {
  1144.                 uint8_t *p_in, *p_in_end, *p_out;
  1145.                 int i_in_pitch = p_pic->p[i_plane].i_pitch;
  1146.                 int i_out_pitch = p_outpic->p[i_plane].i_pitch;
  1147.                 int i_copy_pitch = p_outpic->p[i_plane].i_visible_pitch;
  1148. #ifdef OVERLAP
  1149.                 if (i_col)
  1150.                     pi_left_skip[i_plane] -= (2 * p_vout->p_sys->i_halfLength) * p_pic->p->i_pixel_pitch;
  1151.                 if( p_vout->p_sys->i_row >= 2 )
  1152.                 {
  1153.                     if( (i_row) && (!i_col))
  1154.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch);
  1155.                     if( (p_vout->p_sys->i_row > 2) && (i_row == 1) && (!i_col) )
  1156.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch);
  1157.                     if( !p_vout->p_sys->pp_vout[p_vout->p_sys->i_col-1].b_active )
  1158.                         pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * i_row * p_pic->p[i_plane].i_pitch);
  1159.                 }
  1160. // i_n : previous inactive pp_vout
  1161.                 int i_n=0;
  1162.                 while ((!p_vout->p_sys->pp_vout[i_row * p_vout->p_sys->i_col + i_col - 1 - i_n].b_active) && (i_col - i_n > 1)) i_n++;
  1163.                 if ((i_col > 1) && i_n)
  1164.                     pi_left_skip[i_plane] -= i_n*(2 * p_vout->p_sys->i_halfLength ) * p_pic->p->i_pixel_pitch;
  1165.                 p_in = p_pic->p[i_plane].p_pixels
  1166.                 /* Wall proprities */
  1167.                 + pi_top_skip[i_plane] + pi_left_skip[i_plane];
  1168.                 int i_lines = p_outpic->p[i_plane].i_visible_lines;
  1169. // 1088 lines bug in a mpeg2 stream of 1080 lines
  1170.                 if ((p_vout->p_sys->i_row - 1 == i_row) &&
  1171.                     (p_pic->p[i_plane].i_lines == 1088))
  1172.                         i_lines -= 8;
  1173.                 p_in_end = p_in + i_lines * p_pic->p[i_plane].i_pitch;
  1174. #else
  1175.                 p_in = p_pic->p[i_plane].p_pixels
  1176.                         + pi_top_skip[i_plane] + pi_left_skip[i_plane];
  1177.                 p_in_end = p_in + p_outpic->p[i_plane].i_visible_lines
  1178.                                         * p_pic->p[i_plane].i_pitch;
  1179. #endif //OVERLAP
  1180.                 p_out = p_outpic->p[i_plane].p_pixels;
  1181. #ifdef OVERLAP
  1182.         if ((p_vout->p_sys->i_row > 2) && (!i_row))
  1183.             p_out += (p_outpic->p[i_plane].i_pitch * (2 * p_vout->p_sys->i_halfHeight) * p_pic->p->i_pixel_pitch);
  1184.         int length;
  1185.         length = 2 * p_vout->p_sys->i_halfLength * p_pic->p->i_pixel_pitch;
  1186.         if (p_vout->p_sys->b_has_changed)
  1187.         {
  1188.             int i_plane_;
  1189.             int i_col_mod;
  1190.             Denom = F2(length / p_pic->p->i_pixel_pitch);
  1191.             a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1192.             a_1 = p_vout->p_sys->a_1 * 2 * p_vout->p_sys->i_halfLength * (ACCURACY / 100);
  1193.             a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1194.             for(i_col_mod = 0; i_col_mod < 2; i_col_mod++)
  1195.                 for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index++)
  1196.                     for (i_plane_ =  0; i_plane_ < p_pic->p->i_pixel_pitch; i_plane_++)
  1197.                         p_vout->p_sys->lambda[i_col_mod][i_plane_][i_index] = CLIP_0A(!i_col_mod ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1198.         }
  1199. #endif
  1200.             while( p_in < p_in_end )
  1201.             {
  1202. #ifndef OVERLAP
  1203.                 vlc_memcpy( p_out, p_in, i_copy_pitch );
  1204. #else
  1205.                 if (p_vout->p_sys->i_col > 2)
  1206.                 {
  1207.                     // vertical blend
  1208.                     length /= 2;
  1209.                     if (i_col == 0)
  1210.                         vlc_memcpy( p_out + length, p_in, i_copy_pitch - length);
  1211.                     else if (i_col + 1 == p_vout->p_sys->i_col)
  1212.                         vlc_memcpy( p_out, p_in - length, i_copy_pitch - length);
  1213.                     else
  1214.                         vlc_memcpy( p_out, p_in - length, i_copy_pitch);
  1215.                     if ((i_col == 0))
  1216.                     // black bar
  1217.                     {
  1218.                         LeftOffset = 0;
  1219.                         p_out += LeftOffset;
  1220.                         p_in += LeftOffset;
  1221.                         for (i_index = 0; i_index < length; i_index++)
  1222.                                 *(p_out + i_index) = 0;
  1223.                         p_out -= LeftOffset;
  1224.                         p_in -= LeftOffset;
  1225.                     }
  1226.                     else if ((i_col + 1 == p_vout->p_sys->i_col ))
  1227.                     // black bar
  1228.                         {
  1229.                             LeftOffset = i_copy_pitch - length;
  1230.                             p_out += LeftOffset;
  1231.                             p_in += LeftOffset;
  1232.                             for (i_index = 0; i_index < length; i_index++)
  1233.                                     *(p_out + i_index) = 0;
  1234.                             p_out -= LeftOffset;
  1235.                             p_in -= LeftOffset;
  1236.                         }
  1237.                     length *= 2;
  1238.                 }
  1239.                 else
  1240.                     vlc_memcpy( p_out, p_in, i_copy_pitch);
  1241. // vertical blend
  1242. // first blended zone
  1243.             if (i_col)
  1244.             {
  1245.                 LeftOffset = 0;
  1246.                 p_out += LeftOffset;
  1247.                 for (i_index = 0; i_index < length; i_index++)
  1248. #ifndef GAMMA
  1249.                     *(p_out + i_index) = (p_vout->p_sys->lambda[1][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch] *
  1250.                                  (*(p_out + i_index))) / ACCURACY;
  1251. #else
  1252.                     *(p_out + i_index) = p_vout->p_sys->LUT[i_index % p_pic->p->i_pixel_pitch][p_vout->p_sys->lambda[1][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch]][*(p_out + i_index)];
  1253. #endif
  1254.                 p_out -= LeftOffset;
  1255.             }
  1256. // second blended zone
  1257.             if (i_col + 1 < p_vout->p_sys->i_col)
  1258.             {
  1259.                 LeftOffset = i_copy_pitch - length;
  1260.                 p_out +=  LeftOffset;
  1261.                 for (i_index = 0; i_index < length; i_index++)
  1262. #ifndef GAMMA
  1263.                     *(p_out + i_index) = (p_vout->p_sys->lambda[0][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch] *
  1264.                                  (*(p_out + i_index))) / ACCURACY;
  1265. #else
  1266.                     *(p_out + i_index) = p_vout->p_sys->LUT[i_index % p_pic->p->i_pixel_pitch][p_vout->p_sys->lambda[0][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch]][*(p_out + i_index)];
  1267. #endif
  1268.                 p_out -= LeftOffset;
  1269.             }
  1270. // end blended zone
  1271. #endif //OVERLAP
  1272.                 p_in += i_in_pitch;
  1273.                 p_out += i_out_pitch;
  1274.             }
  1275. #ifdef OVERLAP
  1276. // horizontal blend
  1277.         if (!p_vout->p_sys->b_attenuate)
  1278.         {
  1279.             if ((i_row == 0) && (p_vout->p_sys->i_row > 2))
  1280.             // black bar
  1281.             {
  1282.                     TopOffset = i_lines + (2 * p_vout->p_sys->i_halfHeight);
  1283.                     p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1284.                     for (i_index = 0; i_index < length; i_index++)
  1285.                         for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1286.                             *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = 0;
  1287.                     p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1288.             }
  1289.             else if ((i_row + 1 == p_vout->p_sys->i_row) && (p_vout->p_sys->i_row > 2))
  1290.             // black bar
  1291.                 {
  1292.                     TopOffset = length - (2 * p_vout->p_sys->i_halfHeight);
  1293.                     p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1294.                     for (i_index = 0; i_index < length; i_index++)
  1295.                         for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1296.                             *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = 0;
  1297.                     p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1298.                 }
  1299.         }
  1300.         else
  1301.         {
  1302.             if (p_vout->p_sys->i_row >= 2)
  1303.             {
  1304.                 length = 2 * p_vout->p_sys->i_halfHeight;
  1305.                 if (p_vout->p_sys->b_has_changed)
  1306.                 {
  1307.                     int i_plane_;
  1308.                     int i_row_mod;
  1309.                     Denom = F2(length);
  1310.                     a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1311.                     a_1 = p_vout->p_sys->a_1 * length * (ACCURACY / 100);
  1312.                     a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1313.                     for(i_row_mod = 0; i_row_mod < 2; i_row_mod++)
  1314.                       for (i_index = 0; i_index < length; i_index++)
  1315.                         for (i_plane_ =  0; i_plane_ < p_pic->p->i_pixel_pitch; i_plane_++)
  1316.                             p_vout->p_sys->lambda2[i_row_mod][i_plane_][i_index] = CLIP_0A(!i_row_mod ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length) - i_index) + a_0) / Denom);
  1317.                 }
  1318. // first blended zone
  1319.             if (i_row)
  1320.             {
  1321.                 TopOffset = i_lines;
  1322.                 p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1323.                 for (i_index = 0; i_index < length; i_index++)
  1324.                     for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1325. #ifndef GAMMA
  1326.                     *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = (p_vout->p_sys->lambda2[1][i_index2 % p_pic->p->i_pixel_pitch][i_index] *
  1327.                                  (*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2))) / ACCURACY;
  1328. #else
  1329.                     *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = p_vout->p_sys->LUT[i_index2 % p_pic->p->i_pixel_pitch][p_vout->p_sys->lambda2[1][i_index2 % p_pic->p->i_pixel_pitch][i_index]][*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2)];
  1330. #endif
  1331.                 p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1332.             }
  1333.             else if (p_vout->p_sys->i_row > 2)
  1334.             // black bar
  1335.             {
  1336.                 TopOffset = i_lines + (2 * p_vout->p_sys->i_halfHeight);
  1337.                 p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1338.                 for (i_index = 0; i_index < length; i_index++)
  1339.                     for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1340.                         *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = 0;
  1341.                 p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1342.             }
  1343. // second blended zone
  1344.             if (i_row + 1 < p_vout->p_sys->i_row)
  1345.             {
  1346.                 TopOffset = length;
  1347.                 p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1348.                 for (i_index = 0; i_index < length; i_index++)
  1349.                     for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1350. #ifndef GAMMA
  1351.                     *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = (p_vout->p_sys->lambda2[0][i_index2 % p_pic->p->i_pixel_pitch][i_index] *
  1352.                                  (*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2))) / ACCURACY;
  1353. #else
  1354.                     *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = p_vout->p_sys->LUT[i_index2 % p_pic->p->i_pixel_pitch][p_vout->p_sys->lambda2[0][i_index2 % p_pic->p->i_pixel_pitch][i_index]][*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2)];
  1355. #endif
  1356.                 p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1357.             }
  1358.             else if (p_vout->p_sys->i_row > 2)
  1359.             // black bar
  1360.             {
  1361.                 TopOffset = length - (2 * p_vout->p_sys->i_halfHeight);
  1362.                 p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1363.                 for (i_index = 0; i_index < length; i_index++)
  1364.                     for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1365.                         *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = 0;
  1366.                 p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1367.             }
  1368. // end blended zone
  1369.             }
  1370.         }
  1371. #endif
  1372. // bug for wall filter : fix by CC
  1373. //            pi_left_skip[i_plane] += i_out_pitch;
  1374.             pi_left_skip[i_plane] += i_copy_pitch;
  1375.             }
  1376.             vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1377.                                 p_outpic );
  1378.             vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1379.                                  p_outpic );
  1380.         }
  1381.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1382.         {
  1383.             pi_top_skip[i_plane] += p_vout->p_sys->pp_vout[ i_vout-1 ].i_height
  1384.                                      * p_pic->p[i_plane].i_lines
  1385.                                      / p_vout->output.i_height
  1386.                                      * p_pic->p[i_plane].i_pitch;
  1387.         }
  1388.     }
  1389. #ifdef OVERLAP
  1390.     if (p_vout->p_sys->b_has_changed) p_vout->p_sys->b_has_changed = false;
  1391. #endif
  1392. }
  1393. #ifdef PACKED_YUV
  1394. // WARNING : NO DEBUGGED
  1395. /*****************************************************************************
  1396.  * RenderPackedYUV: displays previously rendered output
  1397.  *****************************************************************************
  1398.  * This function send the currently rendered image to Wall image, waits
  1399.  * until it is displayed and switch the two rendering buffers, preparing next
  1400.  * frame.
  1401.  *****************************************************************************/
  1402. static void RenderPackedYUV( vout_thread_t *p_vout, picture_t *p_pic )
  1403. {
  1404.     picture_t *p_outpic = NULL;
  1405.     int i_col, i_row, i_vout, i_plane;
  1406.     int pi_left_skip[VOUT_MAX_PLANES], pi_top_skip[VOUT_MAX_PLANES];
  1407. #ifdef OVERLAP
  1408.     int LeftOffset, TopOffset;
  1409.     int constantYUV[3] = {0,128,128};
  1410.     int Denom;
  1411.     int a_2;
  1412.     int a_1;
  1413.     int a_0;
  1414.     int i_index, i_index2;
  1415. #endif
  1416.     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1417.         pi_top_skip[i_plane] = 0;
  1418.     for( i_vout = 0;, i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
  1419.     {
  1420.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1421.             pi_left_skip[i_plane] = 0;
  1422.         for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++, i_vout++ )
  1423.         {
  1424.             if( !p_vout->p_sys->pp_vout[ i_vout ].b_active )
  1425.             {
  1426.                 for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1427.                 {
  1428.                     pi_left_skip[i_plane] +=
  1429.                         p_vout->p_sys->pp_vout[ i_vout ].i_width
  1430.                          * p_pic->p[i_plane].i_pitch / p_vout->output.i_width;
  1431.                 }
  1432.                 continue;
  1433.             }
  1434.             while( ( p_outpic =
  1435.                 vout_CreatePicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1436.                                     0, 0, 0 )
  1437.                    ) == NULL )
  1438.             {
  1439.                 if( !vlc_object_alive (p_vout) || p_vout->b_error )
  1440.                 {
  1441.                     vout_DestroyPicture(
  1442.                         p_vout->p_sys->pp_vout[ i_vout ].p_vout, p_outpic );
  1443.                     return;
  1444.                 }
  1445.                 msleep( VOUT_OUTMEM_SLEEP );
  1446.             }
  1447.             p_outpic->date = p_pic->date;
  1448.             vout_LinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1449.                               p_outpic );
  1450.             for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1451.             {
  1452.                 uint8_t *p_in, *p_in_end, *p_out;
  1453.                 int i_in_pitch = p_pic->p[i_plane].i_pitch;
  1454.                 int i_out_pitch = p_outpic->p[i_plane].i_pitch;
  1455.                 int i_copy_pitch = p_outpic->p[i_plane].i_visible_pitch;
  1456.                 const int i_div = p_vout->p_sys->pp_vout[i_vout].i_width / i_copy_pitch;
  1457. #ifdef OVERLAP
  1458.                 if (i_col) pi_left_skip[i_plane] -= (2 * p_vout->p_sys->i_halfLength ) / i_div;
  1459.                 if ((p_vout->p_sys->i_row >= 2) && (i_row) && (!i_col)) pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch) / i_div;
  1460.                 if ((p_vout->p_sys->i_row > 2) && (i_row == 1) && (!i_col)) pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * p_pic->p[i_plane].i_pitch) / i_div;
  1461.                 if( !p_vout->p_sys->pp_vout[p_vout->p_sys->i_col-1].b_active )
  1462.                     pi_top_skip[i_plane] -= (2 * p_vout->p_sys->i_halfHeight * i_row * p_pic->p[i_plane].i_pitch) / i_div;
  1463. // i_n : previous inactive pp_vout
  1464.                 int i_n=0;
  1465.                 while ((!p_vout->p_sys->pp_vout[i_row * p_vout->p_sys->i_col + i_col - 1 - i_n].b_active) && (i_col - i_n > 1)) i_n++;
  1466.                 if ((i_col > 1) && i_n)
  1467.                     pi_left_skip[i_plane] -= i_n*(2 * p_vout->p_sys->i_halfLength ) / i_div;
  1468.                 p_in = p_pic->p[i_plane].p_pixels
  1469.                 /* Wall proprities */
  1470.                 + pi_top_skip[i_plane] + pi_left_skip[i_plane];
  1471.                 int i_lines = p_outpic->p[i_plane].i_visible_lines;
  1472. // 1088 lines bug in a mpeg2 stream of 1080 lines
  1473.                 if ((p_vout->p_sys->i_row - 1 == i_row) &&
  1474.                     (p_pic->p[i_plane].i_lines == 1088))
  1475.                         i_lines -= 8;
  1476.                 p_in_end = p_in + i_lines * p_pic->p[i_plane].i_pitch;
  1477. #else
  1478.                 p_in = p_pic->p[i_plane].p_pixels
  1479.                         + pi_top_skip[i_plane] + pi_left_skip[i_plane];
  1480.                 p_in_end = p_in + p_outpic->p[i_plane].i_visible_lines
  1481.                                         * p_pic->p[i_plane].i_pitch;
  1482. #endif
  1483.                 p_out = p_outpic->p[i_plane].p_pixels;
  1484. #ifdef OVERLAP
  1485.         int length;
  1486.         length = 2 * p_vout->p_sys->i_halfLength * p_pic->p->i_pixel_pitch;
  1487.         LeftOffset = (i_col ? 0 : i_copy_pitch - length);
  1488.         if (p_vout->p_sys->b_has_changed)
  1489.         {
  1490. #ifdef GAMMA
  1491.             int i_plane_;
  1492.             for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index++)
  1493.                 for (i_plane_ =  0; i_plane_ < p_pic->p->i_pixel_pitch; i_plane_++)
  1494.                     for (i_index2 = 0; i_index2 < 256; i_index2++)
  1495.                             p_vout->p_sys->LUT[i_plane_][i_index2][i_index] = F(i_index2, (length / p_pic->p->i_pixel_pitch, i_index, p_vout->p_sys->f_gamma[i_plane_]));
  1496. #endif
  1497.             switch (p_vout->output.i_chroma)
  1498.                 {
  1499.                     case VLC_FOURCC('Y','U','Y','2'):    // packed by 2
  1500.                     case VLC_FOURCC('Y','U','N','V'):    // packed by 2
  1501.                         Denom = F2(length / p_pic->p->i_pixel_pitch);
  1502.                         a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1503.                         a_1 = p_vout->p_sys->a_1 * 2 * p_vout->p_sys->i_halfLength * (ACCURACY / 100);
  1504.                         a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1505.                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index+=p_pic->p->i_pixel_pitch)
  1506.                         // for each macropixel
  1507.                         {
  1508.                                 // first image pixel
  1509.                                 p_vout->p_sys->lambda[i_col][0][i_index] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1510.                                 p_vout->p_sys->cstYUV[i_col][0][i_index] = ((ACCURACY - p_vout->p_sys->lambda[i_col][0][i_index]) * constantYUV[0]) / ACCURACY;
  1511.                                 p_vout->p_sys->lambda[i_col][1][i_index] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1512.                                 p_vout->p_sys->cstYUV[i_col][1][i_index] = ((ACCURACY - p_vout->p_sys->lambda[i_col][1][i_index]) * constantYUV[1]) / ACCURACY;
  1513.                                 // second image pixel
  1514.                                 p_vout->p_sys->lambda[i_col][0][i_index + 1] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index + 1) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - (i_index + 1)) + a_0) / Denom);
  1515.                                 p_vout->p_sys->cstYUV[i_col][0][i_index + 1] = ((ACCURACY - p_vout->p_sys->lambda[i_col][0][i_index]) * constantYUV[0]) / ACCURACY;
  1516.                                 p_vout->p_sys->lambda[i_col][1][i_index + 1] = p_vout->p_sys->lambda[i_col][1][i_index];
  1517.                                 p_vout->p_sys->cstYUV[i_col][1][i_index + 1] = p_vout->p_sys->cstYUV[i_col][1][i_index];
  1518.                         }
  1519.                         break;
  1520.                     case VLC_FOURCC('U','Y','V','Y'):    // packed by 2
  1521.                     case VLC_FOURCC('U','Y','N','V'):    // packed by 2
  1522.                     case VLC_FOURCC('Y','4','2','2'):    // packed by 2
  1523.                         Denom = F2(length / p_pic->p->i_pixel_pitch);
  1524.                         a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1525.                         a_1 = p_vout->p_sys->a_1 * 2 * p_vout->p_sys->i_halfLength * (ACCURACY / 100);
  1526.                         a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1527.                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index+=p_pic->p->i_pixel_pitch)
  1528.                         // for each macropixel
  1529.                         {
  1530.                                 // first image pixel
  1531.                                 p_vout->p_sys->lambda[i_col][0][i_index] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1532.                                 p_vout->p_sys->cstYUV[i_col][0][i_index] = ((ACCURACY - p_vout->p_sys->lambda[i_col][0][i_index]) * constantYUV[1]) / ACCURACY;
  1533.                                 p_vout->p_sys->lambda[i_col][1][i_index] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1534.                                 p_vout->p_sys->cstYUV[i_col][1][i_index] = ((ACCURACY - p_vout->p_sys->lambda[i_col][1][i_index]) * constantYUV[0]) / ACCURACY;
  1535.                                 // second image pixel
  1536.                                 p_vout->p_sys->lambda[i_col][0][i_index + 1] = CLIP_0A(!i_col ? ACCURACY - (F4(a_2, a_1, i_index + 1) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - (i_index + 1)) + a_0) / Denom);
  1537.                                 p_vout->p_sys->cstYUV[i_col][0][i_index + 1] = ((ACCURACY - p_vout->p_sys->lambda[i_col][0][i_index]) * constantYUV[1]) / ACCURACY;
  1538.                                 p_vout->p_sys->lambda[i_col][1][i_index + 1] = p_vout->p_sys->lambda[i_col][1][i_index];
  1539.                                 p_vout->p_sys->cstYUV[i_col][1][i_index + 1] = p_vout->p_sys->cstYUV[i_col][1][i_index];
  1540.                         }
  1541.                         break;
  1542.                     default :
  1543.                         break;
  1544.                 }
  1545.         }
  1546. #endif
  1547.             while( p_in < p_in_end )
  1548.             {
  1549. #ifndef OVERLAP
  1550.                 vlc_memcpy( p_out, p_in, i_copy_pitch);
  1551. #else
  1552.                 vlc_memcpy( p_out + i_col * length, p_in + i_col * length, i_copy_pitch - length);
  1553.                 p_out += LeftOffset;
  1554.                 p_in += LeftOffset;
  1555. #ifndef GAMMA
  1556.                 for (i_index = 0; i_index < length; i_index++)
  1557.                     *(p_out + i_index) = (p_vout->p_sys->lambda[i_col][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch] *
  1558.                              (*(p_in + i_index))) / ACCURACY +
  1559.                              p_vout->p_sys->cstYUV[i_col][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch];
  1560. #else
  1561.                 for (i_index = 0; i_index < length; i_index++)
  1562.                     *(p_out + i_index) = p_vout->p_sys->LUT[i_index % p_pic->p->i_pixel_pitch][(p_vout->p_sys->lambda[i_col][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch] *
  1563.                              (*(p_in + i_index))) / ACCURACY +
  1564.                              p_vout->p_sys->cstYUV[i_col][i_index % p_pic->p->i_pixel_pitch][i_index / p_pic->p->i_pixel_pitch]][i_index / p_pic->p->i_pixel_pitch];
  1565. #endif
  1566.                 p_out -= LeftOffset;
  1567.                 p_in -= LeftOffset;
  1568. #endif
  1569.                 p_in += i_in_pitch;
  1570.                 p_out += i_out_pitch;
  1571.             }
  1572. #ifdef OVERLAP
  1573.             if (p_vout->p_sys->i_row == 2)
  1574.             {
  1575.                         length = 2 * p_vout->p_sys->i_halfHeight * p_pic->p->i_pixel_pitch;
  1576.                         TopOffset = (i_row ? i_lines : length / p_pic->p->i_pixel_pitch);
  1577.                         if (p_vout->p_sys->b_has_changed)
  1578.                         {
  1579. #ifdef GAMMA
  1580.                                 int i_plane_;
  1581.                                 for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index++)
  1582.                                     for (i_plane_ =  0; i_plane_ < p_pic->p->i_pixel_pitch; i_plane_++)
  1583.                                         for (i_index2 = 0; i_index2 < 256; i_index2++)
  1584.                                                 p_vout->p_sys->LUT2[i_plane_][i_index2][i_index] = F(i_index2, (length / p_pic->p->i_pixel_pitch, i_index, p_vout->p_sys->f_gamma[i_plane_]));
  1585. #endif
  1586.                                 switch (p_vout->output.i_chroma)
  1587.                                 {
  1588.                                     case VLC_FOURCC('Y','U','Y','2'):    // packed by 2
  1589.                                     case VLC_FOURCC('Y','U','N','V'):    // packed by 2
  1590.                                         Denom = F2(length / p_pic->p->i_pixel_pitch);
  1591.                                         a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1592.                                         a_1 = p_vout->p_sys->a_1 * 2 * p_vout->p_sys->i_halfHeight * (ACCURACY / 100);
  1593.                                         a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1594.                                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index+=p_pic->p->i_pixel_pitch)
  1595.                                         // for each macropixel
  1596.                                         {
  1597.                                                 // first image pixel
  1598.                                                 p_vout->p_sys->lambda2[i_row][0][i_index] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1599.                                                 p_vout->p_sys->cstYUV2[i_row][0][i_index] = ((ACCURACY - p_vout->p_sys->lambda2[i_row][0][i_index]) * constantYUV[0]) / ACCURACY;
  1600.                                                 p_vout->p_sys->lambda2[i_row][1][i_index] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1601.                                                 p_vout->p_sys->cstYUV2[i_row][1][i_index] = ((ACCURACY - p_vout->p_sys->lambda2[i_row][1][i_index]) * constantYUV[1]) / ACCURACY;
  1602.                                                 // second image pixel
  1603.                                                 p_vout->p_sys->lambda2[i_row][0][i_index + 1] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index + 1) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - (i_index + 1)) + a_0) / Denom);
  1604.                                                 p_vout->p_sys->cstYUV2[i_row][0][i_index + 1] = ((ACCURACY - p_vout->p_sys->lambda2[i_row][0][i_index]) * constantYUV[0]) / ACCURACY;
  1605.                                                 p_vout->p_sys->lambda2[i_row][1][i_index + 1] = p_vout->p_sys->lambda2[i_row][1][i_index];
  1606.                                                 p_vout->p_sys->cstYUV2[i_row][1][i_index + 1] = p_vout->p_sys->cstYUV2[i_row][1][i_index];
  1607.                                         }
  1608.                                         break;
  1609.                                     case VLC_FOURCC('U','Y','V','Y'):    // packed by 2
  1610.                                     case VLC_FOURCC('U','Y','N','V'):    // packed by 2
  1611.                                     case VLC_FOURCC('Y','4','2','2'):    // packed by 2
  1612.                                         Denom = F2(length / p_pic->p->i_pixel_pitch);
  1613.                                         a_2 = p_vout->p_sys->a_2 * (ACCURACY / 100);
  1614.                                         a_1 = p_vout->p_sys->a_1 * 2 * p_vout->p_sys->i_halfHeight * (ACCURACY / 100);
  1615.                                         a_0 = p_vout->p_sys->a_0 * Denom * (ACCURACY / 100);
  1616.                                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index+=p_pic->p->i_pixel_pitch)
  1617.                                         // for each macropixel
  1618.                                         {
  1619.                                                 // first image pixel
  1620.                                                 p_vout->p_sys->lambda2[i_row][0][i_index] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1621.                                                 p_vout->p_sys->cstYUV2[i_row][0][i_index] = ((ACCURACY - p_vout->p_sys->lambda2[i_col][0][i_index]) * constantYUV[1]) / ACCURACY;
  1622.                                                 p_vout->p_sys->lambda2[i_row][1][i_index] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - i_index) + a_0) / Denom);
  1623.                                                 p_vout->p_sys->cstYUV2[i_row][1][i_index] = ((ACCURACY - p_vout->p_sys->lambda2[i_row][1][i_index]) * constantYUV[0]) / ACCURACY;
  1624.                                                 // second image pixel
  1625.                                                 p_vout->p_sys->lambda2[i_row][0][i_index + 1] = CLIP_0A(!i_row ? ACCURACY - (F4(a_2, a_1, i_index + 1) + a_0) / Denom : ACCURACY - (F4(a_2, a_1,(length / p_pic->p->i_pixel_pitch) - (i_index + 1)) + a_0) / Denom);
  1626.                                                 p_vout->p_sys->cstYUV2[i_row][0][i_index + 1] = ((ACCURACY - p_vout->p_sys->lambda2[i_row][0][i_index]) * constantYUV[1]) / ACCURACY;
  1627.                                                 p_vout->p_sys->lambda2[i_row][1][i_index + 1] = p_vout->p_sys->lambda2[i_row][1][i_index];
  1628.                                                 p_vout->p_sys->cstYUV2[i_row][1][i_index + 1] = p_vout->p_sys->cstYUV2[i_row][1][i_index];
  1629.                                         }
  1630.                                         break;
  1631.                                     default :
  1632.                                         break;
  1633.                                 }
  1634.                         }
  1635.                         p_out -= TopOffset * p_outpic->p[i_plane].i_pitch;
  1636. #ifndef GAMMA
  1637.                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index++)
  1638.                             for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1639.                                 *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = (p_vout->p_sys->lambda2[i_row][i_index2 % p_pic->p->i_pixel_pitch][i_index] *
  1640.                                      (*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2))) / ACCURACY +
  1641.                                      p_vout->p_sys->cstYUV2[i_row][i_index2 % p_pic->p->i_pixel_pitch][i_index];
  1642. #else
  1643.                         for (i_index = 0; i_index < length / p_pic->p->i_pixel_pitch; i_index++)
  1644.                             for (i_index2 = 0; i_index2 < i_copy_pitch; i_index2++)
  1645.                                 *(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2) = p_vout->p_sys->LUT[i_index % p_pic->p->i_pixel_pitch][(p_vout->p_sys->lambda2[i_row][i_index2 % p_pic->p->i_pixel_pitch][i_index] *
  1646.                                      (*(p_out + (i_index * p_outpic->p[i_plane].i_pitch) + i_index2))) / ACCURACY +
  1647.                                      p_vout->p_sys->cstYUV2[i_row][i_index2 % p_pic->p->i_pixel_pitch][i_index]][i_index / p_pic->p->i_pixel_pitch];
  1648. #endif
  1649.                         p_out += TopOffset * p_outpic->p[i_plane].i_pitch;
  1650.             }
  1651. #endif
  1652. // bug for wall filter : fix by CC
  1653. //            pi_left_skip[i_plane] += i_out_pitch;
  1654.             pi_left_skip[i_plane] += i_copy_pitch;
  1655.             }
  1656.             vout_UnlinkPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1657.                                 p_outpic );
  1658.             vout_DisplayPicture( p_vout->p_sys->pp_vout[ i_vout ].p_vout,
  1659.                                  p_outpic );
  1660.         }
  1661.         for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  1662.         {
  1663.             pi_top_skip[i_plane] += p_vout->p_sys->pp_vout[ i_vout-1 ].i_height
  1664.                                      * p_pic->p[i_plane].i_lines
  1665.                                      / p_vout->output.i_height
  1666.                                      * p_pic->p[i_plane].i_pitch;
  1667.         }
  1668.     }
  1669. #ifdef OVERLAP
  1670.     if (p_vout->p_sys->b_has_changed) p_vout->p_sys->b_has_changed = false;
  1671. #endif
  1672. }
  1673. #endif
  1674. /*****************************************************************************
  1675.  * RemoveAllVout: destroy all the child video output threads
  1676.  *****************************************************************************/
  1677. static void RemoveAllVout( vout_thread_t *p_vout )
  1678. {
  1679.     vout_sys_t *p_sys = p_vout->p_sys;
  1680.     for( int i = 0; i < p_vout->p_sys->i_vout; i++ )
  1681.     {
  1682.         if( p_sys->pp_vout[i].b_active )
  1683.         {
  1684.             vout_filter_SetupChild( p_vout, p_sys->pp_vout[i].p_vout,
  1685.                                     MouseEvent, FullscreenEventUp, FullscreenEventDown, true );
  1686.             vout_CloseAndRelease( p_sys->pp_vout[i].p_vout );
  1687.             p_sys->pp_vout[i].p_vout = NULL;
  1688.         }
  1689.     }
  1690. }
  1691. /*****************************************************************************
  1692.  * SendEvents: forward mouse and keyboard events to the parent p_vout
  1693.  *****************************************************************************/
  1694. static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
  1695.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  1696. {
  1697.     vout_thread_t *p_vout = p_data;
  1698.     vout_sys_t *p_sys = p_vout->p_sys;
  1699.     VLC_UNUSED(oldval);
  1700.     int i_vout;
  1701.     /* Find the video output index */
  1702.     for( i_vout = 0; i_vout < p_sys->i_vout; i_vout++ )
  1703.     {
  1704.         if( p_sys->pp_vout[i_vout].b_active &&
  1705.             p_this == VLC_OBJECT(p_sys->pp_vout[i_vout].p_vout) )
  1706.             break;
  1707.     }
  1708.     assert( i_vout < p_vout->p_sys->i_vout );
  1709.     /* Translate the mouse coordinates */
  1710.     if( !strcmp( psz_var, "mouse-x" ) )
  1711.     {
  1712. #ifdef OVERLAP
  1713.         int i_overlap = ((p_sys->i_col > 2) ? 0 : 2 * p_sys->i_halfLength);
  1714.            newval.i_int += (p_vout->output.i_width - i_overlap)
  1715. #else
  1716.            newval.i_int += p_vout->output.i_width
  1717. #endif
  1718.                          * (i_vout % p_sys->i_col)
  1719.                           / p_sys->i_col;
  1720.     }
  1721.     else if( !strcmp( psz_var, "mouse-y" ) )
  1722.     {
  1723. #ifdef OVERLAP
  1724.         int i_overlap = ((p_sys->i_row > 2) ? 0 : 2 * p_sys->i_halfHeight);
  1725.            newval.i_int += (p_vout->output.i_height - i_overlap)
  1726. #else
  1727.            newval.i_int += p_vout->output.i_height
  1728. #endif
  1729. //bug fix in Wall plug-in
  1730. //                         * (i_vout / p_vout->p_sys->i_row)
  1731.                          * (i_vout / p_sys->i_col)
  1732.                           / p_sys->i_row;
  1733.     }
  1734.     return var_Set( p_vout, psz_var, newval );
  1735. }
  1736. /**
  1737.  * Forward fullscreen event to/from the childrens.
  1738.  * FIXME pretty much duplicated from wall.c
  1739.  */
  1740. static bool IsFullscreenActive( vout_thread_t *p_vout )
  1741. {
  1742.     vout_sys_t *p_sys = p_vout->p_sys;
  1743.     for( int i = 0; i < p_sys->i_vout; i++ )
  1744.     {
  1745.         if( p_sys->pp_vout[i].b_active &&
  1746.             var_GetBool( p_sys->pp_vout[i].p_vout, "fullscreen" ) )
  1747.             return true;
  1748.     }
  1749.     return false;
  1750. }
  1751. static int FullscreenEventUp( vlc_object_t *p_this, char const *psz_var,
  1752.                               vlc_value_t oldval, vlc_value_t newval, void *p_data )
  1753. {
  1754.     vout_thread_t *p_vout = p_data;
  1755.     VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(newval);
  1756.     const bool b_fullscreen = IsFullscreenActive( p_vout );
  1757.     if( !var_GetBool( p_vout, "fullscreen" ) != !b_fullscreen )
  1758.         return var_SetBool( p_vout, "fullscreen", b_fullscreen );
  1759.     return VLC_SUCCESS;
  1760. }
  1761. static int FullscreenEventDown( vlc_object_t *p_this, char const *psz_var,
  1762.                                 vlc_value_t oldval, vlc_value_t newval, void *p_data )
  1763. {
  1764.     vout_thread_t *p_vout = (vout_thread_t*)p_this;
  1765.     vout_sys_t *p_sys = p_vout->p_sys;
  1766.     VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_var);
  1767.     const bool b_fullscreen = IsFullscreenActive( p_vout );
  1768.     if( !b_fullscreen != !newval.b_bool )
  1769.     {
  1770.         for( int i = 0; i < p_sys->i_vout; i++ )
  1771.         {
  1772.             if( !p_sys->pp_vout[i].b_active )
  1773.                 continue;
  1774.             vout_thread_t *p_child = p_sys->pp_vout[i].p_vout;
  1775.             if( !var_GetBool( p_child, "fullscreen" ) != !newval.b_bool )
  1776.             {
  1777.                 var_SetBool( p_child, "fullscreen", newval.b_bool );
  1778.                 if( newval.b_bool )
  1779.                     return VLC_SUCCESS;
  1780.             }
  1781.         }
  1782.     }
  1783.     return VLC_SUCCESS;
  1784. }