1 /*****************************************************************************
2 * gradfun.c: wrapper for the gradfun filter from mplayer
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ 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>
35 #include <vlc_filter.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int Open (vlc_object_t *);
41 static void Close(vlc_object_t *);
43 #define CFG_PREFIX "gradfun-"
45 #define RADIUS_MIN (4)
46 #define RADIUS_MAX (32)
47 #define RADIUS_TEXT N_("Radius")
48 #define RADIUS_LONGTEXT N_("Radius in pixels")
50 #define STRENGTH_MIN (0.51)
51 #define STRENGTH_MAX (255)
52 #define STRENGTH_TEXT N_("Strength")
53 #define STRENGTH_LONGTEXT N_("Strength used to modify the value of a pixel")
56 set_description(N_("Gradfun video filter"))
57 set_shortname(N_("Gradfun"))
58 set_help("Debanding algorithm")
59 set_capability("video filter2", 0)
60 set_category(CAT_VIDEO)
61 set_subcategory(SUBCAT_VIDEO_VFILTER)
62 add_integer_with_range(CFG_PREFIX "radius", 16, RADIUS_MIN, RADIUS_MAX,
63 NULL, RADIUS_TEXT, RADIUS_LONGTEXT, false)
64 add_float_with_range(CFG_PREFIX "strength", 1.2, STRENGTH_MIN, STRENGTH_MAX,
65 NULL, STRENGTH_TEXT, STRENGTH_LONGTEXT, false)
67 set_callbacks(Open, Close)
70 /*****************************************************************************
72 *****************************************************************************/
73 #define FFMAX(a,b) __MAX(a,b)
74 #ifdef CAN_COMPILE_MMXEXT
79 #ifdef CAN_COMPILE_SSE2
84 #ifdef CAN_COMPILE_SSSE3
89 // FIXME too restrictive
95 #define av_clip_uint8 clip_uint8_vlc
98 static picture_t *Filter(filter_t *, picture_t *);
99 static int Callback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
101 struct filter_sys_t {
108 struct vf_priv_s cfg;
111 static int Open(vlc_object_t *object)
113 filter_t *filter = (filter_t *)object;
117 switch (filter->fmt_in.video.i_chroma) {
120 h_shift = 2; v_shift = 2;
123 h_shift = 2; v_shift = 0;
128 h_shift = 1; v_shift = 1;
132 h_shift = 1; v_shift = 0;
137 h_shift = 0; v_shift = 0;
141 h_shift = 0; v_shift = 1;
147 filter_sys_t *sys = malloc(sizeof(*sys));
151 vlc_mutex_init(&sys->lock);
152 sys->h_shift = h_shift;
153 sys->v_shift = v_shift;
154 sys->strength = var_CreateGetFloatCommand(filter, CFG_PREFIX "strength");
155 sys->radius = var_CreateGetIntegerCommand(filter, CFG_PREFIX "radius");
156 var_AddCallback(filter, CFG_PREFIX "strength", Callback, NULL);
157 var_AddCallback(filter, CFG_PREFIX "radius", Callback, NULL);
158 sys->base_buf = NULL;
160 struct vf_priv_s *cfg = &sys->cfg;
164 cfg->filter_line = filter_line_c;
165 cfg->blur_line = blur_line_c;
167 #if HAVE_SSE2 && HAVE_6REGS
168 if (vlc_CPU() & CPU_CAPABILITY_SSE2)
169 cfg->blur_line = blur_line_sse2;
172 if (vlc_CPU() & CPU_CAPABILITY_MMXEXT)
173 cfg->filter_line = filter_line_mmx2;
176 if (vlc_CPU() & CPU_CAPABILITY_SSSE3)
177 cfg->filter_line = filter_line_ssse3;
181 filter->pf_video_filter = Filter;
185 static void Close(vlc_object_t *object)
187 filter_t *filter = (filter_t *)object;
188 filter_sys_t *sys = filter->p_sys;
191 vlc_mutex_destroy(&sys->lock);
195 static picture_t *Filter(filter_t *filter, picture_t *src)
197 filter_sys_t *sys = filter->p_sys;
199 picture_t *dst = filter_NewPicture(filter);
201 picture_Release(src);
205 vlc_mutex_lock(&sys->lock);
206 float strength = __MIN(__MAX(sys->strength, STRENGTH_MIN), STRENGTH_MAX);
207 int radius = __MIN(__MAX((sys->radius + 1) & ~1, RADIUS_MIN), RADIUS_MAX);
208 vlc_mutex_unlock(&sys->lock);
210 const video_format_t *fmt = &filter->fmt_in.video;
211 struct vf_priv_s *cfg = &sys->cfg;
213 cfg->thresh = (1 << 15) / strength;
214 if (cfg->radius != radius) {
215 cfg->radius = radius;
216 cfg->buf = vlc_memalign(&sys->base_buf, 16,
217 (((fmt->i_width + 15) & ~15) * (cfg->radius + 1) / 2 + 32) * sizeof(*cfg->buf));
220 for (int i = 0; i < dst->i_planes; i++) {
221 const plane_t *srcp = &src->p[i];
222 plane_t *dstp = &dst->p[i];
224 int w = fmt->i_width;
225 int h = fmt->i_height;
230 r = ((r >> sys->h_shift) + (r >> sys->v_shift)) / 2;
231 r = __MIN(__MAX((r + 1) & ~1, RADIUS_MIN), RADIUS_MAX);
233 if (__MIN(w, h) > 2 * r && cfg->buf) {
234 filter_plane(cfg, dstp->p_pixels, srcp->p_pixels,
235 w, h, dstp->i_pitch, srcp->i_pitch, r);
237 plane_CopyPixels(dstp, srcp);
241 picture_CopyProperties(dst, src);
242 picture_Release(src);
246 static int Callback(vlc_object_t *object, char const *cmd,
247 vlc_value_t oldval, vlc_value_t newval, void *data)
249 filter_t *filter = (filter_t *)object;
250 filter_sys_t *sys = filter->p_sys;
251 VLC_UNUSED(oldval); VLC_UNUSED(data);
253 vlc_mutex_lock(&sys->lock);
254 if (!strcmp(cmd, CFG_PREFIX "strength"))
255 sys->strength = newval.f_float;
257 sys->radius = newval.i_int;
258 vlc_mutex_unlock(&sys->lock);