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 {
105 const vlc_chroma_description_t *chroma;
107 struct vf_priv_s cfg;
110 static int Open(vlc_object_t *object)
112 filter_t *filter = (filter_t *)object;
113 const vlc_fourcc_t fourcc = filter->fmt_in.video.i_chroma;
115 const vlc_chroma_description_t *chroma = vlc_fourcc_GetChromaDescription(fourcc);
116 if (!chroma || chroma->plane_count < 3) {
117 msg_Err(filter, "Unsupported chroma (%4.4s)", (char*)&fourcc);
121 filter_sys_t *sys = malloc(sizeof(*sys));
125 vlc_mutex_init(&sys->lock);
126 sys->chroma = chroma;
127 sys->strength = var_CreateGetFloatCommand(filter, CFG_PREFIX "strength");
128 sys->radius = var_CreateGetIntegerCommand(filter, CFG_PREFIX "radius");
129 var_AddCallback(filter, CFG_PREFIX "strength", Callback, NULL);
130 var_AddCallback(filter, CFG_PREFIX "radius", Callback, NULL);
131 sys->base_buf = NULL;
133 struct vf_priv_s *cfg = &sys->cfg;
137 cfg->filter_line = filter_line_c;
138 cfg->blur_line = blur_line_c;
140 #if HAVE_SSE2 && HAVE_6REGS
141 if (vlc_CPU() & CPU_CAPABILITY_SSE2)
142 cfg->blur_line = blur_line_sse2;
145 if (vlc_CPU() & CPU_CAPABILITY_MMXEXT)
146 cfg->filter_line = filter_line_mmx2;
149 if (vlc_CPU() & CPU_CAPABILITY_SSSE3)
150 cfg->filter_line = filter_line_ssse3;
154 filter->pf_video_filter = Filter;
158 static void Close(vlc_object_t *object)
160 filter_t *filter = (filter_t *)object;
161 filter_sys_t *sys = filter->p_sys;
164 vlc_mutex_destroy(&sys->lock);
168 static picture_t *Filter(filter_t *filter, picture_t *src)
170 filter_sys_t *sys = filter->p_sys;
172 picture_t *dst = filter_NewPicture(filter);
174 picture_Release(src);
178 vlc_mutex_lock(&sys->lock);
179 float strength = __MIN(__MAX(sys->strength, STRENGTH_MIN), STRENGTH_MAX);
180 int radius = __MIN(__MAX((sys->radius + 1) & ~1, RADIUS_MIN), RADIUS_MAX);
181 vlc_mutex_unlock(&sys->lock);
183 const video_format_t *fmt = &filter->fmt_in.video;
184 struct vf_priv_s *cfg = &sys->cfg;
186 cfg->thresh = (1 << 15) / strength;
187 if (cfg->radius != radius) {
188 cfg->radius = radius;
189 cfg->buf = vlc_memalign(&sys->base_buf, 16,
190 (((fmt->i_width + 15) & ~15) * (cfg->radius + 1) / 2 + 32) * sizeof(*cfg->buf));
193 for (int i = 0; i < dst->i_planes; i++) {
194 const plane_t *srcp = &src->p[i];
195 plane_t *dstp = &dst->p[i];
197 const vlc_chroma_description_t *chroma = sys->chroma;
198 int w = fmt->i_width * chroma->p[i].w.num / chroma->p[i].w.den;
199 int h = fmt->i_height * chroma->p[i].h.num / chroma->p[i].h.den;
200 int r = (cfg->radius * chroma->p[i].w.num / chroma->p[i].w.den +
201 cfg->radius * chroma->p[i].h.num / chroma->p[i].h.den) / 2;
202 r = __MIN(__MAX((r + 1) & ~1, RADIUS_MIN), RADIUS_MAX);
203 if (__MIN(w, h) > 2 * r && cfg->buf) {
204 filter_plane(cfg, dstp->p_pixels, srcp->p_pixels,
205 w, h, dstp->i_pitch, srcp->i_pitch, r);
207 plane_CopyPixels(dstp, srcp);
211 picture_CopyProperties(dst, src);
212 picture_Release(src);
216 static int Callback(vlc_object_t *object, char const *cmd,
217 vlc_value_t oldval, vlc_value_t newval, void *data)
219 filter_t *filter = (filter_t *)object;
220 filter_sys_t *sys = filter->p_sys;
221 VLC_UNUSED(oldval); VLC_UNUSED(data);
223 vlc_mutex_lock(&sys->lock);
224 if (!strcmp(cmd, CFG_PREFIX "strength"))
225 sys->strength = newval.f_float;
227 sys->radius = newval.i_int;
228 vlc_mutex_unlock(&sys->lock);