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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * bluescreen.c : Bluescreen (weather channel like) video filter for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2005-2007 the VideoLAN team
  5.  * $Id: 90396c81cc447b473d6fddf74300c1a4acc1aa35 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea at videolan tod org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_vout.h>
  32. #include "vlc_filter.h"
  33. #define BLUESCREEN_HELP N_( 
  34.     "This effect, also known as "greenscreen" or "chroma key" blends " 
  35.     "the "blue parts" of the foreground image of the mosaic on the " 
  36.     "background (like weather forecasts). You can choose the "key" " 
  37.     "color for blending (blue by default)." )
  38. #define BLUESCREENU_TEXT N_("Bluescreen U value")
  39. #define BLUESCREENU_LONGTEXT N_( 
  40.         ""U" value for the bluescreen key color " 
  41.         "(in YUV values). From 0 to 255. Defaults to 120 for blue." )
  42. #define BLUESCREENV_TEXT N_("Bluescreen V value")
  43. #define BLUESCREENV_LONGTEXT N_( 
  44.         ""V" value for the bluescreen key color " 
  45.         "(in YUV values). From 0 to 255. Defaults to 90 for blue." )
  46. #define BLUESCREENUTOL_TEXT N_("Bluescreen U tolerance")
  47. #define BLUESCREENUTOL_LONGTEXT N_( 
  48.         "Tolerance of the bluescreen blender " 
  49.         "on color variations for the U plane. A value between 10 and 20 " 
  50.         "seems sensible." )
  51. #define BLUESCREENVTOL_TEXT N_("Bluescreen V tolerance")
  52. #define BLUESCREENVTOL_LONGTEXT N_( 
  53.         "Tolerance of the bluescreen blender " 
  54.         "on color variations for the V plane. A value between 10 and 20 " 
  55.         "seems sensible." )
  56. #define CFG_PREFIX "bluescreen-"
  57. /*****************************************************************************
  58.  * Local prototypes
  59.  *****************************************************************************/
  60. static int  Create      ( vlc_object_t * );
  61. static void Destroy     ( vlc_object_t * );
  62. static picture_t *Filter( filter_t *, picture_t * );
  63. static int BluescreenCallback( vlc_object_t *, char const *,
  64.                                vlc_value_t, vlc_value_t, void * );
  65. /*****************************************************************************
  66.  * Module descriptor
  67.  *****************************************************************************/
  68. vlc_module_begin ()
  69.     set_description( N_("Bluescreen video filter") )
  70.     set_shortname( N_("Bluescreen" ))
  71.     set_help( BLUESCREEN_HELP )
  72.     set_category( CAT_VIDEO )
  73.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  74.     set_capability( "video filter2", 0 )
  75.     add_shortcut( "bluescreen" )
  76.     set_callbacks( Create, Destroy )
  77.     add_integer_with_range( CFG_PREFIX "u", 120, 0, 255, NULL,
  78.                             BLUESCREENU_TEXT, BLUESCREENU_LONGTEXT, false )
  79.     add_integer_with_range( CFG_PREFIX "v", 90, 0, 255, NULL,
  80.                             BLUESCREENV_TEXT, BLUESCREENV_LONGTEXT, false )
  81.     add_integer_with_range( CFG_PREFIX "ut", 17, 0, 255, NULL,
  82.                             BLUESCREENUTOL_TEXT, BLUESCREENUTOL_LONGTEXT,
  83.                             false )
  84.     add_integer_with_range( CFG_PREFIX "vt", 17, 0, 255, NULL,
  85.                             BLUESCREENVTOL_TEXT, BLUESCREENVTOL_LONGTEXT,
  86.                             false )
  87. vlc_module_end ()
  88. static const char *const ppsz_filter_options[] = {
  89.     "u", "v", "ut", "vt", NULL
  90. };
  91. struct filter_sys_t
  92. {
  93.     vlc_mutex_t lock;
  94.     int i_u, i_v, i_ut, i_vt;
  95.     uint8_t *p_at;
  96. };
  97. static int Create( vlc_object_t *p_this )
  98. {
  99.     filter_t *p_filter = (filter_t *)p_this;
  100.     filter_sys_t *p_sys;
  101.     if( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','A') )
  102.     {
  103.         msg_Err( p_filter,
  104.                  "Unsupported input chroma "%4s". "
  105.                  "Bluescreen can only use "YUVA".",
  106.                  (char*)&p_filter->fmt_in.video.i_chroma );
  107.         return VLC_EGENERIC;
  108.     }
  109.     /* Allocate structure */
  110.     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
  111.     if( p_filter->p_sys == NULL )
  112.         return VLC_ENOMEM;
  113.     p_sys = p_filter->p_sys;
  114.     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
  115.                        p_filter->p_cfg );
  116.     int val;
  117.     vlc_mutex_init( &p_sys->lock );
  118. #define GET_VAR( name, min, max )                                           
  119.     val = var_CreateGetIntegerCommand( p_filter, CFG_PREFIX #name );        
  120.     p_sys->i_##name = __MIN( max, __MAX( min, val ) );                      
  121.     var_AddCallback( p_filter, CFG_PREFIX #name, BluescreenCallback, p_sys );
  122.     GET_VAR( u, 0x00, 0xff );
  123.     GET_VAR( v, 0x00, 0xff );
  124.     GET_VAR( ut, 0x00, 0xff );
  125.     GET_VAR( vt, 0x00, 0xff );
  126.     p_sys->p_at = NULL;
  127. #undef GET_VAR
  128.     p_filter->pf_video_filter = Filter;
  129.     return VLC_SUCCESS;
  130. }
  131. static void Destroy( vlc_object_t *p_this )
  132. {
  133.     filter_t *p_filter = (filter_t *)p_this;
  134.     filter_sys_t *p_sys = p_filter->p_sys;
  135.     var_DelCallback( p_filter, CFG_PREFIX "u", BluescreenCallback, p_sys );
  136.     var_DelCallback( p_filter, CFG_PREFIX "v", BluescreenCallback, p_sys );
  137.     var_DelCallback( p_filter, CFG_PREFIX "ut", BluescreenCallback, p_sys );
  138.     var_DelCallback( p_filter, CFG_PREFIX "vt", BluescreenCallback, p_sys );
  139.     free( p_sys->p_at );
  140.     vlc_mutex_destroy( &p_sys->lock );
  141.     free( p_sys );
  142. }
  143. static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
  144. {
  145.     filter_sys_t *p_sys = p_filter->p_sys;
  146.     int i,j;
  147.     int i_lines = p_pic->p[ A_PLANE ].i_lines;
  148.     int i_pitch = p_pic->p[ A_PLANE ].i_pitch;
  149.     uint8_t *p_a = p_pic->p[ A_PLANE ].p_pixels;
  150.     uint8_t *p_at;
  151.     uint8_t *p_u = p_pic->p[ U_PLANE ].p_pixels;
  152.     uint8_t *p_v = p_pic->p[ V_PLANE ].p_pixels;
  153.     uint8_t umin, umax, vmin, vmax;
  154.     if( p_pic->format.i_chroma != VLC_FOURCC('Y','U','V','A') )
  155.     {
  156.         msg_Err( p_filter,
  157.                  "Unsupported input chroma "%4s". "
  158.                  "Bluescreen can only use "YUVA".",
  159.                  (char*)&p_pic->format.i_chroma );
  160.         return NULL;
  161.     }
  162.     p_sys->p_at = realloc( p_sys->p_at, i_lines * i_pitch * sizeof( uint8_t ) );
  163.     p_at = p_sys->p_at;
  164.     vlc_mutex_lock( &p_sys->lock );
  165.     umin = p_sys->i_u - p_sys->i_ut >= 0x00 ? p_sys->i_u - p_sys->i_ut : 0x00;
  166.     umax = p_sys->i_u + p_sys->i_ut <= 0xff ? p_sys->i_u + p_sys->i_ut : 0xff;
  167.     vmin = p_sys->i_v - p_sys->i_vt >= 0x00 ? p_sys->i_v - p_sys->i_vt : 0x00;
  168.     vmax = p_sys->i_v + p_sys->i_vt <= 0xff ? p_sys->i_v + p_sys->i_vt : 0xff;
  169.     vlc_mutex_unlock( &p_sys->lock );
  170.     for( i = 0; i < i_lines*i_pitch; i++ )
  171.     {
  172.         if(    p_u[i] < umax && p_u[i] > umin
  173.             && p_v[i] < vmax && p_v[i] > vmin )
  174.         {
  175.             p_at[i] = 0x00;
  176.         }
  177.         else
  178.         {
  179.             p_at[i] = 0xff;
  180.         }
  181.     }
  182.     /* Gaussian convolution to make it look cleaner */
  183.     vlc_memset( p_a, 0, 2 * i_pitch );
  184.     for( i = 2; i < i_lines - 2; i++ )
  185.     {
  186.         p_a[i*i_pitch] = 0x00;
  187.         p_a[i*i_pitch+1] = 0x00;
  188.         for( j = 2; j < i_pitch - 2; j ++ )
  189.         {
  190.             p_a[i*i_pitch+j] = (uint8_t)((
  191.               /* 2 rows up */
  192.                 ( p_at[(i-2)*i_pitch+j-2]<<1 )
  193.               + ( p_at[(i-2)*i_pitch+j-1]<<2 )
  194.               + ( p_at[(i-2)*i_pitch+j]<<2 )
  195.               + ( p_at[(i-2)*i_pitch+j+1]<<2 )
  196.               + ( p_at[(i-2)*i_pitch+j+2]<<1 )
  197.               /* 1 row up */
  198.               + ( p_at[(i-1)*i_pitch+j-2]<<2 )
  199.               + ( p_at[(i-1)*i_pitch+j-1]<<3 )
  200.               + ( p_at[(i-1)*i_pitch+j]*12 )
  201.               + ( p_at[(i-1)*i_pitch+j+1]<<3 )
  202.               + ( p_at[(i-1)*i_pitch+j+2]<<2 )
  203.               /* */
  204.               + ( p_at[i*i_pitch+j-2]<<2 )
  205.               + ( p_at[i*i_pitch+j-1]*12 )
  206.               + ( p_at[i*i_pitch+j]<<4 )
  207.               + ( p_at[i*i_pitch+j+1]*12 )
  208.               + ( p_at[i*i_pitch+j+2]<<2 )
  209.               /* 1 row down */
  210.               + ( p_at[(i+1)*i_pitch+j-2]<<2 )
  211.               + ( p_at[(i+1)*i_pitch+j-1]<<3 )
  212.               + ( p_at[(i+1)*i_pitch+j]*12 )
  213.               + ( p_at[(i+1)*i_pitch+j+1]<<3 )
  214.               + ( p_at[(i+1)*i_pitch+j+2]<<2 )
  215.               /* 2 rows down */
  216.               + ( p_at[(i+2)*i_pitch+j-2]<<1 )
  217.               + ( p_at[(i+2)*i_pitch+j-1]<<2 )
  218.               + ( p_at[(i+2)*i_pitch+j]<<2 )
  219.               + ( p_at[(i+2)*i_pitch+j+1]<<2 )
  220.               + ( p_at[(i+2)*i_pitch+j+2]<<1 )
  221.               )/152);
  222.               if( p_a[i*i_pitch+j] < 0xbf ) p_a[i*i_pitch+j] = 0x00;
  223.         }
  224.     }
  225.     return p_pic;
  226. }
  227. /*****************************************************************************
  228. * Callback to update params on the fly
  229. *****************************************************************************/
  230. static int BluescreenCallback( vlc_object_t *p_this, char const *psz_var,
  231.                                vlc_value_t oldval, vlc_value_t newval,
  232.                                void *p_data )
  233. {
  234.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  235.     filter_sys_t *p_sys = (filter_sys_t *) p_data;
  236.     vlc_mutex_lock( &p_sys->lock );
  237. #define VAR_IS( a ) !strcmp( psz_var, CFG_PREFIX a )
  238.     if( VAR_IS( "u" ) )
  239.         p_sys->i_u = __MAX( 0, __MIN( 255, newval.i_int ) );
  240.     else if( VAR_IS( "v" ) )
  241.         p_sys->i_v = __MAX( 0, __MIN( 255, newval.i_int ) );
  242.     else if( VAR_IS( "ut" ) )
  243.         p_sys->i_ut = __MAX( 0, __MIN( 255, newval.i_int ) );
  244.     else if( VAR_IS( "vt" ) )
  245.         p_sys->i_vt = __MAX( 0, __MIN( 255, newval.i_int ) );
  246.     vlc_mutex_unlock( &p_sys->lock );
  247.     return VLC_SUCCESS;
  248. }