codec: subsdec: fix variable shadowing
[vlc.git] / modules / video_filter / colorthres.c
blob33af63e5aa76bac183bdb86f2559e76a31fc7b45
1 /*****************************************************************************
2 * colorthres.c: Threshold color based on similarity to reference color
3 *****************************************************************************
4 * Copyright (C) 2000-2009 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Sigmund Augdal <dnumgis@videolan.org>
8 * Antoine Cellerier <dionoea at videolan dot org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <math.h>
34 #include <stdatomic.h>
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_sout.h>
39 #include <vlc_filter.h>
40 #include <vlc_picture.h>
41 #include "filter_picture.h"
43 /*****************************************************************************
44 * Local prototypes
45 *****************************************************************************/
46 static int Create ( vlc_object_t * );
47 static void Destroy ( vlc_object_t * );
49 static picture_t *Filter( filter_t *, picture_t * );
50 static picture_t *FilterPacked( filter_t *, picture_t * );
52 /*****************************************************************************
53 * Module descriptor
54 *****************************************************************************/
55 #define COLOR_TEXT N_("Color")
56 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
57 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
58 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
59 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
60 #define COLOR_HELP N_("Select one color in the video")
61 static const int pi_color_values[] = {
62 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
64 static const char *const ppsz_color_descriptions[] = {
65 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
67 #define CFG_PREFIX "colorthres-"
69 vlc_module_begin ()
70 set_description( N_("Color threshold filter") )
71 set_shortname( N_("Color threshold" ))
72 set_help(COLOR_HELP)
73 set_category( CAT_VIDEO )
74 set_subcategory( SUBCAT_VIDEO_VFILTER )
75 set_capability( "video filter", 0 )
76 add_rgb(CFG_PREFIX "color", 0x00FF0000, COLOR_TEXT, COLOR_LONGTEXT)
77 change_integer_list( pi_color_values, ppsz_color_descriptions )
78 add_integer( CFG_PREFIX "saturationthres", 20,
79 N_("Saturation threshold"), "", false )
80 add_integer( CFG_PREFIX "similaritythres", 15,
81 N_("Similarity threshold"), "", false )
82 set_callbacks( Create, Destroy )
83 vlc_module_end ()
85 static const char *const ppsz_filter_options[] = {
86 "color", "saturationthres", "similaritythres", NULL
89 /*****************************************************************************
90 * callback prototypes
91 *****************************************************************************/
92 static int FilterCallback( vlc_object_t *, char const *,
93 vlc_value_t, vlc_value_t, void * );
96 /*****************************************************************************
97 * filter_sys_t: adjust filter method descriptor
98 *****************************************************************************/
99 typedef struct
101 atomic_int i_simthres;
102 atomic_int i_satthres;
103 atomic_int i_color;
104 } filter_sys_t;
106 /*****************************************************************************
107 * Create: allocates adjust video thread output method
108 *****************************************************************************
109 * This function allocates and initializes a adjust vout method.
110 *****************************************************************************/
111 static int Create( vlc_object_t *p_this )
113 filter_t *p_filter = (filter_t *)p_this;
114 filter_sys_t *p_sys;
116 switch( p_filter->fmt_in.video.i_chroma )
118 CASE_PLANAR_YUV
119 p_filter->pf_video_filter = Filter;
120 break;
122 CASE_PACKED_YUV_422
123 p_filter->pf_video_filter = FilterPacked;
124 break;
126 default:
127 msg_Err( p_filter, "Unsupported input chroma (%4.4s)",
128 (char*)&(p_filter->fmt_in.video.i_chroma) );
129 return VLC_EGENERIC;
132 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
134 msg_Err( p_filter, "Input and output chromas don't match" );
135 return VLC_EGENERIC;
138 /* Allocate structure */
139 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
140 if( p_filter->p_sys == NULL )
141 return VLC_ENOMEM;
143 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
144 p_filter->p_cfg );
145 atomic_init( &p_sys->i_color,
146 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" ) );
147 atomic_init( &p_sys->i_simthres,
148 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "similaritythres" ) );
149 atomic_init( &p_sys->i_satthres,
150 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "saturationthres" ) );
152 var_AddCallback( p_filter, CFG_PREFIX "color", FilterCallback, p_sys );
153 var_AddCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, p_sys );
154 var_AddCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, p_sys );
156 return VLC_SUCCESS;
159 /*****************************************************************************
160 * Destroy: destroy adjust video thread output method
161 *****************************************************************************
162 * Terminate an output method created by adjustCreateOutputMethod
163 *****************************************************************************/
164 static void Destroy( vlc_object_t *p_this )
166 filter_t *p_filter = (filter_t *)p_this;
167 filter_sys_t *p_sys = p_filter->p_sys;
169 var_DelCallback( p_filter, CFG_PREFIX "color", FilterCallback, p_sys );
170 var_DelCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, p_sys );
171 var_DelCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, p_sys );
172 free( p_sys );
175 static void GetReference( int *refu, int *refv, int *reflength,
176 uint32_t i_color )
178 int i_red = ( i_color & 0xFF0000 ) >> 16;
179 int i_green = ( i_color & 0x00FF00 ) >> 8;
180 int i_blue = ( i_color & 0x0000FF );
181 int i_u = (int8_t)(( -38 * i_red - 74 * i_green + 112 * i_blue + 128) >> 8) + 128;
182 int i_v = (int8_t)(( 112 * i_red - 94 * i_green - 18 * i_blue + 128) >> 8) + 128;
183 *refu = i_u - 0x80;
184 *refv = i_v - 0x80;
185 *reflength = sqrt(*refu * *refu + *refv * *refv);
188 static bool IsSimilar( int u, int v,
189 int refu, int refv, int reflength,
190 int i_satthres, int i_simthres )
192 int length = sqrt(u * u + v * v);
194 int diffu = refu * length - u * reflength;
195 int diffv = refv * length - v * reflength;
196 int64_t difflen2 = diffu * diffu + diffv * diffv;
197 int64_t thres = length * reflength;
198 thres *= thres;
199 return length > i_satthres && (difflen2 * i_simthres < thres);
201 /*****************************************************************************
202 * Render: displays previously rendered output
203 *****************************************************************************
204 * This function send the currently rendered image to adjust modified image,
205 * waits until it is displayed and switch the two rendering buffers, preparing
206 * next frame.
207 *****************************************************************************/
208 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
210 picture_t *p_outpic;
211 filter_sys_t *p_sys = p_filter->p_sys;
212 int i_simthres = atomic_load( &p_sys->i_simthres );
213 int i_satthres = atomic_load( &p_sys->i_satthres );
214 int i_color = atomic_load( &p_sys->i_color );
216 if( !p_pic ) return NULL;
218 p_outpic = filter_NewPicture( p_filter );
219 if( !p_outpic )
221 picture_Release( p_pic );
222 return NULL;
225 /* Copy the Y plane */
226 plane_CopyPixels( &p_outpic->p[Y_PLANE], &p_pic->p[Y_PLANE] );
229 * Do the U and V planes
231 int refu, refv, reflength;
232 GetReference( &refu, &refv, &reflength, i_color );
234 for( int y = 0; y < p_pic->p[U_PLANE].i_visible_lines; y++ )
236 uint8_t *p_src_u = &p_pic->p[U_PLANE].p_pixels[y * p_pic->p[U_PLANE].i_pitch];
237 uint8_t *p_src_v = &p_pic->p[V_PLANE].p_pixels[y * p_pic->p[V_PLANE].i_pitch];
238 uint8_t *p_dst_u = &p_outpic->p[U_PLANE].p_pixels[y * p_outpic->p[U_PLANE].i_pitch];
239 uint8_t *p_dst_v = &p_outpic->p[V_PLANE].p_pixels[y * p_outpic->p[V_PLANE].i_pitch];
241 for( int x = 0; x < p_pic->p[U_PLANE].i_visible_pitch; x++ )
243 if( IsSimilar( *p_src_u - 0x80, *p_src_v - 0x80,
244 refu, refv, reflength,
245 i_satthres, i_simthres ) )
248 *p_dst_u++ = *p_src_u;
249 *p_dst_v++ = *p_src_v;
251 else
253 *p_dst_u++ = 0x80;
254 *p_dst_v++ = 0x80;
256 p_src_u++;
257 p_src_v++;
261 return CopyInfoAndRelease( p_outpic, p_pic );
264 static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic )
266 picture_t *p_outpic;
267 filter_sys_t *p_sys = p_filter->p_sys;
268 int i_simthres = atomic_load( &p_sys->i_simthres );
269 int i_satthres = atomic_load( &p_sys->i_satthres );
270 int i_color = atomic_load( &p_sys->i_color );
272 if( !p_pic ) return NULL;
274 p_outpic = filter_NewPicture( p_filter );
275 if( !p_outpic )
277 picture_Release( p_pic );
278 return NULL;
281 int i_y_offset, i_u_offset, i_v_offset;
282 int i_ret = GetPackedYuvOffsets( p_filter->fmt_in.video.i_chroma,
283 &i_y_offset, &i_u_offset, &i_v_offset );
284 if( i_ret == VLC_EGENERIC )
286 picture_Release( p_pic );
287 return NULL;
291 * Copy Y and do the U and V planes
293 int refu, refv, reflength;
294 GetReference( &refu, &refv, &reflength, i_color );
296 for( int y = 0; y < p_pic->p->i_visible_lines; y++ )
298 uint8_t *p_src = &p_pic->p->p_pixels[y * p_pic->p->i_pitch];
299 uint8_t *p_dst = &p_outpic->p->p_pixels[y * p_outpic->p->i_pitch];
301 for( int x = 0; x < p_pic->p->i_visible_pitch / 4; x++ )
303 p_dst[i_y_offset + 0] = p_src[i_y_offset + 0];
304 p_dst[i_y_offset + 2] = p_src[i_y_offset + 2];
306 if( IsSimilar( p_src[i_u_offset] - 0x80, p_src[i_v_offset] - 0x80,
307 refu, refv, reflength,
308 i_satthres, i_simthres ) )
310 p_dst[i_u_offset] = p_src[i_u_offset];
311 p_dst[i_v_offset] = p_src[i_v_offset];
313 else
315 p_dst[i_u_offset] = 0x80;
316 p_dst[i_v_offset] = 0x80;
319 p_dst += 4;
320 p_src += 4;
324 return CopyInfoAndRelease( p_outpic, p_pic );
327 static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
328 vlc_value_t oldval, vlc_value_t newval, void *p_data )
330 filter_sys_t *p_sys = p_data;
332 if( !strcmp( psz_var, CFG_PREFIX "color" ) )
333 atomic_store( &p_sys->i_color, newval.i_int );
334 else if( !strcmp( psz_var, CFG_PREFIX "similaritythres" ) )
335 atomic_store( &p_sys->i_simthres, newval.i_int );
336 else /* CFG_PREFIX "saturationthres" */
337 atomic_store( &p_sys->i_satthres, newval.i_int );
339 (void)p_this; (void)oldval;
340 return VLC_SUCCESS;