add_integer: remove callback parameter
[vlc/asuraparaju-public.git] / modules / video_filter / colorthres.c
blob0f81424b7eb2d48996edc9c33c7945425ee3f1fa
1 /*****************************************************************************
2 * colorthres.c: Threshold color based on similarity to reference color
3 *****************************************************************************
4 * Copyright (C) 2000-2009 the VideoLAN team
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
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.
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.
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., 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>
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_sout.h>
39 #include <vlc_filter.h>
40 #include "filter_picture.h"
42 /*****************************************************************************
43 * Local prototypes
44 *****************************************************************************/
45 static int Create ( vlc_object_t * );
46 static void Destroy ( vlc_object_t * );
48 static picture_t *Filter( filter_t *, picture_t * );
49 static picture_t *FilterPacked( filter_t *, picture_t * );
51 /*****************************************************************************
52 * Module descriptor
53 *****************************************************************************/
54 #define COLOR_TEXT N_("Color")
55 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
56 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
57 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
58 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
59 #define COLOR_HELP N_("Select one color in the video")
60 static const int pi_color_values[] = {
61 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
63 static const char *const ppsz_color_descriptions[] = {
64 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
66 #define CFG_PREFIX "colorthres-"
68 vlc_module_begin ()
69 set_description( N_("Color threshold filter") )
70 set_shortname( N_("Color threshold" ))
71 set_help(COLOR_HELP)
72 set_category( CAT_VIDEO )
73 set_subcategory( SUBCAT_VIDEO_VFILTER )
74 set_capability( "video filter2", 0 )
75 add_integer( CFG_PREFIX "color", 0x00FF0000, COLOR_TEXT,
76 COLOR_LONGTEXT, false )
77 change_integer_list( pi_color_values, ppsz_color_descriptions )
78 add_integer( CFG_PREFIX "saturationthres", 20,
79 N_("Saturaton 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 struct filter_sys_t
101 int i_simthres;
102 int i_satthres;
103 int i_color;
104 vlc_mutex_t lock;
107 /*****************************************************************************
108 * Create: allocates adjust video thread output method
109 *****************************************************************************
110 * This function allocates and initializes a adjust vout method.
111 *****************************************************************************/
112 static int Create( vlc_object_t *p_this )
114 filter_t *p_filter = (filter_t *)p_this;
115 filter_sys_t *p_sys;
117 switch( p_filter->fmt_in.video.i_chroma )
119 CASE_PLANAR_YUV
120 p_filter->pf_video_filter = Filter;
121 break;
123 CASE_PACKED_YUV_422
124 p_filter->pf_video_filter = FilterPacked;
125 break;
127 default:
128 msg_Err( p_filter, "Unsupported input chroma (%4.4s)",
129 (char*)&(p_filter->fmt_in.video.i_chroma) );
130 return VLC_EGENERIC;
133 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
135 msg_Err( p_filter, "Input and output chromas don't match" );
136 return VLC_EGENERIC;
139 /* Allocate structure */
140 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
141 if( p_filter->p_sys == NULL )
142 return VLC_ENOMEM;
144 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
145 p_filter->p_cfg );
146 p_sys->i_color = var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
147 p_sys->i_simthres = var_CreateGetIntegerCommand( p_filter,
148 CFG_PREFIX "similaritythres" );
149 p_sys->i_satthres = var_CreateGetIntegerCommand( p_filter,
150 CFG_PREFIX "saturationthres" );
152 vlc_mutex_init( &p_sys->lock );
154 var_AddCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
155 var_AddCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
156 var_AddCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
158 return VLC_SUCCESS;
161 /*****************************************************************************
162 * Destroy: destroy adjust video thread output method
163 *****************************************************************************
164 * Terminate an output method created by adjustCreateOutputMethod
165 *****************************************************************************/
166 static void Destroy( vlc_object_t *p_this )
168 filter_t *p_filter = (filter_t *)p_this;
170 var_DelCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
171 var_DelCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
172 var_DelCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
174 vlc_mutex_destroy( &p_filter->p_sys->lock );
175 free( p_filter->p_sys );
178 static void GetReference( int *refu, int *refv, int *reflength,
179 uint32_t i_color )
181 int i_red = ( i_color & 0xFF0000 ) >> 16;
182 int i_green = ( i_color & 0x00FF00 ) >> 8;
183 int i_blue = ( i_color & 0x0000FF );
184 int i_u = (int8_t)(( -38 * i_red - 74 * i_green + 112 * i_blue + 128) >> 8) + 128;
185 int i_v = (int8_t)(( 112 * i_red - 94 * i_green - 18 * i_blue + 128) >> 8) + 128;
186 *refu = i_u - 0x80;
187 *refv = i_v - 0x80;
188 *reflength = sqrt(*refu * *refu + *refv * *refv);
191 static bool IsSimilar( int u, int v,
192 int refu, int refv, int reflength,
193 int i_satthres, int i_simthres )
195 int length = sqrt(u * u + v * v);
197 int diffu = refu * length - u * reflength;
198 int diffv = refv * length - v * reflength;
199 int64_t difflen2 = diffu * diffu + diffv * diffv;
200 int64_t thres = length * reflength;
201 thres *= thres;
202 return length > i_satthres && (difflen2 * i_simthres < thres);
204 /*****************************************************************************
205 * Render: displays previously rendered output
206 *****************************************************************************
207 * This function send the currently rendered image to adjust modified image,
208 * waits until it is displayed and switch the two rendering buffers, preparing
209 * next frame.
210 *****************************************************************************/
211 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
213 picture_t *p_outpic;
214 filter_sys_t *p_sys = p_filter->p_sys;
216 vlc_mutex_lock( &p_sys->lock );
217 int i_simthres = p_sys->i_simthres;
218 int i_satthres = p_sys->i_satthres;
219 int i_color = p_sys->i_color;
220 vlc_mutex_unlock( &p_sys->lock );
222 if( !p_pic ) return NULL;
224 p_outpic = filter_NewPicture( p_filter );
225 if( !p_outpic )
227 picture_Release( p_pic );
228 return NULL;
231 /* Copy the Y plane */
232 plane_CopyPixels( &p_outpic->p[Y_PLANE], &p_pic->p[Y_PLANE] );
235 * Do the U and V planes
237 int refu, refv, reflength;
238 GetReference( &refu, &refv, &reflength, i_color );
240 for( int y = 0; y < p_pic->p[U_PLANE].i_visible_lines; y++ )
242 uint8_t *p_src_u = &p_pic->p[U_PLANE].p_pixels[y * p_pic->p[U_PLANE].i_pitch];
243 uint8_t *p_src_v = &p_pic->p[V_PLANE].p_pixels[y * p_pic->p[V_PLANE].i_pitch];
244 uint8_t *p_dst_u = &p_outpic->p[U_PLANE].p_pixels[y * p_outpic->p[U_PLANE].i_pitch];
245 uint8_t *p_dst_v = &p_outpic->p[V_PLANE].p_pixels[y * p_outpic->p[V_PLANE].i_pitch];
247 for( int x = 0; x < p_pic->p[U_PLANE].i_visible_pitch; x++ )
249 if( IsSimilar( *p_src_u - 0x80, *p_src_v - 0x80,
250 refu, refv, reflength,
251 i_satthres, i_simthres ) )
254 *p_dst_u++ = *p_src_u;
255 *p_dst_v++ = *p_src_v;
257 else
259 *p_dst_u++ = 0x80;
260 *p_dst_v++ = 0x80;
262 p_src_u++;
263 p_src_v++;
267 return CopyInfoAndRelease( p_outpic, p_pic );
270 static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic )
272 picture_t *p_outpic;
273 filter_sys_t *p_sys = p_filter->p_sys;
275 vlc_mutex_lock( &p_sys->lock );
276 int i_simthres = p_sys->i_simthres;
277 int i_satthres = p_sys->i_satthres;
278 int i_color = p_sys->i_color;
279 vlc_mutex_unlock( &p_sys->lock );
281 if( !p_pic ) return NULL;
283 p_outpic = filter_NewPicture( p_filter );
284 if( !p_outpic )
286 picture_Release( p_pic );
287 return NULL;
290 int i_y_offset, i_u_offset, i_v_offset;
291 int i_ret = GetPackedYuvOffsets( p_filter->fmt_in.video.i_chroma,
292 &i_y_offset, &i_u_offset, &i_v_offset );
293 if( i_ret == VLC_EGENERIC )
295 picture_Release( p_pic );
296 return NULL;
300 * Copy Y and do the U and V planes
302 int refu, refv, reflength;
303 GetReference( &refu, &refv, &reflength, i_color );
305 for( int y = 0; y < p_pic->p->i_visible_lines; y++ )
307 uint8_t *p_src = &p_pic->p->p_pixels[y * p_pic->p->i_pitch];
308 uint8_t *p_dst = &p_outpic->p->p_pixels[y * p_outpic->p->i_pitch];
310 for( int x = 0; x < p_pic->p->i_visible_pitch / 4; x++ )
312 p_dst[i_y_offset + 0] = p_src[i_y_offset + 0];
313 p_dst[i_y_offset + 2] = p_src[i_y_offset + 2];
315 if( IsSimilar( p_src[i_u_offset] - 0x80, p_src[i_v_offset] - 0x80,
316 refu, refv, reflength,
317 i_satthres, i_simthres ) )
319 p_dst[i_u_offset] = p_src[i_u_offset];
320 p_dst[i_v_offset] = p_src[i_v_offset];
322 else
324 p_dst[i_u_offset] = 0x80;
325 p_dst[i_v_offset] = 0x80;
328 p_dst += 4;
329 p_src += 4;
333 return CopyInfoAndRelease( p_outpic, p_pic );
336 static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
337 vlc_value_t oldval, vlc_value_t newval, void *p_data )
339 (void)oldval; (void)p_data;
340 filter_t *p_filter = (filter_t*)p_this;
341 filter_sys_t *p_sys = p_filter->p_sys;
343 if( !strcmp( psz_var, CFG_PREFIX "color" ) )
345 vlc_mutex_lock( &p_sys->lock );
346 p_sys->i_color = newval.i_int;
347 vlc_mutex_unlock( &p_sys->lock );
349 else if( !strcmp( psz_var, CFG_PREFIX "similaritythres" ) )
351 vlc_mutex_lock( &p_sys->lock );
352 p_sys->i_simthres = newval.i_int;
353 vlc_mutex_unlock( &p_sys->lock );
355 else /* CFG_PREFIX "saturationthres" */
357 vlc_mutex_lock( &p_sys->lock );
358 p_sys->i_satthres = newval.i_int;
359 vlc_mutex_unlock( &p_sys->lock );
362 return VLC_SUCCESS;