1 /*****************************************************************************
2 * bluescreen.c : Bluescreen (weather channel like) video filter for vlc
3 *****************************************************************************
4 * Copyright (C) 2005-2007 VLC authors and VideoLAN
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_filter.h>
36 #define BLUESCREEN_HELP N_( \
37 "This effect, also known as \"greenscreen\" or \"chroma key\" blends " \
38 "the \"blue parts\" of the foreground image of the mosaic on the " \
39 "background (like weather forecasts). You can choose the \"key\" " \
40 "color for blending (blue by default)." )
42 #define BLUESCREENU_TEXT N_("Bluescreen U value")
43 #define BLUESCREENU_LONGTEXT N_( \
44 "\"U\" value for the bluescreen key color " \
45 "(in YUV values). From 0 to 255. Defaults to 120 for blue." )
46 #define BLUESCREENV_TEXT N_("Bluescreen V value")
47 #define BLUESCREENV_LONGTEXT N_( \
48 "\"V\" value for the bluescreen key color " \
49 "(in YUV values). From 0 to 255. Defaults to 90 for blue." )
50 #define BLUESCREENUTOL_TEXT N_("Bluescreen U tolerance")
51 #define BLUESCREENUTOL_LONGTEXT N_( \
52 "Tolerance of the bluescreen blender " \
53 "on color variations for the U plane. A value between 10 and 20 " \
55 #define BLUESCREENVTOL_TEXT N_("Bluescreen V tolerance")
56 #define BLUESCREENVTOL_LONGTEXT N_( \
57 "Tolerance of the bluescreen blender " \
58 "on color variations for the V plane. A value between 10 and 20 " \
61 #define CFG_PREFIX "bluescreen-"
63 /*****************************************************************************
65 *****************************************************************************/
66 static int Create ( vlc_object_t
* );
67 static void Destroy ( vlc_object_t
* );
69 static picture_t
*Filter( filter_t
*, picture_t
* );
70 static int BluescreenCallback( vlc_object_t
*, char const *,
71 vlc_value_t
, vlc_value_t
, void * );
73 /*****************************************************************************
75 *****************************************************************************/
77 set_description( N_("Bluescreen video filter") )
78 set_shortname( N_("Bluescreen" ))
79 set_help( BLUESCREEN_HELP
)
80 set_category( CAT_VIDEO
)
81 set_subcategory( SUBCAT_VIDEO_VFILTER
)
82 set_capability( "video filter2", 0 )
83 add_shortcut( "bluescreen" )
84 set_callbacks( Create
, Destroy
)
86 add_integer_with_range( CFG_PREFIX
"u", 120, 0, 255,
87 BLUESCREENU_TEXT
, BLUESCREENU_LONGTEXT
, false )
88 add_integer_with_range( CFG_PREFIX
"v", 90, 0, 255,
89 BLUESCREENV_TEXT
, BLUESCREENV_LONGTEXT
, false )
90 add_integer_with_range( CFG_PREFIX
"ut", 17, 0, 255,
91 BLUESCREENUTOL_TEXT
, BLUESCREENUTOL_LONGTEXT
,
93 add_integer_with_range( CFG_PREFIX
"vt", 17, 0, 255,
94 BLUESCREENVTOL_TEXT
, BLUESCREENVTOL_LONGTEXT
,
98 static const char *const ppsz_filter_options
[] = {
99 "u", "v", "ut", "vt", NULL
105 int i_u
, i_v
, i_ut
, i_vt
;
109 static int Create( vlc_object_t
*p_this
)
111 filter_t
*p_filter
= (filter_t
*)p_this
;
114 if( p_filter
->fmt_in
.video
.i_chroma
!= VLC_CODEC_YUVA
)
117 "Unsupported input chroma \"%4.4s\". "
118 "Bluescreen can only use \"YUVA\".",
119 (char*)&p_filter
->fmt_in
.video
.i_chroma
);
123 /* Allocate structure */
124 p_filter
->p_sys
= malloc( sizeof( filter_sys_t
) );
125 if( p_filter
->p_sys
== NULL
)
127 p_sys
= p_filter
->p_sys
;
129 config_ChainParse( p_filter
, CFG_PREFIX
, ppsz_filter_options
,
133 vlc_mutex_init( &p_sys
->lock
);
134 #define GET_VAR( name, min, max ) \
135 val = var_CreateGetIntegerCommand( p_filter, CFG_PREFIX #name ); \
136 p_sys->i_##name = VLC_CLIP( val, min, max ); \
137 var_AddCallback( p_filter, CFG_PREFIX #name, BluescreenCallback, p_sys );
139 GET_VAR( u
, 0x00, 0xff );
140 GET_VAR( v
, 0x00, 0xff );
141 GET_VAR( ut
, 0x00, 0xff );
142 GET_VAR( vt
, 0x00, 0xff );
146 p_filter
->pf_video_filter
= Filter
;
151 static void Destroy( vlc_object_t
*p_this
)
153 filter_t
*p_filter
= (filter_t
*)p_this
;
154 filter_sys_t
*p_sys
= p_filter
->p_sys
;
156 var_DelCallback( p_filter
, CFG_PREFIX
"u", BluescreenCallback
, p_sys
);
157 var_DelCallback( p_filter
, CFG_PREFIX
"v", BluescreenCallback
, p_sys
);
158 var_DelCallback( p_filter
, CFG_PREFIX
"ut", BluescreenCallback
, p_sys
);
159 var_DelCallback( p_filter
, CFG_PREFIX
"vt", BluescreenCallback
, p_sys
);
162 vlc_mutex_destroy( &p_sys
->lock
);
166 static picture_t
*Filter( filter_t
*p_filter
, picture_t
*p_pic
)
168 filter_sys_t
*p_sys
= p_filter
->p_sys
;
171 int i_lines
= p_pic
->p
[ A_PLANE
].i_lines
;
172 int i_pitch
= p_pic
->p
[ A_PLANE
].i_pitch
;
173 uint8_t *p_a
= p_pic
->p
[ A_PLANE
].p_pixels
;
175 uint8_t *p_u
= p_pic
->p
[ U_PLANE
].p_pixels
;
176 uint8_t *p_v
= p_pic
->p
[ V_PLANE
].p_pixels
;
177 uint8_t umin
, umax
, vmin
, vmax
;
179 if( p_pic
->format
.i_chroma
!= VLC_CODEC_YUVA
)
182 "Unsupported input chroma \"%4.4s\". "
183 "Bluescreen can only use \"YUVA\".",
184 (char*)&p_pic
->format
.i_chroma
);
188 p_sys
->p_at
= xrealloc( p_sys
->p_at
,
189 i_lines
* i_pitch
* sizeof( uint8_t ) );
192 vlc_mutex_lock( &p_sys
->lock
);
193 umin
= p_sys
->i_u
- p_sys
->i_ut
>= 0x00 ? p_sys
->i_u
- p_sys
->i_ut
: 0x00;
194 umax
= p_sys
->i_u
+ p_sys
->i_ut
<= 0xff ? p_sys
->i_u
+ p_sys
->i_ut
: 0xff;
195 vmin
= p_sys
->i_v
- p_sys
->i_vt
>= 0x00 ? p_sys
->i_v
- p_sys
->i_vt
: 0x00;
196 vmax
= p_sys
->i_v
+ p_sys
->i_vt
<= 0xff ? p_sys
->i_v
+ p_sys
->i_vt
: 0xff;
197 vlc_mutex_unlock( &p_sys
->lock
);
199 for( i
= 0; i
< i_lines
*i_pitch
; i
++ )
201 if( p_u
[i
] < umax
&& p_u
[i
] > umin
202 && p_v
[i
] < vmax
&& p_v
[i
] > vmin
)
211 /* Gaussian convolution to make it look cleaner */
212 memset( p_a
, 0, 2 * i_pitch
);
213 for( i
= 2; i
< i_lines
- 2; i
++ )
215 p_a
[i
*i_pitch
] = 0x00;
216 p_a
[i
*i_pitch
+1] = 0x00;
217 for( j
= 2; j
< i_pitch
- 2; j
++ )
219 p_a
[i
*i_pitch
+j
] = (uint8_t)((
221 ( p_at
[(i
-2)*i_pitch
+j
-2]<<1 )
222 + ( p_at
[(i
-2)*i_pitch
+j
-1]<<2 )
223 + ( p_at
[(i
-2)*i_pitch
+j
]<<2 )
224 + ( p_at
[(i
-2)*i_pitch
+j
+1]<<2 )
225 + ( p_at
[(i
-2)*i_pitch
+j
+2]<<1 )
227 + ( p_at
[(i
-1)*i_pitch
+j
-2]<<2 )
228 + ( p_at
[(i
-1)*i_pitch
+j
-1]<<3 )
229 + ( p_at
[(i
-1)*i_pitch
+j
]*12 )
230 + ( p_at
[(i
-1)*i_pitch
+j
+1]<<3 )
231 + ( p_at
[(i
-1)*i_pitch
+j
+2]<<2 )
233 + ( p_at
[i
*i_pitch
+j
-2]<<2 )
234 + ( p_at
[i
*i_pitch
+j
-1]*12 )
235 + ( p_at
[i
*i_pitch
+j
]<<4 )
236 + ( p_at
[i
*i_pitch
+j
+1]*12 )
237 + ( p_at
[i
*i_pitch
+j
+2]<<2 )
239 + ( p_at
[(i
+1)*i_pitch
+j
-2]<<2 )
240 + ( p_at
[(i
+1)*i_pitch
+j
-1]<<3 )
241 + ( p_at
[(i
+1)*i_pitch
+j
]*12 )
242 + ( p_at
[(i
+1)*i_pitch
+j
+1]<<3 )
243 + ( p_at
[(i
+1)*i_pitch
+j
+2]<<2 )
245 + ( p_at
[(i
+2)*i_pitch
+j
-2]<<1 )
246 + ( p_at
[(i
+2)*i_pitch
+j
-1]<<2 )
247 + ( p_at
[(i
+2)*i_pitch
+j
]<<2 )
248 + ( p_at
[(i
+2)*i_pitch
+j
+1]<<2 )
249 + ( p_at
[(i
+2)*i_pitch
+j
+2]<<1 )
251 if( p_a
[i
*i_pitch
+j
] < 0xbf ) p_a
[i
*i_pitch
+j
] = 0x00;
257 /*****************************************************************************
258 * Callback to update params on the fly
259 *****************************************************************************/
260 static int BluescreenCallback( vlc_object_t
*p_this
, char const *psz_var
,
261 vlc_value_t oldval
, vlc_value_t newval
,
264 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
);
265 filter_sys_t
*p_sys
= (filter_sys_t
*) p_data
;
267 vlc_mutex_lock( &p_sys
->lock
);
268 #define VAR_IS( a ) !strcmp( psz_var, CFG_PREFIX a )
270 p_sys
->i_u
= VLC_CLIP( newval
.i_int
, 0, 255 );
271 else if( VAR_IS( "v" ) )
272 p_sys
->i_v
= VLC_CLIP( newval
.i_int
, 0, 255 );
273 else if( VAR_IS( "ut" ) )
274 p_sys
->i_ut
= VLC_CLIP( newval
.i_int
, 0, 255 );
275 else if( VAR_IS( "vt" ) )
276 p_sys
->i_vt
= VLC_CLIP( newval
.i_int
, 0, 255 );
277 vlc_mutex_unlock( &p_sys
->lock
);