1 /*****************************************************************************
2 * bluescreen.c : Bluescreen (weather channel like) video filter for vlc
3 *****************************************************************************
4 * Copyright (C) 2005-2007 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
36 #include "vlc_filter.h"
38 #define BLUESCREEN_HELP N_( \
39 "This effect, also known as \"greenscreen\" or \"chroma key\" blends " \
40 "the \"blue parts\" of the foreground image of the mosaic on the " \
41 "background (like weather forcasts). You can choose the \"key\" " \
42 "color for blending (blyyue by default)." )
44 #define BLUESCREENU_TEXT N_("Bluescreen U value")
45 #define BLUESCREENU_LONGTEXT N_( \
46 "\"U\" value for the bluescreen key color " \
47 "(in YUV values). From 0 to 255. Defaults to 120 for blue." )
48 #define BLUESCREENV_TEXT N_("Bluescreen V value")
49 #define BLUESCREENV_LONGTEXT N_( \
50 "\"V\" value for the bluescreen key color " \
51 "(in YUV values). From 0 to 255. Defaults to 90 for blue." )
52 #define BLUESCREENUTOL_TEXT N_("Bluescreen U tolerance")
53 #define BLUESCREENUTOL_LONGTEXT N_( \
54 "Tolerance of the bluescreen blender " \
55 "on color variations for the U plane. A value between 10 and 20 " \
57 #define BLUESCREENVTOL_TEXT N_("Bluescreen V tolerance")
58 #define BLUESCREENVTOL_LONGTEXT N_( \
59 "Tolerance of the bluescreen blender " \
60 "on color variations for the V plane. A value between 10 and 20 " \
63 #define CFG_PREFIX "bluescreen-"
65 /*****************************************************************************
67 *****************************************************************************/
68 static int Create ( vlc_object_t
* );
69 static void Destroy ( vlc_object_t
* );
71 static picture_t
*Filter( filter_t
*, picture_t
* );
72 static int BluescreenCallback( vlc_object_t
*, char const *,
73 vlc_value_t
, vlc_value_t
, void * );
75 /*****************************************************************************
77 *****************************************************************************/
79 set_description( N_("Bluescreen video filter") );
80 set_shortname( N_("Bluescreen" ));
81 set_help( BLUESCREEN_HELP
);
82 set_category( CAT_VIDEO
);
83 set_subcategory( SUBCAT_VIDEO_VFILTER
);
84 set_capability( "video filter2", 0 );
85 add_shortcut( "bluescreen" );
86 set_callbacks( Create
, Destroy
);
88 add_integer_with_range( CFG_PREFIX
"u", 120, 0, 255, NULL
,
89 BLUESCREENU_TEXT
, BLUESCREENU_LONGTEXT
, false );
90 add_integer_with_range( CFG_PREFIX
"v", 90, 0, 255, NULL
,
91 BLUESCREENV_TEXT
, BLUESCREENV_LONGTEXT
, false );
92 add_integer_with_range( CFG_PREFIX
"ut", 17, 0, 255, NULL
,
93 BLUESCREENUTOL_TEXT
, BLUESCREENUTOL_LONGTEXT
,
95 add_integer_with_range( CFG_PREFIX
"vt", 17, 0, 255, NULL
,
96 BLUESCREENVTOL_TEXT
, BLUESCREENVTOL_LONGTEXT
,
100 static const char *const ppsz_filter_options
[] = {
101 "u", "v", "ut", "vt", NULL
106 int i_u
, i_v
, i_ut
, i_vt
;
110 static int Create( vlc_object_t
*p_this
)
112 filter_t
*p_filter
= (filter_t
*)p_this
;
115 if( p_filter
->fmt_in
.video
.i_chroma
!= VLC_FOURCC('Y','U','V','A') )
118 "Unsupported input chroma \"%4s\". "
119 "Bluescreen can only use \"YUVA\".",
120 (char*)&p_filter
->fmt_in
.video
.i_chroma
);
124 /* Allocate structure */
125 p_filter
->p_sys
= malloc( sizeof( filter_sys_t
) );
126 if( p_filter
->p_sys
== NULL
)
128 msg_Err( p_filter
, "out of memory" );
131 p_sys
= p_filter
->p_sys
;
133 config_ChainParse( p_filter
, CFG_PREFIX
, ppsz_filter_options
,
136 #define GET_VAR( name, min, max ) \
137 p_sys->i_##name = __MIN( max, __MAX( min, \
138 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX #name ) ) ); \
139 var_AddCallback( p_filter, CFG_PREFIX #name, BluescreenCallback, p_sys );
141 GET_VAR( u
, 0x00, 0xff );
142 GET_VAR( v
, 0x00, 0xff );
143 GET_VAR( ut
, 0x00, 0xff );
144 GET_VAR( vt
, 0x00, 0xff );
147 p_filter
->pf_video_filter
= Filter
;
152 static void Destroy( vlc_object_t
*p_this
)
154 filter_t
*p_filter
= (filter_t
*)p_this
;
156 free( p_filter
->p_sys
->p_at
);
157 free( p_filter
->p_sys
);
160 static picture_t
*Filter( filter_t
*p_filter
, picture_t
*p_pic
)
162 filter_sys_t
*p_sys
= p_filter
->p_sys
;
165 int i_lines
= p_pic
->p
[ A_PLANE
].i_lines
;
166 int i_pitch
= p_pic
->p
[ A_PLANE
].i_pitch
;
167 uint8_t *p_a
= p_pic
->p
[ A_PLANE
].p_pixels
;
169 uint8_t *p_u
= p_pic
->p
[ U_PLANE
].p_pixels
;
170 uint8_t *p_v
= p_pic
->p
[ V_PLANE
].p_pixels
;
171 uint8_t umin
, umax
, vmin
, vmax
;
173 if( p_pic
->format
.i_chroma
!= VLC_FOURCC('Y','U','V','A') )
176 "Unsupported input chroma \"%4s\". "
177 "Bluescreen can only use \"YUVA\".",
178 (char*)&p_pic
->format
.i_chroma
);
182 p_sys
->p_at
= realloc( p_sys
->p_at
, i_lines
* i_pitch
* sizeof( uint8_t ) );
185 umin
= p_sys
->i_u
- p_sys
->i_ut
>= 0x00 ? p_sys
->i_u
- p_sys
->i_ut
: 0x00;
186 umax
= p_sys
->i_u
+ p_sys
->i_ut
<= 0xff ? p_sys
->i_u
+ p_sys
->i_ut
: 0xff;
187 vmin
= p_sys
->i_v
- p_sys
->i_vt
>= 0x00 ? p_sys
->i_v
- p_sys
->i_vt
: 0x00;
188 vmax
= p_sys
->i_v
+ p_sys
->i_vt
<= 0xff ? p_sys
->i_v
+ p_sys
->i_vt
: 0xff;
190 for( i
= 0; i
< i_lines
*i_pitch
; i
++ )
192 if( p_u
[i
] < umax
&& p_u
[i
] > umin
193 && p_v
[i
] < vmax
&& p_v
[i
] > vmin
)
202 /* Gaussian convolution to make it look cleaner */
203 vlc_memset( p_a
, 0, 2 * i_pitch
);
204 for( i
= 2; i
< i_lines
- 2; i
++ )
206 p_a
[i
*i_pitch
] = 0x00;
207 p_a
[i
*i_pitch
+1] = 0x00;
208 for( j
= 2; j
< i_pitch
- 2; j
++ )
210 p_a
[i
*i_pitch
+j
] = (uint8_t)((
212 ( p_at
[(i
-2)*i_pitch
+j
-2]<<1 )
213 + ( p_at
[(i
-2)*i_pitch
+j
-1]<<2 )
214 + ( p_at
[(i
-2)*i_pitch
+j
]<<2 )
215 + ( p_at
[(i
-2)*i_pitch
+j
+1]<<2 )
216 + ( p_at
[(i
-2)*i_pitch
+j
+2]<<1 )
218 + ( p_at
[(i
-1)*i_pitch
+j
-2]<<2 )
219 + ( p_at
[(i
-1)*i_pitch
+j
-1]<<3 )
220 + ( p_at
[(i
-1)*i_pitch
+j
]*12 )
221 + ( p_at
[(i
-1)*i_pitch
+j
+1]<<3 )
222 + ( p_at
[(i
-1)*i_pitch
+j
+2]<<2 )
224 + ( p_at
[i
*i_pitch
+j
-2]<<2 )
225 + ( p_at
[i
*i_pitch
+j
-1]*12 )
226 + ( p_at
[i
*i_pitch
+j
]<<4 )
227 + ( p_at
[i
*i_pitch
+j
+1]*12 )
228 + ( p_at
[i
*i_pitch
+j
+2]<<2 )
230 + ( p_at
[(i
+1)*i_pitch
+j
-2]<<2 )
231 + ( p_at
[(i
+1)*i_pitch
+j
-1]<<3 )
232 + ( p_at
[(i
+1)*i_pitch
+j
]*12 )
233 + ( p_at
[(i
+1)*i_pitch
+j
+1]<<3 )
234 + ( p_at
[(i
+1)*i_pitch
+j
+2]<<2 )
236 + ( p_at
[(i
+2)*i_pitch
+j
-2]<<1 )
237 + ( p_at
[(i
+2)*i_pitch
+j
-1]<<2 )
238 + ( p_at
[(i
+2)*i_pitch
+j
]<<2 )
239 + ( p_at
[(i
+2)*i_pitch
+j
+1]<<2 )
240 + ( p_at
[(i
+2)*i_pitch
+j
+2]<<1 )
242 if( p_a
[i
*i_pitch
+j
] < 0xbf ) p_a
[i
*i_pitch
+j
] = 0x00;
248 /*****************************************************************************
249 * Callback to update params on the fly
250 *****************************************************************************/
251 static int BluescreenCallback( vlc_object_t
*p_this
, char const *psz_var
,
252 vlc_value_t oldval
, vlc_value_t newval
,
255 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
);
256 filter_sys_t
*p_sys
= (filter_sys_t
*) p_data
;
258 #define VAR_IS( a ) !strcmp( psz_var, CFG_PREFIX a )
261 p_sys
->i_u
= __MAX( 0, __MIN( 255, newval
.i_int
) );
263 else if( VAR_IS( "v" ) )
265 p_sys
->i_v
= __MAX( 0, __MIN( 255, newval
.i_int
) );
267 else if( VAR_IS( "ut" ) )
269 p_sys
->i_ut
= __MAX( 0, __MIN( 255, newval
.i_int
) );
271 else if( VAR_IS( "vt" ) )
273 p_sys
->i_vt
= __MAX( 0, __MIN( 255, newval
.i_int
) );